xref: /qemu/hw/riscv/virt-acpi-build.c (revision f0737158b483e7ec2b2512145aeab888b85cc1f7)
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 
acpi_align_size(GArray * blob,unsigned align)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 
riscv_acpi_madt_add_rintc(uint32_t uid,const CPUArchIdList * arch_ids,GArray * entry,RISCVVirtState * s)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 
acpi_dsdt_add_cpus(Aml * scope,RISCVVirtState * s)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 
acpi_dsdt_add_plic_aplic(Aml * scope,uint8_t socket_count,uint64_t mmio_base,uint64_t mmio_size,const char * hid)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
acpi_dsdt_add_uart(Aml * scope,const MemMapEntry * uart_memmap,uint32_t uart_irq)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  */
acpi_dsdt_add_iommu_sys(Aml * scope,const MemMapEntry * iommu_memmap,uint32_t iommu_irq)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
spcr_setup(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s)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  */
build_rhct(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s)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     bool rv32 = riscv_cpu_is_32bit(cpu);
291     g_autofree char *isa = NULL;
292 
293     AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id,
294                         .oem_table_id = s->oem_table_id };
295 
296     acpi_table_begin(&table, table_data);
297 
298     build_append_int_noprefix(table_data, 0x0, 4);   /* Reserved */
299 
300     /* Time Base Frequency */
301     build_append_int_noprefix(table_data,
302                               RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, 8);
303 
304     /* ISA + N hart info */
305     num_rhct_nodes = 1 + ms->smp.cpus;
306     if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) {
307         num_rhct_nodes++;
308     }
309 
310     if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
311         num_rhct_nodes++;
312     }
313 
314     /* Number of RHCT nodes*/
315     build_append_int_noprefix(table_data, num_rhct_nodes, 4);
316 
317     /* Offset to the RHCT node array */
318     build_append_int_noprefix(table_data, RHCT_NODE_ARRAY_OFFSET, 4);
319 
320     /* ISA String Node */
321     isa_offset = table_data->len - table.table_offset;
322     build_append_int_noprefix(table_data, 0, 2);   /* Type 0 */
323 
324     isa = riscv_isa_string(cpu);
325     len = 8 + strlen(isa) + 1;
326     aligned_len = (len % 2) ? (len + 1) : len;
327 
328     build_append_int_noprefix(table_data, aligned_len, 2);   /* Length */
329     build_append_int_noprefix(table_data, 0x1, 2);           /* Revision */
330 
331     /* ISA string length including NUL */
332     build_append_int_noprefix(table_data, strlen(isa) + 1, 2);
333     g_array_append_vals(table_data, isa, strlen(isa) + 1);   /* ISA string */
334 
335     if (aligned_len != len) {
336         build_append_int_noprefix(table_data, 0x0, 1);   /* Optional Padding */
337     }
338 
339     /* CMO node */
340     if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) {
341         cmo_offset = table_data->len - table.table_offset;
342         build_append_int_noprefix(table_data, 1, 2);    /* Type */
343         build_append_int_noprefix(table_data, 10, 2);   /* Length */
344         build_append_int_noprefix(table_data, 0x1, 2);  /* Revision */
345         build_append_int_noprefix(table_data, 0, 1);    /* Reserved */
346 
347         /* CBOM block size */
348         if (cpu->cfg.cbom_blocksize) {
349             build_append_int_noprefix(table_data,
350                                       __builtin_ctz(cpu->cfg.cbom_blocksize),
351                                       1);
352         } else {
353             build_append_int_noprefix(table_data, 0, 1);
354         }
355 
356         /* CBOP block size */
357         build_append_int_noprefix(table_data, 0, 1);
358 
359         /* CBOZ block size */
360         if (cpu->cfg.cboz_blocksize) {
361             build_append_int_noprefix(table_data,
362                                       __builtin_ctz(cpu->cfg.cboz_blocksize),
363                                       1);
364         } else {
365             build_append_int_noprefix(table_data, 0, 1);
366         }
367     }
368 
369     /* MMU node structure */
370     if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
371         mmu_offset = table_data->len - table.table_offset;
372         build_append_int_noprefix(table_data, 2, 2);    /* Type */
373         build_append_int_noprefix(table_data, 8, 2);    /* Length */
374         build_append_int_noprefix(table_data, 0x1, 2);  /* Revision */
375         build_append_int_noprefix(table_data, 0, 1);    /* Reserved */
376         /* MMU Type */
377         if (cpu->cfg.max_satp_mode == VM_1_10_SV57) {
378             build_append_int_noprefix(table_data, 2, 1);    /* Sv57 */
379         } else if (cpu->cfg.max_satp_mode == VM_1_10_SV48) {
380             build_append_int_noprefix(table_data, 1, 1);    /* Sv48 */
381         } else if (cpu->cfg.max_satp_mode == VM_1_10_SV39) {
382             build_append_int_noprefix(table_data, 0, 1);    /* Sv39 */
383         } else {
384             g_assert_not_reached();
385         }
386     }
387 
388     /* Hart Info Node */
389     for (int i = 0; i < arch_ids->len; i++) {
390         len = 16;
391         int num_offsets = 1;
392         build_append_int_noprefix(table_data, 0xFFFF, 2);  /* Type */
393 
394         /* Length */
395         if (cmo_offset) {
396             len += 4;
397             num_offsets++;
398         }
399 
400         if (mmu_offset) {
401             len += 4;
402             num_offsets++;
403         }
404 
405         build_append_int_noprefix(table_data, len, 2);
406         build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
407         /* Number of offsets */
408         build_append_int_noprefix(table_data, num_offsets, 2);
409         build_append_int_noprefix(table_data, i, 4);   /* ACPI Processor UID */
410         /* Offsets */
411         build_append_int_noprefix(table_data, isa_offset, 4);
412         if (cmo_offset) {
413             build_append_int_noprefix(table_data, cmo_offset, 4);
414         }
415 
416         if (mmu_offset) {
417             build_append_int_noprefix(table_data, mmu_offset, 4);
418         }
419     }
420 
421     acpi_table_end(linker, &table);
422 }
423 
424 /* FADT */
build_fadt_rev6(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s,unsigned dsdt_tbl_offset)425 static void build_fadt_rev6(GArray *table_data,
426                             BIOSLinker *linker,
427                             RISCVVirtState *s,
428                             unsigned dsdt_tbl_offset)
429 {
430     AcpiFadtData fadt = {
431         .rev = 6,
432         .minor_ver = 5,
433         .flags = 1 << ACPI_FADT_F_HW_REDUCED_ACPI,
434         .xdsdt_tbl_offset = &dsdt_tbl_offset,
435     };
436 
437     build_fadt(table_data, linker, &fadt, s->oem_id, s->oem_table_id);
438 }
439 
440 /* DSDT */
build_dsdt(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s)441 static void build_dsdt(GArray *table_data,
442                        BIOSLinker *linker,
443                        RISCVVirtState *s)
444 {
445     Aml *scope, *dsdt;
446     MachineState *ms = MACHINE(s);
447     uint8_t socket_count;
448     const MemMapEntry *memmap = s->memmap;
449     AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = s->oem_id,
450                         .oem_table_id = s->oem_table_id };
451 
452 
453     acpi_table_begin(&table, table_data);
454     dsdt = init_aml_allocator();
455 
456     /*
457      * When booting the VM with UEFI, UEFI takes ownership of the RTC hardware.
458      * While UEFI can use libfdt to disable the RTC device node in the DTB that
459      * it passes to the OS, it cannot modify AML. Therefore, we won't generate
460      * the RTC ACPI device at all when using UEFI.
461      */
462     scope = aml_scope("\\_SB");
463     acpi_dsdt_add_cpus(scope, s);
464 
465     fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]);
466 
467     socket_count = riscv_socket_count(ms);
468 
469     if (s->aia_type == VIRT_AIA_TYPE_NONE) {
470         acpi_dsdt_add_plic_aplic(scope, socket_count, memmap[VIRT_PLIC].base,
471                                  memmap[VIRT_PLIC].size, "RSCV0001");
472     } else {
473         acpi_dsdt_add_plic_aplic(scope, socket_count, memmap[VIRT_APLIC_S].base,
474                                  memmap[VIRT_APLIC_S].size, "RSCV0002");
475     }
476 
477     acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ);
478     if (virt_is_iommu_sys_enabled(s)) {
479         acpi_dsdt_add_iommu_sys(scope, &memmap[VIRT_IOMMU_SYS], IOMMU_SYS_IRQ);
480     }
481 
482     if (socket_count == 1) {
483         virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
484                              memmap[VIRT_VIRTIO].size,
485                              VIRTIO_IRQ, 0, VIRTIO_COUNT);
486         acpi_dsdt_add_gpex_host(scope, PCIE_IRQ);
487     } else if (socket_count == 2) {
488         virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
489                              memmap[VIRT_VIRTIO].size,
490                              VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0,
491                              VIRTIO_COUNT);
492         acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES);
493     } else {
494         virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
495                              memmap[VIRT_VIRTIO].size,
496                              VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0,
497                              VIRTIO_COUNT);
498         acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES * 2);
499     }
500 
501     aml_append(dsdt, scope);
502 
503     /* copy AML table into ACPI tables blob and patch header there */
504     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
505 
506     acpi_table_end(linker, &table);
507     free_aml_allocator();
508 }
509 
510 /*
511  * ACPI spec, Revision 6.5+
512  * 5.2.12 Multiple APIC Description Table (MADT)
513  * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/15
514  *      https://drive.google.com/file/d/1R6k4MshhN3WTT-hwqAquu5nX6xSEqK2l/view
515  *      https://drive.google.com/file/d/1oMGPyOD58JaPgMl1pKasT-VKsIKia7zR/view
516  */
build_madt(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s)517 static void build_madt(GArray *table_data,
518                        BIOSLinker *linker,
519                        RISCVVirtState *s)
520 {
521     MachineClass *mc = MACHINE_GET_CLASS(s);
522     MachineState *ms = MACHINE(s);
523     const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms);
524     uint8_t  group_index_bits = imsic_num_bits(riscv_socket_count(ms));
525     uint8_t  guest_index_bits = imsic_num_bits(s->aia_guests + 1);
526     uint16_t imsic_max_hart_per_socket = 0;
527     uint8_t  hart_index_bits;
528     uint64_t aplic_addr;
529     uint32_t gsi_base;
530     uint8_t  socket;
531 
532     for (socket = 0; socket < riscv_socket_count(ms); socket++) {
533         if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
534             imsic_max_hart_per_socket = s->soc[socket].num_harts;
535         }
536     }
537 
538     hart_index_bits = imsic_num_bits(imsic_max_hart_per_socket);
539 
540     AcpiTable table = { .sig = "APIC", .rev = 6, .oem_id = s->oem_id,
541                         .oem_table_id = s->oem_table_id };
542 
543     acpi_table_begin(&table, table_data);
544     /* Local Interrupt Controller Address */
545     build_append_int_noprefix(table_data, 0, 4);
546     build_append_int_noprefix(table_data, 0, 4);   /* MADT Flags */
547 
548     /* RISC-V Local INTC structures per HART */
549     for (int i = 0; i < arch_ids->len; i++) {
550         riscv_acpi_madt_add_rintc(i, arch_ids, table_data, s);
551     }
552 
553     /* IMSIC */
554     if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
555         /* IMSIC */
556         build_append_int_noprefix(table_data, 0x19, 1);     /* Type */
557         build_append_int_noprefix(table_data, 16, 1);       /* Length */
558         build_append_int_noprefix(table_data, 1, 1);        /* Version */
559         build_append_int_noprefix(table_data, 0, 1);        /* Reserved */
560         build_append_int_noprefix(table_data, 0, 4);        /* Flags */
561         /* Number of supervisor mode Interrupt Identities */
562         build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2);
563         /* Number of guest mode Interrupt Identities */
564         build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2);
565         /* Guest Index Bits */
566         build_append_int_noprefix(table_data, guest_index_bits, 1);
567         /* Hart Index Bits */
568         build_append_int_noprefix(table_data, hart_index_bits, 1);
569         /* Group Index Bits */
570         build_append_int_noprefix(table_data, group_index_bits, 1);
571         /* Group Index Shift */
572         build_append_int_noprefix(table_data, IMSIC_MMIO_GROUP_MIN_SHIFT, 1);
573     }
574 
575     if (s->aia_type != VIRT_AIA_TYPE_NONE) {
576         /* APLICs */
577         for (socket = 0; socket < riscv_socket_count(ms); socket++) {
578             aplic_addr = s->memmap[VIRT_APLIC_S].base +
579                              s->memmap[VIRT_APLIC_S].size * socket;
580             gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket;
581             build_append_int_noprefix(table_data, 0x1A, 1);    /* Type */
582             build_append_int_noprefix(table_data, 36, 1);      /* Length */
583             build_append_int_noprefix(table_data, 1, 1);       /* Version */
584             build_append_int_noprefix(table_data, socket, 1);  /* APLIC ID */
585             build_append_int_noprefix(table_data, 0, 4);       /* Flags */
586             build_append_int_noprefix(table_data, 0, 8);       /* Hardware ID */
587             /* Number of IDCs */
588             if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
589                 build_append_int_noprefix(table_data,
590                                           s->soc[socket].num_harts,
591                                           2);
592             } else {
593                 build_append_int_noprefix(table_data, 0, 2);
594             }
595             /* Total External Interrupt Sources Supported */
596             build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_SOURCES, 2);
597             /* Global System Interrupt Base */
598             build_append_int_noprefix(table_data, gsi_base, 4);
599             /* APLIC Address */
600             build_append_int_noprefix(table_data, aplic_addr, 8);
601             /* APLIC size */
602             build_append_int_noprefix(table_data,
603                                       s->memmap[VIRT_APLIC_S].size, 4);
604         }
605     } else {
606         /* PLICs */
607         for (socket = 0; socket < riscv_socket_count(ms); socket++) {
608             aplic_addr = s->memmap[VIRT_PLIC].base +
609                          s->memmap[VIRT_PLIC].size * socket;
610             gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket;
611             build_append_int_noprefix(table_data, 0x1B, 1);   /* Type */
612             build_append_int_noprefix(table_data, 36, 1);     /* Length */
613             build_append_int_noprefix(table_data, 1, 1);      /* Version */
614             build_append_int_noprefix(table_data, socket, 1); /* PLIC ID */
615             build_append_int_noprefix(table_data, 0, 8);      /* Hardware ID */
616             /* Total External Interrupt Sources Supported */
617             build_append_int_noprefix(table_data,
618                                       VIRT_IRQCHIP_NUM_SOURCES - 1, 2);
619             build_append_int_noprefix(table_data, 0, 2);     /* Max Priority */
620             build_append_int_noprefix(table_data, 0, 4);     /* Flags */
621             /* PLIC Size */
622             build_append_int_noprefix(table_data, s->memmap[VIRT_PLIC].size, 4);
623             /* PLIC Address */
624             build_append_int_noprefix(table_data, aplic_addr, 8);
625             /* Global System Interrupt Vector Base */
626             build_append_int_noprefix(table_data, gsi_base, 4);
627         }
628     }
629 
630     acpi_table_end(linker, &table);
631 }
632 
633 #define ID_MAPPING_ENTRY_SIZE        20
634 #define IOMMU_ENTRY_SIZE             40
635 #define RISCV_INTERRUPT_WIRE_OFFSSET 40
636 #define ROOT_COMPLEX_ENTRY_SIZE      20
637 #define RIMT_NODE_OFFSET             48
638 
639 /*
640  * ID Mapping Structure
641  */
build_rimt_id_mapping(GArray * table_data,uint32_t source_id_base,uint32_t num_ids,uint32_t dest_id_base)642 static void build_rimt_id_mapping(GArray *table_data, uint32_t source_id_base,
643                                   uint32_t num_ids, uint32_t dest_id_base)
644 {
645     /* Source ID Base */
646     build_append_int_noprefix(table_data, source_id_base, 4);
647     /* Number of IDs */
648     build_append_int_noprefix(table_data, num_ids, 4);
649     /* Destination Device ID Base */
650     build_append_int_noprefix(table_data, source_id_base, 4);
651     /* Destination IOMMU Offset */
652     build_append_int_noprefix(table_data, dest_id_base, 4);
653     /* Flags */
654     build_append_int_noprefix(table_data, 0, 4);
655 }
656 
657 struct AcpiRimtIdMapping {
658     uint32_t source_id_base;
659     uint32_t num_ids;
660 };
661 typedef struct AcpiRimtIdMapping AcpiRimtIdMapping;
662 
663 /* Build the rimt ID mapping to IOMMU for a given PCI host bridge */
rimt_host_bridges(Object * obj,void * opaque)664 static int rimt_host_bridges(Object *obj, void *opaque)
665 {
666     GArray *idmap_blob = opaque;
667 
668     if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
669         PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
670 
671         if (bus && !pci_bus_bypass_iommu(bus)) {
672             int min_bus, max_bus;
673 
674             pci_bus_range(bus, &min_bus, &max_bus);
675 
676             AcpiRimtIdMapping idmap = {
677                 .source_id_base = min_bus << 8,
678                 .num_ids = (max_bus - min_bus + 1) << 8,
679             };
680             g_array_append_val(idmap_blob, idmap);
681         }
682     }
683 
684     return 0;
685 }
686 
rimt_idmap_compare(gconstpointer a,gconstpointer b)687 static int rimt_idmap_compare(gconstpointer a, gconstpointer b)
688 {
689     AcpiRimtIdMapping *idmap_a = (AcpiRimtIdMapping *)a;
690     AcpiRimtIdMapping *idmap_b = (AcpiRimtIdMapping *)b;
691 
692     return idmap_a->source_id_base - idmap_b->source_id_base;
693 }
694 
695 /*
696  * RISC-V IO Mapping Table (RIMT)
697  * https://github.com/riscv-non-isa/riscv-acpi-rimt/releases/download/v0.99/rimt-spec.pdf
698  */
build_rimt(GArray * table_data,BIOSLinker * linker,RISCVVirtState * s)699 static void build_rimt(GArray *table_data, BIOSLinker *linker,
700                        RISCVVirtState *s)
701 {
702     int i, nb_nodes, rc_mapping_count;
703     size_t node_size, iommu_offset = 0;
704     uint32_t id = 0;
705     g_autoptr(GArray) iommu_idmaps = g_array_new(false, true,
706                                                  sizeof(AcpiRimtIdMapping));
707 
708     AcpiTable table = { .sig = "RIMT", .rev = 1, .oem_id = s->oem_id,
709                         .oem_table_id = s->oem_table_id };
710 
711     acpi_table_begin(&table, table_data);
712 
713     object_child_foreach_recursive(object_get_root(),
714                                    rimt_host_bridges, iommu_idmaps);
715 
716     /* Sort the ID mapping  by Source ID Base*/
717     g_array_sort(iommu_idmaps, rimt_idmap_compare);
718 
719     nb_nodes = 2; /* RC, IOMMU */
720     rc_mapping_count = iommu_idmaps->len;
721     /* Number of RIMT Nodes */
722     build_append_int_noprefix(table_data, nb_nodes, 4);
723 
724     /* Offset to Array of RIMT Nodes */
725     build_append_int_noprefix(table_data, RIMT_NODE_OFFSET, 4);
726     build_append_int_noprefix(table_data, 0, 4); /* Reserved */
727 
728     iommu_offset = table_data->len - table.table_offset;
729     /*  IOMMU Device Structure */
730     build_append_int_noprefix(table_data, 0, 1);         /* Type - IOMMU*/
731     build_append_int_noprefix(table_data, 1, 1);         /* Revision */
732     node_size =  IOMMU_ENTRY_SIZE;
733     build_append_int_noprefix(table_data, node_size, 2); /* Length */
734     build_append_int_noprefix(table_data, 0, 2);         /* Reserved */
735     build_append_int_noprefix(table_data, id++, 2);      /* ID */
736     if (virt_is_iommu_sys_enabled(s)) {
737         /* Hardware ID */
738         build_append_int_noprefix(table_data, 'R', 1);
739         build_append_int_noprefix(table_data, 'S', 1);
740         build_append_int_noprefix(table_data, 'C', 1);
741         build_append_int_noprefix(table_data, 'V', 1);
742         build_append_int_noprefix(table_data, '0', 1);
743         build_append_int_noprefix(table_data, '0', 1);
744         build_append_int_noprefix(table_data, '0', 1);
745         build_append_int_noprefix(table_data, '4', 1);
746         /* Base Address */
747         build_append_int_noprefix(table_data,
748                                   s->memmap[VIRT_IOMMU_SYS].base, 8);
749         build_append_int_noprefix(table_data, 0, 4);   /* Flags */
750     } else {
751         /* Hardware ID */
752         build_append_int_noprefix(table_data, '0', 1);
753         build_append_int_noprefix(table_data, '0', 1);
754         build_append_int_noprefix(table_data, '1', 1);
755         build_append_int_noprefix(table_data, '0', 1);
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, '4', 1);
760 
761         build_append_int_noprefix(table_data, 0, 8);   /* Base Address */
762         build_append_int_noprefix(table_data, 1, 4);   /* Flags */
763     }
764 
765     build_append_int_noprefix(table_data, 0, 4);       /* Proximity Domain */
766     build_append_int_noprefix(table_data, 0, 2);       /* PCI Segment number */
767     /* PCIe B/D/F */
768     if (virt_is_iommu_sys_enabled(s)) {
769         build_append_int_noprefix(table_data, 0, 2);
770     } else {
771         build_append_int_noprefix(table_data, s->pci_iommu_bdf, 2);
772     }
773     /* Number of interrupt wires */
774     build_append_int_noprefix(table_data, 0, 2);
775     /* Interrupt wire array offset */
776     build_append_int_noprefix(table_data, RISCV_INTERRUPT_WIRE_OFFSSET, 2);
777 
778     /*  PCIe Root Complex Node */
779     build_append_int_noprefix(table_data, 1, 1);           /* Type */
780     build_append_int_noprefix(table_data, 1, 1);           /* Revision */
781     node_size =  ROOT_COMPLEX_ENTRY_SIZE +
782                  ID_MAPPING_ENTRY_SIZE * rc_mapping_count;
783     build_append_int_noprefix(table_data, node_size, 2);   /* Length */
784     build_append_int_noprefix(table_data, 0, 2);           /* Reserved */
785     build_append_int_noprefix(table_data, id++, 2);        /* ID */
786     build_append_int_noprefix(table_data, 0, 4);           /* Flags */
787     build_append_int_noprefix(table_data, 0, 2);           /* Reserved */
788     /* PCI Segment number */
789     build_append_int_noprefix(table_data, 0, 2);
790     /* ID mapping array offset */
791     build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 2);
792     /* Number of ID mappings */
793     build_append_int_noprefix(table_data, rc_mapping_count, 2);
794 
795     /* Output Reference */
796     AcpiRimtIdMapping *range;
797 
798     /* ID mapping array */
799     for (i = 0; i < iommu_idmaps->len; i++) {
800         range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i);
801         if (virt_is_iommu_sys_enabled(s)) {
802             range->source_id_base = 0;
803         } else {
804             range->source_id_base = s->pci_iommu_bdf + 1;
805         }
806         range->num_ids = 0xffff - s->pci_iommu_bdf;
807         build_rimt_id_mapping(table_data, range->source_id_base,
808                               range->num_ids, iommu_offset);
809     }
810 
811     acpi_table_end(linker, &table);
812 }
813 
814 /*
815  * ACPI spec, Revision 6.5+
816  * 5.2.16 System Resource Affinity Table (SRAT)
817  * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/25
818  *      https://drive.google.com/file/d/1YTdDx2IPm5IeZjAW932EYU-tUtgS08tX/view
819  */
820 static void
build_srat(GArray * table_data,BIOSLinker * linker,RISCVVirtState * vms)821 build_srat(GArray *table_data, BIOSLinker *linker, RISCVVirtState *vms)
822 {
823     int i;
824     uint64_t mem_base;
825     MachineClass *mc = MACHINE_GET_CLASS(vms);
826     MachineState *ms = MACHINE(vms);
827     const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(ms);
828     AcpiTable table = { .sig = "SRAT", .rev = 3, .oem_id = vms->oem_id,
829                         .oem_table_id = vms->oem_table_id };
830 
831     acpi_table_begin(&table, table_data);
832     build_append_int_noprefix(table_data, 1, 4); /* Reserved */
833     build_append_int_noprefix(table_data, 0, 8); /* Reserved */
834 
835     for (i = 0; i < cpu_list->len; ++i) {
836         uint32_t nodeid = cpu_list->cpus[i].props.node_id;
837         /*
838          * 5.2.16.8 RINTC Affinity Structure
839          */
840         build_append_int_noprefix(table_data, 7, 1);      /* Type */
841         build_append_int_noprefix(table_data, 20, 1);     /* Length */
842         build_append_int_noprefix(table_data, 0, 2);        /* Reserved */
843         build_append_int_noprefix(table_data, nodeid, 4); /* Proximity Domain */
844         build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
845         /* Flags, Table 5-70 */
846         build_append_int_noprefix(table_data, 1 /* Flags: Enabled */, 4);
847         build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
848     }
849 
850     mem_base = vms->memmap[VIRT_DRAM].base;
851     for (i = 0; i < ms->numa_state->num_nodes; ++i) {
852         if (ms->numa_state->nodes[i].node_mem > 0) {
853             build_srat_memory(table_data, mem_base,
854                               ms->numa_state->nodes[i].node_mem, i,
855                               MEM_AFFINITY_ENABLED);
856             mem_base += ms->numa_state->nodes[i].node_mem;
857         }
858     }
859 
860     acpi_table_end(linker, &table);
861 }
862 
virt_acpi_build(RISCVVirtState * s,AcpiBuildTables * tables)863 static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables)
864 {
865     GArray *table_offsets;
866     unsigned dsdt, xsdt;
867     GArray *tables_blob = tables->table_data;
868     MachineState *ms = MACHINE(s);
869 
870     table_offsets = g_array_new(false, true,
871                                 sizeof(uint32_t));
872 
873     bios_linker_loader_alloc(tables->linker,
874                              ACPI_BUILD_TABLE_FILE, tables_blob,
875                              64, false);
876 
877     /* DSDT is pointed to by FADT */
878     dsdt = tables_blob->len;
879     build_dsdt(tables_blob, tables->linker, s);
880 
881     /* FADT and others pointed to by XSDT */
882     acpi_add_table(table_offsets, tables_blob);
883     build_fadt_rev6(tables_blob, tables->linker, s, dsdt);
884 
885     acpi_add_table(table_offsets, tables_blob);
886     build_madt(tables_blob, tables->linker, s);
887 
888     acpi_add_table(table_offsets, tables_blob);
889     build_rhct(tables_blob, tables->linker, s);
890 
891     if (virt_is_iommu_sys_enabled(s) || s->pci_iommu_bdf) {
892         acpi_add_table(table_offsets, tables_blob);
893         build_rimt(tables_blob, tables->linker, s);
894     }
895 
896     acpi_add_table(table_offsets, tables_blob);
897     spcr_setup(tables_blob, tables->linker, s);
898 
899     acpi_add_table(table_offsets, tables_blob);
900     {
901         AcpiMcfgInfo mcfg = {
902            .base = s->memmap[VIRT_PCIE_ECAM].base,
903            .size = s->memmap[VIRT_PCIE_ECAM].size,
904         };
905         build_mcfg(tables_blob, tables->linker, &mcfg, s->oem_id,
906                    s->oem_table_id);
907     }
908 
909     if (ms->numa_state->num_nodes > 0) {
910         acpi_add_table(table_offsets, tables_blob);
911         build_srat(tables_blob, tables->linker, s);
912         if (ms->numa_state->have_numa_distance) {
913             acpi_add_table(table_offsets, tables_blob);
914             build_slit(tables_blob, tables->linker, ms, s->oem_id,
915                        s->oem_table_id);
916         }
917     }
918 
919     /* XSDT is pointed to by RSDP */
920     xsdt = tables_blob->len;
921     build_xsdt(tables_blob, tables->linker, table_offsets, s->oem_id,
922                 s->oem_table_id);
923 
924     /* RSDP is in FSEG memory, so allocate it separately */
925     {
926         AcpiRsdpData rsdp_data = {
927             .revision = 2,
928             .oem_id = s->oem_id,
929             .xsdt_tbl_offset = &xsdt,
930             .rsdt_tbl_offset = NULL,
931         };
932         build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
933     }
934 
935     /*
936      * The align size is 128, warn if 64k is not enough therefore
937      * the align size could be resized.
938      */
939     if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
940         warn_report("ACPI table size %u exceeds %d bytes,"
941                     " migration may not work",
942                     tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
943         error_printf("Try removing some objects.");
944     }
945 
946     acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
947 
948     /* Clean up memory that's no longer used */
949     g_array_free(table_offsets, true);
950 }
951 
acpi_ram_update(MemoryRegion * mr,GArray * data)952 static void acpi_ram_update(MemoryRegion *mr, GArray *data)
953 {
954     uint32_t size = acpi_data_len(data);
955 
956     /*
957      * Make sure RAM size is correct - in case it got changed
958      * e.g. by migration
959      */
960     memory_region_ram_resize(mr, size, &error_abort);
961 
962     memcpy(memory_region_get_ram_ptr(mr), data->data, size);
963     memory_region_set_dirty(mr, 0, size);
964 }
965 
virt_acpi_build_update(void * build_opaque)966 static void virt_acpi_build_update(void *build_opaque)
967 {
968     AcpiBuildState *build_state = build_opaque;
969     AcpiBuildTables tables;
970 
971     /* No state to update or already patched? Nothing to do. */
972     if (!build_state || build_state->patched) {
973         return;
974     }
975 
976     build_state->patched = true;
977 
978     acpi_build_tables_init(&tables);
979 
980     virt_acpi_build(RISCV_VIRT_MACHINE(qdev_get_machine()), &tables);
981 
982     acpi_ram_update(build_state->table_mr, tables.table_data);
983     acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
984     acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
985 
986     acpi_build_tables_cleanup(&tables, true);
987 }
988 
virt_acpi_build_reset(void * build_opaque)989 static void virt_acpi_build_reset(void *build_opaque)
990 {
991     AcpiBuildState *build_state = build_opaque;
992     build_state->patched = false;
993 }
994 
995 static const VMStateDescription vmstate_virt_acpi_build = {
996     .name = "virt_acpi_build",
997     .version_id = 1,
998     .minimum_version_id = 1,
999     .fields = (const VMStateField[]) {
1000         VMSTATE_BOOL(patched, AcpiBuildState),
1001         VMSTATE_END_OF_LIST()
1002     },
1003 };
1004 
virt_acpi_setup(RISCVVirtState * s)1005 void virt_acpi_setup(RISCVVirtState *s)
1006 {
1007     AcpiBuildTables tables;
1008     AcpiBuildState *build_state;
1009 
1010     build_state = g_malloc0(sizeof *build_state);
1011 
1012     acpi_build_tables_init(&tables);
1013     virt_acpi_build(s, &tables);
1014 
1015     /* Now expose it all to Guest */
1016     build_state->table_mr = acpi_add_rom_blob(virt_acpi_build_update,
1017                                               build_state, tables.table_data,
1018                                               ACPI_BUILD_TABLE_FILE);
1019     assert(build_state->table_mr != NULL);
1020 
1021     build_state->linker_mr = acpi_add_rom_blob(virt_acpi_build_update,
1022                                                build_state,
1023                                                tables.linker->cmd_blob,
1024                                                ACPI_BUILD_LOADER_FILE);
1025 
1026     build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
1027                                              build_state, tables.rsdp,
1028                                              ACPI_BUILD_RSDP_FILE);
1029 
1030     qemu_register_reset(virt_acpi_build_reset, build_state);
1031     virt_acpi_build_reset(build_state);
1032     vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state);
1033 
1034     /*
1035      * Clean up tables but don't free the memory: we track it
1036      * in build_state.
1037      */
1038     acpi_build_tables_cleanup(&tables, false);
1039 }
1040