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"
24
#include "hw/pci-host/ls7a.h"
25
#include "hw/loongarch/virt.h"
27
#include "hw/acpi/utils.h"
28
#include "hw/acpi/pci.h"
30
#include "qom/qom-qobject.h"
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"
39
#define ACPI_BUILD_ALIGN_SIZE 0x1000
40
#define ACPI_BUILD_TABLE_SIZE 0x20000
42
#ifdef DEBUG_ACPI_BUILD
43
#define ACPI_BUILD_DPRINTF(fmt, ...) \
44
do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0)
46
#define ACPI_BUILD_DPRINTF(fmt, ...)
50
static void init_common_fadt_data(AcpiFadtData *data)
55
.flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) |
56
(1 << ACPI_FADT_F_RESET_REG_SUP)),
60
.space_id = AML_AS_SYSTEM_MEMORY,
62
.address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_CTL,
65
.space_id = AML_AS_SYSTEM_MEMORY,
67
.address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_STS,
72
.space_id = AML_AS_SYSTEM_MEMORY,
74
.address = VIRT_GED_REG_ADDR + ACPI_GED_REG_RESET,
76
.reset_val = ACPI_GED_RESET_VALUE,
81
static void acpi_align_size(GArray *blob, unsigned align)
87
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
92
build_facs(GArray *table_data)
94
const char *sig = "FACS";
95
const uint8_t reserved[40] = {};
97
g_array_append_vals(table_data, sig, 4);
98
build_append_int_noprefix(table_data, 64, 4);
99
build_append_int_noprefix(table_data, 0, 4);
100
build_append_int_noprefix(table_data, 0, 4);
101
build_append_int_noprefix(table_data, 0, 4);
102
build_append_int_noprefix(table_data, 0, 4);
103
g_array_append_vals(table_data, reserved, 40);
108
build_madt(GArray *table_data, BIOSLinker *linker,
109
LoongArchVirtMachineState *lvms)
111
MachineState *ms = MACHINE(lvms);
112
MachineClass *mc = MACHINE_GET_CLASS(ms);
113
const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
115
AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lvms->oem_id,
116
.oem_table_id = lvms->oem_table_id };
118
acpi_table_begin(&table, table_data);
121
build_append_int_noprefix(table_data, 0, 4);
122
build_append_int_noprefix(table_data, 1 , 4);
124
for (i = 0; i < arch_ids->len; i++) {
126
arch_id = arch_ids->cpus[i].arch_id;
128
build_append_int_noprefix(table_data, 17, 1);
129
build_append_int_noprefix(table_data, 15, 1);
130
build_append_int_noprefix(table_data, 1, 1);
131
build_append_int_noprefix(table_data, i, 4);
132
build_append_int_noprefix(table_data, arch_id, 4);
133
build_append_int_noprefix(table_data, 1, 4);
137
build_append_int_noprefix(table_data, 20, 1);
138
build_append_int_noprefix(table_data, 13, 1);
139
build_append_int_noprefix(table_data, 1, 1);
140
build_append_int_noprefix(table_data, 3, 1);
141
build_append_int_noprefix(table_data, 0, 1);
142
build_append_int_noprefix(table_data, 0xffff, 8);
145
build_append_int_noprefix(table_data, 21, 1);
146
build_append_int_noprefix(table_data, 19, 1);
147
build_append_int_noprefix(table_data, 1, 1);
148
build_append_int_noprefix(table_data, VIRT_PCH_MSI_ADDR_LOW, 8);
149
build_append_int_noprefix(table_data, 0x40, 4);
150
build_append_int_noprefix(table_data, 0xc0, 4);
153
build_append_int_noprefix(table_data, 22, 1);
154
build_append_int_noprefix(table_data, 17, 1);
155
build_append_int_noprefix(table_data, 1, 1);
156
build_append_int_noprefix(table_data, VIRT_PCH_REG_BASE, 8);
157
build_append_int_noprefix(table_data, 0x1000, 2);
158
build_append_int_noprefix(table_data, 0, 2);
159
build_append_int_noprefix(table_data, 0x40, 2);
161
acpi_table_end(linker, &table);
166
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
168
int i, arch_id, node_id;
169
hwaddr len, base, gap;
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 };
178
acpi_table_begin(&table, table_data);
179
build_append_int_noprefix(table_data, 1, 4);
180
build_append_int_noprefix(table_data, 0, 8);
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;
187
build_append_int_noprefix(table_data, 0, 1);
188
build_append_int_noprefix(table_data, 16, 1);
190
build_append_int_noprefix(table_data, node_id, 1);
191
build_append_int_noprefix(table_data, arch_id, 1);
193
build_append_int_noprefix(table_data, 1, 4);
194
build_append_int_noprefix(table_data, 0, 1);
196
build_append_int_noprefix(table_data, 0, 3);
197
build_append_int_noprefix(table_data, 0, 4);
200
base = VIRT_LOWMEM_BASE;
201
gap = VIRT_LOWMEM_SIZE;
202
numa_info = machine->numa_state->nodes;
203
nodes = nb_numa_nodes;
208
for (i = 0; i < nodes; i++) {
210
len = numa_info[i].node_mem;
212
len = machine->ram_size;
221
build_srat_memory(table_data, base, gap, i, MEM_AFFINITY_ENABLED);
223
base = VIRT_HIGHMEM_BASE;
224
gap = machine->ram_size - VIRT_LOWMEM_SIZE;
228
build_srat_memory(table_data, base, len, i, MEM_AFFINITY_ENABLED);
234
if (machine->device_memory) {
235
build_srat_memory(table_data, machine->device_memory->base,
236
memory_region_size(&machine->device_memory->mr),
238
MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
241
acpi_table_end(linker, &table);
245
struct AcpiBuildState {
247
MemoryRegion *table_mr;
251
MemoryRegion *rsdp_mr;
252
MemoryRegion *linker_mr;
255
static void build_uart_device_aml(Aml *table)
259
Aml *pkg0, *pkg1, *pkg2;
260
uint32_t uart_irq = VIRT_UART_IRQ;
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();
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,
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);
290
build_la_ged_aml(Aml *dsdt, MachineState *machine)
293
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
295
build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
296
HOTPLUG_HANDLER(lvms->acpi_ged),
297
VIRT_SCI_IRQ, AML_SYSTEM_MEMORY,
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,
306
acpi_dsdt_add_power_button(dsdt);
309
static void build_pci_device_aml(Aml *scope, LoongArchVirtMachineState *lvms)
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,
322
acpi_dsdt_add_gpex(scope, &cfg);
325
static void build_flash_aml(Aml *scope, LoongArchVirtMachineState *lvms)
328
MemoryRegion *flash_mem;
336
flash_mem = pflash_cfi01_get_memory(lvms->flash[0]);
337
flash0_base = flash_mem->addr;
338
flash0_size = memory_region_size(flash_mem);
340
flash_mem = pflash_cfi01_get_memory(lvms->flash[1]);
341
flash1_base = flash_mem->addr;
342
flash1_size = memory_region_size(flash_mem);
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)));
348
crs = aml_resource_template();
349
aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
351
aml_append(dev, aml_name_decl("_CRS", crs));
352
aml_append(scope, dev);
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)));
358
crs = aml_resource_template();
359
aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
361
aml_append(dev, aml_name_decl("_CRS", crs));
362
aml_append(scope, dev);
366
static void acpi_dsdt_add_tpm(Aml *scope, LoongArchVirtMachineState *vms)
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;
378
tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
379
assert(tpm_base != -1);
381
tpm_base += pbus_base;
383
sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
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)));
390
Aml *crs = aml_resource_template();
392
aml_memory32_fixed(tpm_base,
393
(uint32_t)memory_region_size(sbdev_mr),
395
aml_append(dev, aml_name_decl("_CRS", crs));
396
aml_append(scope, dev);
402
build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
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 };
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);
416
acpi_dsdt_add_tpm(dsdt, lvms);
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));
423
aml_append(pkg, aml_int(0));
424
aml_append(pkg, aml_int(0));
425
aml_append(scope, aml_name_decl("_S5", pkg));
426
aml_append(dsdt, scope);
428
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
429
acpi_table_end(linker, &table);
430
free_aml_allocator();
433
static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
435
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
436
GArray *table_offsets;
437
AcpiFadtData fadt_data;
438
unsigned facs, rsdt, dsdt;
440
GArray *tables_blob = tables->table_data;
442
init_common_fadt_data(&fadt_data);
444
table_offsets = g_array_new(false, true, sizeof(uint32_t));
445
ACPI_BUILD_DPRINTF("init ACPI tables\n");
447
bios_linker_loader_alloc(tables->linker,
448
ACPI_BUILD_TABLE_FILE, tables_blob,
456
facs = tables_blob->len;
457
build_facs(tables_blob);
460
dsdt = tables_blob->len;
461
build_dsdt(tables_blob, tables->linker, machine);
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);
471
acpi_add_table(table_offsets, tables_blob);
472
build_madt(tables_blob, tables->linker, lvms);
474
acpi_add_table(table_offsets, tables_blob);
475
build_pptt(tables_blob, tables->linker, machine,
476
lvms->oem_id, lvms->oem_table_id);
478
acpi_add_table(table_offsets, tables_blob);
479
build_srat(tables_blob, tables->linker, machine);
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,
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);
494
acpi_add_table(table_offsets, tables_blob);
496
AcpiMcfgInfo mcfg = {
497
.base = cpu_to_le64(VIRT_PCI_CFG_BASE),
498
.size = cpu_to_le64(VIRT_PCI_CFG_SIZE),
500
build_mcfg(tables_blob, tables->linker, &mcfg, lvms->oem_id,
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,
514
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
515
unsigned len = acpi_table_len(u);
517
acpi_add_table(table_offsets, tables_blob);
518
g_array_append_vals(tables_blob, u, len);
522
rsdt = tables_blob->len;
523
build_rsdt(tables_blob, tables->linker, table_offsets,
524
lvms->oem_id, lvms->oem_table_id);
528
AcpiRsdpData rsdp_data = {
530
.oem_id = lvms->oem_id,
531
.xsdt_tbl_offset = NULL,
532
.rsdt_tbl_offset = &rsdt,
534
build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
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");
549
acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE);
552
g_array_free(table_offsets, true);
555
static void acpi_ram_update(MemoryRegion *mr, GArray *data)
557
uint32_t size = acpi_data_len(data);
563
memory_region_ram_resize(mr, size, &error_abort);
565
memcpy(memory_region_get_ram_ptr(mr), data->data, size);
566
memory_region_set_dirty(mr, 0, size);
569
static void acpi_build_update(void *build_opaque)
571
AcpiBuildState *build_state = build_opaque;
572
AcpiBuildTables tables;
575
if (!build_state || build_state->patched) {
578
build_state->patched = 1;
580
acpi_build_tables_init(&tables);
582
acpi_build(&tables, MACHINE(qdev_get_machine()));
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);
588
acpi_build_tables_cleanup(&tables, true);
591
static void acpi_build_reset(void *build_opaque)
593
AcpiBuildState *build_state = build_opaque;
594
build_state->patched = 0;
597
static const VMStateDescription vmstate_acpi_build = {
598
.name = "acpi_build",
600
.minimum_version_id = 1,
601
.fields = (const VMStateField[]) {
602
VMSTATE_UINT8(patched, AcpiBuildState),
603
VMSTATE_END_OF_LIST()
607
static bool loongarch_is_acpi_enabled(LoongArchVirtMachineState *lvms)
609
if (lvms->acpi == ON_OFF_AUTO_OFF) {
615
void loongarch_acpi_setup(LoongArchVirtMachineState *lvms)
617
AcpiBuildTables tables;
618
AcpiBuildState *build_state;
621
ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
625
if (!loongarch_is_acpi_enabled(lvms)) {
626
ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
630
build_state = g_malloc0(sizeof *build_state);
632
acpi_build_tables_init(&tables);
633
acpi_build(&tables, MACHINE(lvms));
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);
641
build_state->linker_mr =
642
acpi_add_rom_blob(acpi_build_update, build_state,
643
tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE);
645
build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update,
646
build_state, tables.rsdp,
647
ACPI_BUILD_RSDP_FILE);
649
fw_cfg_add_file(lvms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
650
acpi_data_len(tables.tcpalog));
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);
660
acpi_build_tables_cleanup(&tables, false);