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