master
c 1,058 lines 38.3 KB
Raw
1 /*
2 * Support for generating ACPI tables and passing them to Guests
3 *
4 * RISC-V virt ACPI generation
5 *
6 * Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
7 * Copyright (C) 2006 Fabrice Bellard
8 * Copyright (C) 2013 Red Hat Inc
9 * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD.
10 * Copyright (C) 2021-2023 Ventana Micro Systems Inc
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "qemu/osdep.h"
27 #include "hw/acpi/acpi-defs.h"
28 #include "hw/acpi/acpi.h"
29 #include "hw/acpi/aml-build.h"
30 #include "hw/acpi/pci.h"
31 #include "hw/acpi/utils.h"
32 #include "hw/intc/riscv_aclint.h"
33 #include "hw/nvram/fw_cfg_acpi.h"
34 #include "hw/pci-host/gpex.h"
35 #include "hw/riscv/virt.h"
36 #include "hw/riscv/numa.h"
37 #include "hw/virtio/virtio-acpi.h"
38 #include "kvm/kvm_riscv.h"
39 #include "migration/vmstate.h"
40 #include "qapi/error.h"
41 #include "qemu/error-report.h"
42 #include "system/kvm.h"
43 #include "system/reset.h"
44
45 #include "aia.h"
46
47 #define ACPI_BUILD_TABLE_SIZE 0x20000
48 #define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index))
49
50 typedef struct AcpiBuildState {
51 /* Copy of table in RAM (for patching) */
52 MemoryRegion *table_mr;
53 MemoryRegion *rsdp_mr;
54 MemoryRegion *linker_mr;
55 /* Is table patched? */
56 bool patched;
57 } AcpiBuildState;
58
59 static void acpi_align_size(GArray *blob, unsigned align)
60 {
61 /*
62 * Align size to multiple of given size. This reduces the chance
63 * we need to change size in the future (breaking cross version migration).
64 */
65 g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
66 }
67
68 static void riscv_acpi_madt_add_rintc(uint32_t uid,
69 const CPUArchIdList *arch_ids,
70 GArray *entry,
71 RISCVVirtState *s)
72 {
73 uint8_t guest_index_bits = imsic_num_bits(s->aia_guests + 1);
74 uint64_t hart_id = arch_ids->cpus[uid].arch_id;
75 uint32_t imsic_size, local_cpu_id, socket_id;
76 uint64_t imsic_socket_addr, imsic_addr;
77 MachineState *ms = MACHINE(s);
78
79 socket_id = arch_ids->cpus[uid].props.node_id;
80 local_cpu_id = (arch_ids->cpus[uid].arch_id -
81 riscv_socket_first_hartid(ms, socket_id)) %
82 riscv_socket_hart_count(ms, socket_id);
83 imsic_socket_addr = s->memmap[VIRT_IMSIC_S].base +
84 (socket_id * VIRT_IMSIC_GROUP_MAX_SIZE);
85 imsic_size = IMSIC_HART_SIZE(guest_index_bits);
86 imsic_addr = imsic_socket_addr + local_cpu_id * imsic_size;
87 build_append_int_noprefix(entry, 0x18, 1); /* Type */
88 build_append_int_noprefix(entry, 36, 1); /* Length */
89 build_append_int_noprefix(entry, 1, 1); /* Version */
90 build_append_int_noprefix(entry, 0, 1); /* Reserved */
91 build_append_int_noprefix(entry, 0x1, 4); /* Flags */
92 build_append_int_noprefix(entry, hart_id, 8); /* Hart ID */
93 build_append_int_noprefix(entry, uid, 4); /* ACPI Processor UID */
94 /* External Interrupt Controller ID */
95 if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
96 build_append_int_noprefix(entry,
97 ACPI_BUILD_INTC_ID(
98 arch_ids->cpus[uid].props.node_id,
99 local_cpu_id),
100 4);
101 } else if (s->aia_type == VIRT_AIA_TYPE_NONE) {
102 build_append_int_noprefix(entry,
103 ACPI_BUILD_INTC_ID(
104 arch_ids->cpus[uid].props.node_id,
105 kvm_enabled() ?
106 local_cpu_id :
107 2 * local_cpu_id + 1),
108 4);
109 } else {
110 build_append_int_noprefix(entry, 0, 4);
111 }
112
113 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
114 /* IMSIC Base address */
115 build_append_int_noprefix(entry, imsic_addr, 8);
116 /* IMSIC Size */
117 build_append_int_noprefix(entry, imsic_size, 4);
118 } else {
119 build_append_int_noprefix(entry, 0, 8);
120 build_append_int_noprefix(entry, 0, 4);
121 }
122 }
123
124 static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s)
125 {
126 MachineClass *mc = MACHINE_GET_CLASS(s);
127 MachineState *ms = MACHINE(s);
128 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
129
130 for (int i = 0; i < arch_ids->len; i++) {
131 Aml *dev;
132 GArray *madt_buf = g_array_new(0, 1, 1);
133
134 dev = aml_device("C%.03X", i);
135 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
136 aml_append(dev, aml_name_decl("_UID",
137 aml_int(arch_ids->cpus[i].arch_id)));
138
139 /* build _MAT object */
140 riscv_acpi_madt_add_rintc(i, arch_ids, madt_buf, s);
141 aml_append(dev, aml_name_decl("_MAT",
142 aml_buffer(madt_buf->len,
143 (uint8_t *)madt_buf->data)));
144 g_array_free(madt_buf, true);
145
146 aml_append(scope, dev);
147 }
148 }
149
150 static void acpi_dsdt_add_plic_aplic(Aml *scope, uint8_t socket_count,
151 uint16_t num_sources,
152 uint64_t mmio_base, uint64_t mmio_size,
153 const char *hid)
154 {
155 uint64_t plic_aplic_addr;
156 uint32_t gsi_base;
157 uint8_t socket;
158
159 /* The RISC-V Advanced Interrupt Architecture, Chapter 1.2. Limits */
160 g_assert(num_sources <= 1023);
161
162 for (socket = 0; socket < socket_count; socket++) {
163 plic_aplic_addr = mmio_base + mmio_size * socket;
164 gsi_base = num_sources * socket;
165 Aml *dev = aml_device("IC%.02X", socket);
166 aml_append(dev, aml_name_decl("_HID", aml_string("%s", hid)));
167 aml_append(dev, aml_name_decl("_UID", aml_int(socket)));
168 aml_append(dev, aml_name_decl("_GSB", aml_int(gsi_base)));
169
170 Aml *crs = aml_resource_template();
171 aml_append(crs, aml_memory32_fixed(plic_aplic_addr, mmio_size,
172 AML_READ_WRITE));
173 aml_append(dev, aml_name_decl("_CRS", crs));
174 aml_append(scope, dev);
175 }
176 }
177
178 static void
179 acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
180 uint32_t uart_irq, int uartidx)
181 {
182 Aml *dev = aml_device("COM%d", uartidx);
183 aml_append(dev, aml_name_decl("_HID", aml_string("RSCV0003")));
184 aml_append(dev, aml_name_decl("_UID", aml_int(uartidx)));
185
186 Aml *crs = aml_resource_template();
187 aml_append(crs, aml_memory32_fixed(uart_memmap->base,
188 uart_memmap->size, AML_READ_WRITE));
189 aml_append(crs,
190 aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
191 AML_EXCLUSIVE, &uart_irq, 1));
192 aml_append(dev, aml_name_decl("_CRS", crs));
193
194 Aml *pkg = aml_package(2);
195 aml_append(pkg, aml_string("clock-frequency"));
196 aml_append(pkg, aml_int(3686400));
197
198 Aml *UUID = aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301");
199
200 Aml *pkg1 = aml_package(1);
201 aml_append(pkg1, pkg);
202
203 Aml *package = aml_package(2);
204 aml_append(package, UUID);
205 aml_append(package, pkg1);
206
207 aml_append(dev, aml_name_decl("_DSD", package));
208 aml_append(scope, dev);
209 }
210
211 /*
212 * Add DSDT entry for the IOMMU platform device.
213 * ACPI ID for IOMMU is defined in the section 6.2 of RISC-V BRS spec.
214 * https://github.com/riscv-non-isa/riscv-brs/releases/download/v0.8/riscv-brs-spec.pdf
215 */
216 static void acpi_dsdt_add_iommu_sys(Aml *scope, const MemMapEntry *iommu_memmap,
217 uint32_t iommu_irq)
218 {
219 uint32_t i;
220
221 Aml *dev = aml_device("IMU0");
222 aml_append(dev, aml_name_decl("_HID", aml_string("RSCV0004")));
223 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
224
225 Aml *crs = aml_resource_template();
226 aml_append(crs, aml_memory32_fixed(iommu_memmap->base,
227 iommu_memmap->size, AML_READ_WRITE));
228 for (i = iommu_irq; i < iommu_irq + 4; i++) {
229 aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_LOW,
230 AML_EXCLUSIVE, &i, 1));
231 }
232
233 aml_append(dev, aml_name_decl("_CRS", crs));
234 aml_append(scope, dev);
235 }
236
237 /*
238 * Serial Port Console Redirection Table (SPCR)
239 * Rev: 1.10
240 */
241
242 static void
243 spcr_setup(GArray *table_data, BIOSLinker *linker, RISCVVirtState *s)
244 {
245 const char name[] = ".";
246 AcpiSpcrData serial = {
247 .interface_type = 0x12, /* 16550 compatible */
248 .base_addr.id = AML_AS_SYSTEM_MEMORY,
249 .base_addr.width = 32,
250 .base_addr.offset = 0,
251 .base_addr.size = 1,
252 .base_addr.addr = s->memmap[VIRT_UART0].base,
253 .interrupt_type = (1 << 4),/* Bit[4] RISC-V PLIC/APLIC */
254 .pc_interrupt = 0,
255 .interrupt = UART0_IRQ,
256 .baud_rate = 7, /* 15200 */
257 .parity = 0,
258 .stop_bits = 1,
259 .flow_control = 0,
260 .terminal_type = 3, /* ANSI */
261 .language = 0, /* Language */
262 .pci_device_id = 0xffff, /* not a PCI device*/
263 .pci_vendor_id = 0xffff, /* not a PCI device*/
264 .pci_bus = 0,
265 .pci_device = 0,
266 .pci_function = 0,
267 .pci_flags = 0,
268 .pci_segment = 0,
269 .uart_clk_freq = 0,
270 .precise_baudrate = 0,
271 .namespace_string_length = sizeof(name),
272 .namespace_string_offset = 88,
273 };
274
275 build_spcr(table_data, linker, &serial, 4, s->oem_id, s->oem_table_id,
276 name);
277 }
278
279 /* RHCT Node[N] starts at offset 56 */
280 #define RHCT_NODE_ARRAY_OFFSET 56
281
282 /*
283 * ACPI spec, Revision 6.6
284 * 5.2.37 RISC-V Hart Capabilities Table (RHCT)
285 */
286 static void build_rhct(GArray *table_data,
287 BIOSLinker *linker,
288 RISCVVirtState *s)
289 {
290 MachineClass *mc = MACHINE_GET_CLASS(s);
291 MachineState *ms = MACHINE(s);
292 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
293 size_t len, aligned_len;
294 uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0;
295 RISCVCPU *cpu = &s->soc[0].harts[0];
296 uint32_t mmu_offset = 0;
297 bool rv32 = riscv_cpu_is_32bit(cpu);
298 g_autofree char *isa = NULL;
299
300 AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id,
301 .oem_table_id = s->oem_table_id };
302
303 acpi_table_begin(&table, table_data);
304
305 build_append_int_noprefix(table_data, 0x0, 4); /* Reserved */
306
307 /* Time Base Frequency */
308 build_append_int_noprefix(table_data,
309 kvm_enabled() ?
310 kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) :
311 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ,
312 8);
313
314 /* ISA + N hart info */
315 num_rhct_nodes = 1 + ms->smp.cpus;
316 if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) {
317 num_rhct_nodes++;
318 }
319
320 if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
321 num_rhct_nodes++;
322 }
323
324 /* Number of RHCT nodes*/
325 build_append_int_noprefix(table_data, num_rhct_nodes, 4);
326
327 /* Offset to the RHCT node array */
328 build_append_int_noprefix(table_data, RHCT_NODE_ARRAY_OFFSET, 4);
329
330 /* ISA String Node */
331 isa_offset = table_data->len - table.table_offset;
332 build_append_int_noprefix(table_data, 0, 2); /* Type 0 */
333
334 isa = riscv_isa_string(cpu);
335 len = 8 + strlen(isa) + 1;
336 aligned_len = (len % 2) ? (len + 1) : len;
337
338 build_append_int_noprefix(table_data, aligned_len, 2); /* Length */
339 build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
340
341 /* ISA string length including NUL */
342 build_append_int_noprefix(table_data, strlen(isa) + 1, 2);
343 g_array_append_vals(table_data, isa, strlen(isa) + 1); /* ISA string */
344
345 if (aligned_len != len) {
346 build_append_int_noprefix(table_data, 0x0, 1); /* Optional Padding */
347 }
348
349 /* CMO node */
350 if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) {
351 cmo_offset = table_data->len - table.table_offset;
352 build_append_int_noprefix(table_data, 1, 2); /* Type */
353 build_append_int_noprefix(table_data, 10, 2); /* Length */
354 build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
355 build_append_int_noprefix(table_data, 0, 1); /* Reserved */
356
357 /* CBOM block size */
358 if (cpu->cfg.cbom_blocksize) {
359 build_append_int_noprefix(table_data,
360 __builtin_ctz(cpu->cfg.cbom_blocksize),
361 1);
362 } else {
363 build_append_int_noprefix(table_data, 0, 1);
364 }
365
366 /* CBOP block size */
367 build_append_int_noprefix(table_data, 0, 1);
368
369 /* CBOZ block size */
370 if (cpu->cfg.cboz_blocksize) {
371 build_append_int_noprefix(table_data,
372 __builtin_ctz(cpu->cfg.cboz_blocksize),
373 1);
374 } else {
375 build_append_int_noprefix(table_data, 0, 1);
376 }
377 }
378
379 /* MMU node structure */
380 if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
381 mmu_offset = table_data->len - table.table_offset;
382 build_append_int_noprefix(table_data, 2, 2); /* Type */
383 build_append_int_noprefix(table_data, 8, 2); /* Length */
384 build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
385 build_append_int_noprefix(table_data, 0, 1); /* Reserved */
386 /* MMU Type */
387 if (cpu->cfg.max_satp_mode == VM_1_10_SV57) {
388 build_append_int_noprefix(table_data, 2, 1); /* Sv57 */
389 } else if (cpu->cfg.max_satp_mode == VM_1_10_SV48) {
390 build_append_int_noprefix(table_data, 1, 1); /* Sv48 */
391 } else if (cpu->cfg.max_satp_mode == VM_1_10_SV39) {
392 build_append_int_noprefix(table_data, 0, 1); /* Sv39 */
393 } else {
394 g_assert_not_reached();
395 }
396 }
397
398 /* Hart Info Node */
399 for (int i = 0; i < arch_ids->len; i++) {
400 len = 16;
401 int num_offsets = 1;
402 build_append_int_noprefix(table_data, 0xFFFF, 2); /* Type */
403
404 /* Length */
405 if (cmo_offset) {
406 len += 4;
407 num_offsets++;
408 }
409
410 if (mmu_offset) {
411 len += 4;
412 num_offsets++;
413 }
414
415 build_append_int_noprefix(table_data, len, 2);
416 build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
417 /* Number of offsets */
418 build_append_int_noprefix(table_data, num_offsets, 2);
419 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
420 /* Offsets */
421 build_append_int_noprefix(table_data, isa_offset, 4);
422 if (cmo_offset) {
423 build_append_int_noprefix(table_data, cmo_offset, 4);
424 }
425
426 if (mmu_offset) {
427 build_append_int_noprefix(table_data, mmu_offset, 4);
428 }
429 }
430
431 acpi_table_end(linker, &table);
432 }
433
434 /*
435 * ACPI spec, Revision 6.6
436 * 5.2.9 Fixed ACPI Description Table (MADT)
437 */
438 static void build_fadt_rev6(GArray *table_data,
439 BIOSLinker *linker,
440 RISCVVirtState *s,
441 unsigned dsdt_tbl_offset)
442 {
443 AcpiFadtData fadt = {
444 .rev = 6,
445 .minor_ver = 6,
446 .flags = 1 << ACPI_FADT_F_HW_REDUCED_ACPI,
447 .xdsdt_tbl_offset = &dsdt_tbl_offset,
448 };
449
450 build_fadt(table_data, linker, &fadt, s->oem_id, s->oem_table_id);
451 }
452
453 /* DSDT */
454 static void build_dsdt(GArray *table_data,
455 BIOSLinker *linker,
456 RISCVVirtState *s)
457 {
458 Aml *scope, *dsdt;
459 MachineState *ms = MACHINE(s);
460 uint8_t socket_count;
461 const MemMapEntry *memmap = s->memmap;
462 AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = s->oem_id,
463 .oem_table_id = s->oem_table_id };
464
465
466 acpi_table_begin(&table, table_data);
467 dsdt = init_aml_allocator();
468
469 /*
470 * When booting the VM with UEFI, UEFI takes ownership of the RTC hardware.
471 * While UEFI can use libfdt to disable the RTC device node in the DTB that
472 * it passes to the OS, it cannot modify AML. Therefore, we won't generate
473 * the RTC ACPI device at all when using UEFI.
474 */
475 scope = aml_scope("\\_SB");
476 acpi_dsdt_add_cpus(scope, s);
477
478 fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]);
479
480 socket_count = riscv_socket_count(ms);
481
482 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
483 acpi_dsdt_add_plic_aplic(scope, socket_count, s->num_sources,
484 memmap[VIRT_PLIC].base,
485 memmap[VIRT_PLIC].size,
486 "RSCV0001");
487 } else {
488 acpi_dsdt_add_plic_aplic(scope, socket_count, s->num_sources,
489 memmap[VIRT_APLIC_S].base,
490 memmap[VIRT_APLIC_S].size, "RSCV0002");
491 }
492
493 acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ, 0);
494 if (s->uart1_present) {
495 acpi_dsdt_add_uart(scope, &memmap[VIRT_UART1], UART1_IRQ, 1);
496 }
497
498 if (virt_is_iommu_sys_enabled(s)) {
499 acpi_dsdt_add_iommu_sys(scope, &memmap[VIRT_IOMMU_SYS], IOMMU_SYS_IRQ);
500 }
501
502 if (socket_count == 1) {
503 virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
504 memmap[VIRT_VIRTIO].size,
505 VIRTIO_IRQ, 0, VIRTIO_COUNT);
506 acpi_dsdt_add_gpex_host(scope, PCIE_IRQ);
507 } else if (socket_count == 2) {
508 virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
509 memmap[VIRT_VIRTIO].size,
510 VIRTIO_IRQ + s->num_sources, 0,
511 VIRTIO_COUNT);
512 acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + s->num_sources);
513 } else {
514 virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
515 memmap[VIRT_VIRTIO].size,
516 VIRTIO_IRQ + s->num_sources, 0,
517 VIRTIO_COUNT);
518 acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + s->num_sources * 2);
519 }
520
521 aml_append(dsdt, scope);
522
523 /* copy AML table into ACPI tables blob and patch header there */
524 g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
525
526 acpi_table_end(linker, &table);
527 free_aml_allocator();
528 }
529
530 /*
531 * ACPI spec, Revision 6.6
532 * 5.2.12 Multiple APIC Description Table (MADT)
533 */
534 static void build_madt(GArray *table_data,
535 BIOSLinker *linker,
536 RISCVVirtState *s)
537 {
538 MachineClass *mc = MACHINE_GET_CLASS(s);
539 MachineState *ms = MACHINE(s);
540 const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
541 uint8_t group_index_bits = imsic_num_bits(riscv_socket_count(ms));
542 uint8_t guest_index_bits = imsic_num_bits(s->aia_guests + 1);
543 uint16_t imsic_max_hart_per_socket = 0;
544 uint8_t hart_index_bits;
545 uint64_t aplic_addr;
546 uint32_t gsi_base;
547 uint8_t socket;
548
549 for (socket = 0; socket < riscv_socket_count(ms); socket++) {
550 if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
551 imsic_max_hart_per_socket = s->soc[socket].num_harts;
552 }
553 }
554
555 hart_index_bits = imsic_num_bits(imsic_max_hart_per_socket);
556
557 AcpiTable table = { .sig = "APIC", .rev = 7, .oem_id = s->oem_id,
558 .oem_table_id = s->oem_table_id };
559
560 acpi_table_begin(&table, table_data);
561 /* Local Interrupt Controller Address */
562 build_append_int_noprefix(table_data, 0, 4);
563 build_append_int_noprefix(table_data, 0, 4); /* MADT Flags */
564
565 /* RISC-V Local INTC structures per HART */
566 for (int i = 0; i < arch_ids->len; i++) {
567 riscv_acpi_madt_add_rintc(i, arch_ids, table_data, s);
568 }
569
570 /* IMSIC */
571 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
572 /* IMSIC */
573 build_append_int_noprefix(table_data, 0x19, 1); /* Type */
574 build_append_int_noprefix(table_data, 16, 1); /* Length */
575 build_append_int_noprefix(table_data, 1, 1); /* Version */
576 build_append_int_noprefix(table_data, 0, 1); /* Reserved */
577 build_append_int_noprefix(table_data, 0, 4); /* Flags */
578 /* Number of supervisor mode Interrupt Identities */
579 build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2);
580 /* Number of guest mode Interrupt Identities */
581 build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2);
582 /* Guest Index Bits */
583 build_append_int_noprefix(table_data, guest_index_bits, 1);
584 /* Hart Index Bits */
585 build_append_int_noprefix(table_data, hart_index_bits, 1);
586 /* Group Index Bits */
587 build_append_int_noprefix(table_data, group_index_bits, 1);
588 /* Group Index Shift */
589 build_append_int_noprefix(table_data, IMSIC_MMIO_GROUP_MIN_SHIFT, 1);
590 }
591
592 if (s->aia_type != VIRT_AIA_TYPE_NONE) {
593 /* APLICs */
594 for (socket = 0; socket < riscv_socket_count(ms); socket++) {
595 aplic_addr = s->memmap[VIRT_APLIC_S].base +
596 s->memmap[VIRT_APLIC_S].size * socket;
597 gsi_base = s->num_sources * socket;
598 build_append_int_noprefix(table_data, 0x1A, 1); /* Type */
599 build_append_int_noprefix(table_data, 36, 1); /* Length */
600 build_append_int_noprefix(table_data, 1, 1); /* Version */
601 build_append_int_noprefix(table_data, socket, 1); /* APLIC ID */
602 build_append_int_noprefix(table_data, 0, 4); /* Flags */
603 build_append_int_noprefix(table_data, 0, 8); /* Hardware ID */
604 /* Number of IDCs */
605 if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
606 build_append_int_noprefix(table_data,
607 s->soc[socket].num_harts,
608 2);
609 } else {
610 build_append_int_noprefix(table_data, 0, 2);
611 }
612 /* Total External Interrupt Sources Supported */
613 build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_SOURCES, 2);
614 /* Global System Interrupt Base */
615 build_append_int_noprefix(table_data, gsi_base, 4);
616 /* APLIC Address */
617 build_append_int_noprefix(table_data, aplic_addr, 8);
618 /* APLIC size */
619 build_append_int_noprefix(table_data,
620 s->memmap[VIRT_APLIC_S].size, 4);
621 }
622 } else {
623 /* PLICs */
624 for (socket = 0; socket < riscv_socket_count(ms); socket++) {
625 aplic_addr = s->memmap[VIRT_PLIC].base +
626 s->memmap[VIRT_PLIC].size * socket;
627 gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket;
628 build_append_int_noprefix(table_data, 0x1B, 1); /* Type */
629 build_append_int_noprefix(table_data, 36, 1); /* Length */
630 build_append_int_noprefix(table_data, 1, 1); /* Version */
631 build_append_int_noprefix(table_data, socket, 1); /* PLIC ID */
632 build_append_int_noprefix(table_data, 0, 8); /* Hardware ID */
633 /* Total External Interrupt Sources Supported */
634 build_append_int_noprefix(table_data,
635 VIRT_IRQCHIP_NUM_SOURCES - 1, 2);
636 build_append_int_noprefix(table_data, 0, 2); /* Max Priority */
637 build_append_int_noprefix(table_data, 0, 4); /* Flags */
638 /* PLIC Size */
639 build_append_int_noprefix(table_data, s->memmap[VIRT_PLIC].size, 4);
640 /* PLIC Address */
641 build_append_int_noprefix(table_data, aplic_addr, 8);
642 /* Global System Interrupt Vector Base */
643 build_append_int_noprefix(table_data, gsi_base, 4);
644 }
645 }
646
647 acpi_table_end(linker, &table);
648 }
649
650 #define ID_MAPPING_ENTRY_SIZE 20
651 #define IOMMU_ENTRY_SIZE 40
652 #define RISCV_INTERRUPT_WIRE_OFFSSET 40
653 #define ROOT_COMPLEX_ENTRY_SIZE 20
654 #define RIMT_NODE_OFFSET 48
655
656 /*
657 * ID Mapping Structure
658 */
659 static void build_rimt_id_mapping(GArray *table_data, uint32_t source_id_base,
660 uint32_t num_ids, uint32_t dest_id_base)
661 {
662 /* Source ID Base */
663 build_append_int_noprefix(table_data, source_id_base, 4);
664 /* Number of IDs */
665 build_append_int_noprefix(table_data, num_ids, 4);
666 /* Destination Device ID Base */
667 build_append_int_noprefix(table_data, source_id_base, 4);
668 /* Destination IOMMU Offset */
669 build_append_int_noprefix(table_data, dest_id_base, 4);
670 /* Flags */
671 build_append_int_noprefix(table_data, 0, 4);
672 }
673
674 struct AcpiRimtIdMapping {
675 uint32_t source_id_base;
676 uint32_t num_ids;
677 };
678 typedef struct AcpiRimtIdMapping AcpiRimtIdMapping;
679
680 /* Build the rimt ID mapping to IOMMU for a given PCI host bridge */
681 static int rimt_host_bridges(Object *obj, void *opaque)
682 {
683 GArray *idmap_blob = opaque;
684
685 if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
686 PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
687
688 if (bus && !pci_bus_bypass_iommu(bus)) {
689 int min_bus, max_bus;
690
691 pci_bus_range(bus, &min_bus, &max_bus);
692
693 AcpiRimtIdMapping idmap = {
694 .source_id_base = min_bus << 8,
695 .num_ids = (max_bus - min_bus + 1) << 8,
696 };
697 g_array_append_val(idmap_blob, idmap);
698 }
699 }
700
701 return 0;
702 }
703
704 static int rimt_idmap_compare(gconstpointer a, gconstpointer b)
705 {
706 AcpiRimtIdMapping *idmap_a = (AcpiRimtIdMapping *)a;
707 AcpiRimtIdMapping *idmap_b = (AcpiRimtIdMapping *)b;
708
709 return idmap_a->source_id_base - idmap_b->source_id_base;
710 }
711
712 /*
713 * RISC-V IO Mapping Table (RIMT)
714 * https://github.com/riscv-non-isa/riscv-acpi-rimt/releases/download/v0.99/rimt-spec.pdf
715 */
716 static void build_rimt(GArray *table_data, BIOSLinker *linker,
717 RISCVVirtState *s)
718 {
719 int i, nb_nodes, rc_mapping_count;
720 size_t node_size, iommu_offset = 0;
721 uint32_t id = 0;
722 g_autoptr(GArray) iommu_idmaps = g_array_new(false, true,
723 sizeof(AcpiRimtIdMapping));
724
725 AcpiTable table = { .sig = "RIMT", .rev = 1, .oem_id = s->oem_id,
726 .oem_table_id = s->oem_table_id };
727
728 acpi_table_begin(&table, table_data);
729
730 object_child_foreach_recursive(object_get_root(),
731 rimt_host_bridges, iommu_idmaps);
732
733 /* Sort the ID mapping by Source ID Base*/
734 g_array_sort(iommu_idmaps, rimt_idmap_compare);
735
736 nb_nodes = 2; /* RC, IOMMU */
737 rc_mapping_count = iommu_idmaps->len;
738 /* Number of RIMT Nodes */
739 build_append_int_noprefix(table_data, nb_nodes, 4);
740
741 /* Offset to Array of RIMT Nodes */
742 build_append_int_noprefix(table_data, RIMT_NODE_OFFSET, 4);
743 build_append_int_noprefix(table_data, 0, 4); /* Reserved */
744
745 iommu_offset = table_data->len - table.table_offset;
746 /* IOMMU Device Structure */
747 build_append_int_noprefix(table_data, 0, 1); /* Type - IOMMU*/
748 build_append_int_noprefix(table_data, 1, 1); /* Revision */
749 node_size = IOMMU_ENTRY_SIZE;
750 build_append_int_noprefix(table_data, node_size, 2); /* Length */
751 build_append_int_noprefix(table_data, 0, 2); /* Reserved */
752 build_append_int_noprefix(table_data, id++, 2); /* ID */
753 if (virt_is_iommu_sys_enabled(s)) {
754 /* Hardware ID */
755 build_append_int_noprefix(table_data, 'R', 1);
756 build_append_int_noprefix(table_data, 'S', 1);
757 build_append_int_noprefix(table_data, 'C', 1);
758 build_append_int_noprefix(table_data, 'V', 1);
759 build_append_int_noprefix(table_data, '0', 1);
760 build_append_int_noprefix(table_data, '0', 1);
761 build_append_int_noprefix(table_data, '0', 1);
762 build_append_int_noprefix(table_data, '4', 1);
763 /* Base Address */
764 build_append_int_noprefix(table_data,
765 s->memmap[VIRT_IOMMU_SYS].base, 8);
766 build_append_int_noprefix(table_data, 0, 4); /* Flags */
767 } else {
768 /* Hardware ID */
769 build_append_int_noprefix(table_data, '0', 1);
770 build_append_int_noprefix(table_data, '0', 1);
771 build_append_int_noprefix(table_data, '1', 1);
772 build_append_int_noprefix(table_data, '0', 1);
773 build_append_int_noprefix(table_data, '0', 1);
774 build_append_int_noprefix(table_data, '0', 1);
775 build_append_int_noprefix(table_data, '1', 1);
776 build_append_int_noprefix(table_data, '4', 1);
777
778 build_append_int_noprefix(table_data, 0, 8); /* Base Address */
779 build_append_int_noprefix(table_data, 1, 4); /* Flags */
780 }
781
782 build_append_int_noprefix(table_data, 0, 4); /* Proximity Domain */
783 build_append_int_noprefix(table_data, 0, 2); /* PCI Segment number */
784 /* PCIe B/D/F */
785 if (virt_is_iommu_sys_enabled(s)) {
786 build_append_int_noprefix(table_data, 0, 2);
787 } else {
788 build_append_int_noprefix(table_data, s->pci_iommu_bdf, 2);
789 }
790 /* Number of interrupt wires */
791 build_append_int_noprefix(table_data, 0, 2);
792 /* Interrupt wire array offset */
793 build_append_int_noprefix(table_data, RISCV_INTERRUPT_WIRE_OFFSSET, 2);
794
795 /* PCIe Root Complex Node */
796 build_append_int_noprefix(table_data, 1, 1); /* Type */
797 build_append_int_noprefix(table_data, 1, 1); /* Revision */
798 node_size = ROOT_COMPLEX_ENTRY_SIZE +
799 ID_MAPPING_ENTRY_SIZE * rc_mapping_count;
800 build_append_int_noprefix(table_data, node_size, 2); /* Length */
801 build_append_int_noprefix(table_data, 0, 2); /* Reserved */
802 build_append_int_noprefix(table_data, id++, 2); /* ID */
803 build_append_int_noprefix(table_data, 0, 4); /* Flags */
804 build_append_int_noprefix(table_data, 0, 2); /* Reserved */
805 /* PCI Segment number */
806 build_append_int_noprefix(table_data, 0, 2);
807 /* ID mapping array offset */
808 build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 2);
809 /* Number of ID mappings */
810 build_append_int_noprefix(table_data, rc_mapping_count, 2);
811
812 /* Output Reference */
813 AcpiRimtIdMapping *range;
814
815 /* ID mapping array */
816 for (i = 0; i < iommu_idmaps->len; i++) {
817 range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i);
818 if (virt_is_iommu_sys_enabled(s)) {
819 range->source_id_base = 0;
820 range->num_ids = 0x10000;
821 } else {
822 range->source_id_base = s->pci_iommu_bdf + 1;
823 range->num_ids = 0xffff - s->pci_iommu_bdf;
824 }
825 build_rimt_id_mapping(table_data, range->source_id_base,
826 range->num_ids, iommu_offset);
827 }
828
829 acpi_table_end(linker, &table);
830 }
831
832 /*
833 * ACPI spec, Revision 6.6
834 * 5.2.16 System Resource Affinity Table (SRAT)
835 */
836 static void
837 build_srat(GArray *table_data, BIOSLinker *linker, RISCVVirtState *vms)
838 {
839 int i;
840 uint64_t mem_base;
841 MachineClass *mc = MACHINE_GET_CLASS(vms);
842 MachineState *ms = MACHINE(vms);
843 const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(ms);
844 AcpiTable table = { .sig = "SRAT", .rev = 3, .oem_id = vms->oem_id,
845 .oem_table_id = vms->oem_table_id };
846
847 acpi_table_begin(&table, table_data);
848 build_append_int_noprefix(table_data, 1, 4); /* Reserved */
849 build_append_int_noprefix(table_data, 0, 8); /* Reserved */
850
851 for (i = 0; i < cpu_list->len; ++i) {
852 uint32_t nodeid = cpu_list->cpus[i].props.node_id;
853 /*
854 * 5.2.16.8 RINTC Affinity Structure
855 */
856 build_append_int_noprefix(table_data, 7, 1); /* Type */
857 build_append_int_noprefix(table_data, 20, 1); /* Length */
858 build_append_int_noprefix(table_data, 0, 2); /* Reserved */
859 build_append_int_noprefix(table_data, nodeid, 4); /* Proximity Domain */
860 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
861 /* Flags, Table 5-70 */
862 build_append_int_noprefix(table_data, 1 /* Flags: Enabled */, 4);
863 build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
864 }
865
866 mem_base = vms->memmap[VIRT_DRAM].base;
867 for (i = 0; i < ms->numa_state->num_nodes; ++i) {
868 if (ms->numa_state->nodes[i].node_mem > 0) {
869 build_srat_memory(table_data, mem_base,
870 ms->numa_state->nodes[i].node_mem, i,
871 MEM_AFFINITY_ENABLED);
872 mem_base += ms->numa_state->nodes[i].node_mem;
873 }
874 }
875
876 acpi_table_end(linker, &table);
877 }
878
879 static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables)
880 {
881 GArray *table_offsets;
882 unsigned dsdt, xsdt;
883 GArray *tables_blob = tables->table_data;
884 MachineState *ms = MACHINE(s);
885
886 table_offsets = g_array_new(false, true,
887 sizeof(uint32_t));
888
889 bios_linker_loader_alloc(tables->linker,
890 ACPI_BUILD_TABLE_FILE, tables_blob,
891 64, false);
892
893 /* DSDT is pointed to by FADT */
894 dsdt = tables_blob->len;
895 build_dsdt(tables_blob, tables->linker, s);
896
897 /* FADT and others pointed to by XSDT */
898 acpi_add_table(table_offsets, tables_blob);
899 build_fadt_rev6(tables_blob, tables->linker, s, dsdt);
900
901 acpi_add_table(table_offsets, tables_blob);
902 build_madt(tables_blob, tables->linker, s);
903
904 acpi_add_table(table_offsets, tables_blob);
905 build_rhct(tables_blob, tables->linker, s);
906
907 if (virt_is_iommu_sys_enabled(s) || s->pci_iommu_bdf) {
908 acpi_add_table(table_offsets, tables_blob);
909 build_rimt(tables_blob, tables->linker, s);
910 }
911
912 acpi_add_table(table_offsets, tables_blob);
913
914 if (ms->acpi_spcr_enabled) {
915 spcr_setup(tables_blob, tables->linker, s);
916 }
917
918 acpi_add_table(table_offsets, tables_blob);
919 {
920 AcpiMcfgInfo mcfg = {
921 .base = s->memmap[VIRT_PCIE_ECAM].base,
922 .size = s->memmap[VIRT_PCIE_ECAM].size,
923 };
924 build_mcfg(tables_blob, tables->linker, &mcfg, s->oem_id,
925 s->oem_table_id);
926 }
927
928 if (ms->numa_state->num_nodes > 0) {
929 acpi_add_table(table_offsets, tables_blob);
930 build_srat(tables_blob, tables->linker, s);
931 if (ms->numa_state->have_numa_distance) {
932 acpi_add_table(table_offsets, tables_blob);
933 build_slit(tables_blob, tables->linker, ms, s->oem_id,
934 s->oem_table_id);
935 }
936 }
937
938 /* XSDT is pointed to by RSDP */
939 xsdt = tables_blob->len;
940 build_xsdt(tables_blob, tables->linker, table_offsets, s->oem_id,
941 s->oem_table_id);
942
943 /* RSDP is in FSEG memory, so allocate it separately */
944 {
945 AcpiRsdpData rsdp_data = {
946 .revision = 2,
947 .oem_id = s->oem_id,
948 .xsdt_tbl_offset = &xsdt,
949 .rsdt_tbl_offset = NULL,
950 };
951 build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
952 }
953
954 /*
955 * The align size is 128, warn if 64k is not enough therefore
956 * the align size could be resized.
957 */
958 if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
959 warn_report("ACPI table size %u exceeds %d bytes,"
960 " migration may not work",
961 tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
962 error_printf("Try removing some objects.");
963 }
964
965 acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
966
967 /* Clean up memory that's no longer used */
968 g_array_free(table_offsets, true);
969 }
970
971 static void acpi_ram_update(MemoryRegion *mr, GArray *data)
972 {
973 uint32_t size = acpi_data_len(data);
974
975 /*
976 * Make sure RAM size is correct - in case it got changed
977 * e.g. by migration
978 */
979 memory_region_ram_resize(mr, size, &error_abort);
980
981 memcpy(memory_region_get_ram_ptr(mr), data->data, size);
982 memory_region_set_dirty(mr, 0, size);
983 }
984
985 static void virt_acpi_build_update(void *build_opaque)
986 {
987 AcpiBuildState *build_state = build_opaque;
988 AcpiBuildTables tables;
989
990 /* No state to update or already patched? Nothing to do. */
991 if (!build_state || build_state->patched) {
992 return;
993 }
994
995 build_state->patched = true;
996
997 acpi_build_tables_init(&tables);
998
999 virt_acpi_build(RISCV_VIRT_MACHINE(qdev_get_machine()), &tables);
1000
1001 acpi_ram_update(build_state->table_mr, tables.table_data);
1002 acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
1003 acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
1004
1005 acpi_build_tables_cleanup(&tables, true);
1006 }
1007
1008 static void virt_acpi_build_reset(void *build_opaque)
1009 {
1010 AcpiBuildState *build_state = build_opaque;
1011 build_state->patched = false;
1012 }
1013
1014 static const VMStateDescription vmstate_virt_acpi_build = {
1015 .name = "virt_acpi_build",
1016 .version_id = 1,
1017 .minimum_version_id = 1,
1018 .fields = (const VMStateField[]) {
1019 VMSTATE_BOOL(patched, AcpiBuildState),
1020 VMSTATE_END_OF_LIST()
1021 },
1022 };
1023
1024 void virt_acpi_setup(RISCVVirtState *s)
1025 {
1026 AcpiBuildTables tables;
1027 AcpiBuildState *build_state;
1028
1029 build_state = g_malloc0(sizeof *build_state);
1030
1031 acpi_build_tables_init(&tables);
1032 virt_acpi_build(s, &tables);
1033
1034 /* Now expose it all to Guest */
1035 build_state->table_mr = acpi_add_rom_blob(virt_acpi_build_update,
1036 build_state, tables.table_data,
1037 ACPI_BUILD_TABLE_FILE);
1038 assert(build_state->table_mr != NULL);
1039
1040 build_state->linker_mr = acpi_add_rom_blob(virt_acpi_build_update,
1041 build_state,
1042 tables.linker->cmd_blob,
1043 ACPI_BUILD_LOADER_FILE);
1044
1045 build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
1046 build_state, tables.rsdp,
1047 ACPI_BUILD_RSDP_FILE);
1048
1049 qemu_register_reset(virt_acpi_build_reset, build_state);
1050 virt_acpi_build_reset(build_state);
1051 vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state);
1052
1053 /*
1054 * Clean up tables but don't free the memory: we track it
1055 * in build_state.
1056 */
1057 acpi_build_tables_cleanup(&tables, false);
1058 }