qemu

Форк
0
/
acpi-build.c 
661 строка · 21.8 Кб
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
/*
3
 * Support for generating ACPI tables and passing them to Guests
4
 *
5
 * Copyright (C) 2021 Loongson Technology Corporation Limited
6
 */
7

8
#include "qemu/osdep.h"
9
#include "qapi/error.h"
10
#include "qemu/error-report.h"
11
#include "qemu/bitmap.h"
12
#include "hw/pci/pci.h"
13
#include "hw/core/cpu.h"
14
#include "target/loongarch/cpu.h"
15
#include "hw/acpi/acpi-defs.h"
16
#include "hw/acpi/acpi.h"
17
#include "hw/nvram/fw_cfg.h"
18
#include "hw/acpi/bios-linker-loader.h"
19
#include "migration/vmstate.h"
20
#include "hw/mem/memory-device.h"
21
#include "sysemu/reset.h"
22

23
/* Supported chipsets: */
24
#include "hw/pci-host/ls7a.h"
25
#include "hw/loongarch/virt.h"
26

27
#include "hw/acpi/utils.h"
28
#include "hw/acpi/pci.h"
29

30
#include "qom/qom-qobject.h"
31

32
#include "hw/acpi/generic_event_device.h"
33
#include "hw/pci-host/gpex.h"
34
#include "sysemu/tpm.h"
35
#include "hw/platform-bus.h"
36
#include "hw/acpi/aml-build.h"
37
#include "hw/acpi/hmat.h"
38

39
#define ACPI_BUILD_ALIGN_SIZE             0x1000
40
#define ACPI_BUILD_TABLE_SIZE             0x20000
41

42
#ifdef DEBUG_ACPI_BUILD
43
#define ACPI_BUILD_DPRINTF(fmt, ...)        \
44
    do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0)
45
#else
46
#define ACPI_BUILD_DPRINTF(fmt, ...)
47
#endif
48

49
/* build FADT */
50
static void init_common_fadt_data(AcpiFadtData *data)
51
{
52
    AcpiFadtData fadt = {
53
        /* ACPI 5.0: 4.1 Hardware-Reduced ACPI */
54
        .rev = 5,
55
        .flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) |
56
                  (1 << ACPI_FADT_F_RESET_REG_SUP)),
57

58
        /* ACPI 5.0: 4.8.3.7 Sleep Control and Status Registers */
59
        .sleep_ctl = {
60
            .space_id = AML_AS_SYSTEM_MEMORY,
61
            .bit_width = 8,
62
            .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_CTL,
63
        },
64
        .sleep_sts = {
65
            .space_id = AML_AS_SYSTEM_MEMORY,
66
            .bit_width = 8,
67
            .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_STS,
68
        },
69

70
        /* ACPI 5.0: 4.8.3.6 Reset Register */
71
        .reset_reg = {
72
            .space_id = AML_AS_SYSTEM_MEMORY,
73
            .bit_width = 8,
74
            .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_RESET,
75
        },
76
        .reset_val = ACPI_GED_RESET_VALUE,
77
    };
78
    *data = fadt;
79
}
80

81
static void acpi_align_size(GArray *blob, unsigned align)
82
{
83
    /*
84
     * Align size to multiple of given size. This reduces the chance
85
     * we need to change size in the future (breaking cross version migration).
86
     */
87
    g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
88
}
89

90
/* build FACS */
91
static void
92
build_facs(GArray *table_data)
93
{
94
    const char *sig = "FACS";
95
    const uint8_t reserved[40] = {};
96

97
    g_array_append_vals(table_data, sig, 4); /* Signature */
98
    build_append_int_noprefix(table_data, 64, 4); /* Length */
99
    build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */
100
    build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */
101
    build_append_int_noprefix(table_data, 0, 4); /* Global Lock */
102
    build_append_int_noprefix(table_data, 0, 4); /* Flags */
103
    g_array_append_vals(table_data, reserved, 40); /* Reserved */
104
}
105

106
/* build MADT */
107
static void
108
build_madt(GArray *table_data, BIOSLinker *linker,
109
           LoongArchVirtMachineState *lvms)
110
{
111
    MachineState *ms = MACHINE(lvms);
112
    MachineClass *mc = MACHINE_GET_CLASS(ms);
113
    const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
114
    int i, arch_id;
115
    AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lvms->oem_id,
116
                        .oem_table_id = lvms->oem_table_id };
117

118
    acpi_table_begin(&table, table_data);
119

120
    /* Local APIC Address */
121
    build_append_int_noprefix(table_data, 0, 4);
122
    build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
123

124
    for (i = 0; i < arch_ids->len; i++) {
125
        /* Processor Core Interrupt Controller Structure */
126
        arch_id = arch_ids->cpus[i].arch_id;
127

128
        build_append_int_noprefix(table_data, 17, 1);    /* Type */
129
        build_append_int_noprefix(table_data, 15, 1);    /* Length */
130
        build_append_int_noprefix(table_data, 1, 1);     /* Version */
131
        build_append_int_noprefix(table_data, i, 4);     /* ACPI Processor ID */
132
        build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
133
        build_append_int_noprefix(table_data, 1, 4);     /* Flags */
134
    }
135

136
    /* Extend I/O Interrupt Controller Structure */
137
    build_append_int_noprefix(table_data, 20, 1);        /* Type */
138
    build_append_int_noprefix(table_data, 13, 1);        /* Length */
139
    build_append_int_noprefix(table_data, 1, 1);         /* Version */
140
    build_append_int_noprefix(table_data, 3, 1);         /* Cascade */
141
    build_append_int_noprefix(table_data, 0, 1);         /* Node */
142
    build_append_int_noprefix(table_data, 0xffff, 8);    /* Node map */
143

144
    /* MSI Interrupt Controller Structure */
145
    build_append_int_noprefix(table_data, 21, 1);        /* Type */
146
    build_append_int_noprefix(table_data, 19, 1);        /* Length */
147
    build_append_int_noprefix(table_data, 1, 1);         /* Version */
148
    build_append_int_noprefix(table_data, VIRT_PCH_MSI_ADDR_LOW, 8);/* Address */
149
    build_append_int_noprefix(table_data, 0x40, 4);      /* Start */
150
    build_append_int_noprefix(table_data, 0xc0, 4);      /* Count */
151

152
    /* Bridge I/O Interrupt Controller Structure */
153
    build_append_int_noprefix(table_data, 22, 1);        /* Type */
154
    build_append_int_noprefix(table_data, 17, 1);        /* Length */
155
    build_append_int_noprefix(table_data, 1, 1);         /* Version */
156
    build_append_int_noprefix(table_data, VIRT_PCH_REG_BASE, 8);/* Address */
157
    build_append_int_noprefix(table_data, 0x1000, 2);    /* Size */
158
    build_append_int_noprefix(table_data, 0, 2);         /* Id */
159
    build_append_int_noprefix(table_data, 0x40, 2);      /* Base */
160

161
    acpi_table_end(linker, &table);
162
}
163

164
/* build SRAT */
165
static void
166
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
167
{
168
    int i, arch_id, node_id;
169
    hwaddr len, base, gap;
170
    NodeInfo *numa_info;
171
    int nodes, nb_numa_nodes = machine->numa_state->num_nodes;
172
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
173
    MachineClass *mc = MACHINE_GET_CLASS(lvms);
174
    const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
175
    AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lvms->oem_id,
176
                        .oem_table_id = lvms->oem_table_id };
177

178
    acpi_table_begin(&table, table_data);
179
    build_append_int_noprefix(table_data, 1, 4); /* Reserved */
180
    build_append_int_noprefix(table_data, 0, 8); /* Reserved */
181

182
    for (i = 0; i < arch_ids->len; ++i) {
183
        arch_id = arch_ids->cpus[i].arch_id;
184
        node_id = arch_ids->cpus[i].props.node_id;
185

186
        /* Processor Local APIC/SAPIC Affinity Structure */
187
        build_append_int_noprefix(table_data, 0, 1);  /* Type  */
188
        build_append_int_noprefix(table_data, 16, 1); /* Length */
189
        /* Proximity Domain [7:0] */
190
        build_append_int_noprefix(table_data, node_id, 1);
191
        build_append_int_noprefix(table_data, arch_id, 1); /* APIC ID */
192
        /* Flags, Table 5-36 */
193
        build_append_int_noprefix(table_data, 1, 4);
194
        build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */
195
        /* Proximity Domain [31:8] */
196
        build_append_int_noprefix(table_data, 0, 3);
197
        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
198
    }
199

200
    base = VIRT_LOWMEM_BASE;
201
    gap = VIRT_LOWMEM_SIZE;
202
    numa_info = machine->numa_state->nodes;
203
    nodes = nb_numa_nodes;
204
    if (!nodes) {
205
        nodes = 1;
206
    }
207

208
    for (i = 0; i < nodes; i++) {
209
        if (nb_numa_nodes) {
210
            len = numa_info[i].node_mem;
211
        } else {
212
            len = machine->ram_size;
213
        }
214

215
        /*
216
         * memory for the node splited into two part
217
         *   lowram:  [base, +gap)
218
         *   highram: [VIRT_HIGHMEM_BASE, +(len - gap))
219
         */
220
        if (len >= gap) {
221
            build_srat_memory(table_data, base, gap, i, MEM_AFFINITY_ENABLED);
222
            len -= gap;
223
            base = VIRT_HIGHMEM_BASE;
224
            gap = machine->ram_size - VIRT_LOWMEM_SIZE;
225
        }
226

227
        if (len) {
228
            build_srat_memory(table_data, base, len, i, MEM_AFFINITY_ENABLED);
229
            base += len;
230
            gap  -= len;
231
        }
232
    }
233

234
    if (machine->device_memory) {
235
        build_srat_memory(table_data, machine->device_memory->base,
236
                          memory_region_size(&machine->device_memory->mr),
237
                          nodes - 1,
238
                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
239
    }
240

241
    acpi_table_end(linker, &table);
242
}
243

244
typedef
245
struct AcpiBuildState {
246
    /* Copy of table in RAM (for patching). */
247
    MemoryRegion *table_mr;
248
    /* Is table patched? */
249
    uint8_t patched;
250
    void *rsdp;
251
    MemoryRegion *rsdp_mr;
252
    MemoryRegion *linker_mr;
253
} AcpiBuildState;
254

255
static void build_uart_device_aml(Aml *table)
256
{
257
    Aml *dev;
258
    Aml *crs;
259
    Aml *pkg0, *pkg1, *pkg2;
260
    uint32_t uart_irq = VIRT_UART_IRQ;
261

262
    Aml *scope = aml_scope("_SB");
263
    dev = aml_device("COMA");
264
    aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501")));
265
    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
266
    aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
267
    crs = aml_resource_template();
268
    aml_append(crs,
269
        aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
270
                         AML_NON_CACHEABLE, AML_READ_WRITE,
271
                         0, VIRT_UART_BASE, VIRT_UART_BASE + VIRT_UART_SIZE - 1,
272
                         0, VIRT_UART_SIZE));
273
    aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
274
                                  AML_SHARED, &uart_irq, 1));
275
    aml_append(dev, aml_name_decl("_CRS", crs));
276
    pkg0 = aml_package(0x2);
277
    aml_append(pkg0, aml_int(0x05F5E100));
278
    aml_append(pkg0, aml_string("clock-frenquency"));
279
    pkg1 = aml_package(0x1);
280
    aml_append(pkg1, pkg0);
281
    pkg2 = aml_package(0x2);
282
    aml_append(pkg2, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"));
283
    aml_append(pkg2, pkg1);
284
    aml_append(dev, aml_name_decl("_DSD", pkg2));
285
    aml_append(scope, dev);
286
    aml_append(table, scope);
287
}
288

289
static void
290
build_la_ged_aml(Aml *dsdt, MachineState *machine)
291
{
292
    uint32_t event;
293
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
294

295
    build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
296
                  HOTPLUG_HANDLER(lvms->acpi_ged),
297
                  VIRT_SCI_IRQ, AML_SYSTEM_MEMORY,
298
                  VIRT_GED_EVT_ADDR);
299
    event = object_property_get_uint(OBJECT(lvms->acpi_ged),
300
                                     "ged-event", &error_abort);
301
    if (event & ACPI_GED_MEM_HOTPLUG_EVT) {
302
        build_memory_hotplug_aml(dsdt, machine->ram_slots, "\\_SB", NULL,
303
                                 AML_SYSTEM_MEMORY,
304
                                 VIRT_GED_MEM_ADDR);
305
    }
306
    acpi_dsdt_add_power_button(dsdt);
307
}
308

309
static void build_pci_device_aml(Aml *scope, LoongArchVirtMachineState *lvms)
310
{
311
    struct GPEXConfig cfg = {
312
        .mmio64.base = VIRT_PCI_MEM_BASE,
313
        .mmio64.size = VIRT_PCI_MEM_SIZE,
314
        .pio.base    = VIRT_PCI_IO_BASE,
315
        .pio.size    = VIRT_PCI_IO_SIZE,
316
        .ecam.base   = VIRT_PCI_CFG_BASE,
317
        .ecam.size   = VIRT_PCI_CFG_SIZE,
318
        .irq         = VIRT_GSI_BASE + VIRT_DEVICE_IRQS,
319
        .bus         = lvms->pci_bus,
320
    };
321

322
    acpi_dsdt_add_gpex(scope, &cfg);
323
}
324

325
static void build_flash_aml(Aml *scope, LoongArchVirtMachineState *lvms)
326
{
327
    Aml *dev, *crs;
328
    MemoryRegion *flash_mem;
329

330
    hwaddr flash0_base;
331
    hwaddr flash0_size;
332

333
    hwaddr flash1_base;
334
    hwaddr flash1_size;
335

336
    flash_mem = pflash_cfi01_get_memory(lvms->flash[0]);
337
    flash0_base = flash_mem->addr;
338
    flash0_size = memory_region_size(flash_mem);
339

340
    flash_mem = pflash_cfi01_get_memory(lvms->flash[1]);
341
    flash1_base = flash_mem->addr;
342
    flash1_size = memory_region_size(flash_mem);
343

344
    dev = aml_device("FLS0");
345
    aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
346
    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
347

348
    crs = aml_resource_template();
349
    aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
350
                                       AML_READ_WRITE));
351
    aml_append(dev, aml_name_decl("_CRS", crs));
352
    aml_append(scope, dev);
353

354
    dev = aml_device("FLS1");
355
    aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
356
    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
357

358
    crs = aml_resource_template();
359
    aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
360
                                       AML_READ_WRITE));
361
    aml_append(dev, aml_name_decl("_CRS", crs));
362
    aml_append(scope, dev);
363
}
364

365
#ifdef CONFIG_TPM
366
static void acpi_dsdt_add_tpm(Aml *scope, LoongArchVirtMachineState *vms)
367
{
368
    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
369
    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
370
    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
371
    MemoryRegion *sbdev_mr;
372
    hwaddr tpm_base;
373

374
    if (!sbdev) {
375
        return;
376
    }
377

378
    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
379
    assert(tpm_base != -1);
380

381
    tpm_base += pbus_base;
382

383
    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
384

385
    Aml *dev = aml_device("TPM0");
386
    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
387
    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
388
    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
389

390
    Aml *crs = aml_resource_template();
391
    aml_append(crs,
392
               aml_memory32_fixed(tpm_base,
393
                                  (uint32_t)memory_region_size(sbdev_mr),
394
                                  AML_READ_WRITE));
395
    aml_append(dev, aml_name_decl("_CRS", crs));
396
    aml_append(scope, dev);
397
}
398
#endif
399

400
/* build DSDT */
401
static void
402
build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
403
{
404
    Aml *dsdt, *scope, *pkg;
405
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
406
    AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lvms->oem_id,
407
                        .oem_table_id = lvms->oem_table_id };
408

409
    acpi_table_begin(&table, table_data);
410
    dsdt = init_aml_allocator();
411
    build_uart_device_aml(dsdt);
412
    build_pci_device_aml(dsdt, lvms);
413
    build_la_ged_aml(dsdt, machine);
414
    build_flash_aml(dsdt, lvms);
415
#ifdef CONFIG_TPM
416
    acpi_dsdt_add_tpm(dsdt, lvms);
417
#endif
418
    /* System State Package */
419
    scope = aml_scope("\\");
420
    pkg = aml_package(4);
421
    aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5));
422
    aml_append(pkg, aml_int(0)); /* ignored */
423
    aml_append(pkg, aml_int(0)); /* reserved */
424
    aml_append(pkg, aml_int(0)); /* reserved */
425
    aml_append(scope, aml_name_decl("_S5", pkg));
426
    aml_append(dsdt, scope);
427
    /* Copy AML table into ACPI tables blob and patch header there */
428
    g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
429
    acpi_table_end(linker, &table);
430
    free_aml_allocator();
431
}
432

433
static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
434
{
435
    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
436
    GArray *table_offsets;
437
    AcpiFadtData fadt_data;
438
    unsigned facs, rsdt, dsdt;
439
    uint8_t *u;
440
    GArray *tables_blob = tables->table_data;
441

442
    init_common_fadt_data(&fadt_data);
443

444
    table_offsets = g_array_new(false, true, sizeof(uint32_t));
445
    ACPI_BUILD_DPRINTF("init ACPI tables\n");
446

447
    bios_linker_loader_alloc(tables->linker,
448
                             ACPI_BUILD_TABLE_FILE, tables_blob,
449
                             64, false);
450

451
    /*
452
     * FACS is pointed to by FADT.
453
     * We place it first since it's the only table that has alignment
454
     * requirements.
455
     */
456
    facs = tables_blob->len;
457
    build_facs(tables_blob);
458

459
    /* DSDT is pointed to by FADT */
460
    dsdt = tables_blob->len;
461
    build_dsdt(tables_blob, tables->linker, machine);
462

463
    /* ACPI tables pointed to by RSDT */
464
    acpi_add_table(table_offsets, tables_blob);
465
    fadt_data.facs_tbl_offset = &facs;
466
    fadt_data.dsdt_tbl_offset = &dsdt;
467
    fadt_data.xdsdt_tbl_offset = &dsdt;
468
    build_fadt(tables_blob, tables->linker, &fadt_data,
469
               lvms->oem_id, lvms->oem_table_id);
470

471
    acpi_add_table(table_offsets, tables_blob);
472
    build_madt(tables_blob, tables->linker, lvms);
473

474
    acpi_add_table(table_offsets, tables_blob);
475
    build_pptt(tables_blob, tables->linker, machine,
476
               lvms->oem_id, lvms->oem_table_id);
477

478
    acpi_add_table(table_offsets, tables_blob);
479
    build_srat(tables_blob, tables->linker, machine);
480

481
    if (machine->numa_state->num_nodes) {
482
        if (machine->numa_state->have_numa_distance) {
483
            acpi_add_table(table_offsets, tables_blob);
484
            build_slit(tables_blob, tables->linker, machine, lvms->oem_id,
485
                       lvms->oem_table_id);
486
        }
487
        if (machine->numa_state->hmat_enabled) {
488
            acpi_add_table(table_offsets, tables_blob);
489
            build_hmat(tables_blob, tables->linker, machine->numa_state,
490
                       lvms->oem_id, lvms->oem_table_id);
491
        }
492
    }
493

494
    acpi_add_table(table_offsets, tables_blob);
495
    {
496
        AcpiMcfgInfo mcfg = {
497
           .base = cpu_to_le64(VIRT_PCI_CFG_BASE),
498
           .size = cpu_to_le64(VIRT_PCI_CFG_SIZE),
499
        };
500
        build_mcfg(tables_blob, tables->linker, &mcfg, lvms->oem_id,
501
                   lvms->oem_table_id);
502
    }
503

504
#ifdef CONFIG_TPM
505
    /* TPM info */
506
    if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) {
507
        acpi_add_table(table_offsets, tables_blob);
508
        build_tpm2(tables_blob, tables->linker,
509
                   tables->tcpalog, lvms->oem_id,
510
                   lvms->oem_table_id);
511
    }
512
#endif
513
    /* Add tables supplied by user (if any) */
514
    for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
515
        unsigned len = acpi_table_len(u);
516

517
        acpi_add_table(table_offsets, tables_blob);
518
        g_array_append_vals(tables_blob, u, len);
519
    }
520

521
    /* RSDT is pointed to by RSDP */
522
    rsdt = tables_blob->len;
523
    build_rsdt(tables_blob, tables->linker, table_offsets,
524
               lvms->oem_id, lvms->oem_table_id);
525

526
    /* RSDP is in FSEG memory, so allocate it separately */
527
    {
528
        AcpiRsdpData rsdp_data = {
529
            .revision = 0,
530
            .oem_id = lvms->oem_id,
531
            .xsdt_tbl_offset = NULL,
532
            .rsdt_tbl_offset = &rsdt,
533
        };
534
        build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
535
    }
536

537
    /*
538
     * The align size is 128, warn if 64k is not enough therefore
539
     * the align size could be resized.
540
     */
541
    if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
542
        warn_report("ACPI table size %u exceeds %d bytes,"
543
                    " migration may not work",
544
                    tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
545
        error_printf("Try removing CPUs, NUMA nodes, memory slots"
546
                     " or PCI bridges.\n");
547
    }
548

549
    acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE);
550

551
    /* Cleanup memory that's no longer used. */
552
    g_array_free(table_offsets, true);
553
}
554

555
static void acpi_ram_update(MemoryRegion *mr, GArray *data)
556
{
557
    uint32_t size = acpi_data_len(data);
558

559
    /*
560
     * Make sure RAM size is correct - in case it got changed
561
     * e.g. by migration
562
     */
563
    memory_region_ram_resize(mr, size, &error_abort);
564

565
    memcpy(memory_region_get_ram_ptr(mr), data->data, size);
566
    memory_region_set_dirty(mr, 0, size);
567
}
568

569
static void acpi_build_update(void *build_opaque)
570
{
571
    AcpiBuildState *build_state = build_opaque;
572
    AcpiBuildTables tables;
573

574
    /* No state to update or already patched? Nothing to do. */
575
    if (!build_state || build_state->patched) {
576
        return;
577
    }
578
    build_state->patched = 1;
579

580
    acpi_build_tables_init(&tables);
581

582
    acpi_build(&tables, MACHINE(qdev_get_machine()));
583

584
    acpi_ram_update(build_state->table_mr, tables.table_data);
585
    acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
586
    acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
587

588
    acpi_build_tables_cleanup(&tables, true);
589
}
590

591
static void acpi_build_reset(void *build_opaque)
592
{
593
    AcpiBuildState *build_state = build_opaque;
594
    build_state->patched = 0;
595
}
596

597
static const VMStateDescription vmstate_acpi_build = {
598
    .name = "acpi_build",
599
    .version_id = 1,
600
    .minimum_version_id = 1,
601
    .fields = (const VMStateField[]) {
602
        VMSTATE_UINT8(patched, AcpiBuildState),
603
        VMSTATE_END_OF_LIST()
604
    },
605
};
606

607
static bool loongarch_is_acpi_enabled(LoongArchVirtMachineState *lvms)
608
{
609
    if (lvms->acpi == ON_OFF_AUTO_OFF) {
610
        return false;
611
    }
612
    return true;
613
}
614

615
void loongarch_acpi_setup(LoongArchVirtMachineState *lvms)
616
{
617
    AcpiBuildTables tables;
618
    AcpiBuildState *build_state;
619

620
    if (!lvms->fw_cfg) {
621
        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
622
        return;
623
    }
624

625
    if (!loongarch_is_acpi_enabled(lvms)) {
626
        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
627
        return;
628
    }
629

630
    build_state = g_malloc0(sizeof *build_state);
631

632
    acpi_build_tables_init(&tables);
633
    acpi_build(&tables, MACHINE(lvms));
634

635
    /* Now expose it all to Guest */
636
    build_state->table_mr = acpi_add_rom_blob(acpi_build_update,
637
                                              build_state, tables.table_data,
638
                                              ACPI_BUILD_TABLE_FILE);
639
    assert(build_state->table_mr != NULL);
640

641
    build_state->linker_mr =
642
        acpi_add_rom_blob(acpi_build_update, build_state,
643
                          tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE);
644

645
    build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update,
646
                                             build_state, tables.rsdp,
647
                                             ACPI_BUILD_RSDP_FILE);
648

649
    fw_cfg_add_file(lvms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
650
                    acpi_data_len(tables.tcpalog));
651

652
    qemu_register_reset(acpi_build_reset, build_state);
653
    acpi_build_reset(build_state);
654
    vmstate_register(NULL, 0, &vmstate_acpi_build, build_state);
655

656
    /*
657
     * Cleanup tables but don't free the memory: we track it
658
     * in build_state.
659
     */
660
    acpi_build_tables_cleanup(&tables, false);
661
}
662

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.