blob: 2bc5a9dd981c44d503bd9cf7eabc61c1e10703f5 [file] [log] [blame]
Michael Clark04331d02018-03-03 01:31:13 +13001/*
2 * QEMU RISC-V VirtIO Board
3 *
4 * Copyright (c) 2017 SiFive, Inc.
5 *
6 * RISC-V machine with 16550a UART and VirtIO MMIO
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "qemu/osdep.h"
Philippe Mathieu-Daudé4bf46af2018-06-25 09:42:08 -030022#include "qemu/units.h"
Michael Clark04331d02018-03-03 01:31:13 +130023#include "qemu/error-report.h"
Jason A. Donenfelde4b4f0b2022-06-13 13:58:10 +020024#include "qemu/guest-random.h"
Michael Clark04331d02018-03-03 01:31:13 +130025#include "qapi/error.h"
Michael Clark04331d02018-03-03 01:31:13 +130026#include "hw/boards.h"
27#include "hw/loader.h"
28#include "hw/sysbus.h"
Alistair Francis71eb5222019-10-08 16:32:25 -070029#include "hw/qdev-properties.h"
Bernhard Beschow7e6b5492024-09-05 09:38:32 +020030#include "hw/char/serial-mm.h"
Michael Clark04331d02018-03-03 01:31:13 +130031#include "target/riscv/cpu.h"
Alistair Francis3029fab2022-04-28 09:41:44 +100032#include "hw/core/sysbus-fdt.h"
Atish Patraabd9a202022-08-24 15:17:00 -070033#include "target/riscv/pmu.h"
Michael Clark04331d02018-03-03 01:31:13 +130034#include "hw/riscv/riscv_hart.h"
Tomasz Jeznachdf240d62024-10-16 17:40:30 -030035#include "hw/riscv/iommu.h"
Sunil V L2c12de12024-11-06 10:34:04 -030036#include "hw/riscv/riscv-iommu-bits.h"
Michael Clark04331d02018-03-03 01:31:13 +130037#include "hw/riscv/virt.h"
Alistair Francis0ac24d52019-06-24 15:11:49 -070038#include "hw/riscv/boot.h"
Anup Patel18df0b42020-05-15 14:58:50 +053039#include "hw/riscv/numa.h"
Daniel Henrique Barbozafb80f332023-09-25 14:57:02 -030040#include "kvm/kvm_riscv.h"
Heinrich Schuchardtecf28642024-01-23 19:42:28 +010041#include "hw/firmware/smbios.h"
Anup Patelcc63a182021-08-31 16:36:00 +053042#include "hw/intc/riscv_aclint.h"
Anup Patele6faee62022-02-20 14:25:22 +053043#include "hw/intc/riscv_aplic.h"
Bin Meng84fcf3c2020-09-03 18:40:17 +080044#include "hw/intc/sifive_plic.h"
Bin Menga4b84602020-09-03 18:40:20 +080045#include "hw/misc/sifive_test.h"
Alistair Francis1832b7c2022-04-28 09:41:43 +100046#include "hw/platform-bus.h"
Michael Clark04331d02018-03-03 01:31:13 +130047#include "chardev/char.h"
Philippe Mathieu-Daudé32cad1f2024-12-03 15:20:13 +010048#include "system/device_tree.h"
49#include "system/system.h"
50#include "system/tcg.h"
51#include "system/kvm.h"
52#include "system/tpm.h"
53#include "system/qtest.h"
Alistair Francis6d56e392018-12-11 22:37:36 +000054#include "hw/pci/pci.h"
55#include "hw/pci-host/gpex.h"
Asherah Connorc3467492021-03-19 10:50:41 +110056#include "hw/display/ramfb.h"
Sunil V L90477a62023-03-02 14:42:05 +053057#include "hw/acpi/aml-build.h"
Sunil V L168b8c22023-03-02 14:42:06 +053058#include "qapi/qapi-visit-common.h"
Daniel Henrique Barboza7778cdd2024-02-17 16:26:05 -030059#include "hw/virtio/virtio-iommu.h"
Michael Clark04331d02018-03-03 01:31:13 +130060
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +000061/* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */
Daniel Henrique Barboza2711e1e2024-11-19 16:17:01 -030062static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type)
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +000063{
Daniel Henrique Barboza2711e1e2024-11-19 16:17:01 -030064 bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
65
66 return riscv_is_kvm_aia_aplic_imsic(msimode);
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +000067}
68
Daniel Henrique Barbozab319ef12024-11-19 16:17:03 -030069static bool virt_use_emulated_aplic(RISCVVirtAIAType aia_type)
70{
71 bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
72
73 return riscv_use_emulated_aplic(msimode);
74}
75
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -030076static bool virt_aclint_allowed(void)
77{
78 return tcg_enabled() || qtest_enabled();
79}
80
Bin Meng73261282021-02-20 22:48:04 +080081static const MemMapEntry virt_memmap[] = {
Alistair Francis1832b7c2022-04-28 09:41:43 +100082 [VIRT_DEBUG] = { 0x0, 0x100 },
83 [VIRT_MROM] = { 0x1000, 0xf000 },
84 [VIRT_TEST] = { 0x100000, 0x1000 },
85 [VIRT_RTC] = { 0x101000, 0x1000 },
86 [VIRT_CLINT] = { 0x2000000, 0x10000 },
87 [VIRT_ACLINT_SSWI] = { 0x2F00000, 0x4000 },
88 [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 },
Sunil V L2c12de12024-11-06 10:34:04 -030089 [VIRT_IOMMU_SYS] = { 0x3010000, 0x1000 },
Alistair Francis1832b7c2022-04-28 09:41:43 +100090 [VIRT_PLATFORM_BUS] = { 0x4000000, 0x2000000 },
91 [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
92 [VIRT_APLIC_M] = { 0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) },
93 [VIRT_APLIC_S] = { 0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) },
94 [VIRT_UART0] = { 0x10000000, 0x100 },
95 [VIRT_VIRTIO] = { 0x10001000, 0x1000 },
96 [VIRT_FW_CFG] = { 0x10100000, 0x18 },
97 [VIRT_FLASH] = { 0x20000000, 0x4000000 },
98 [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE },
99 [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE },
100 [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
101 [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 },
102 [VIRT_DRAM] = { 0x80000000, 0x0 },
Michael Clark04331d02018-03-03 01:31:13 +1300103};
104
Bin Meng19800262021-02-20 22:48:07 +0800105/* PCIe high mmio is fixed for RV32 */
106#define VIRT32_HIGH_PCIE_MMIO_BASE 0x300000000ULL
107#define VIRT32_HIGH_PCIE_MMIO_SIZE (4 * GiB)
108
109/* PCIe high mmio for RV64, size is fixed but base depends on top of RAM */
110#define VIRT64_HIGH_PCIE_MMIO_SIZE (16 * GiB)
111
112static MemMapEntry virt_high_pcie_memmap;
113
Alistair Francis71eb5222019-10-08 16:32:25 -0700114#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
115
116static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s,
117 const char *name,
118 const char *alias_prop_name)
119{
120 /*
121 * Create a single flash device. We use the same parameters as
122 * the flash devices on the ARM virt board.
123 */
Markus Armbrusterdf707962020-06-10 07:31:59 +0200124 DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
Alistair Francis71eb5222019-10-08 16:32:25 -0700125
126 qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
127 qdev_prop_set_uint8(dev, "width", 4);
128 qdev_prop_set_uint8(dev, "device-width", 2);
129 qdev_prop_set_bit(dev, "big-endian", false);
130 qdev_prop_set_uint16(dev, "id0", 0x89);
131 qdev_prop_set_uint16(dev, "id1", 0x18);
132 qdev_prop_set_uint16(dev, "id2", 0x00);
133 qdev_prop_set_uint16(dev, "id3", 0x00);
134 qdev_prop_set_string(dev, "name", name);
135
Markus Armbrusterd2623122020-05-05 17:29:22 +0200136 object_property_add_child(OBJECT(s), name, OBJECT(dev));
Alistair Francis71eb5222019-10-08 16:32:25 -0700137 object_property_add_alias(OBJECT(s), alias_prop_name,
Markus Armbrusterd2623122020-05-05 17:29:22 +0200138 OBJECT(dev), "drive");
Alistair Francis71eb5222019-10-08 16:32:25 -0700139
140 return PFLASH_CFI01(dev);
141}
142
143static void virt_flash_create(RISCVVirtState *s)
144{
145 s->flash[0] = virt_flash_create1(s, "virt.flash0", "pflash0");
146 s->flash[1] = virt_flash_create1(s, "virt.flash1", "pflash1");
147}
148
149static void virt_flash_map1(PFlashCFI01 *flash,
150 hwaddr base, hwaddr size,
151 MemoryRegion *sysmem)
152{
153 DeviceState *dev = DEVICE(flash);
154
Philippe Mathieu-Daudé4cdd0a72020-05-11 22:52:46 +0200155 assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE));
Alistair Francis71eb5222019-10-08 16:32:25 -0700156 assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
157 qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
Markus Armbruster3c6ef472020-06-10 07:32:34 +0200158 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
Alistair Francis71eb5222019-10-08 16:32:25 -0700159
160 memory_region_add_subregion(sysmem, base,
161 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
162 0));
163}
164
165static void virt_flash_map(RISCVVirtState *s,
166 MemoryRegion *sysmem)
167{
168 hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
169 hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
170
171 virt_flash_map1(s->flash[0], flashbase, flashsize,
172 sysmem);
173 virt_flash_map1(s->flash[1], flashbase + flashsize, flashsize,
174 sysmem);
175}
176
Anup Patele6faee62022-02-20 14:25:22 +0530177static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
178 uint32_t irqchip_phandle)
Alistair Francis6d56e392018-12-11 22:37:36 +0000179{
180 int pin, dev;
Anup Patele6faee62022-02-20 14:25:22 +0530181 uint32_t irq_map_stride = 0;
Alexander Grafff871d02023-06-14 22:56:24 +0000182 uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS *
Anup Patele6faee62022-02-20 14:25:22 +0530183 FDT_MAX_INT_MAP_WIDTH] = {};
Alistair Francis6d56e392018-12-11 22:37:36 +0000184 uint32_t *irq_map = full_irq_map;
185
186 /* This code creates a standard swizzle of interrupts such that
187 * each device's first interrupt is based on it's PCI_SLOT number.
188 * (See pci_swizzle_map_irq_fn())
189 *
190 * We only need one entry per interrupt in the table (not one per
191 * possible slot) seeing the interrupt-map-mask will allow the table
192 * to wrap to any number of devices.
193 */
Alexander Grafff871d02023-06-14 22:56:24 +0000194 for (dev = 0; dev < PCI_NUM_PINS; dev++) {
Alistair Francis6d56e392018-12-11 22:37:36 +0000195 int devfn = dev * 0x8;
196
Alexander Grafff871d02023-06-14 22:56:24 +0000197 for (pin = 0; pin < PCI_NUM_PINS; pin++) {
198 int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
Alistair Francis6d56e392018-12-11 22:37:36 +0000199 int i = 0;
200
Anup Patele6faee62022-02-20 14:25:22 +0530201 /* Fill PCI address cells */
Alistair Francis6d56e392018-12-11 22:37:36 +0000202 irq_map[i] = cpu_to_be32(devfn << 8);
Alistair Francis6d56e392018-12-11 22:37:36 +0000203 i += FDT_PCI_ADDR_CELLS;
Anup Patele6faee62022-02-20 14:25:22 +0530204
205 /* Fill PCI Interrupt cells */
Alistair Francis6d56e392018-12-11 22:37:36 +0000206 irq_map[i] = cpu_to_be32(pin + 1);
Alistair Francis6d56e392018-12-11 22:37:36 +0000207 i += FDT_PCI_INT_CELLS;
Alistair Francis6d56e392018-12-11 22:37:36 +0000208
Anup Patele6faee62022-02-20 14:25:22 +0530209 /* Fill interrupt controller phandle and cells */
210 irq_map[i++] = cpu_to_be32(irqchip_phandle);
211 irq_map[i++] = cpu_to_be32(irq_nr);
212 if (s->aia_type != VIRT_AIA_TYPE_NONE) {
213 irq_map[i++] = cpu_to_be32(0x4);
214 }
Alistair Francis6d56e392018-12-11 22:37:36 +0000215
Anup Patele6faee62022-02-20 14:25:22 +0530216 if (!irq_map_stride) {
217 irq_map_stride = i;
218 }
219 irq_map += irq_map_stride;
Alistair Francis6d56e392018-12-11 22:37:36 +0000220 }
221 }
222
Anup Patele6faee62022-02-20 14:25:22 +0530223 qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
Alexander Grafff871d02023-06-14 22:56:24 +0000224 PCI_NUM_PINS * PCI_NUM_PINS *
Anup Patele6faee62022-02-20 14:25:22 +0530225 irq_map_stride * sizeof(uint32_t));
Alistair Francis6d56e392018-12-11 22:37:36 +0000226
227 qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
228 0x1800, 0, 0, 0x7);
229}
230
Anup Patel0ffc1a92021-08-31 16:36:02 +0530231static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
232 char *clust_name, uint32_t *phandle,
Daniel Henrique Barboza914c97f2023-01-11 14:09:42 -0300233 uint32_t *intc_phandles)
Michael Clark04331d02018-03-03 01:31:13 +1300234{
Anup Patel0ffc1a92021-08-31 16:36:02 +0530235 int cpu;
236 uint32_t cpu_phandle;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300237 MachineState *ms = MACHINE(s);
Daniel Henrique Barboza914c97f2023-01-11 14:09:42 -0300238 bool is_32_bit = riscv_is_32bit(&s->soc[0]);
Alexandre Ghitied9eb202023-03-03 14:12:52 +0100239 uint8_t satp_mode_max;
Anup Patel0ffc1a92021-08-31 16:36:02 +0530240
241 for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
Daniel Henrique Barbozac95c9d22023-02-22 15:52:03 -0300242 RISCVCPU *cpu_ptr = &s->soc[socket].harts[cpu];
Daniel Henrique Barboza73cdf382024-01-22 19:15:25 -0300243 g_autofree char *cpu_name = NULL;
244 g_autofree char *core_name = NULL;
245 g_autofree char *intc_name = NULL;
246 g_autofree char *sv_name = NULL;
Daniel Henrique Barbozac95c9d22023-02-22 15:52:03 -0300247
Anup Patel0ffc1a92021-08-31 16:36:02 +0530248 cpu_phandle = (*phandle)++;
249
250 cpu_name = g_strdup_printf("/cpus/cpu@%d",
251 s->soc[socket].hartid_base + cpu);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300252 qemu_fdt_add_subnode(ms->fdt, cpu_name);
Alexandre Ghitied9eb202023-03-03 14:12:52 +0100253
Daniel Henrique Barboza43d1de32023-07-06 07:17:20 -0300254 if (cpu_ptr->cfg.satp_mode.supported != 0) {
255 satp_mode_max = satp_mode_max_from_map(cpu_ptr->cfg.satp_mode.map);
256 sv_name = g_strdup_printf("riscv,%s",
257 satp_mode_str(satp_mode_max, is_32_bit));
258 qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
Daniel Henrique Barboza43d1de32023-07-06 07:17:20 -0300259 }
Alexandre Ghitied9eb202023-03-03 14:12:52 +0100260
Conor Dooley1c8e4912024-01-24 12:55:50 +0000261 riscv_isa_write_fdt(cpu_ptr, ms->fdt, cpu_name);
Anup Patel00769862023-03-02 06:14:06 -0300262
Daniel Henrique Barbozaa326a2b2023-10-12 13:46:03 -0300263 if (cpu_ptr->cfg.ext_zicbom) {
Anup Patel00769862023-03-02 06:14:06 -0300264 qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cbom-block-size",
265 cpu_ptr->cfg.cbom_blocksize);
266 }
267
Daniel Henrique Barbozae57039d2023-10-12 13:46:04 -0300268 if (cpu_ptr->cfg.ext_zicboz) {
Anup Patel00769862023-03-02 06:14:06 -0300269 qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cboz-block-size",
270 cpu_ptr->cfg.cboz_blocksize);
271 }
272
Daniel Henrique Barbozacc2bf692023-12-18 09:53:13 -0300273 if (cpu_ptr->cfg.ext_zicbop) {
274 qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cbop-block-size",
275 cpu_ptr->cfg.cbop_blocksize);
276 }
277
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300278 qemu_fdt_setprop_string(ms->fdt, cpu_name, "compatible", "riscv");
279 qemu_fdt_setprop_string(ms->fdt, cpu_name, "status", "okay");
280 qemu_fdt_setprop_cell(ms->fdt, cpu_name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530281 s->soc[socket].hartid_base + cpu);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300282 qemu_fdt_setprop_string(ms->fdt, cpu_name, "device_type", "cpu");
283 riscv_socket_fdt_write_id(ms, cpu_name, socket);
284 qemu_fdt_setprop_cell(ms->fdt, cpu_name, "phandle", cpu_phandle);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530285
286 intc_phandles[cpu] = (*phandle)++;
287
288 intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300289 qemu_fdt_add_subnode(ms->fdt, intc_name);
290 qemu_fdt_setprop_cell(ms->fdt, intc_name, "phandle",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530291 intc_phandles[cpu]);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300292 qemu_fdt_setprop_string(ms->fdt, intc_name, "compatible",
Anup Pateldc9acc92022-08-20 09:59:58 +0530293 "riscv,cpu-intc");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300294 qemu_fdt_setprop(ms->fdt, intc_name, "interrupt-controller", NULL, 0);
295 qemu_fdt_setprop_cell(ms->fdt, intc_name, "#interrupt-cells", 1);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530296
297 core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300298 qemu_fdt_add_subnode(ms->fdt, core_name);
299 qemu_fdt_setprop_cell(ms->fdt, core_name, "cpu", cpu_phandle);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530300 }
301}
302
303static void create_fdt_socket_memory(RISCVVirtState *s,
304 const MemMapEntry *memmap, int socket)
305{
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300306 g_autofree char *mem_name = NULL;
Anup Patel18df0b42020-05-15 14:58:50 +0530307 uint64_t addr, size;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300308 MachineState *ms = MACHINE(s);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530309
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300310 addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(ms, socket);
311 size = riscv_socket_mem_size(ms, socket);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530312 mem_name = g_strdup_printf("/memory@%lx", (long)addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300313 qemu_fdt_add_subnode(ms->fdt, mem_name);
314 qemu_fdt_setprop_cells(ms->fdt, mem_name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530315 addr >> 32, addr, size >> 32, size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300316 qemu_fdt_setprop_string(ms->fdt, mem_name, "device_type", "memory");
317 riscv_socket_fdt_write_id(ms, mem_name, socket);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530318}
319
320static void create_fdt_socket_clint(RISCVVirtState *s,
321 const MemMapEntry *memmap, int socket,
322 uint32_t *intc_phandles)
323{
324 int cpu;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300325 g_autofree char *clint_name = NULL;
326 g_autofree uint32_t *clint_cells = NULL;
Anup Patel0ffc1a92021-08-31 16:36:02 +0530327 unsigned long clint_addr;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300328 MachineState *ms = MACHINE(s);
Bin Meng7cfbb172021-04-30 15:12:57 +0800329 static const char * const clint_compat[2] = {
330 "sifive,clint0", "riscv,clint0"
331 };
Anup Patel0ffc1a92021-08-31 16:36:02 +0530332
333 clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
334
335 for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
336 clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
337 clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT);
338 clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
339 clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER);
340 }
341
342 clint_addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
343 clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300344 qemu_fdt_add_subnode(ms->fdt, clint_name);
345 qemu_fdt_setprop_string_array(ms->fdt, clint_name, "compatible",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530346 (char **)&clint_compat,
347 ARRAY_SIZE(clint_compat));
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300348 qemu_fdt_setprop_cells(ms->fdt, clint_name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530349 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300350 qemu_fdt_setprop(ms->fdt, clint_name, "interrupts-extended",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530351 clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300352 riscv_socket_fdt_write_id(ms, clint_name, socket);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530353}
354
Anup Patel954886e2021-08-31 16:36:03 +0530355static void create_fdt_socket_aclint(RISCVVirtState *s,
356 const MemMapEntry *memmap, int socket,
357 uint32_t *intc_phandles)
358{
359 int cpu;
360 char *name;
Anup Patel28d8c282022-02-20 14:25:24 +0530361 unsigned long addr, size;
Anup Patel954886e2021-08-31 16:36:03 +0530362 uint32_t aclint_cells_size;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300363 g_autofree uint32_t *aclint_mswi_cells = NULL;
364 g_autofree uint32_t *aclint_sswi_cells = NULL;
365 g_autofree uint32_t *aclint_mtimer_cells = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300366 MachineState *ms = MACHINE(s);
Anup Patel954886e2021-08-31 16:36:03 +0530367
368 aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
369 aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
370 aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
371
372 for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
373 aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
374 aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
375 aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
376 aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
377 aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
378 aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
379 }
380 aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
381
Anup Patel28d8c282022-02-20 14:25:24 +0530382 if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
383 addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
384 name = g_strdup_printf("/soc/mswi@%lx", addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300385 qemu_fdt_add_subnode(ms->fdt, name);
386 qemu_fdt_setprop_string(ms->fdt, name, "compatible",
Anup Patel28d8c282022-02-20 14:25:24 +0530387 "riscv,aclint-mswi");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300388 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Anup Patel28d8c282022-02-20 14:25:24 +0530389 0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300390 qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
Anup Patel28d8c282022-02-20 14:25:24 +0530391 aclint_mswi_cells, aclint_cells_size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300392 qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0);
393 qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0);
394 riscv_socket_fdt_write_id(ms, name, socket);
Anup Patel28d8c282022-02-20 14:25:24 +0530395 g_free(name);
396 }
Anup Patel954886e2021-08-31 16:36:03 +0530397
Anup Patel28d8c282022-02-20 14:25:24 +0530398 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
399 addr = memmap[VIRT_CLINT].base +
400 (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * socket);
401 size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE;
402 } else {
403 addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
404 (memmap[VIRT_CLINT].size * socket);
405 size = memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE;
406 }
Anup Patel954886e2021-08-31 16:36:03 +0530407 name = g_strdup_printf("/soc/mtimer@%lx", addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300408 qemu_fdt_add_subnode(ms->fdt, name);
409 qemu_fdt_setprop_string(ms->fdt, name, "compatible",
Anup Patel954886e2021-08-31 16:36:03 +0530410 "riscv,aclint-mtimer");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300411 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Anup Patel954886e2021-08-31 16:36:03 +0530412 0x0, addr + RISCV_ACLINT_DEFAULT_MTIME,
Anup Patel28d8c282022-02-20 14:25:24 +0530413 0x0, size - RISCV_ACLINT_DEFAULT_MTIME,
Anup Patel954886e2021-08-31 16:36:03 +0530414 0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
415 0x0, RISCV_ACLINT_DEFAULT_MTIME);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300416 qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
Anup Patel954886e2021-08-31 16:36:03 +0530417 aclint_mtimer_cells, aclint_cells_size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300418 riscv_socket_fdt_write_id(ms, name, socket);
Anup Patel954886e2021-08-31 16:36:03 +0530419 g_free(name);
420
Anup Patel28d8c282022-02-20 14:25:24 +0530421 if (s->aia_type != VIRT_AIA_TYPE_APLIC_IMSIC) {
422 addr = memmap[VIRT_ACLINT_SSWI].base +
423 (memmap[VIRT_ACLINT_SSWI].size * socket);
424 name = g_strdup_printf("/soc/sswi@%lx", addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300425 qemu_fdt_add_subnode(ms->fdt, name);
426 qemu_fdt_setprop_string(ms->fdt, name, "compatible",
Anup Patel28d8c282022-02-20 14:25:24 +0530427 "riscv,aclint-sswi");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300428 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Anup Patel28d8c282022-02-20 14:25:24 +0530429 0x0, addr, 0x0, memmap[VIRT_ACLINT_SSWI].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300430 qemu_fdt_setprop(ms->fdt, name, "interrupts-extended",
Anup Patel28d8c282022-02-20 14:25:24 +0530431 aclint_sswi_cells, aclint_cells_size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300432 qemu_fdt_setprop(ms->fdt, name, "interrupt-controller", NULL, 0);
433 qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells", 0);
434 riscv_socket_fdt_write_id(ms, name, socket);
Anup Patel28d8c282022-02-20 14:25:24 +0530435 g_free(name);
436 }
Anup Patel954886e2021-08-31 16:36:03 +0530437}
438
Anup Patel0ffc1a92021-08-31 16:36:02 +0530439static void create_fdt_socket_plic(RISCVVirtState *s,
440 const MemMapEntry *memmap, int socket,
441 uint32_t *phandle, uint32_t *intc_phandles,
442 uint32_t *plic_phandles)
443{
444 int cpu;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300445 g_autofree char *plic_name = NULL;
446 g_autofree uint32_t *plic_cells;
Anup Patel0ffc1a92021-08-31 16:36:02 +0530447 unsigned long plic_addr;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300448 MachineState *ms = MACHINE(s);
Bin Meng60bb5402021-04-30 15:12:58 +0800449 static const char * const plic_compat[2] = {
450 "sifive,plic-1.0.0", "riscv,plic0"
451 };
Michael Clark04331d02018-03-03 01:31:13 +1300452
Anup Patel0ffc1a92021-08-31 16:36:02 +0530453 plic_phandles[socket] = (*phandle)++;
454 plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket);
455 plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300456 qemu_fdt_add_subnode(ms->fdt, plic_name);
457 qemu_fdt_setprop_cell(ms->fdt, plic_name,
Anup Patel0ffc1a92021-08-31 16:36:02 +0530458 "#interrupt-cells", FDT_PLIC_INT_CELLS);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300459 qemu_fdt_setprop_cell(ms->fdt, plic_name,
Conor Dooley95e401d2022-08-10 19:46:10 +0100460 "#address-cells", FDT_PLIC_ADDR_CELLS);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300461 qemu_fdt_setprop_string_array(ms->fdt, plic_name, "compatible",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530462 (char **)&plic_compat,
463 ARRAY_SIZE(plic_compat));
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300464 qemu_fdt_setprop(ms->fdt, plic_name, "interrupt-controller", NULL, 0);
Yong-Xuan Wangca334e12023-12-18 09:05:40 +0000465
466 if (kvm_enabled()) {
467 plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
468
469 for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
470 plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
471 plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
472 }
473
474 qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
475 plic_cells,
476 s->soc[socket].num_harts * sizeof(uint32_t) * 2);
477 } else {
478 plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
479
480 for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
481 plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
482 plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT);
483 plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]);
484 plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT);
485 }
486
487 qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended",
488 plic_cells,
489 s->soc[socket].num_harts * sizeof(uint32_t) * 4);
490 }
491
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300492 qemu_fdt_setprop_cells(ms->fdt, plic_name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530493 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300494 qemu_fdt_setprop_cell(ms->fdt, plic_name, "riscv,ndev",
Bin Meng59f74482022-12-11 11:08:26 +0800495 VIRT_IRQCHIP_NUM_SOURCES - 1);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300496 riscv_socket_fdt_write_id(ms, plic_name, socket);
497 qemu_fdt_setprop_cell(ms->fdt, plic_name, "phandle",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530498 plic_phandles[socket]);
Alistair Francis3029fab2022-04-28 09:41:44 +1000499
Anup Pateld644e5e2022-05-11 20:15:28 +0530500 if (!socket) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300501 platform_bus_add_all_fdt_nodes(ms->fdt, plic_name,
Anup Pateld644e5e2022-05-11 20:15:28 +0530502 memmap[VIRT_PLATFORM_BUS].base,
503 memmap[VIRT_PLATFORM_BUS].size,
504 VIRT_PLATFORM_BUS_IRQ);
505 }
Anup Patel0ffc1a92021-08-31 16:36:02 +0530506}
Michael Clark04331d02018-03-03 01:31:13 +1300507
Sunil V L68c8b402023-12-18 20:32:38 +0530508uint32_t imsic_num_bits(uint32_t count)
Anup Patel28d8c282022-02-20 14:25:24 +0530509{
510 uint32_t ret = 0;
511
512 while (BIT(ret) < count) {
513 ret++;
514 }
515
516 return ret;
517}
518
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000519static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr,
520 uint32_t *intc_phandles, uint32_t msi_phandle,
521 bool m_mode, uint32_t imsic_guest_bits)
Anup Patel28d8c282022-02-20 14:25:24 +0530522{
523 int cpu, socket;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300524 g_autofree char *imsic_name = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300525 MachineState *ms = MACHINE(s);
526 int socket_count = riscv_socket_count(ms);
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300527 uint32_t imsic_max_hart_per_socket, imsic_addr, imsic_size;
528 g_autofree uint32_t *imsic_cells = NULL;
529 g_autofree uint32_t *imsic_regs = NULL;
Daniel Henrique Barboza8fb0bb52024-05-31 17:27:58 -0300530 static const char * const imsic_compat[2] = {
531 "qemu,imsics", "riscv,imsics"
532 };
Anup Patel28d8c282022-02-20 14:25:24 +0530533
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300534 imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -0300535 imsic_regs = g_new0(uint32_t, socket_count * 4);
Anup Patel28d8c282022-02-20 14:25:24 +0530536
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300537 for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
Anup Patel28d8c282022-02-20 14:25:24 +0530538 imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000539 imsic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
Anup Patel28d8c282022-02-20 14:25:24 +0530540 }
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000541
Anup Patel28d8c282022-02-20 14:25:24 +0530542 imsic_max_hart_per_socket = 0;
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -0300543 for (socket = 0; socket < socket_count; socket++) {
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000544 imsic_addr = base_addr + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
Anup Patel28d8c282022-02-20 14:25:24 +0530545 imsic_size = IMSIC_HART_SIZE(imsic_guest_bits) *
546 s->soc[socket].num_harts;
547 imsic_regs[socket * 4 + 0] = 0;
548 imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
549 imsic_regs[socket * 4 + 2] = 0;
550 imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
551 if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
552 imsic_max_hart_per_socket = s->soc[socket].num_harts;
553 }
554 }
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000555
Daniel Henrique Barbozae8ad5812024-05-31 17:27:57 -0300556 imsic_name = g_strdup_printf("/soc/interrupt-controller@%lx",
557 (unsigned long)base_addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300558 qemu_fdt_add_subnode(ms->fdt, imsic_name);
Daniel Henrique Barboza8fb0bb52024-05-31 17:27:58 -0300559 qemu_fdt_setprop_string_array(ms->fdt, imsic_name, "compatible",
560 (char **)&imsic_compat,
561 ARRAY_SIZE(imsic_compat));
562
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300563 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000564 FDT_IMSIC_INT_CELLS);
565 qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller", NULL, 0);
566 qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller", NULL, 0);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300567 qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000568 imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300569 qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000570 socket_count * sizeof(uint32_t) * 4);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300571 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000572 VIRT_IRQCHIP_NUM_MSIS);
573
Anup Patel28d8c282022-02-20 14:25:24 +0530574 if (imsic_guest_bits) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300575 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,guest-index-bits",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000576 imsic_guest_bits);
Anup Patel28d8c282022-02-20 14:25:24 +0530577 }
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000578
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -0300579 if (socket_count > 1) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300580 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000581 imsic_num_bits(imsic_max_hart_per_socket));
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300582 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000583 imsic_num_bits(socket_count));
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300584 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000585 IMSIC_MMIO_GROUP_MIN_SHIFT);
Anup Patel28d8c282022-02-20 14:25:24 +0530586 }
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000587 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", msi_phandle);
Anup Patel28d8c282022-02-20 14:25:24 +0530588}
589
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000590static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
591 uint32_t *phandle, uint32_t *intc_phandles,
592 uint32_t *msi_m_phandle, uint32_t *msi_s_phandle)
593{
594 *msi_m_phandle = (*phandle)++;
595 *msi_s_phandle = (*phandle)++;
596
597 if (!kvm_enabled()) {
598 /* M-level IMSIC node */
599 create_fdt_one_imsic(s, memmap[VIRT_IMSIC_M].base, intc_phandles,
600 *msi_m_phandle, true, 0);
601 }
602
603 /* S-level IMSIC node */
604 create_fdt_one_imsic(s, memmap[VIRT_IMSIC_S].base, intc_phandles,
605 *msi_s_phandle, false,
606 imsic_num_bits(s->aia_guests + 1));
607
608}
609
Daniel Henrique Barboza02dd57b2024-05-31 17:27:53 -0300610/* Caller must free string after use */
611static char *fdt_get_aplic_nodename(unsigned long aplic_addr)
612{
Daniel Henrique Barboza29390fd2024-05-31 17:27:54 -0300613 return g_strdup_printf("/soc/interrupt-controller@%lx", aplic_addr);
Daniel Henrique Barboza02dd57b2024-05-31 17:27:53 -0300614}
615
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000616static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
617 unsigned long aplic_addr, uint32_t aplic_size,
618 uint32_t msi_phandle,
619 uint32_t *intc_phandles,
620 uint32_t aplic_phandle,
621 uint32_t aplic_child_phandle,
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000622 bool m_mode, int num_harts)
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000623{
624 int cpu;
Daniel Henrique Barboza02dd57b2024-05-31 17:27:53 -0300625 g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr);
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300626 g_autofree uint32_t *aplic_cells = g_new0(uint32_t, num_harts * 2);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000627 MachineState *ms = MACHINE(s);
Daniel Henrique Barboza362b31f2024-05-31 17:27:55 -0300628 static const char * const aplic_compat[2] = {
629 "qemu,aplic", "riscv,aplic"
630 };
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000631
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000632 for (cpu = 0; cpu < num_harts; cpu++) {
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000633 aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
634 aplic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
635 }
636
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000637 qemu_fdt_add_subnode(ms->fdt, aplic_name);
Daniel Henrique Barboza362b31f2024-05-31 17:27:55 -0300638 qemu_fdt_setprop_string_array(ms->fdt, aplic_name, "compatible",
639 (char **)&aplic_compat,
640 ARRAY_SIZE(aplic_compat));
Daniel Henrique Barboza190e0ae2024-05-31 17:27:52 -0300641 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
642 FDT_APLIC_ADDR_CELLS);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000643 qemu_fdt_setprop_cell(ms->fdt, aplic_name,
644 "#interrupt-cells", FDT_APLIC_INT_CELLS);
645 qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
646
647 if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
648 qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000649 aplic_cells, num_harts * sizeof(uint32_t) * 2);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000650 } else {
651 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent", msi_phandle);
652 }
653
654 qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
655 0x0, aplic_addr, 0x0, aplic_size);
656 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
657 VIRT_IRQCHIP_NUM_SOURCES);
658
659 if (aplic_child_phandle) {
660 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
661 aplic_child_phandle);
Daniel Henrique Barbozab1f1e9d2024-05-31 17:27:56 -0300662 qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000663 aplic_child_phandle, 0x1,
664 VIRT_IRQCHIP_NUM_SOURCES);
Daniel Henrique Barboza38facfa2024-07-15 06:04:55 -0300665 /*
666 * DEPRECATED_9.1: Compat property kept temporarily
667 * to allow old firmwares to work with AIA. Do *not*
668 * use 'riscv,delegate' in new code: use
669 * 'riscv,delegation' instead.
670 */
671 qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
672 aplic_child_phandle, 0x1,
673 VIRT_IRQCHIP_NUM_SOURCES);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000674 }
675
676 riscv_socket_fdt_write_id(ms, aplic_name, socket);
677 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_phandle);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000678}
679
Anup Patel28d8c282022-02-20 14:25:24 +0530680static void create_fdt_socket_aplic(RISCVVirtState *s,
681 const MemMapEntry *memmap, int socket,
682 uint32_t msi_m_phandle,
683 uint32_t msi_s_phandle,
684 uint32_t *phandle,
685 uint32_t *intc_phandles,
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000686 uint32_t *aplic_phandles,
687 int num_harts)
Anup Patele6faee62022-02-20 14:25:22 +0530688{
Anup Patele6faee62022-02-20 14:25:22 +0530689 unsigned long aplic_addr;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300690 MachineState *ms = MACHINE(s);
Anup Patele6faee62022-02-20 14:25:22 +0530691 uint32_t aplic_m_phandle, aplic_s_phandle;
692
693 aplic_m_phandle = (*phandle)++;
694 aplic_s_phandle = (*phandle)++;
Anup Patele6faee62022-02-20 14:25:22 +0530695
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000696 if (!kvm_enabled()) {
697 /* M-level APLIC node */
698 aplic_addr = memmap[VIRT_APLIC_M].base +
699 (memmap[VIRT_APLIC_M].size * socket);
700 create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_M].size,
701 msi_m_phandle, intc_phandles,
702 aplic_m_phandle, aplic_s_phandle,
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000703 true, num_harts);
Anup Patele6faee62022-02-20 14:25:22 +0530704 }
Anup Patele6faee62022-02-20 14:25:22 +0530705
706 /* S-level APLIC node */
Anup Patele6faee62022-02-20 14:25:22 +0530707 aplic_addr = memmap[VIRT_APLIC_S].base +
708 (memmap[VIRT_APLIC_S].size * socket);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000709 create_fdt_one_aplic(s, socket, aplic_addr, memmap[VIRT_APLIC_S].size,
710 msi_s_phandle, intc_phandles,
711 aplic_s_phandle, 0,
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000712 false, num_harts);
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +0000713
Anup Pateld644e5e2022-05-11 20:15:28 +0530714 if (!socket) {
Daniel Henrique Barboza02dd57b2024-05-31 17:27:53 -0300715 g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300716 platform_bus_add_all_fdt_nodes(ms->fdt, aplic_name,
Anup Pateld644e5e2022-05-11 20:15:28 +0530717 memmap[VIRT_PLATFORM_BUS].base,
718 memmap[VIRT_PLATFORM_BUS].size,
719 VIRT_PLATFORM_BUS_IRQ);
720 }
Alistair Francis3029fab2022-04-28 09:41:44 +1000721
Anup Patele6faee62022-02-20 14:25:22 +0530722 aplic_phandles[socket] = aplic_s_phandle;
723}
724
Atish Patraabd9a202022-08-24 15:17:00 -0700725static void create_fdt_pmu(RISCVVirtState *s)
726{
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300727 g_autofree char *pmu_name = g_strdup_printf("/pmu");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300728 MachineState *ms = MACHINE(s);
Atish Patraabd9a202022-08-24 15:17:00 -0700729 RISCVCPU hart = s->soc[0].harts[0];
730
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300731 qemu_fdt_add_subnode(ms->fdt, pmu_name);
732 qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu");
Rob Bradford2571a642023-10-31 15:37:15 +0000733 riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name);
Atish Patraabd9a202022-08-24 15:17:00 -0700734}
735
Anup Patel0ffc1a92021-08-31 16:36:02 +0530736static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
Daniel Henrique Barboza914c97f2023-01-11 14:09:42 -0300737 uint32_t *phandle,
Anup Patel0ffc1a92021-08-31 16:36:02 +0530738 uint32_t *irq_mmio_phandle,
739 uint32_t *irq_pcie_phandle,
Anup Patel28d8c282022-02-20 14:25:24 +0530740 uint32_t *irq_virtio_phandle,
741 uint32_t *msi_pcie_phandle)
Anup Patel0ffc1a92021-08-31 16:36:02 +0530742{
Anup Patel28d8c282022-02-20 14:25:24 +0530743 int socket, phandle_pos;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300744 MachineState *ms = MACHINE(s);
Anup Patel28d8c282022-02-20 14:25:24 +0530745 uint32_t msi_m_phandle = 0, msi_s_phandle = 0;
Daniel Henrique Barboza5d0e3bc2024-01-22 19:15:26 -0300746 uint32_t xplic_phandles[MAX_NODES];
747 g_autofree uint32_t *intc_phandles = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300748 int socket_count = riscv_socket_count(ms);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530749
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300750 qemu_fdt_add_subnode(ms->fdt, "/cpus");
751 qemu_fdt_setprop_cell(ms->fdt, "/cpus", "timebase-frequency",
Yong-Xuan Wang385e5752024-03-14 14:15:09 +0800752 kvm_enabled() ?
753 kvm_riscv_get_timebase_frequency(first_cpu) :
Anup Patelb8fb8782021-08-31 16:36:01 +0530754 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300755 qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
756 qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1);
757 qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map");
Anup Patel18df0b42020-05-15 14:58:50 +0530758
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300759 intc_phandles = g_new0(uint32_t, ms->smp.cpus);
Anup Patel28d8c282022-02-20 14:25:24 +0530760
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300761 phandle_pos = ms->smp.cpus;
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -0300762 for (socket = (socket_count - 1); socket >= 0; socket--) {
Daniel Henrique Barboza5d0e3bc2024-01-22 19:15:26 -0300763 g_autofree char *clust_name = NULL;
Anup Patel28d8c282022-02-20 14:25:24 +0530764 phandle_pos -= s->soc[socket].num_harts;
765
Anup Patel18df0b42020-05-15 14:58:50 +0530766 clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300767 qemu_fdt_add_subnode(ms->fdt, clust_name);
Anup Patel18df0b42020-05-15 14:58:50 +0530768
Anup Patel0ffc1a92021-08-31 16:36:02 +0530769 create_fdt_socket_cpus(s, socket, clust_name, phandle,
Daniel Henrique Barboza914c97f2023-01-11 14:09:42 -0300770 &intc_phandles[phandle_pos]);
Anup Patel18df0b42020-05-15 14:58:50 +0530771
Anup Patel0ffc1a92021-08-31 16:36:02 +0530772 create_fdt_socket_memory(s, memmap, socket);
Anup Patel18df0b42020-05-15 14:58:50 +0530773
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -0300774 if (virt_aclint_allowed() && s->have_aclint) {
775 create_fdt_socket_aclint(s, memmap, socket,
776 &intc_phandles[phandle_pos]);
777 } else if (tcg_enabled()) {
778 create_fdt_socket_clint(s, memmap, socket,
779 &intc_phandles[phandle_pos]);
Anup Patel954886e2021-08-31 16:36:03 +0530780 }
Anup Patel28d8c282022-02-20 14:25:24 +0530781 }
782
783 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
784 create_fdt_imsic(s, memmap, phandle, intc_phandles,
785 &msi_m_phandle, &msi_s_phandle);
786 *msi_pcie_phandle = msi_s_phandle;
787 }
788
Daniel Henrique Barbozab319ef12024-11-19 16:17:03 -0300789 /*
790 * With KVM AIA aplic-imsic, using an irqchip without split
791 * mode, we'll use only one APLIC instance.
792 */
793 if (!virt_use_emulated_aplic(s->aia_type)) {
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000794 create_fdt_socket_aplic(s, memmap, 0,
795 msi_m_phandle, msi_s_phandle, phandle,
796 &intc_phandles[0], xplic_phandles,
797 ms->smp.cpus);
Daniel Henrique Barboza01948b12024-11-19 16:17:00 -0300798
799 *irq_mmio_phandle = xplic_phandles[0];
800 *irq_virtio_phandle = xplic_phandles[0];
801 *irq_pcie_phandle = xplic_phandles[0];
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000802 } else {
803 phandle_pos = ms->smp.cpus;
804 for (socket = (socket_count - 1); socket >= 0; socket--) {
805 phandle_pos -= s->soc[socket].num_harts;
Anup Patel18df0b42020-05-15 14:58:50 +0530806
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000807 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
808 create_fdt_socket_plic(s, memmap, socket, phandle,
809 &intc_phandles[phandle_pos],
810 xplic_phandles);
811 } else {
812 create_fdt_socket_aplic(s, memmap, socket,
813 msi_m_phandle, msi_s_phandle, phandle,
814 &intc_phandles[phandle_pos],
815 xplic_phandles,
816 s->soc[socket].num_harts);
817 }
Anup Patele6faee62022-02-20 14:25:22 +0530818 }
Atish Patra28a4df92019-06-24 16:41:44 -0700819
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +0000820 for (socket = 0; socket < socket_count; socket++) {
821 if (socket == 0) {
822 *irq_mmio_phandle = xplic_phandles[socket];
823 *irq_virtio_phandle = xplic_phandles[socket];
824 *irq_pcie_phandle = xplic_phandles[socket];
825 }
826 if (socket == 1) {
827 *irq_virtio_phandle = xplic_phandles[socket];
828 *irq_pcie_phandle = xplic_phandles[socket];
829 }
830 if (socket == 2) {
831 *irq_pcie_phandle = xplic_phandles[socket];
832 }
Anup Patel18df0b42020-05-15 14:58:50 +0530833 }
Michael Clark04331d02018-03-03 01:31:13 +1300834 }
Michael Clark04331d02018-03-03 01:31:13 +1300835
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300836 riscv_socket_fdt_write_distance_matrix(ms);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530837}
838
839static void create_fdt_virtio(RISCVVirtState *s, const MemMapEntry *memmap,
840 uint32_t irq_virtio_phandle)
841{
842 int i;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300843 MachineState *ms = MACHINE(s);
Michael Clark04331d02018-03-03 01:31:13 +1300844
845 for (i = 0; i < VIRTIO_COUNT; i++) {
Daniel Henrique Barboza1d873c62024-01-22 19:15:27 -0300846 g_autofree char *name = g_strdup_printf("/soc/virtio_mmio@%lx",
Michael Clark04331d02018-03-03 01:31:13 +1300847 (long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size));
Daniel Henrique Barboza1d873c62024-01-22 19:15:27 -0300848
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300849 qemu_fdt_add_subnode(ms->fdt, name);
850 qemu_fdt_setprop_string(ms->fdt, name, "compatible", "virtio,mmio");
851 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Michael Clark04331d02018-03-03 01:31:13 +1300852 0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
853 0x0, memmap[VIRT_VIRTIO].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300854 qemu_fdt_setprop_cell(ms->fdt, name, "interrupt-parent",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530855 irq_virtio_phandle);
Anup Patele6faee62022-02-20 14:25:22 +0530856 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300857 qemu_fdt_setprop_cell(ms->fdt, name, "interrupts",
Anup Patele6faee62022-02-20 14:25:22 +0530858 VIRTIO_IRQ + i);
859 } else {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300860 qemu_fdt_setprop_cells(ms->fdt, name, "interrupts",
Anup Patele6faee62022-02-20 14:25:22 +0530861 VIRTIO_IRQ + i, 0x4);
862 }
Michael Clark04331d02018-03-03 01:31:13 +1300863 }
Anup Patel0ffc1a92021-08-31 16:36:02 +0530864}
865
866static void create_fdt_pcie(RISCVVirtState *s, const MemMapEntry *memmap,
Anup Patel28d8c282022-02-20 14:25:24 +0530867 uint32_t irq_pcie_phandle,
Sunil V L2c12de12024-11-06 10:34:04 -0300868 uint32_t msi_pcie_phandle,
869 uint32_t iommu_sys_phandle)
Anup Patel0ffc1a92021-08-31 16:36:02 +0530870{
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300871 g_autofree char *name = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300872 MachineState *ms = MACHINE(s);
Michael Clark04331d02018-03-03 01:31:13 +1300873
Anup Patel18df0b42020-05-15 14:58:50 +0530874 name = g_strdup_printf("/soc/pci@%lx",
Alistair Francis6d56e392018-12-11 22:37:36 +0000875 (long) memmap[VIRT_PCIE_ECAM].base);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300876 qemu_fdt_setprop_cell(ms->fdt, name, "#address-cells",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530877 FDT_PCI_ADDR_CELLS);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300878 qemu_fdt_setprop_cell(ms->fdt, name, "#interrupt-cells",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530879 FDT_PCI_INT_CELLS);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300880 qemu_fdt_setprop_cell(ms->fdt, name, "#size-cells", 0x2);
881 qemu_fdt_setprop_string(ms->fdt, name, "compatible",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530882 "pci-host-ecam-generic");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300883 qemu_fdt_setprop_string(ms->fdt, name, "device_type", "pci");
884 qemu_fdt_setprop_cell(ms->fdt, name, "linux,pci-domain", 0);
885 qemu_fdt_setprop_cells(ms->fdt, name, "bus-range", 0,
Anup Patel18df0b42020-05-15 14:58:50 +0530886 memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300887 qemu_fdt_setprop(ms->fdt, name, "dma-coherent", NULL, 0);
Anup Patel28d8c282022-02-20 14:25:24 +0530888 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300889 qemu_fdt_setprop_cell(ms->fdt, name, "msi-parent", msi_pcie_phandle);
Anup Patel28d8c282022-02-20 14:25:24 +0530890 }
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300891 qemu_fdt_setprop_cells(ms->fdt, name, "reg", 0,
Anup Patel18df0b42020-05-15 14:58:50 +0530892 memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300893 qemu_fdt_setprop_sized_cells(ms->fdt, name, "ranges",
Alistair Francis6d56e392018-12-11 22:37:36 +0000894 1, FDT_PCI_RANGE_IOPORT, 2, 0,
895 2, memmap[VIRT_PCIE_PIO].base, 2, memmap[VIRT_PCIE_PIO].size,
896 1, FDT_PCI_RANGE_MMIO,
897 2, memmap[VIRT_PCIE_MMIO].base,
Bin Meng19800262021-02-20 22:48:07 +0800898 2, memmap[VIRT_PCIE_MMIO].base, 2, memmap[VIRT_PCIE_MMIO].size,
899 1, FDT_PCI_RANGE_MMIO_64BIT,
900 2, virt_high_pcie_memmap.base,
901 2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size);
902
Sunil V L2c12de12024-11-06 10:34:04 -0300903 if (virt_is_iommu_sys_enabled(s)) {
904 qemu_fdt_setprop_cells(ms->fdt, name, "iommu-map",
905 0, iommu_sys_phandle, 0, 0, 0,
906 iommu_sys_phandle, 0, 0xffff);
907 }
908
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300909 create_pcie_irq_map(s, ms->fdt, name, irq_pcie_phandle);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530910}
Alistair Francis6d56e392018-12-11 22:37:36 +0000911
Anup Patel0ffc1a92021-08-31 16:36:02 +0530912static void create_fdt_reset(RISCVVirtState *s, const MemMapEntry *memmap,
913 uint32_t *phandle)
914{
915 char *name;
916 uint32_t test_phandle;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300917 MachineState *ms = MACHINE(s);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530918
919 test_phandle = (*phandle)++;
Anup Patel18df0b42020-05-15 14:58:50 +0530920 name = g_strdup_printf("/soc/test@%lx",
Michael Clark04331d02018-03-03 01:31:13 +1300921 (long)memmap[VIRT_TEST].base);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300922 qemu_fdt_add_subnode(ms->fdt, name);
Palmer Dabbelt9c0fb202019-11-07 14:25:00 -0800923 {
Bin Meng2cc04552021-04-30 15:12:56 +0800924 static const char * const compat[3] = {
925 "sifive,test1", "sifive,test0", "syscon"
926 };
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300927 qemu_fdt_setprop_string_array(ms->fdt, name, "compatible",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530928 (char **)&compat, ARRAY_SIZE(compat));
Palmer Dabbelt9c0fb202019-11-07 14:25:00 -0800929 }
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300930 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530931 0x0, memmap[VIRT_TEST].base, 0x0, memmap[VIRT_TEST].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300932 qemu_fdt_setprop_cell(ms->fdt, name, "phandle", test_phandle);
933 test_phandle = qemu_fdt_get_phandle(ms->fdt, name);
Anup Patel18df0b42020-05-15 14:58:50 +0530934 g_free(name);
Anup Patel0e404da2020-01-22 13:17:23 +0000935
Conor Dooleyae293792022-08-10 19:46:11 +0100936 name = g_strdup_printf("/reboot");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300937 qemu_fdt_add_subnode(ms->fdt, name);
938 qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-reboot");
939 qemu_fdt_setprop_cell(ms->fdt, name, "regmap", test_phandle);
940 qemu_fdt_setprop_cell(ms->fdt, name, "offset", 0x0);
941 qemu_fdt_setprop_cell(ms->fdt, name, "value", FINISHER_RESET);
Anup Patel18df0b42020-05-15 14:58:50 +0530942 g_free(name);
Anup Patel0e404da2020-01-22 13:17:23 +0000943
Conor Dooleyae293792022-08-10 19:46:11 +0100944 name = g_strdup_printf("/poweroff");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300945 qemu_fdt_add_subnode(ms->fdt, name);
946 qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-poweroff");
947 qemu_fdt_setprop_cell(ms->fdt, name, "regmap", test_phandle);
948 qemu_fdt_setprop_cell(ms->fdt, name, "offset", 0x0);
949 qemu_fdt_setprop_cell(ms->fdt, name, "value", FINISHER_PASS);
Anup Patel18df0b42020-05-15 14:58:50 +0530950 g_free(name);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530951}
952
953static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
954 uint32_t irq_mmio_phandle)
955{
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300956 g_autofree char *name = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300957 MachineState *ms = MACHINE(s);
Michael Clark04331d02018-03-03 01:31:13 +1300958
Conor Dooley53c38f72022-08-10 19:46:09 +0100959 name = g_strdup_printf("/soc/serial@%lx", (long)memmap[VIRT_UART0].base);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300960 qemu_fdt_add_subnode(ms->fdt, name);
961 qemu_fdt_setprop_string(ms->fdt, name, "compatible", "ns16550a");
962 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Michael Clark04331d02018-03-03 01:31:13 +1300963 0x0, memmap[VIRT_UART0].base,
964 0x0, memmap[VIRT_UART0].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300965 qemu_fdt_setprop_cell(ms->fdt, name, "clock-frequency", 3686400);
966 qemu_fdt_setprop_cell(ms->fdt, name, "interrupt-parent", irq_mmio_phandle);
Anup Patele6faee62022-02-20 14:25:22 +0530967 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300968 qemu_fdt_setprop_cell(ms->fdt, name, "interrupts", UART0_IRQ);
Anup Patele6faee62022-02-20 14:25:22 +0530969 } else {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300970 qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", UART0_IRQ, 0x4);
Anup Patele6faee62022-02-20 14:25:22 +0530971 }
Michael Clark04331d02018-03-03 01:31:13 +1300972
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300973 qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name);
Anup Patel0ffc1a92021-08-31 16:36:02 +0530974}
975
976static void create_fdt_rtc(RISCVVirtState *s, const MemMapEntry *memmap,
977 uint32_t irq_mmio_phandle)
978{
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -0300979 g_autofree char *name = NULL;
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300980 MachineState *ms = MACHINE(s);
Alistair Francis71eb5222019-10-08 16:32:25 -0700981
Anup Patel18df0b42020-05-15 14:58:50 +0530982 name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300983 qemu_fdt_add_subnode(ms->fdt, name);
984 qemu_fdt_setprop_string(ms->fdt, name, "compatible",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530985 "google,goldfish-rtc");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300986 qemu_fdt_setprop_cells(ms->fdt, name, "reg",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530987 0x0, memmap[VIRT_RTC].base, 0x0, memmap[VIRT_RTC].size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300988 qemu_fdt_setprop_cell(ms->fdt, name, "interrupt-parent",
Anup Patel0ffc1a92021-08-31 16:36:02 +0530989 irq_mmio_phandle);
Anup Patele6faee62022-02-20 14:25:22 +0530990 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300991 qemu_fdt_setprop_cell(ms->fdt, name, "interrupts", RTC_IRQ);
Anup Patele6faee62022-02-20 14:25:22 +0530992 } else {
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300993 qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", RTC_IRQ, 0x4);
Anup Patele6faee62022-02-20 14:25:22 +0530994 }
Anup Patel0ffc1a92021-08-31 16:36:02 +0530995}
996
997static void create_fdt_flash(RISCVVirtState *s, const MemMapEntry *memmap)
998{
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -0300999 MachineState *ms = MACHINE(s);
Anup Patel0ffc1a92021-08-31 16:36:02 +05301000 hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
1001 hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -03001002 g_autofree char *name = g_strdup_printf("/flash@%" PRIx64, flashbase);
Anup Patel67b5ef32019-11-06 11:56:43 +00001003
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001004 qemu_fdt_add_subnode(ms->fdt, name);
1005 qemu_fdt_setprop_string(ms->fdt, name, "compatible", "cfi-flash");
1006 qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg",
Alistair Francis71eb5222019-10-08 16:32:25 -07001007 2, flashbase, 2, flashsize,
1008 2, flashbase + flashsize, 2, flashsize);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001009 qemu_fdt_setprop_cell(ms->fdt, name, "bank-width", 4);
Anup Patel0ffc1a92021-08-31 16:36:02 +05301010}
1011
Atish Patraf9a461b2022-05-26 13:35:00 -07001012static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap)
1013{
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001014 MachineState *ms = MACHINE(s);
Atish Patraf9a461b2022-05-26 13:35:00 -07001015 hwaddr base = memmap[VIRT_FW_CFG].base;
1016 hwaddr size = memmap[VIRT_FW_CFG].size;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -03001017 g_autofree char *nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
Atish Patraf9a461b2022-05-26 13:35:00 -07001018
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001019 qemu_fdt_add_subnode(ms->fdt, nodename);
1020 qemu_fdt_setprop_string(ms->fdt, nodename,
Atish Patraf9a461b2022-05-26 13:35:00 -07001021 "compatible", "qemu,fw-cfg-mmio");
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001022 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
Atish Patraf9a461b2022-05-26 13:35:00 -07001023 2, base, 2, size);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001024 qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
Atish Patraf9a461b2022-05-26 13:35:00 -07001025}
1026
Daniel Henrique Barboza7778cdd2024-02-17 16:26:05 -03001027static void create_fdt_virtio_iommu(RISCVVirtState *s, uint16_t bdf)
1028{
1029 const char compat[] = "virtio,pci-iommu\0pci1af4,1057";
1030 void *fdt = MACHINE(s)->fdt;
1031 uint32_t iommu_phandle;
1032 g_autofree char *iommu_node = NULL;
1033 g_autofree char *pci_node = NULL;
1034
1035 pci_node = g_strdup_printf("/soc/pci@%lx",
1036 (long) virt_memmap[VIRT_PCIE_ECAM].base);
1037 iommu_node = g_strdup_printf("%s/virtio_iommu@%x,%x", pci_node,
1038 PCI_SLOT(bdf), PCI_FUNC(bdf));
1039 iommu_phandle = qemu_fdt_alloc_phandle(fdt);
1040
1041 qemu_fdt_add_subnode(fdt, iommu_node);
1042
1043 qemu_fdt_setprop(fdt, iommu_node, "compatible", compat, sizeof(compat));
1044 qemu_fdt_setprop_sized_cells(fdt, iommu_node, "reg",
1045 1, bdf << 8, 1, 0, 1, 0,
1046 1, 0, 1, 0);
1047 qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
1048 qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
1049
1050 qemu_fdt_setprop_cells(fdt, pci_node, "iommu-map",
1051 0, iommu_phandle, 0, bdf,
1052 bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf);
1053}
1054
Sunil V L2c12de12024-11-06 10:34:04 -03001055static void create_fdt_iommu_sys(RISCVVirtState *s, uint32_t irq_chip,
Daniel Henrique Barboza01c1caa2024-11-06 10:34:05 -03001056 uint32_t msi_phandle,
Sunil V L2c12de12024-11-06 10:34:04 -03001057 uint32_t *iommu_sys_phandle)
1058{
1059 const char comp[] = "riscv,iommu";
1060 void *fdt = MACHINE(s)->fdt;
1061 uint32_t iommu_phandle;
1062 g_autofree char *iommu_node = NULL;
1063 hwaddr addr = s->memmap[VIRT_IOMMU_SYS].base;
1064 hwaddr size = s->memmap[VIRT_IOMMU_SYS].size;
1065 uint32_t iommu_irq_map[RISCV_IOMMU_INTR_COUNT] = {
1066 IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_CQ,
1067 IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_FQ,
1068 IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PM,
1069 IOMMU_SYS_IRQ + RISCV_IOMMU_INTR_PQ,
1070 };
1071
1072 iommu_node = g_strdup_printf("/soc/iommu@%x",
1073 (unsigned int) s->memmap[VIRT_IOMMU_SYS].base);
1074 iommu_phandle = qemu_fdt_alloc_phandle(fdt);
1075 qemu_fdt_add_subnode(fdt, iommu_node);
1076
1077 qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
1078 qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
1079 qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
1080
1081 qemu_fdt_setprop_cells(fdt, iommu_node, "reg",
1082 addr >> 32, addr, size >> 32, size);
1083 qemu_fdt_setprop_cell(fdt, iommu_node, "interrupt-parent", irq_chip);
1084
1085 qemu_fdt_setprop_cells(fdt, iommu_node, "interrupts",
1086 iommu_irq_map[0], FDT_IRQ_TYPE_EDGE_LOW,
1087 iommu_irq_map[1], FDT_IRQ_TYPE_EDGE_LOW,
1088 iommu_irq_map[2], FDT_IRQ_TYPE_EDGE_LOW,
1089 iommu_irq_map[3], FDT_IRQ_TYPE_EDGE_LOW);
1090
Daniel Henrique Barboza01c1caa2024-11-06 10:34:05 -03001091 qemu_fdt_setprop_cell(fdt, iommu_node, "msi-parent", msi_phandle);
1092
Sunil V L2c12de12024-11-06 10:34:04 -03001093 *iommu_sys_phandle = iommu_phandle;
1094}
1095
Tomasz Jeznachdf240d62024-10-16 17:40:30 -03001096static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf)
1097{
1098 const char comp[] = "riscv,pci-iommu";
1099 void *fdt = MACHINE(s)->fdt;
1100 uint32_t iommu_phandle;
1101 g_autofree char *iommu_node = NULL;
1102 g_autofree char *pci_node = NULL;
1103
1104 pci_node = g_strdup_printf("/soc/pci@%lx",
1105 (long) virt_memmap[VIRT_PCIE_ECAM].base);
1106 iommu_node = g_strdup_printf("%s/iommu@%x", pci_node, bdf);
1107 iommu_phandle = qemu_fdt_alloc_phandle(fdt);
1108 qemu_fdt_add_subnode(fdt, iommu_node);
1109
1110 qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
1111 qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
1112 qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
1113 qemu_fdt_setprop_cells(fdt, iommu_node, "reg",
1114 bdf << 8, 0, 0, 0, 0);
1115 qemu_fdt_setprop_cells(fdt, pci_node, "iommu-map",
1116 0, iommu_phandle, 0, bdf,
1117 bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf);
1118}
1119
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001120static void finalize_fdt(RISCVVirtState *s)
1121{
1122 uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
1123 uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
Sunil V L2c12de12024-11-06 10:34:04 -03001124 uint32_t iommu_sys_phandle = 1;
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001125
1126 create_fdt_sockets(s, virt_memmap, &phandle, &irq_mmio_phandle,
1127 &irq_pcie_phandle, &irq_virtio_phandle,
1128 &msi_pcie_phandle);
1129
1130 create_fdt_virtio(s, virt_memmap, irq_virtio_phandle);
1131
Sunil V L2c12de12024-11-06 10:34:04 -03001132 if (virt_is_iommu_sys_enabled(s)) {
Daniel Henrique Barboza01c1caa2024-11-06 10:34:05 -03001133 create_fdt_iommu_sys(s, irq_mmio_phandle, msi_pcie_phandle,
1134 &iommu_sys_phandle);
Sunil V L2c12de12024-11-06 10:34:04 -03001135 }
1136 create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle,
1137 iommu_sys_phandle);
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001138
1139 create_fdt_reset(s, virt_memmap, &phandle);
1140
1141 create_fdt_uart(s, virt_memmap, irq_mmio_phandle);
1142
1143 create_fdt_rtc(s, virt_memmap, irq_mmio_phandle);
1144}
1145
Daniel Henrique Barboza914c97f2023-01-11 14:09:42 -03001146static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
Anup Patel0ffc1a92021-08-31 16:36:02 +05301147{
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001148 MachineState *ms = MACHINE(s);
Jason A. Donenfelde4b4f0b2022-06-13 13:58:10 +02001149 uint8_t rng_seed[32];
Daniel Henrique Barboza3fe88962024-02-17 16:26:04 -03001150 g_autofree char *name = NULL;
Anup Patel0ffc1a92021-08-31 16:36:02 +05301151
Bin Mengfc9ec362023-02-28 15:45:22 +08001152 ms->fdt = create_device_tree(&s->fdt_size);
1153 if (!ms->fdt) {
1154 error_report("create_device_tree() failed");
1155 exit(1);
Anup Patel0ffc1a92021-08-31 16:36:02 +05301156 }
1157
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001158 qemu_fdt_setprop_string(ms->fdt, "/", "model", "riscv-virtio,qemu");
1159 qemu_fdt_setprop_string(ms->fdt, "/", "compatible", "riscv-virtio");
1160 qemu_fdt_setprop_cell(ms->fdt, "/", "#size-cells", 0x2);
1161 qemu_fdt_setprop_cell(ms->fdt, "/", "#address-cells", 0x2);
Anup Patel0ffc1a92021-08-31 16:36:02 +05301162
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001163 qemu_fdt_add_subnode(ms->fdt, "/soc");
1164 qemu_fdt_setprop(ms->fdt, "/soc", "ranges", NULL, 0);
1165 qemu_fdt_setprop_string(ms->fdt, "/soc", "compatible", "simple-bus");
1166 qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2);
1167 qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2);
Anup Patel0ffc1a92021-08-31 16:36:02 +05301168
Daniel Henrique Barboza3fe88962024-02-17 16:26:04 -03001169 /*
1170 * The "/soc/pci@..." node is needed for PCIE hotplugs
1171 * that might happen before finalize_fdt().
1172 */
1173 name = g_strdup_printf("/soc/pci@%lx", (long) memmap[VIRT_PCIE_ECAM].base);
1174 qemu_fdt_add_subnode(ms->fdt, name);
1175
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001176 qemu_fdt_add_subnode(ms->fdt, "/chosen");
Anup Patel4e1e3002020-10-22 11:02:25 +05301177
Jason A. Donenfelde4b4f0b2022-06-13 13:58:10 +02001178 /* Pass seed to RNG */
1179 qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001180 qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed",
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -03001181 rng_seed, sizeof(rng_seed));
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001182
1183 create_fdt_flash(s, memmap);
1184 create_fdt_fw_cfg(s, memmap);
1185 create_fdt_pmu(s);
Michael Clark04331d02018-03-03 01:31:13 +13001186}
1187
Alistair Francis6d56e392018-12-11 22:37:36 +00001188static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
Sunil V Le86e9522023-12-18 20:32:45 +05301189 DeviceState *irqchip,
1190 RISCVVirtState *s)
Alistair Francis6d56e392018-12-11 22:37:36 +00001191{
1192 DeviceState *dev;
1193 MemoryRegion *ecam_alias, *ecam_reg;
Bin Meng19800262021-02-20 22:48:07 +08001194 MemoryRegion *mmio_alias, *high_mmio_alias, *mmio_reg;
Sunil V Le86e9522023-12-18 20:32:45 +05301195 hwaddr ecam_base = s->memmap[VIRT_PCIE_ECAM].base;
1196 hwaddr ecam_size = s->memmap[VIRT_PCIE_ECAM].size;
1197 hwaddr mmio_base = s->memmap[VIRT_PCIE_MMIO].base;
1198 hwaddr mmio_size = s->memmap[VIRT_PCIE_MMIO].size;
1199 hwaddr high_mmio_base = virt_high_pcie_memmap.base;
1200 hwaddr high_mmio_size = virt_high_pcie_memmap.size;
1201 hwaddr pio_base = s->memmap[VIRT_PCIE_PIO].base;
1202 hwaddr pio_size = s->memmap[VIRT_PCIE_PIO].size;
Alistair Francis6d56e392018-12-11 22:37:36 +00001203 qemu_irq irq;
1204 int i;
1205
Markus Armbruster3e80f692020-06-10 07:31:58 +02001206 dev = qdev_new(TYPE_GPEX_HOST);
Alistair Francis6d56e392018-12-11 22:37:36 +00001207
Sunil V Le86e9522023-12-18 20:32:45 +05301208 /* Set GPEX object properties for the virt machine */
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001209 object_property_set_uint(OBJECT(dev), PCI_HOST_ECAM_BASE,
Sunil V Le86e9522023-12-18 20:32:45 +05301210 ecam_base, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001211 object_property_set_int(OBJECT(dev), PCI_HOST_ECAM_SIZE,
Sunil V Le86e9522023-12-18 20:32:45 +05301212 ecam_size, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001213 object_property_set_uint(OBJECT(dev), PCI_HOST_BELOW_4G_MMIO_BASE,
Sunil V Le86e9522023-12-18 20:32:45 +05301214 mmio_base, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001215 object_property_set_int(OBJECT(dev), PCI_HOST_BELOW_4G_MMIO_SIZE,
Sunil V Le86e9522023-12-18 20:32:45 +05301216 mmio_size, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001217 object_property_set_uint(OBJECT(dev), PCI_HOST_ABOVE_4G_MMIO_BASE,
Sunil V Le86e9522023-12-18 20:32:45 +05301218 high_mmio_base, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001219 object_property_set_int(OBJECT(dev), PCI_HOST_ABOVE_4G_MMIO_SIZE,
Sunil V Le86e9522023-12-18 20:32:45 +05301220 high_mmio_size, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001221 object_property_set_uint(OBJECT(dev), PCI_HOST_PIO_BASE,
Sunil V Le86e9522023-12-18 20:32:45 +05301222 pio_base, NULL);
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001223 object_property_set_int(OBJECT(dev), PCI_HOST_PIO_SIZE,
Sunil V Le86e9522023-12-18 20:32:45 +05301224 pio_size, NULL);
1225
Markus Armbruster3c6ef472020-06-10 07:32:34 +02001226 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
Alistair Francis6d56e392018-12-11 22:37:36 +00001227
1228 ecam_alias = g_new0(MemoryRegion, 1);
1229 ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
1230 memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
1231 ecam_reg, 0, ecam_size);
1232 memory_region_add_subregion(get_system_memory(), ecam_base, ecam_alias);
1233
1234 mmio_alias = g_new0(MemoryRegion, 1);
1235 mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
1236 memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
1237 mmio_reg, mmio_base, mmio_size);
1238 memory_region_add_subregion(get_system_memory(), mmio_base, mmio_alias);
1239
Bin Meng19800262021-02-20 22:48:07 +08001240 /* Map high MMIO space */
1241 high_mmio_alias = g_new0(MemoryRegion, 1);
1242 memory_region_init_alias(high_mmio_alias, OBJECT(dev), "pcie-mmio-high",
1243 mmio_reg, high_mmio_base, high_mmio_size);
1244 memory_region_add_subregion(get_system_memory(), high_mmio_base,
1245 high_mmio_alias);
1246
Alistair Francis6d56e392018-12-11 22:37:36 +00001247 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base);
1248
Alexander Grafff871d02023-06-14 22:56:24 +00001249 for (i = 0; i < PCI_NUM_PINS; i++) {
Anup Patele6faee62022-02-20 14:25:22 +05301250 irq = qdev_get_gpio_in(irqchip, PCIE_IRQ + i);
Alistair Francis6d56e392018-12-11 22:37:36 +00001251
1252 sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
1253 gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i);
1254 }
1255
Philippe Mathieu-Daudé37bae932024-11-25 14:07:25 +01001256 GPEX_HOST(dev)->gpex_cfg.bus = PCI_HOST_BRIDGE(dev)->bus;
Alistair Francis6d56e392018-12-11 22:37:36 +00001257 return dev;
1258}
1259
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001260static FWCfgState *create_fw_cfg(const MachineState *ms)
Asherah Connor04893482021-03-19 10:50:40 +11001261{
1262 hwaddr base = virt_memmap[VIRT_FW_CFG].base;
Asherah Connor04893482021-03-19 10:50:40 +11001263 FWCfgState *fw_cfg;
Asherah Connor04893482021-03-19 10:50:40 +11001264
1265 fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16,
1266 &address_space_memory);
Daniel Henrique Barboza568e0612023-01-24 18:22:33 -03001267 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
Asherah Connor04893482021-03-19 10:50:40 +11001268
Asherah Connor04893482021-03-19 10:50:40 +11001269 return fw_cfg;
1270}
1271
Anup Patele6faee62022-02-20 14:25:22 +05301272static DeviceState *virt_create_plic(const MemMapEntry *memmap, int socket,
1273 int base_hartid, int hart_count)
1274{
1275 DeviceState *ret;
Daniel Henrique Barboza5fb20f72024-01-22 19:15:29 -03001276 g_autofree char *plic_hart_config = NULL;
Anup Patele6faee62022-02-20 14:25:22 +05301277
1278 /* Per-socket PLIC hart topology configuration string */
1279 plic_hart_config = riscv_plic_hart_config_string(hart_count);
1280
1281 /* Per-socket PLIC */
1282 ret = sifive_plic_create(
1283 memmap[VIRT_PLIC].base + socket * memmap[VIRT_PLIC].size,
1284 plic_hart_config, hart_count, base_hartid,
1285 VIRT_IRQCHIP_NUM_SOURCES,
1286 ((1U << VIRT_IRQCHIP_NUM_PRIO_BITS) - 1),
1287 VIRT_PLIC_PRIORITY_BASE,
1288 VIRT_PLIC_PENDING_BASE,
1289 VIRT_PLIC_ENABLE_BASE,
1290 VIRT_PLIC_ENABLE_STRIDE,
1291 VIRT_PLIC_CONTEXT_BASE,
1292 VIRT_PLIC_CONTEXT_STRIDE,
1293 memmap[VIRT_PLIC].size);
1294
Anup Patele6faee62022-02-20 14:25:22 +05301295 return ret;
1296}
1297
Anup Patel28d8c282022-02-20 14:25:24 +05301298static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
Anup Patele6faee62022-02-20 14:25:22 +05301299 const MemMapEntry *memmap, int socket,
1300 int base_hartid, int hart_count)
1301{
Anup Patel28d8c282022-02-20 14:25:24 +05301302 int i;
Daniel Henrique Barbozae0c87e32024-11-19 16:17:04 -03001303 hwaddr addr = 0;
Anup Patel28d8c282022-02-20 14:25:24 +05301304 uint32_t guest_bits;
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +00001305 DeviceState *aplic_s = NULL;
1306 DeviceState *aplic_m = NULL;
1307 bool msimode = aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
Anup Patel28d8c282022-02-20 14:25:24 +05301308
1309 if (msimode) {
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +00001310 if (!kvm_enabled()) {
1311 /* Per-socket M-level IMSICs */
1312 addr = memmap[VIRT_IMSIC_M].base +
1313 socket * VIRT_IMSIC_GROUP_MAX_SIZE;
1314 for (i = 0; i < hart_count; i++) {
1315 riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
1316 base_hartid + i, true, 1,
1317 VIRT_IRQCHIP_NUM_MSIS);
1318 }
Anup Patel28d8c282022-02-20 14:25:24 +05301319 }
1320
1321 /* Per-socket S-level IMSICs */
1322 guest_bits = imsic_num_bits(aia_guests + 1);
1323 addr = memmap[VIRT_IMSIC_S].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
1324 for (i = 0; i < hart_count; i++) {
1325 riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
1326 base_hartid + i, false, 1 + aia_guests,
1327 VIRT_IRQCHIP_NUM_MSIS);
1328 }
1329 }
Anup Patele6faee62022-02-20 14:25:22 +05301330
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +00001331 if (!kvm_enabled()) {
1332 /* Per-socket M-level APLIC */
1333 aplic_m = riscv_aplic_create(memmap[VIRT_APLIC_M].base +
1334 socket * memmap[VIRT_APLIC_M].size,
1335 memmap[VIRT_APLIC_M].size,
1336 (msimode) ? 0 : base_hartid,
1337 (msimode) ? 0 : hart_count,
1338 VIRT_IRQCHIP_NUM_SOURCES,
1339 VIRT_IRQCHIP_NUM_PRIO_BITS,
1340 msimode, true, NULL);
Anup Patele6faee62022-02-20 14:25:22 +05301341 }
1342
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +00001343 /* Per-socket S-level APLIC */
1344 aplic_s = riscv_aplic_create(memmap[VIRT_APLIC_S].base +
1345 socket * memmap[VIRT_APLIC_S].size,
1346 memmap[VIRT_APLIC_S].size,
1347 (msimode) ? 0 : base_hartid,
1348 (msimode) ? 0 : hart_count,
1349 VIRT_IRQCHIP_NUM_SOURCES,
1350 VIRT_IRQCHIP_NUM_PRIO_BITS,
1351 msimode, false, aplic_m);
1352
Daniel Henrique Barbozae0c87e32024-11-19 16:17:04 -03001353 if (kvm_enabled() && msimode) {
1354 riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s), addr);
1355 }
1356
Yong-Xuan Wang59a07d32023-07-27 10:24:33 +00001357 return kvm_enabled() ? aplic_s : aplic_m;
Anup Patele6faee62022-02-20 14:25:22 +05301358}
1359
Alistair Francis1832b7c2022-04-28 09:41:43 +10001360static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
1361{
1362 DeviceState *dev;
1363 SysBusDevice *sysbus;
1364 const MemMapEntry *memmap = virt_memmap;
1365 int i;
1366 MemoryRegion *sysmem = get_system_memory();
1367
1368 dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
1369 dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
1370 qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS);
1371 qdev_prop_set_uint32(dev, "mmio_size", memmap[VIRT_PLATFORM_BUS].size);
1372 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1373 s->platform_bus_dev = dev;
1374
1375 sysbus = SYS_BUS_DEVICE(dev);
1376 for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) {
1377 int irq = VIRT_PLATFORM_BUS_IRQ + i;
1378 sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(irqchip, irq));
1379 }
1380
1381 memory_region_add_subregion(sysmem,
1382 memmap[VIRT_PLATFORM_BUS].base,
1383 sysbus_mmio_get_region(sysbus, 0));
1384}
1385
Heinrich Schuchardtecf28642024-01-23 19:42:28 +01001386static void virt_build_smbios(RISCVVirtState *s)
1387{
1388 MachineClass *mc = MACHINE_GET_CLASS(s);
1389 MachineState *ms = MACHINE(s);
1390 uint8_t *smbios_tables, *smbios_anchor;
1391 size_t smbios_tables_len, smbios_anchor_len;
1392 struct smbios_phys_mem_area mem_array;
1393 const char *product = "QEMU Virtual Machine";
1394
1395 if (kvm_enabled()) {
1396 product = "KVM Virtual Machine";
1397 }
1398
Philippe Mathieu-Daudéc3381282024-03-27 10:08:05 +01001399 smbios_set_defaults("QEMU", product, mc->name);
Heinrich Schuchardtecf28642024-01-23 19:42:28 +01001400
1401 if (riscv_is_32bit(&s->soc[0])) {
1402 smbios_set_default_processor_family(0x200);
1403 } else {
1404 smbios_set_default_processor_family(0x201);
1405 }
1406
1407 /* build the array of physical mem area from base_memmap */
1408 mem_array.address = s->memmap[VIRT_DRAM].base;
1409 mem_array.length = ms->ram_size;
1410
Igor Mammedov69ea07a2024-03-14 16:22:54 +01001411 smbios_get_tables(ms, SMBIOS_ENTRY_POINT_TYPE_64,
1412 &mem_array, 1,
Heinrich Schuchardtecf28642024-01-23 19:42:28 +01001413 &smbios_tables, &smbios_tables_len,
1414 &smbios_anchor, &smbios_anchor_len,
1415 &error_fatal);
1416
1417 if (smbios_anchor) {
1418 fw_cfg_add_file(s->fw_cfg, "etc/smbios/smbios-tables",
1419 smbios_tables, smbios_tables_len);
1420 fw_cfg_add_file(s->fw_cfg, "etc/smbios/smbios-anchor",
1421 smbios_anchor, smbios_anchor_len);
1422 }
1423}
1424
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001425static void virt_machine_done(Notifier *notifier, void *data)
1426{
1427 RISCVVirtState *s = container_of(notifier, RISCVVirtState,
1428 machine_done);
1429 const MemMapEntry *memmap = virt_memmap;
1430 MachineState *machine = MACHINE(s);
Samuel Holland55c13652024-08-16 17:25:02 -07001431 hwaddr start_addr = memmap[VIRT_DRAM].base;
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001432 target_ulong firmware_end_addr, kernel_start_addr;
Daniel Henrique Barboza9d3f7102022-12-29 17:18:26 +08001433 const char *firmware_name = riscv_default_firmware_name(&s->soc[0]);
Lakshmi Bai Raja Subramanian1ad53682023-06-20 19:20:06 +05301434 uint64_t fdt_load_addr;
Sunil V L4263e272023-06-01 10:29:08 +05301435 uint64_t kernel_entry = 0;
Sunil V L13bdfb82023-06-01 10:29:09 +05301436 BlockBackend *pflash_blk0;
Jim Shud3592952024-11-20 23:39:34 +08001437 RISCVBootInfo boot_info;
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001438
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001439 /*
1440 * An user provided dtb must include everything, including
1441 * dynamic sysbus devices. Our FDT needs to be finalized.
1442 */
1443 if (machine->dtb == NULL) {
1444 finalize_fdt(s);
Guenter Roeck49554852023-07-05 20:59:37 -07001445 }
1446
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001447 /*
1448 * Only direct boot kernel is currently supported for KVM VM,
1449 * so the "-bios" parameter is not supported when KVM is enabled.
1450 */
1451 if (kvm_enabled()) {
1452 if (machine->firmware) {
1453 if (strcmp(machine->firmware, "none")) {
1454 error_report("Machine mode firmware is not supported in "
1455 "combination with KVM.");
1456 exit(1);
1457 }
1458 } else {
1459 machine->firmware = g_strdup("none");
1460 }
1461 }
1462
Daniel Henrique Barboza9d3f7102022-12-29 17:18:26 +08001463 firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
Samuel Holland55c13652024-08-16 17:25:02 -07001464 &start_addr, NULL);
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001465
Sunil V L13bdfb82023-06-01 10:29:09 +05301466 pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]);
1467 if (pflash_blk0) {
Sunil V L4263e272023-06-01 10:29:08 +05301468 if (machine->firmware && !strcmp(machine->firmware, "none") &&
1469 !kvm_enabled()) {
1470 /*
1471 * Pflash was supplied but bios is none and not KVM guest,
1472 * let's overwrite the address we jump to after reset to
1473 * the base of the flash.
1474 */
1475 start_addr = virt_memmap[VIRT_FLASH].base;
1476 } else {
1477 /*
1478 * Pflash was supplied but either KVM guest or bios is not none.
1479 * In this case, base of the flash would contain S-mode payload.
1480 */
1481 riscv_setup_firmware_boot(machine);
1482 kernel_entry = virt_memmap[VIRT_FLASH].base;
1483 }
1484 }
1485
Jim Shud3592952024-11-20 23:39:34 +08001486 riscv_boot_info_init(&boot_info, &s->soc[0]);
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001487
Jim Shud3592952024-11-20 23:39:34 +08001488 if (machine->kernel_filename && !kernel_entry) {
1489 kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
1490 firmware_end_addr);
1491 riscv_load_kernel(machine, &boot_info, kernel_start_addr,
1492 true, NULL);
1493 kernel_entry = boot_info.image_low_addr;
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001494 }
1495
Daniel Henrique Barbozabc2c0152023-02-01 14:12:11 -03001496 fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
Daniel Henrique Barboza4b402882023-02-01 14:12:12 -03001497 memmap[VIRT_DRAM].size,
Jim Shud3592952024-11-20 23:39:34 +08001498 machine, &boot_info);
Daniel Henrique Barbozabc2c0152023-02-01 14:12:11 -03001499 riscv_load_fdt(fdt_load_addr, machine->fdt);
1500
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001501 /* load the reset vector */
1502 riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr,
1503 virt_memmap[VIRT_MROM].base,
1504 virt_memmap[VIRT_MROM].size, kernel_entry,
Daniel Henrique Barboza6934f152022-07-28 15:19:26 -03001505 fdt_load_addr);
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001506
1507 /*
1508 * Only direct boot kernel is currently supported for KVM VM,
1509 * So here setup kernel start address and fdt address.
1510 * TODO:Support firmware loading and integrate to TCG start
1511 */
1512 if (kvm_enabled()) {
1513 riscv_setup_direct_kernel(kernel_entry, fdt_load_addr);
1514 }
Sunil V Lf7093602023-03-02 14:42:11 +05301515
Heinrich Schuchardtecf28642024-01-23 19:42:28 +01001516 virt_build_smbios(s);
1517
Sunil V Lf7093602023-03-02 14:42:11 +05301518 if (virt_is_acpi_enabled(s)) {
1519 virt_acpi_setup(s);
1520 }
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001521}
1522
Bin Mengb2a3a072020-05-21 07:42:27 -07001523static void virt_machine_init(MachineState *machine)
Michael Clark04331d02018-03-03 01:31:13 +13001524{
Bin Meng73261282021-02-20 22:48:04 +08001525 const MemMapEntry *memmap = virt_memmap;
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001526 RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
Michael Clark04331d02018-03-03 01:31:13 +13001527 MemoryRegion *system_memory = get_system_memory();
Michael Clark5aec3242018-03-04 11:52:13 +13001528 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
Anup Patele6faee62022-02-20 14:25:22 +05301529 DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
Peter Maydell33fcedf2021-08-12 15:46:47 +01001530 int i, base_hartid, hart_count;
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -03001531 int socket_count = riscv_socket_count(machine);
Michael Clark04331d02018-03-03 01:31:13 +13001532
Anup Patel18df0b42020-05-15 14:58:50 +05301533 /* Check socket count limit */
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -03001534 if (VIRT_SOCKETS_MAX < socket_count) {
Anup Patel18df0b42020-05-15 14:58:50 +05301535 error_report("number of sockets/nodes should be less than %d",
1536 VIRT_SOCKETS_MAX);
1537 exit(1);
1538 }
1539
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001540 if (!virt_aclint_allowed() && s->have_aclint) {
Daniel Henrique Barbozab274c232023-08-11 13:02:24 -03001541 error_report("'aclint' is only available with TCG acceleration");
1542 exit(1);
1543 }
1544
Anup Patel18df0b42020-05-15 14:58:50 +05301545 /* Initialize sockets */
Anup Patele6faee62022-02-20 14:25:22 +05301546 mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
Daniel Henrique Barboza2967f372023-01-24 18:22:32 -03001547 for (i = 0; i < socket_count; i++) {
Daniel Henrique Barbozac70dc312024-01-22 19:15:28 -03001548 g_autofree char *soc_name = g_strdup_printf("soc%d", i);
1549
Anup Patel18df0b42020-05-15 14:58:50 +05301550 if (!riscv_socket_check_hartids(machine, i)) {
1551 error_report("discontinuous hartids in socket%d", i);
1552 exit(1);
1553 }
1554
1555 base_hartid = riscv_socket_first_hartid(machine, i);
1556 if (base_hartid < 0) {
1557 error_report("can't find hartid base for socket%d", i);
1558 exit(1);
1559 }
1560
1561 hart_count = riscv_socket_hart_count(machine, i);
1562 if (hart_count < 0) {
1563 error_report("can't find hart count for socket%d", i);
1564 exit(1);
1565 }
1566
Anup Patel18df0b42020-05-15 14:58:50 +05301567 object_initialize_child(OBJECT(machine), soc_name, &s->soc[i],
1568 TYPE_RISCV_HART_ARRAY);
Anup Patel18df0b42020-05-15 14:58:50 +05301569 object_property_set_str(OBJECT(&s->soc[i]), "cpu-type",
1570 machine->cpu_type, &error_abort);
1571 object_property_set_int(OBJECT(&s->soc[i]), "hartid-base",
1572 base_hartid, &error_abort);
1573 object_property_set_int(OBJECT(&s->soc[i]), "num-harts",
1574 hart_count, &error_abort);
Tsukasa OI4bcfc392022-05-14 15:29:40 +09001575 sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal);
Anup Patel18df0b42020-05-15 14:58:50 +05301576
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001577 if (virt_aclint_allowed() && s->have_aclint) {
1578 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
1579 /* Per-socket ACLINT MTIMER */
1580 riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
Anup Patel28d8c282022-02-20 14:25:24 +05301581 i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
1582 RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
1583 base_hartid, hart_count,
1584 RISCV_ACLINT_DEFAULT_MTIMECMP,
1585 RISCV_ACLINT_DEFAULT_MTIME,
1586 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001587 } else {
1588 /* Per-socket ACLINT MSWI, MTIMER, and SSWI */
1589 riscv_aclint_swi_create(memmap[VIRT_CLINT].base +
Anup Patel28d8c282022-02-20 14:25:24 +05301590 i * memmap[VIRT_CLINT].size,
1591 base_hartid, hart_count, false);
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001592 riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
Anup Patel28d8c282022-02-20 14:25:24 +05301593 i * memmap[VIRT_CLINT].size +
1594 RISCV_ACLINT_SWI_SIZE,
1595 RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
1596 base_hartid, hart_count,
1597 RISCV_ACLINT_DEFAULT_MTIMECMP,
1598 RISCV_ACLINT_DEFAULT_MTIME,
1599 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001600 riscv_aclint_swi_create(memmap[VIRT_ACLINT_SSWI].base +
Anup Patel28d8c282022-02-20 14:25:24 +05301601 i * memmap[VIRT_ACLINT_SSWI].size,
1602 base_hartid, hart_count, true);
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001603 }
1604 } else if (tcg_enabled()) {
1605 /* Per-socket SiFive CLINT */
1606 riscv_aclint_swi_create(
Anup Patel28d8c282022-02-20 14:25:24 +05301607 memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
1608 base_hartid, hart_count, false);
Daniel Henrique Barbozaf2d44e92024-02-17 16:26:06 -03001609 riscv_aclint_mtimer_create(memmap[VIRT_CLINT].base +
Anup Patel28d8c282022-02-20 14:25:24 +05301610 i * memmap[VIRT_CLINT].size + RISCV_ACLINT_SWI_SIZE,
1611 RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count,
1612 RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
1613 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
Anup Patel954886e2021-08-31 16:36:03 +05301614 }
1615
Anup Patele6faee62022-02-20 14:25:22 +05301616 /* Per-socket interrupt controller */
1617 if (s->aia_type == VIRT_AIA_TYPE_NONE) {
1618 s->irqchip[i] = virt_create_plic(memmap, i,
1619 base_hartid, hart_count);
1620 } else {
Anup Patel28d8c282022-02-20 14:25:24 +05301621 s->irqchip[i] = virt_create_aia(s->aia_type, s->aia_guests,
1622 memmap, i, base_hartid,
1623 hart_count);
Anup Patele6faee62022-02-20 14:25:22 +05301624 }
Anup Patel18df0b42020-05-15 14:58:50 +05301625
Anup Patele6faee62022-02-20 14:25:22 +05301626 /* Try to use different IRQCHIP instance based device type */
Anup Patel18df0b42020-05-15 14:58:50 +05301627 if (i == 0) {
Anup Patele6faee62022-02-20 14:25:22 +05301628 mmio_irqchip = s->irqchip[i];
1629 virtio_irqchip = s->irqchip[i];
1630 pcie_irqchip = s->irqchip[i];
Anup Patel18df0b42020-05-15 14:58:50 +05301631 }
1632 if (i == 1) {
Anup Patele6faee62022-02-20 14:25:22 +05301633 virtio_irqchip = s->irqchip[i];
1634 pcie_irqchip = s->irqchip[i];
Anup Patel18df0b42020-05-15 14:58:50 +05301635 }
1636 if (i == 2) {
Anup Patele6faee62022-02-20 14:25:22 +05301637 pcie_irqchip = s->irqchip[i];
Anup Patel18df0b42020-05-15 14:58:50 +05301638 }
1639 }
Michael Clark04331d02018-03-03 01:31:13 +13001640
Daniel Henrique Barboza2711e1e2024-11-19 16:17:01 -03001641 if (kvm_enabled() && virt_use_kvm_aia_aplic_imsic(s->aia_type)) {
Yong-Xuan Wang48c2c332023-07-27 10:24:37 +00001642 kvm_riscv_aia_create(machine, IMSIC_MMIO_GROUP_MIN_SHIFT,
1643 VIRT_IRQCHIP_NUM_SOURCES, VIRT_IRQCHIP_NUM_MSIS,
1644 memmap[VIRT_APLIC_S].base,
1645 memmap[VIRT_IMSIC_S].base,
1646 s->aia_guests);
1647 }
1648
Bin Mengcfeb8a12021-02-20 22:48:06 +08001649 if (riscv_is_32bit(&s->soc[0])) {
1650#if HOST_LONG_BITS == 64
1651 /* limit RAM size in a 32-bit system */
1652 if (machine->ram_size > 10 * GiB) {
1653 machine->ram_size = 10 * GiB;
1654 error_report("Limiting RAM size to 10 GiB");
1655 }
1656#endif
Bin Meng19800262021-02-20 22:48:07 +08001657 virt_high_pcie_memmap.base = VIRT32_HIGH_PCIE_MMIO_BASE;
1658 virt_high_pcie_memmap.size = VIRT32_HIGH_PCIE_MMIO_SIZE;
1659 } else {
1660 virt_high_pcie_memmap.size = VIRT64_HIGH_PCIE_MMIO_SIZE;
1661 virt_high_pcie_memmap.base = memmap[VIRT_DRAM].base + machine->ram_size;
1662 virt_high_pcie_memmap.base =
1663 ROUND_UP(virt_high_pcie_memmap.base, virt_high_pcie_memmap.size);
Bin Mengcfeb8a12021-02-20 22:48:06 +08001664 }
1665
Sunil V L71302ff2023-03-02 14:42:07 +05301666 s->memmap = virt_memmap;
1667
Michael Clark04331d02018-03-03 01:31:13 +13001668 /* register system main memory (actual RAM) */
Michael Clark04331d02018-03-03 01:31:13 +13001669 memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base,
Mingwang Li03fd0c52021-10-16 11:09:08 +08001670 machine->ram);
Michael Clark04331d02018-03-03 01:31:13 +13001671
Michael Clark04331d02018-03-03 01:31:13 +13001672 /* boot rom */
Michael Clark5aec3242018-03-04 11:52:13 +13001673 memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
1674 memmap[VIRT_MROM].size, &error_fatal);
1675 memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
1676 mask_rom);
Michael Clark04331d02018-03-03 01:31:13 +13001677
Daniel Henrique Barbozab7483522023-01-17 10:27:51 -03001678 /*
1679 * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the
1680 * device tree cannot be altered and we get FDT_ERR_NOSPACE.
1681 */
1682 s->fw_cfg = create_fw_cfg(machine);
1683 rom_set_fw(s->fw_cfg);
1684
Anup Patel18df0b42020-05-15 14:58:50 +05301685 /* SiFive Test MMIO device */
Michael Clark04331d02018-03-03 01:31:13 +13001686 sifive_test_create(memmap[VIRT_TEST].base);
1687
Anup Patel18df0b42020-05-15 14:58:50 +05301688 /* VirtIO MMIO devices */
Michael Clark04331d02018-03-03 01:31:13 +13001689 for (i = 0; i < VIRTIO_COUNT; i++) {
1690 sysbus_create_simple("virtio-mmio",
1691 memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
Philippe Mathieu-Daudé7d5b0d62023-06-01 11:34:52 +02001692 qdev_get_gpio_in(virtio_irqchip, VIRTIO_IRQ + i));
Michael Clark04331d02018-03-03 01:31:13 +13001693 }
1694
Sunil V Le86e9522023-12-18 20:32:45 +05301695 gpex_pcie_init(system_memory, pcie_irqchip, s);
Alistair Francis6d56e392018-12-11 22:37:36 +00001696
Philippe Mathieu-Daudé7d5b0d62023-06-01 11:34:52 +02001697 create_platform_bus(s, mmio_irqchip);
Alistair Francis1832b7c2022-04-28 09:41:43 +10001698
Michael Clark04331d02018-03-03 01:31:13 +13001699 serial_mm_init(system_memory, memmap[VIRT_UART0].base,
Philippe Mathieu-Daudé7d5b0d62023-06-01 11:34:52 +02001700 0, qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), 399193,
Peter Maydell9bca0ed2018-04-20 15:52:43 +01001701 serial_hd(0), DEVICE_LITTLE_ENDIAN);
Michael Clarkb6aa6ce2018-04-30 12:29:34 +12001702
Anup Patel67b5ef32019-11-06 11:56:43 +00001703 sysbus_create_simple("goldfish_rtc", memmap[VIRT_RTC].base,
Philippe Mathieu-Daudé7d5b0d62023-06-01 11:34:52 +02001704 qdev_get_gpio_in(mmio_irqchip, RTC_IRQ));
Anup Patel67b5ef32019-11-06 11:56:43 +00001705
Alistair Francis71eb5222019-10-08 16:32:25 -07001706 for (i = 0; i < ARRAY_SIZE(s->flash); i++) {
1707 /* Map legacy -drive if=pflash to machine properties */
1708 pflash_cfi01_legacy_drive(s->flash[i],
1709 drive_get(IF_PFLASH, 0, i));
1710 }
1711 virt_flash_map(s, system_memory);
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001712
Daniel Henrique Barboza7a87ba82023-11-10 14:25:59 -03001713 /* load/create device tree */
1714 if (machine->dtb) {
1715 machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
1716 if (!machine->fdt) {
1717 error_report("load_device_tree() failed");
1718 exit(1);
1719 }
1720 } else {
1721 create_fdt(s, memmap);
1722 }
1723
Sunil V L2c12de12024-11-06 10:34:04 -03001724 if (virt_is_iommu_sys_enabled(s)) {
1725 DeviceState *iommu_sys = qdev_new(TYPE_RISCV_IOMMU_SYS);
1726
1727 object_property_set_uint(OBJECT(iommu_sys), "addr",
1728 s->memmap[VIRT_IOMMU_SYS].base,
1729 &error_fatal);
1730 object_property_set_uint(OBJECT(iommu_sys), "base-irq",
1731 IOMMU_SYS_IRQ,
1732 &error_fatal);
1733 object_property_set_link(OBJECT(iommu_sys), "irqchip",
1734 OBJECT(mmio_irqchip),
1735 &error_fatal);
1736
1737 sysbus_realize_and_unref(SYS_BUS_DEVICE(iommu_sys), &error_fatal);
1738 }
1739
Alistair Francis1c20d3f2022-04-28 09:41:41 +10001740 s->machine_done.notify = virt_machine_done;
1741 qemu_add_machine_init_done_notifier(&s->machine_done);
Michael Clark04331d02018-03-03 01:31:13 +13001742}
1743
Bin Mengb2a3a072020-05-21 07:42:27 -07001744static void virt_machine_instance_init(Object *obj)
Michael Clark04331d02018-03-03 01:31:13 +13001745{
Sunil V L90477a62023-03-02 14:42:05 +05301746 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1747
Sunil V L13bdfb82023-06-01 10:29:09 +05301748 virt_flash_create(s);
1749
Sunil V L90477a62023-03-02 14:42:05 +05301750 s->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
1751 s->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
Sunil V L168b8c22023-03-02 14:42:06 +05301752 s->acpi = ON_OFF_AUTO_AUTO;
Sunil V L2c12de12024-11-06 10:34:04 -03001753 s->iommu_sys = ON_OFF_AUTO_AUTO;
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001754}
1755
Anup Patel28d8c282022-02-20 14:25:24 +05301756static char *virt_get_aia_guests(Object *obj, Error **errp)
1757{
1758 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
Anup Patel28d8c282022-02-20 14:25:24 +05301759
Philippe Mathieu-Daudéb8ff8462024-04-11 12:33:31 +02001760 return g_strdup_printf("%d", s->aia_guests);
Anup Patel28d8c282022-02-20 14:25:24 +05301761}
1762
1763static void virt_set_aia_guests(Object *obj, const char *val, Error **errp)
1764{
1765 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1766
1767 s->aia_guests = atoi(val);
1768 if (s->aia_guests < 0 || s->aia_guests > VIRT_IRQCHIP_MAX_GUESTS) {
1769 error_setg(errp, "Invalid number of AIA IMSIC guests");
1770 error_append_hint(errp, "Valid values be between 0 and %d.\n",
1771 VIRT_IRQCHIP_MAX_GUESTS);
1772 }
1773}
1774
Anup Patele6faee62022-02-20 14:25:22 +05301775static char *virt_get_aia(Object *obj, Error **errp)
1776{
1777 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1778 const char *val;
1779
1780 switch (s->aia_type) {
1781 case VIRT_AIA_TYPE_APLIC:
1782 val = "aplic";
1783 break;
Anup Patel28d8c282022-02-20 14:25:24 +05301784 case VIRT_AIA_TYPE_APLIC_IMSIC:
1785 val = "aplic-imsic";
1786 break;
Anup Patele6faee62022-02-20 14:25:22 +05301787 default:
1788 val = "none";
1789 break;
1790 };
1791
1792 return g_strdup(val);
1793}
1794
1795static void virt_set_aia(Object *obj, const char *val, Error **errp)
1796{
1797 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1798
1799 if (!strcmp(val, "none")) {
1800 s->aia_type = VIRT_AIA_TYPE_NONE;
1801 } else if (!strcmp(val, "aplic")) {
1802 s->aia_type = VIRT_AIA_TYPE_APLIC;
Anup Patel28d8c282022-02-20 14:25:24 +05301803 } else if (!strcmp(val, "aplic-imsic")) {
1804 s->aia_type = VIRT_AIA_TYPE_APLIC_IMSIC;
Anup Patele6faee62022-02-20 14:25:22 +05301805 } else {
1806 error_setg(errp, "Invalid AIA interrupt controller type");
Anup Patel28d8c282022-02-20 14:25:24 +05301807 error_append_hint(errp, "Valid values are none, aplic, and "
1808 "aplic-imsic.\n");
Anup Patele6faee62022-02-20 14:25:22 +05301809 }
1810}
1811
Anup Patel954886e2021-08-31 16:36:03 +05301812static bool virt_get_aclint(Object *obj, Error **errp)
1813{
Bin Meng5474aa42023-02-06 16:50:07 +08001814 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
Anup Patel954886e2021-08-31 16:36:03 +05301815
1816 return s->have_aclint;
1817}
1818
1819static void virt_set_aclint(Object *obj, bool value, Error **errp)
1820{
Bin Meng5474aa42023-02-06 16:50:07 +08001821 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
Anup Patel954886e2021-08-31 16:36:03 +05301822
1823 s->have_aclint = value;
1824}
1825
Sunil V L2c12de12024-11-06 10:34:04 -03001826bool virt_is_iommu_sys_enabled(RISCVVirtState *s)
1827{
1828 return s->iommu_sys == ON_OFF_AUTO_ON;
1829}
1830
1831static void virt_get_iommu_sys(Object *obj, Visitor *v, const char *name,
1832 void *opaque, Error **errp)
1833{
1834 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1835 OnOffAuto iommu_sys = s->iommu_sys;
1836
1837 visit_type_OnOffAuto(v, name, &iommu_sys, errp);
1838}
1839
1840static void virt_set_iommu_sys(Object *obj, Visitor *v, const char *name,
1841 void *opaque, Error **errp)
1842{
1843 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1844
1845 visit_type_OnOffAuto(v, name, &s->iommu_sys, errp);
1846}
1847
Sunil V L168b8c22023-03-02 14:42:06 +05301848bool virt_is_acpi_enabled(RISCVVirtState *s)
1849{
1850 return s->acpi != ON_OFF_AUTO_OFF;
1851}
1852
1853static void virt_get_acpi(Object *obj, Visitor *v, const char *name,
1854 void *opaque, Error **errp)
1855{
1856 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1857 OnOffAuto acpi = s->acpi;
1858
1859 visit_type_OnOffAuto(v, name, &acpi, errp);
1860}
1861
1862static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
1863 void *opaque, Error **errp)
1864{
1865 RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
1866
1867 visit_type_OnOffAuto(v, name, &s->acpi, errp);
1868}
1869
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001870static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
1871 DeviceState *dev)
1872{
1873 MachineClass *mc = MACHINE_GET_CLASS(machine);
Sunil V L2c12de12024-11-06 10:34:04 -03001874 RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001875
Daniel Henrique Barboza7778cdd2024-02-17 16:26:05 -03001876 if (device_is_dynamic_sysbus(mc, dev) ||
Tomasz Jeznachdf240d62024-10-16 17:40:30 -03001877 object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
1878 object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
Sunil V L2c12de12024-11-06 10:34:04 -03001879 s->iommu_sys = ON_OFF_AUTO_OFF;
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001880 return HOTPLUG_HANDLER(machine);
1881 }
Tomasz Jeznachdf240d62024-10-16 17:40:30 -03001882
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001883 return NULL;
1884}
1885
1886static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
1887 DeviceState *dev, Error **errp)
1888{
1889 RISCVVirtState *s = RISCV_VIRT_MACHINE(hotplug_dev);
1890
1891 if (s->platform_bus_dev) {
1892 MachineClass *mc = MACHINE_GET_CLASS(s);
1893
1894 if (device_is_dynamic_sysbus(mc, dev)) {
1895 platform_bus_link_device(PLATFORM_BUS_DEVICE(s->platform_bus_dev),
1896 SYS_BUS_DEVICE(dev));
1897 }
1898 }
Daniel Henrique Barboza7778cdd2024-02-17 16:26:05 -03001899
1900 if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
1901 create_fdt_virtio_iommu(s, pci_get_bdf(PCI_DEVICE(dev)));
1902 }
Tomasz Jeznachdf240d62024-10-16 17:40:30 -03001903
1904 if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
1905 create_fdt_iommu(s, pci_get_bdf(PCI_DEVICE(dev)));
Sunil V L2c12de12024-11-06 10:34:04 -03001906 s->iommu_sys = ON_OFF_AUTO_OFF;
Tomasz Jeznachdf240d62024-10-16 17:40:30 -03001907 }
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001908}
1909
Bin Mengb2a3a072020-05-21 07:42:27 -07001910static void virt_machine_class_init(ObjectClass *oc, void *data)
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001911{
1912 MachineClass *mc = MACHINE_CLASS(oc);
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001913 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001914
1915 mc->desc = "RISC-V VirtIO board";
Bin Mengb2a3a072020-05-21 07:42:27 -07001916 mc->init = virt_machine_init;
Anup Patel18df0b42020-05-15 14:58:50 +05301917 mc->max_cpus = VIRT_CPUS_MAX;
Alistair Francis09fe1712020-12-16 10:22:34 -08001918 mc->default_cpu_type = TYPE_RISCV_CPU_BASE;
Sunil V L4406ba22024-06-20 12:17:18 +05301919 mc->block_default_type = IF_VIRTIO;
1920 mc->no_cdrom = 1;
Bin Mengacead542019-11-22 07:27:52 -08001921 mc->pci_allow_0_address = true;
Anup Patel18df0b42020-05-15 14:58:50 +05301922 mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids;
1923 mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
1924 mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
1925 mc->numa_mem_supported = true;
Gavin Shan3d9981c2023-05-09 10:27:39 +10001926 /* platform instead of architectural choice */
1927 mc->cpu_cluster_has_numa_boundary = true;
Mingwang Li03fd0c52021-10-16 11:09:08 +08001928 mc->default_ram_id = "riscv_virt_board.ram";
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001929 assert(!mc->get_hotplug_handler);
1930 mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
1931
1932 hc->plug = virt_machine_device_plug_cb;
Asherah Connorc3467492021-03-19 10:50:41 +11001933
1934 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
Alistair Francis325b7c42022-04-28 09:41:46 +10001935#ifdef CONFIG_TPM
1936 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
1937#endif
Anup Patel954886e2021-08-31 16:36:03 +05301938
Daniel Henrique Barbozab274c232023-08-11 13:02:24 -03001939 object_class_property_add_bool(oc, "aclint", virt_get_aclint,
1940 virt_set_aclint);
1941 object_class_property_set_description(oc, "aclint",
1942 "(TCG only) Set on/off to "
1943 "enable/disable emulating "
1944 "ACLINT devices");
1945
Anup Patele6faee62022-02-20 14:25:22 +05301946 object_class_property_add_str(oc, "aia", virt_get_aia,
1947 virt_set_aia);
1948 object_class_property_set_description(oc, "aia",
1949 "Set type of AIA interrupt "
Daniel Henrique Barbozac92ac072023-06-15 06:21:48 -03001950 "controller. Valid values are "
Anup Patel28d8c282022-02-20 14:25:24 +05301951 "none, aplic, and aplic-imsic.");
1952
1953 object_class_property_add_str(oc, "aia-guests",
1954 virt_get_aia_guests,
1955 virt_set_aia_guests);
Philippe Mathieu-Daudéb8ff8462024-04-11 12:33:31 +02001956 {
1957 g_autofree char *str =
1958 g_strdup_printf("Set number of guest MMIO pages for AIA IMSIC. "
1959 "Valid value should be between 0 and %d.",
1960 VIRT_IRQCHIP_MAX_GUESTS);
1961 object_class_property_set_description(oc, "aia-guests", str);
1962 }
1963
Sunil V L168b8c22023-03-02 14:42:06 +05301964 object_class_property_add(oc, "acpi", "OnOffAuto",
1965 virt_get_acpi, virt_set_acpi,
1966 NULL, NULL);
1967 object_class_property_set_description(oc, "acpi",
1968 "Enable ACPI");
Sunil V L2c12de12024-11-06 10:34:04 -03001969
1970 object_class_property_add(oc, "iommu-sys", "OnOffAuto",
1971 virt_get_iommu_sys, virt_set_iommu_sys,
1972 NULL, NULL);
1973 object_class_property_set_description(oc, "iommu-sys",
1974 "Enable IOMMU platform device");
Michael Clark04331d02018-03-03 01:31:13 +13001975}
1976
Bin Mengb2a3a072020-05-21 07:42:27 -07001977static const TypeInfo virt_machine_typeinfo = {
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001978 .name = MACHINE_TYPE_NAME("virt"),
1979 .parent = TYPE_MACHINE,
Bin Mengb2a3a072020-05-21 07:42:27 -07001980 .class_init = virt_machine_class_init,
1981 .instance_init = virt_machine_instance_init,
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001982 .instance_size = sizeof(RISCVVirtState),
Alistair Francis58d5a5a2022-04-28 09:41:45 +10001983 .interfaces = (InterfaceInfo[]) {
1984 { TYPE_HOTPLUG_HANDLER },
1985 { }
1986 },
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001987};
1988
Bin Mengb2a3a072020-05-21 07:42:27 -07001989static void virt_machine_init_register_types(void)
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001990{
Bin Mengb2a3a072020-05-21 07:42:27 -07001991 type_register_static(&virt_machine_typeinfo);
Alistair Franciscdfc19e2019-10-08 16:32:22 -07001992}
1993
Bin Mengb2a3a072020-05-21 07:42:27 -07001994type_init(virt_machine_init_register_types)