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