1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * QEMU loongson 3a5000 develop board emulation
5 * Copyright (c) 2021 Loongson Technology Corporation Limited
7 #include "qemu/osdep.h"
8 #include "qemu/units.h"
9 #include "qemu/datadir.h"
10 #include "qapi/error.h"
11 #include "hw/boards.h"
12 #include "hw/char/serial-mm.h"
13 #include "sysemu/kvm.h"
14 #include "sysemu/tcg.h"
15 #include "sysemu/sysemu.h"
16 #include "sysemu/qtest.h"
17 #include "sysemu/runstate.h"
18 #include "sysemu/reset.h"
19 #include "sysemu/rtc.h"
20 #include "hw/loongarch/virt.h"
21 #include "exec/address-spaces.h"
24 #include "hw/loader.h"
26 #include "hw/intc/loongarch_ipi.h"
27 #include "hw/intc/loongarch_extioi.h"
28 #include "hw/intc/loongarch_pch_pic.h"
29 #include "hw/intc/loongarch_pch_msi.h"
30 #include "hw/pci-host/ls7a.h"
31 #include "hw/pci-host/gpex.h"
32 #include "hw/misc/unimp.h"
33 #include "hw/loongarch/fw_cfg.h"
34 #include "target/loongarch/cpu.h"
35 #include "hw/firmware/smbios.h"
36 #include "hw/acpi/aml-build.h"
37 #include "qapi/qapi-visit-common.h"
38 #include "hw/acpi/generic_event_device.h"
39 #include "hw/mem/nvdimm.h"
40 #include "sysemu/device_tree.h"
42 #include "hw/core/sysbus-fdt.h"
43 #include "hw/platform-bus.h"
44 #include "hw/display/ramfb.h"
45 #include "hw/mem/pc-dimm.h"
46 #include "sysemu/tpm.h"
47 #include "sysemu/block-backend.h"
48 #include "hw/block/flash.h"
49 #include "hw/virtio/virtio-iommu.h"
50 #include "qemu/error-report.h"
51 #include "qemu/guest-random.h"
53 static bool virt_is_veiointc_enabled(LoongArchVirtMachineState
*lvms
)
55 if (lvms
->veiointc
== ON_OFF_AUTO_OFF
) {
61 static void virt_get_veiointc(Object
*obj
, Visitor
*v
, const char *name
,
62 void *opaque
, Error
**errp
)
64 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(obj
);
65 OnOffAuto veiointc
= lvms
->veiointc
;
67 visit_type_OnOffAuto(v
, name
, &veiointc
, errp
);
70 static void virt_set_veiointc(Object
*obj
, Visitor
*v
, const char *name
,
71 void *opaque
, Error
**errp
)
73 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(obj
);
75 visit_type_OnOffAuto(v
, name
, &lvms
->veiointc
, errp
);
78 static PFlashCFI01
*virt_flash_create1(LoongArchVirtMachineState
*lvms
,
80 const char *alias_prop_name
)
82 DeviceState
*dev
= qdev_new(TYPE_PFLASH_CFI01
);
84 qdev_prop_set_uint64(dev
, "sector-length", VIRT_FLASH_SECTOR_SIZE
);
85 qdev_prop_set_uint8(dev
, "width", 4);
86 qdev_prop_set_uint8(dev
, "device-width", 2);
87 qdev_prop_set_bit(dev
, "big-endian", false);
88 qdev_prop_set_uint16(dev
, "id0", 0x89);
89 qdev_prop_set_uint16(dev
, "id1", 0x18);
90 qdev_prop_set_uint16(dev
, "id2", 0x00);
91 qdev_prop_set_uint16(dev
, "id3", 0x00);
92 qdev_prop_set_string(dev
, "name", name
);
93 object_property_add_child(OBJECT(lvms
), name
, OBJECT(dev
));
94 object_property_add_alias(OBJECT(lvms
), alias_prop_name
,
95 OBJECT(dev
), "drive");
96 return PFLASH_CFI01(dev
);
99 static void virt_flash_create(LoongArchVirtMachineState
*lvms
)
101 lvms
->flash
[0] = virt_flash_create1(lvms
, "virt.flash0", "pflash0");
102 lvms
->flash
[1] = virt_flash_create1(lvms
, "virt.flash1", "pflash1");
105 static void virt_flash_map1(PFlashCFI01
*flash
,
106 hwaddr base
, hwaddr size
,
107 MemoryRegion
*sysmem
)
109 DeviceState
*dev
= DEVICE(flash
);
111 hwaddr real_size
= size
;
113 blk
= pflash_cfi01_get_blk(flash
);
115 real_size
= blk_getlength(blk
);
116 assert(real_size
&& real_size
<= size
);
119 assert(QEMU_IS_ALIGNED(real_size
, VIRT_FLASH_SECTOR_SIZE
));
120 assert(real_size
/ VIRT_FLASH_SECTOR_SIZE
<= UINT32_MAX
);
122 qdev_prop_set_uint32(dev
, "num-blocks", real_size
/ VIRT_FLASH_SECTOR_SIZE
);
123 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
124 memory_region_add_subregion(sysmem
, base
,
125 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev
), 0));
128 static void virt_flash_map(LoongArchVirtMachineState
*lvms
,
129 MemoryRegion
*sysmem
)
131 PFlashCFI01
*flash0
= lvms
->flash
[0];
132 PFlashCFI01
*flash1
= lvms
->flash
[1];
134 virt_flash_map1(flash0
, VIRT_FLASH0_BASE
, VIRT_FLASH0_SIZE
, sysmem
);
135 virt_flash_map1(flash1
, VIRT_FLASH1_BASE
, VIRT_FLASH1_SIZE
, sysmem
);
138 static void fdt_add_cpuic_node(LoongArchVirtMachineState
*lvms
,
139 uint32_t *cpuintc_phandle
)
141 MachineState
*ms
= MACHINE(lvms
);
144 *cpuintc_phandle
= qemu_fdt_alloc_phandle(ms
->fdt
);
145 nodename
= g_strdup_printf("/cpuic");
146 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
147 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle", *cpuintc_phandle
);
148 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
149 "loongson,cpu-interrupt-controller");
150 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-controller", NULL
, 0);
151 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#interrupt-cells", 1);
155 static void fdt_add_eiointc_node(LoongArchVirtMachineState
*lvms
,
156 uint32_t *cpuintc_phandle
,
157 uint32_t *eiointc_phandle
)
159 MachineState
*ms
= MACHINE(lvms
);
161 hwaddr extioi_base
= APIC_BASE
;
162 hwaddr extioi_size
= EXTIOI_SIZE
;
164 *eiointc_phandle
= qemu_fdt_alloc_phandle(ms
->fdt
);
165 nodename
= g_strdup_printf("/eiointc@%" PRIx64
, extioi_base
);
166 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
167 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle", *eiointc_phandle
);
168 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
169 "loongson,ls2k2000-eiointc");
170 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-controller", NULL
, 0);
171 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#interrupt-cells", 1);
172 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupt-parent",
174 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupts", 3);
175 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "reg", 0x0,
176 extioi_base
, 0x0, extioi_size
);
180 static void fdt_add_pch_pic_node(LoongArchVirtMachineState
*lvms
,
181 uint32_t *eiointc_phandle
,
182 uint32_t *pch_pic_phandle
)
184 MachineState
*ms
= MACHINE(lvms
);
186 hwaddr pch_pic_base
= VIRT_PCH_REG_BASE
;
187 hwaddr pch_pic_size
= VIRT_PCH_REG_SIZE
;
189 *pch_pic_phandle
= qemu_fdt_alloc_phandle(ms
->fdt
);
190 nodename
= g_strdup_printf("/platic@%" PRIx64
, pch_pic_base
);
191 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
192 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle", *pch_pic_phandle
);
193 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
194 "loongson,pch-pic-1.0");
195 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "reg", 0,
196 pch_pic_base
, 0, pch_pic_size
);
197 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-controller", NULL
, 0);
198 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#interrupt-cells", 2);
199 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupt-parent",
201 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "loongson,pic-base-vec", 0);
205 static void fdt_add_pch_msi_node(LoongArchVirtMachineState
*lvms
,
206 uint32_t *eiointc_phandle
,
207 uint32_t *pch_msi_phandle
)
209 MachineState
*ms
= MACHINE(lvms
);
211 hwaddr pch_msi_base
= VIRT_PCH_MSI_ADDR_LOW
;
212 hwaddr pch_msi_size
= VIRT_PCH_MSI_SIZE
;
214 *pch_msi_phandle
= qemu_fdt_alloc_phandle(ms
->fdt
);
215 nodename
= g_strdup_printf("/msi@%" PRIx64
, pch_msi_base
);
216 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
217 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle", *pch_msi_phandle
);
218 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
219 "loongson,pch-msi-1.0");
220 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "reg",
223 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-controller", NULL
, 0);
224 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupt-parent",
226 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "loongson,msi-base-vec",
227 VIRT_PCH_PIC_IRQ_NUM
);
228 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "loongson,msi-num-vecs",
229 EXTIOI_IRQS
- VIRT_PCH_PIC_IRQ_NUM
);
233 static void fdt_add_flash_node(LoongArchVirtMachineState
*lvms
)
235 MachineState
*ms
= MACHINE(lvms
);
237 MemoryRegion
*flash_mem
;
245 flash_mem
= pflash_cfi01_get_memory(lvms
->flash
[0]);
246 flash0_base
= flash_mem
->addr
;
247 flash0_size
= memory_region_size(flash_mem
);
249 flash_mem
= pflash_cfi01_get_memory(lvms
->flash
[1]);
250 flash1_base
= flash_mem
->addr
;
251 flash1_size
= memory_region_size(flash_mem
);
253 nodename
= g_strdup_printf("/flash@%" PRIx64
, flash0_base
);
254 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
255 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible", "cfi-flash");
256 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
257 2, flash0_base
, 2, flash0_size
,
258 2, flash1_base
, 2, flash1_size
);
259 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "bank-width", 4);
263 static void fdt_add_rtc_node(LoongArchVirtMachineState
*lvms
,
264 uint32_t *pch_pic_phandle
)
267 hwaddr base
= VIRT_RTC_REG_BASE
;
268 hwaddr size
= VIRT_RTC_LEN
;
269 MachineState
*ms
= MACHINE(lvms
);
271 nodename
= g_strdup_printf("/rtc@%" PRIx64
, base
);
272 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
273 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
274 "loongson,ls7a-rtc");
275 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg", 2, base
, 2, size
);
276 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "interrupts",
277 VIRT_RTC_IRQ
- VIRT_GSI_BASE
, 0x4);
278 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupt-parent",
283 static void fdt_add_ged_reset(LoongArchVirtMachineState
*lvms
)
287 MachineState
*ms
= MACHINE(lvms
);
288 hwaddr base
= VIRT_GED_REG_ADDR
;
289 hwaddr size
= ACPI_GED_REG_COUNT
;
291 ged_handle
= qemu_fdt_alloc_phandle(ms
->fdt
);
292 name
= g_strdup_printf("/ged@%" PRIx64
, base
);
293 qemu_fdt_add_subnode(ms
->fdt
, name
);
294 qemu_fdt_setprop_string(ms
->fdt
, name
, "compatible", "syscon");
295 qemu_fdt_setprop_cells(ms
->fdt
, name
, "reg", 0x0, base
, 0x0, size
);
296 /* 8 bit registers */
297 qemu_fdt_setprop_cell(ms
->fdt
, name
, "reg-shift", 0);
298 qemu_fdt_setprop_cell(ms
->fdt
, name
, "reg-io-width", 1);
299 qemu_fdt_setprop_cell(ms
->fdt
, name
, "phandle", ged_handle
);
300 ged_handle
= qemu_fdt_get_phandle(ms
->fdt
, name
);
303 name
= g_strdup_printf("/reboot");
304 qemu_fdt_add_subnode(ms
->fdt
, name
);
305 qemu_fdt_setprop_string(ms
->fdt
, name
, "compatible", "syscon-reboot");
306 qemu_fdt_setprop_cell(ms
->fdt
, name
, "regmap", ged_handle
);
307 qemu_fdt_setprop_cell(ms
->fdt
, name
, "offset", ACPI_GED_REG_RESET
);
308 qemu_fdt_setprop_cell(ms
->fdt
, name
, "value", ACPI_GED_RESET_VALUE
);
311 name
= g_strdup_printf("/poweroff");
312 qemu_fdt_add_subnode(ms
->fdt
, name
);
313 qemu_fdt_setprop_string(ms
->fdt
, name
, "compatible", "syscon-poweroff");
314 qemu_fdt_setprop_cell(ms
->fdt
, name
, "regmap", ged_handle
);
315 qemu_fdt_setprop_cell(ms
->fdt
, name
, "offset", ACPI_GED_REG_SLEEP_CTL
);
316 qemu_fdt_setprop_cell(ms
->fdt
, name
, "value", ACPI_GED_SLP_EN
|
317 (ACPI_GED_SLP_TYP_S5
<< ACPI_GED_SLP_TYP_POS
));
321 static void fdt_add_uart_node(LoongArchVirtMachineState
*lvms
,
322 uint32_t *pch_pic_phandle
, hwaddr base
,
323 int irq
, bool chosen
)
326 hwaddr size
= VIRT_UART_SIZE
;
327 MachineState
*ms
= MACHINE(lvms
);
329 nodename
= g_strdup_printf("/serial@%" PRIx64
, base
);
330 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
331 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible", "ns16550a");
332 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "reg", 0x0, base
, 0x0, size
);
333 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "clock-frequency", 100000000);
335 qemu_fdt_setprop_string(ms
->fdt
, "/chosen", "stdout-path", nodename
);
336 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "interrupts", irq
, 0x4);
337 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "interrupt-parent",
342 static void create_fdt(LoongArchVirtMachineState
*lvms
)
344 MachineState
*ms
= MACHINE(lvms
);
345 uint8_t rng_seed
[32];
347 ms
->fdt
= create_device_tree(&lvms
->fdt_size
);
349 error_report("create_device_tree() failed");
354 qemu_fdt_setprop_string(ms
->fdt
, "/", "compatible",
355 "linux,dummy-loongson3");
356 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#address-cells", 0x2);
357 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#size-cells", 0x2);
358 qemu_fdt_add_subnode(ms
->fdt
, "/chosen");
360 /* Pass seed to RNG */
361 qemu_guest_getrandom_nofail(rng_seed
, sizeof(rng_seed
));
362 qemu_fdt_setprop(ms
->fdt
, "/chosen", "rng-seed", rng_seed
, sizeof(rng_seed
));
365 static void fdt_add_cpu_nodes(const LoongArchVirtMachineState
*lvms
)
368 const MachineState
*ms
= MACHINE(lvms
);
369 int smp_cpus
= ms
->smp
.cpus
;
371 qemu_fdt_add_subnode(ms
->fdt
, "/cpus");
372 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#address-cells", 0x1);
373 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#size-cells", 0x0);
376 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
377 char *nodename
= g_strdup_printf("/cpus/cpu@%d", num
);
378 LoongArchCPU
*cpu
= LOONGARCH_CPU(qemu_get_cpu(num
));
379 CPUState
*cs
= CPU(cpu
);
381 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
382 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "cpu");
383 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
384 cpu
->dtb_compatible
);
385 if (ms
->possible_cpus
->cpus
[cs
->cpu_index
].props
.has_node_id
) {
386 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "numa-node-id",
387 ms
->possible_cpus
->cpus
[cs
->cpu_index
].props
.node_id
);
389 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "reg", num
);
390 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle",
391 qemu_fdt_alloc_phandle(ms
->fdt
));
396 qemu_fdt_add_subnode(ms
->fdt
, "/cpus/cpu-map");
398 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
399 char *cpu_path
= g_strdup_printf("/cpus/cpu@%d", num
);
402 if (ms
->smp
.threads
> 1) {
403 map_path
= g_strdup_printf(
404 "/cpus/cpu-map/socket%d/core%d/thread%d",
405 num
/ (ms
->smp
.cores
* ms
->smp
.threads
),
406 (num
/ ms
->smp
.threads
) % ms
->smp
.cores
,
407 num
% ms
->smp
.threads
);
409 map_path
= g_strdup_printf(
410 "/cpus/cpu-map/socket%d/core%d",
412 num
% ms
->smp
.cores
);
414 qemu_fdt_add_path(ms
->fdt
, map_path
);
415 qemu_fdt_setprop_phandle(ms
->fdt
, map_path
, "cpu", cpu_path
);
422 static void fdt_add_fw_cfg_node(const LoongArchVirtMachineState
*lvms
)
425 hwaddr base
= VIRT_FWCFG_BASE
;
426 const MachineState
*ms
= MACHINE(lvms
);
428 nodename
= g_strdup_printf("/fw_cfg@%" PRIx64
, base
);
429 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
430 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
431 "compatible", "qemu,fw-cfg-mmio");
432 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
434 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
438 static void fdt_add_pcie_irq_map_node(const LoongArchVirtMachineState
*lvms
,
440 uint32_t *pch_pic_phandle
)
443 uint32_t irq_map_stride
= 0;
444 uint32_t full_irq_map
[GPEX_NUM_IRQS
*GPEX_NUM_IRQS
* 10] = {};
445 uint32_t *irq_map
= full_irq_map
;
446 const MachineState
*ms
= MACHINE(lvms
);
448 /* This code creates a standard swizzle of interrupts such that
449 * each device's first interrupt is based on it's PCI_SLOT number.
450 * (See pci_swizzle_map_irq_fn())
452 * We only need one entry per interrupt in the table (not one per
453 * possible slot) seeing the interrupt-map-mask will allow the table
454 * to wrap to any number of devices.
457 for (dev
= 0; dev
< GPEX_NUM_IRQS
; dev
++) {
458 int devfn
= dev
* 0x8;
460 for (pin
= 0; pin
< GPEX_NUM_IRQS
; pin
++) {
461 int irq_nr
= 16 + ((pin
+ PCI_SLOT(devfn
)) % GPEX_NUM_IRQS
);
464 /* Fill PCI address cells */
465 irq_map
[i
] = cpu_to_be32(devfn
<< 8);
468 /* Fill PCI Interrupt cells */
469 irq_map
[i
] = cpu_to_be32(pin
+ 1);
472 /* Fill interrupt controller phandle and cells */
473 irq_map
[i
++] = cpu_to_be32(*pch_pic_phandle
);
474 irq_map
[i
++] = cpu_to_be32(irq_nr
);
476 if (!irq_map_stride
) {
479 irq_map
+= irq_map_stride
;
484 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-map", full_irq_map
,
485 GPEX_NUM_IRQS
* GPEX_NUM_IRQS
*
486 irq_map_stride
* sizeof(uint32_t));
487 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "interrupt-map-mask",
491 static void fdt_add_pcie_node(const LoongArchVirtMachineState
*lvms
,
492 uint32_t *pch_pic_phandle
,
493 uint32_t *pch_msi_phandle
)
496 hwaddr base_mmio
= VIRT_PCI_MEM_BASE
;
497 hwaddr size_mmio
= VIRT_PCI_MEM_SIZE
;
498 hwaddr base_pio
= VIRT_PCI_IO_BASE
;
499 hwaddr size_pio
= VIRT_PCI_IO_SIZE
;
500 hwaddr base_pcie
= VIRT_PCI_CFG_BASE
;
501 hwaddr size_pcie
= VIRT_PCI_CFG_SIZE
;
502 hwaddr base
= base_pcie
;
504 const MachineState
*ms
= MACHINE(lvms
);
506 nodename
= g_strdup_printf("/pcie@%" PRIx64
, base
);
507 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
508 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
509 "compatible", "pci-host-ecam-generic");
510 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "pci");
511 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#address-cells", 3);
512 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#size-cells", 2);
513 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "linux,pci-domain", 0);
514 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "bus-range", 0,
515 PCIE_MMCFG_BUS(VIRT_PCI_CFG_SIZE
- 1));
516 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
517 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
518 2, base_pcie
, 2, size_pcie
);
519 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "ranges",
520 1, FDT_PCI_RANGE_IOPORT
, 2, VIRT_PCI_IO_OFFSET
,
521 2, base_pio
, 2, size_pio
,
522 1, FDT_PCI_RANGE_MMIO
, 2, base_mmio
,
523 2, base_mmio
, 2, size_mmio
);
524 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "msi-map",
525 0, *pch_msi_phandle
, 0, 0x10000);
527 fdt_add_pcie_irq_map_node(lvms
, nodename
, pch_pic_phandle
);
532 static void fdt_add_memory_node(MachineState
*ms
,
533 uint64_t base
, uint64_t size
, int node_id
)
535 char *nodename
= g_strdup_printf("/memory@%" PRIx64
, base
);
537 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
538 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "reg", base
>> 32, base
,
540 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "memory");
542 if (ms
->numa_state
&& ms
->numa_state
->num_nodes
) {
543 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "numa-node-id", node_id
);
549 static void fdt_add_memory_nodes(MachineState
*ms
)
551 hwaddr base
, size
, ram_size
, gap
;
552 int i
, nb_numa_nodes
, nodes
;
555 ram_size
= ms
->ram_size
;
556 base
= VIRT_LOWMEM_BASE
;
557 gap
= VIRT_LOWMEM_SIZE
;
558 nodes
= nb_numa_nodes
= ms
->numa_state
->num_nodes
;
559 numa_info
= ms
->numa_state
->nodes
;
564 for (i
= 0; i
< nodes
; i
++) {
566 size
= numa_info
[i
].node_mem
;
572 * memory for the node splited into two part
573 * lowram: [base, +gap)
574 * highram: [VIRT_HIGHMEM_BASE, +(len - gap))
577 fdt_add_memory_node(ms
, base
, gap
, i
);
579 base
= VIRT_HIGHMEM_BASE
;
580 gap
= ram_size
- VIRT_LOWMEM_SIZE
;
584 fdt_add_memory_node(ms
, base
, size
, i
);
591 static void virt_build_smbios(LoongArchVirtMachineState
*lvms
)
593 MachineState
*ms
= MACHINE(lvms
);
594 MachineClass
*mc
= MACHINE_GET_CLASS(lvms
);
595 uint8_t *smbios_tables
, *smbios_anchor
;
596 size_t smbios_tables_len
, smbios_anchor_len
;
597 const char *product
= "QEMU Virtual Machine";
603 smbios_set_defaults("QEMU", product
, mc
->name
);
605 smbios_get_tables(ms
, SMBIOS_ENTRY_POINT_TYPE_64
,
607 &smbios_tables
, &smbios_tables_len
,
608 &smbios_anchor
, &smbios_anchor_len
, &error_fatal
);
611 fw_cfg_add_file(lvms
->fw_cfg
, "etc/smbios/smbios-tables",
612 smbios_tables
, smbios_tables_len
);
613 fw_cfg_add_file(lvms
->fw_cfg
, "etc/smbios/smbios-anchor",
614 smbios_anchor
, smbios_anchor_len
);
618 static void virt_done(Notifier
*notifier
, void *data
)
620 LoongArchVirtMachineState
*lvms
= container_of(notifier
,
621 LoongArchVirtMachineState
, machine_done
);
622 virt_build_smbios(lvms
);
623 loongarch_acpi_setup(lvms
);
626 static void virt_powerdown_req(Notifier
*notifier
, void *opaque
)
628 LoongArchVirtMachineState
*s
;
630 s
= container_of(notifier
, LoongArchVirtMachineState
, powerdown_notifier
);
631 acpi_send_event(s
->acpi_ged
, ACPI_POWER_DOWN_STATUS
);
634 static void memmap_add_entry(uint64_t address
, uint64_t length
, uint32_t type
)
636 /* Ensure there are no duplicate entries. */
637 for (unsigned i
= 0; i
< memmap_entries
; i
++) {
638 assert(memmap_table
[i
].address
!= address
);
641 memmap_table
= g_renew(struct memmap_entry
, memmap_table
,
643 memmap_table
[memmap_entries
].address
= cpu_to_le64(address
);
644 memmap_table
[memmap_entries
].length
= cpu_to_le64(length
);
645 memmap_table
[memmap_entries
].type
= cpu_to_le32(type
);
646 memmap_table
[memmap_entries
].reserved
= 0;
650 static DeviceState
*create_acpi_ged(DeviceState
*pch_pic
,
651 LoongArchVirtMachineState
*lvms
)
654 MachineState
*ms
= MACHINE(lvms
);
655 uint32_t event
= ACPI_GED_PWR_DOWN_EVT
;
658 event
|= ACPI_GED_MEM_HOTPLUG_EVT
;
660 dev
= qdev_new(TYPE_ACPI_GED
);
661 qdev_prop_set_uint32(dev
, "ged-event", event
);
662 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
665 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, VIRT_GED_EVT_ADDR
);
667 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 1, VIRT_GED_MEM_ADDR
);
668 /* ged regs used for reset and power down */
669 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 2, VIRT_GED_REG_ADDR
);
671 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0,
672 qdev_get_gpio_in(pch_pic
, VIRT_SCI_IRQ
- VIRT_GSI_BASE
));
676 static DeviceState
*create_platform_bus(DeviceState
*pch_pic
)
679 SysBusDevice
*sysbus
;
681 MemoryRegion
*sysmem
= get_system_memory();
683 dev
= qdev_new(TYPE_PLATFORM_BUS_DEVICE
);
684 dev
->id
= g_strdup(TYPE_PLATFORM_BUS_DEVICE
);
685 qdev_prop_set_uint32(dev
, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS
);
686 qdev_prop_set_uint32(dev
, "mmio_size", VIRT_PLATFORM_BUS_SIZE
);
687 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
689 sysbus
= SYS_BUS_DEVICE(dev
);
690 for (i
= 0; i
< VIRT_PLATFORM_BUS_NUM_IRQS
; i
++) {
691 irq
= VIRT_PLATFORM_BUS_IRQ
- VIRT_GSI_BASE
+ i
;
692 sysbus_connect_irq(sysbus
, i
, qdev_get_gpio_in(pch_pic
, irq
));
695 memory_region_add_subregion(sysmem
,
696 VIRT_PLATFORM_BUS_BASEADDRESS
,
697 sysbus_mmio_get_region(sysbus
, 0));
701 static void virt_devices_init(DeviceState
*pch_pic
,
702 LoongArchVirtMachineState
*lvms
,
703 uint32_t *pch_pic_phandle
,
704 uint32_t *pch_msi_phandle
)
706 MachineClass
*mc
= MACHINE_GET_CLASS(lvms
);
707 DeviceState
*gpex_dev
;
710 MemoryRegion
*ecam_alias
, *ecam_reg
, *pio_alias
, *pio_reg
;
711 MemoryRegion
*mmio_alias
, *mmio_reg
;
714 gpex_dev
= qdev_new(TYPE_GPEX_HOST
);
715 d
= SYS_BUS_DEVICE(gpex_dev
);
716 sysbus_realize_and_unref(d
, &error_fatal
);
717 pci_bus
= PCI_HOST_BRIDGE(gpex_dev
)->bus
;
718 lvms
->pci_bus
= pci_bus
;
720 /* Map only part size_ecam bytes of ECAM space */
721 ecam_alias
= g_new0(MemoryRegion
, 1);
722 ecam_reg
= sysbus_mmio_get_region(d
, 0);
723 memory_region_init_alias(ecam_alias
, OBJECT(gpex_dev
), "pcie-ecam",
724 ecam_reg
, 0, VIRT_PCI_CFG_SIZE
);
725 memory_region_add_subregion(get_system_memory(), VIRT_PCI_CFG_BASE
,
728 /* Map PCI mem space */
729 mmio_alias
= g_new0(MemoryRegion
, 1);
730 mmio_reg
= sysbus_mmio_get_region(d
, 1);
731 memory_region_init_alias(mmio_alias
, OBJECT(gpex_dev
), "pcie-mmio",
732 mmio_reg
, VIRT_PCI_MEM_BASE
, VIRT_PCI_MEM_SIZE
);
733 memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE
,
736 /* Map PCI IO port space. */
737 pio_alias
= g_new0(MemoryRegion
, 1);
738 pio_reg
= sysbus_mmio_get_region(d
, 2);
739 memory_region_init_alias(pio_alias
, OBJECT(gpex_dev
), "pcie-io", pio_reg
,
740 VIRT_PCI_IO_OFFSET
, VIRT_PCI_IO_SIZE
);
741 memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE
,
744 for (i
= 0; i
< GPEX_NUM_IRQS
; i
++) {
745 sysbus_connect_irq(d
, i
,
746 qdev_get_gpio_in(pch_pic
, 16 + i
));
747 gpex_set_irq_num(GPEX_HOST(gpex_dev
), i
, 16 + i
);
751 fdt_add_pcie_node(lvms
, pch_pic_phandle
, pch_msi_phandle
);
754 * Create uart fdt node in reverse order so that they appear
755 * in the finished device tree lowest address first
757 for (i
= VIRT_UART_COUNT
; i
--> 0;) {
758 hwaddr base
= VIRT_UART_BASE
+ i
* VIRT_UART_SIZE
;
759 int irq
= VIRT_UART_IRQ
+ i
- VIRT_GSI_BASE
;
760 serial_mm_init(get_system_memory(), base
, 0,
761 qdev_get_gpio_in(pch_pic
, irq
),
762 115200, serial_hd(i
), DEVICE_LITTLE_ENDIAN
);
763 fdt_add_uart_node(lvms
, pch_pic_phandle
, base
, irq
, i
== 0);
767 pci_init_nic_devices(pci_bus
, mc
->default_nic
);
770 * There are some invalid guest memory access.
771 * Create some unimplemented devices to emulate this.
773 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
774 sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE
,
775 qdev_get_gpio_in(pch_pic
,
776 VIRT_RTC_IRQ
- VIRT_GSI_BASE
));
777 fdt_add_rtc_node(lvms
, pch_pic_phandle
);
778 fdt_add_ged_reset(lvms
);
781 lvms
->acpi_ged
= create_acpi_ged(pch_pic
, lvms
);
783 lvms
->platform_bus_dev
= create_platform_bus(pch_pic
);
786 static void virt_irq_init(LoongArchVirtMachineState
*lvms
)
788 MachineState
*ms
= MACHINE(lvms
);
789 DeviceState
*pch_pic
, *pch_msi
, *cpudev
;
790 DeviceState
*ipi
, *extioi
;
793 CPULoongArchState
*env
;
795 int cpu
, pin
, i
, start
, num
;
796 uint32_t cpuintc_phandle
, eiointc_phandle
, pch_pic_phandle
, pch_msi_phandle
;
799 * Extended IRQ model.
801 * +-----------+ +-------------|--------+ +-----------+
802 * | IPI/Timer | --> | CPUINTC(0-3)|(4-255) | <-- | IPI/Timer |
803 * +-----------+ +-------------|--------+ +-----------+
811 * +---------+ +---------+
812 * | PCH-PIC | | PCH-MSI |
813 * +---------+ +---------+
816 * +--------+ +---------+ +---------+
817 * | UARTs | | Devices | | Devices |
818 * +--------+ +---------+ +---------+
820 * Virt extended IRQ model.
822 * +-----+ +---------------+ +-------+
823 * | IPI |--> | CPUINTC(0-255)| <-- | Timer |
824 * +-----+ +---------------+ +-------+
832 * +---------+ +---------+
833 * | PCH-PIC | | PCH-MSI |
834 * +---------+ +---------+
837 * +--------+ +---------+ +---------+
838 * | UARTs | | Devices | | Devices |
839 * +--------+ +---------+ +---------+
842 /* Create IPI device */
843 ipi
= qdev_new(TYPE_LOONGARCH_IPI
);
844 qdev_prop_set_uint32(ipi
, "num-cpu", ms
->smp
.cpus
);
845 sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi
), &error_fatal
);
847 /* IPI iocsr memory region */
848 memory_region_add_subregion(&lvms
->system_iocsr
, SMP_IPI_MAILBOX
,
849 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
), 0));
850 memory_region_add_subregion(&lvms
->system_iocsr
, MAIL_SEND_ADDR
,
851 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
), 1));
853 /* Add cpu interrupt-controller */
854 fdt_add_cpuic_node(lvms
, &cpuintc_phandle
);
856 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
857 cpu_state
= qemu_get_cpu(cpu
);
858 cpudev
= DEVICE(cpu_state
);
859 lacpu
= LOONGARCH_CPU(cpu_state
);
861 env
->address_space_iocsr
= &lvms
->as_iocsr
;
863 /* connect ipi irq to cpu irq */
864 qdev_connect_gpio_out(ipi
, cpu
, qdev_get_gpio_in(cpudev
, IRQ_IPI
));
868 /* Create EXTIOI device */
869 extioi
= qdev_new(TYPE_LOONGARCH_EXTIOI
);
870 qdev_prop_set_uint32(extioi
, "num-cpu", ms
->smp
.cpus
);
871 if (virt_is_veiointc_enabled(lvms
)) {
872 qdev_prop_set_bit(extioi
, "has-virtualization-extension", true);
874 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi
), &error_fatal
);
875 memory_region_add_subregion(&lvms
->system_iocsr
, APIC_BASE
,
876 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi
), 0));
877 if (virt_is_veiointc_enabled(lvms
)) {
878 memory_region_add_subregion(&lvms
->system_iocsr
, EXTIOI_VIRT_BASE
,
879 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi
), 1));
883 * connect ext irq to the cpu irq
884 * cpu_pin[9:2] <= intc_pin[7:0]
886 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
887 cpudev
= DEVICE(qemu_get_cpu(cpu
));
888 for (pin
= 0; pin
< LS3A_INTC_IP
; pin
++) {
889 qdev_connect_gpio_out(extioi
, (cpu
* 8 + pin
),
890 qdev_get_gpio_in(cpudev
, pin
+ 2));
894 /* Add Extend I/O Interrupt Controller node */
895 fdt_add_eiointc_node(lvms
, &cpuintc_phandle
, &eiointc_phandle
);
897 pch_pic
= qdev_new(TYPE_LOONGARCH_PCH_PIC
);
898 num
= VIRT_PCH_PIC_IRQ_NUM
;
899 qdev_prop_set_uint32(pch_pic
, "pch_pic_irq_num", num
);
900 d
= SYS_BUS_DEVICE(pch_pic
);
901 sysbus_realize_and_unref(d
, &error_fatal
);
902 memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE
,
903 sysbus_mmio_get_region(d
, 0));
904 memory_region_add_subregion(get_system_memory(),
905 VIRT_IOAPIC_REG_BASE
+ PCH_PIC_ROUTE_ENTRY_OFFSET
,
906 sysbus_mmio_get_region(d
, 1));
907 memory_region_add_subregion(get_system_memory(),
908 VIRT_IOAPIC_REG_BASE
+ PCH_PIC_INT_STATUS_LO
,
909 sysbus_mmio_get_region(d
, 2));
911 /* Connect pch_pic irqs to extioi */
912 for (i
= 0; i
< num
; i
++) {
913 qdev_connect_gpio_out(DEVICE(d
), i
, qdev_get_gpio_in(extioi
, i
));
916 /* Add PCH PIC node */
917 fdt_add_pch_pic_node(lvms
, &eiointc_phandle
, &pch_pic_phandle
);
919 pch_msi
= qdev_new(TYPE_LOONGARCH_PCH_MSI
);
921 num
= EXTIOI_IRQS
- start
;
922 qdev_prop_set_uint32(pch_msi
, "msi_irq_base", start
);
923 qdev_prop_set_uint32(pch_msi
, "msi_irq_num", num
);
924 d
= SYS_BUS_DEVICE(pch_msi
);
925 sysbus_realize_and_unref(d
, &error_fatal
);
926 sysbus_mmio_map(d
, 0, VIRT_PCH_MSI_ADDR_LOW
);
927 for (i
= 0; i
< num
; i
++) {
928 /* Connect pch_msi irqs to extioi */
929 qdev_connect_gpio_out(DEVICE(d
), i
,
930 qdev_get_gpio_in(extioi
, i
+ start
));
933 /* Add PCH MSI node */
934 fdt_add_pch_msi_node(lvms
, &eiointc_phandle
, &pch_msi_phandle
);
936 virt_devices_init(pch_pic
, lvms
, &pch_pic_phandle
, &pch_msi_phandle
);
939 static void virt_firmware_init(LoongArchVirtMachineState
*lvms
)
941 char *filename
= MACHINE(lvms
)->firmware
;
942 char *bios_name
= NULL
;
944 BlockBackend
*pflash_blk0
;
947 lvms
->bios_loaded
= false;
949 /* Map legacy -drive if=pflash to machine properties */
950 for (i
= 0; i
< ARRAY_SIZE(lvms
->flash
); i
++) {
951 pflash_cfi01_legacy_drive(lvms
->flash
[i
],
952 drive_get(IF_PFLASH
, 0, i
));
955 virt_flash_map(lvms
, get_system_memory());
957 pflash_blk0
= pflash_cfi01_get_blk(lvms
->flash
[0]);
961 error_report("cannot use both '-bios' and '-drive if=pflash'"
965 lvms
->bios_loaded
= true;
970 bios_name
= qemu_find_file(QEMU_FILE_TYPE_BIOS
, filename
);
972 error_report("Could not find ROM image '%s'", filename
);
976 mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(lvms
->flash
[0]), 0);
977 bios_size
= load_image_mr(bios_name
, mr
);
979 error_report("Could not load ROM image '%s'", bios_name
);
983 lvms
->bios_loaded
= true;
987 static MemTxResult
virt_iocsr_misc_write(void *opaque
, hwaddr addr
,
988 uint64_t val
, unsigned size
,
991 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(opaque
);
996 if (!virt_is_veiointc_enabled(lvms
)) {
1000 features
= address_space_ldl(&lvms
->as_iocsr
,
1001 EXTIOI_VIRT_BASE
+ EXTIOI_VIRT_CONFIG
,
1003 if (val
& BIT_ULL(IOCSRM_EXTIOI_EN
)) {
1004 features
|= BIT(EXTIOI_ENABLE
);
1006 if (val
& BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE
)) {
1007 features
|= BIT(EXTIOI_ENABLE_INT_ENCODE
);
1010 address_space_stl(&lvms
->as_iocsr
,
1011 EXTIOI_VIRT_BASE
+ EXTIOI_VIRT_CONFIG
,
1012 features
, attrs
, NULL
);
1015 g_assert_not_reached();
1021 static MemTxResult
virt_iocsr_misc_read(void *opaque
, hwaddr addr
,
1023 unsigned size
, MemTxAttrs attrs
)
1025 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(opaque
);
1034 ret
= BIT(IOCSRF_MSI
) | BIT(IOCSRF_EXTIOI
) | BIT(IOCSRF_CSRIPI
);
1035 if (kvm_enabled()) {
1036 ret
|= BIT(IOCSRF_VM
);
1040 ret
= 0x6e6f73676e6f6f4cULL
; /* "Loongson" */
1043 ret
= 0x303030354133ULL
; /* "3A5000" */
1046 if (!virt_is_veiointc_enabled(lvms
)) {
1047 ret
|= BIT_ULL(IOCSRM_EXTIOI_EN
);
1051 features
= address_space_ldl(&lvms
->as_iocsr
,
1052 EXTIOI_VIRT_BASE
+ EXTIOI_VIRT_CONFIG
,
1054 if (features
& BIT(EXTIOI_ENABLE
)) {
1055 ret
|= BIT_ULL(IOCSRM_EXTIOI_EN
);
1057 if (features
& BIT(EXTIOI_ENABLE_INT_ENCODE
)) {
1058 ret
|= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE
);
1062 g_assert_not_reached();
1069 static const MemoryRegionOps virt_iocsr_misc_ops
= {
1070 .read_with_attrs
= virt_iocsr_misc_read
,
1071 .write_with_attrs
= virt_iocsr_misc_write
,
1072 .endianness
= DEVICE_LITTLE_ENDIAN
,
1074 .min_access_size
= 4,
1075 .max_access_size
= 8,
1078 .min_access_size
= 8,
1079 .max_access_size
= 8,
1083 static void fw_cfg_add_memory(MachineState
*ms
)
1085 hwaddr base
, size
, ram_size
, gap
;
1086 int nb_numa_nodes
, nodes
;
1087 NodeInfo
*numa_info
;
1089 ram_size
= ms
->ram_size
;
1090 base
= VIRT_LOWMEM_BASE
;
1091 gap
= VIRT_LOWMEM_SIZE
;
1092 nodes
= nb_numa_nodes
= ms
->numa_state
->num_nodes
;
1093 numa_info
= ms
->numa_state
->nodes
;
1098 /* add fw_cfg memory map of node0 */
1099 if (nb_numa_nodes
) {
1100 size
= numa_info
[0].node_mem
;
1106 memmap_add_entry(base
, gap
, 1);
1108 base
= VIRT_HIGHMEM_BASE
;
1112 memmap_add_entry(base
, size
, 1);
1120 /* add fw_cfg memory map of other nodes */
1121 if (numa_info
[0].node_mem
< gap
&& ram_size
> gap
) {
1123 * memory map for the maining nodes splited into two part
1124 * lowram: [base, +(gap - numa_info[0].node_mem))
1125 * highram: [VIRT_HIGHMEM_BASE, +(ram_size - gap))
1127 memmap_add_entry(base
, gap
- numa_info
[0].node_mem
, 1);
1128 size
= ram_size
- gap
;
1129 base
= VIRT_HIGHMEM_BASE
;
1131 size
= ram_size
- numa_info
[0].node_mem
;
1135 memmap_add_entry(base
, size
, 1);
1138 static void virt_init(MachineState
*machine
)
1140 LoongArchCPU
*lacpu
;
1141 const char *cpu_model
= machine
->cpu_type
;
1142 MemoryRegion
*address_space_mem
= get_system_memory();
1143 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(machine
);
1145 hwaddr base
, size
, ram_size
= machine
->ram_size
;
1146 const CPUArchIdList
*possible_cpus
;
1147 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
1151 cpu_model
= LOONGARCH_CPU_TYPE_NAME("la464");
1156 /* Create IOCSR space */
1157 memory_region_init_io(&lvms
->system_iocsr
, OBJECT(machine
), NULL
,
1158 machine
, "iocsr", UINT64_MAX
);
1159 address_space_init(&lvms
->as_iocsr
, &lvms
->system_iocsr
, "IOCSR");
1160 memory_region_init_io(&lvms
->iocsr_mem
, OBJECT(machine
),
1161 &virt_iocsr_misc_ops
,
1162 machine
, "iocsr_misc", 0x428);
1163 memory_region_add_subregion(&lvms
->system_iocsr
, 0, &lvms
->iocsr_mem
);
1166 possible_cpus
= mc
->possible_cpu_arch_ids(machine
);
1167 for (i
= 0; i
< possible_cpus
->len
; i
++) {
1168 cpu
= cpu_create(machine
->cpu_type
);
1170 machine
->possible_cpus
->cpus
[i
].cpu
= cpu
;
1171 lacpu
= LOONGARCH_CPU(cpu
);
1172 lacpu
->phy_id
= machine
->possible_cpus
->cpus
[i
].arch_id
;
1174 fdt_add_cpu_nodes(lvms
);
1175 fdt_add_memory_nodes(machine
);
1176 fw_cfg_add_memory(machine
);
1180 base
= VIRT_LOWMEM_BASE
;
1181 if (size
> VIRT_LOWMEM_SIZE
) {
1182 size
= VIRT_LOWMEM_SIZE
;
1185 memory_region_init_alias(&lvms
->lowmem
, NULL
, "loongarch.lowram",
1186 machine
->ram
, base
, size
);
1187 memory_region_add_subregion(address_space_mem
, base
, &lvms
->lowmem
);
1189 if (ram_size
- size
) {
1190 base
= VIRT_HIGHMEM_BASE
;
1191 memory_region_init_alias(&lvms
->highmem
, NULL
, "loongarch.highram",
1192 machine
->ram
, VIRT_LOWMEM_BASE
+ size
, ram_size
- size
);
1193 memory_region_add_subregion(address_space_mem
, base
, &lvms
->highmem
);
1194 base
+= ram_size
- size
;
1197 /* initialize device memory address space */
1198 if (machine
->ram_size
< machine
->maxram_size
) {
1199 ram_addr_t device_mem_size
= machine
->maxram_size
- machine
->ram_size
;
1201 if (machine
->ram_slots
> ACPI_MAX_RAM_SLOTS
) {
1202 error_report("unsupported amount of memory slots: %"PRIu64
,
1203 machine
->ram_slots
);
1207 if (QEMU_ALIGN_UP(machine
->maxram_size
,
1208 TARGET_PAGE_SIZE
) != machine
->maxram_size
) {
1209 error_report("maximum memory size must by aligned to multiple of "
1210 "%d bytes", TARGET_PAGE_SIZE
);
1213 machine_memory_devices_init(machine
, base
, device_mem_size
);
1216 /* load the BIOS image. */
1217 virt_firmware_init(lvms
);
1220 lvms
->fw_cfg
= virt_fw_cfg_init(ram_size
, machine
);
1221 rom_set_fw(lvms
->fw_cfg
);
1222 if (lvms
->fw_cfg
!= NULL
) {
1223 fw_cfg_add_file(lvms
->fw_cfg
, "etc/memmap",
1225 sizeof(struct memmap_entry
) * (memmap_entries
));
1227 fdt_add_fw_cfg_node(lvms
);
1228 fdt_add_flash_node(lvms
);
1230 /* Initialize the IO interrupt subsystem */
1231 virt_irq_init(lvms
);
1232 platform_bus_add_all_fdt_nodes(machine
->fdt
, "/platic",
1233 VIRT_PLATFORM_BUS_BASEADDRESS
,
1234 VIRT_PLATFORM_BUS_SIZE
,
1235 VIRT_PLATFORM_BUS_IRQ
);
1236 lvms
->machine_done
.notify
= virt_done
;
1237 qemu_add_machine_init_done_notifier(&lvms
->machine_done
);
1238 /* connect powerdown request */
1239 lvms
->powerdown_notifier
.notify
= virt_powerdown_req
;
1240 qemu_register_powerdown_notifier(&lvms
->powerdown_notifier
);
1243 * Since lowmem region starts from 0 and Linux kernel legacy start address
1244 * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
1245 * access. FDT size limit with 1 MiB.
1246 * Put the FDT into the memory map as a ROM image: this will ensure
1247 * the FDT is copied again upon reset, even if addr points into RAM.
1249 qemu_fdt_dumpdtb(machine
->fdt
, lvms
->fdt_size
);
1250 rom_add_blob_fixed_as("fdt", machine
->fdt
, lvms
->fdt_size
, FDT_BASE
,
1251 &address_space_memory
);
1252 qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds
,
1253 rom_ptr_for_as(&address_space_memory
, FDT_BASE
, lvms
->fdt_size
));
1255 lvms
->bootinfo
.ram_size
= ram_size
;
1256 loongarch_load_kernel(machine
, &lvms
->bootinfo
);
1259 static void virt_get_acpi(Object
*obj
, Visitor
*v
, const char *name
,
1260 void *opaque
, Error
**errp
)
1262 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(obj
);
1263 OnOffAuto acpi
= lvms
->acpi
;
1265 visit_type_OnOffAuto(v
, name
, &acpi
, errp
);
1268 static void virt_set_acpi(Object
*obj
, Visitor
*v
, const char *name
,
1269 void *opaque
, Error
**errp
)
1271 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(obj
);
1273 visit_type_OnOffAuto(v
, name
, &lvms
->acpi
, errp
);
1276 static void virt_initfn(Object
*obj
)
1278 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(obj
);
1280 if (tcg_enabled()) {
1281 lvms
->veiointc
= ON_OFF_AUTO_OFF
;
1283 lvms
->acpi
= ON_OFF_AUTO_AUTO
;
1284 lvms
->oem_id
= g_strndup(ACPI_BUILD_APPNAME6
, 6);
1285 lvms
->oem_table_id
= g_strndup(ACPI_BUILD_APPNAME8
, 8);
1286 virt_flash_create(lvms
);
1289 static bool memhp_type_supported(DeviceState
*dev
)
1291 /* we only support pc dimm now */
1292 return object_dynamic_cast(OBJECT(dev
), TYPE_PC_DIMM
) &&
1293 !object_dynamic_cast(OBJECT(dev
), TYPE_NVDIMM
);
1296 static void virt_mem_pre_plug(HotplugHandler
*hotplug_dev
, DeviceState
*dev
,
1299 pc_dimm_pre_plug(PC_DIMM(dev
), MACHINE(hotplug_dev
), errp
);
1302 static void virt_device_pre_plug(HotplugHandler
*hotplug_dev
,
1303 DeviceState
*dev
, Error
**errp
)
1305 if (memhp_type_supported(dev
)) {
1306 virt_mem_pre_plug(hotplug_dev
, dev
, errp
);
1310 static void virt_mem_unplug_request(HotplugHandler
*hotplug_dev
,
1311 DeviceState
*dev
, Error
**errp
)
1313 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(hotplug_dev
);
1315 /* the acpi ged is always exist */
1316 hotplug_handler_unplug_request(HOTPLUG_HANDLER(lvms
->acpi_ged
), dev
,
1320 static void virt_device_unplug_request(HotplugHandler
*hotplug_dev
,
1321 DeviceState
*dev
, Error
**errp
)
1323 if (memhp_type_supported(dev
)) {
1324 virt_mem_unplug_request(hotplug_dev
, dev
, errp
);
1328 static void virt_mem_unplug(HotplugHandler
*hotplug_dev
,
1329 DeviceState
*dev
, Error
**errp
)
1331 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(hotplug_dev
);
1333 hotplug_handler_unplug(HOTPLUG_HANDLER(lvms
->acpi_ged
), dev
, errp
);
1334 pc_dimm_unplug(PC_DIMM(dev
), MACHINE(lvms
));
1335 qdev_unrealize(dev
);
1338 static void virt_device_unplug(HotplugHandler
*hotplug_dev
,
1339 DeviceState
*dev
, Error
**errp
)
1341 if (memhp_type_supported(dev
)) {
1342 virt_mem_unplug(hotplug_dev
, dev
, errp
);
1346 static void virt_mem_plug(HotplugHandler
*hotplug_dev
,
1347 DeviceState
*dev
, Error
**errp
)
1349 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(hotplug_dev
);
1351 pc_dimm_plug(PC_DIMM(dev
), MACHINE(lvms
));
1352 hotplug_handler_plug(HOTPLUG_HANDLER(lvms
->acpi_ged
),
1356 static void virt_device_plug_cb(HotplugHandler
*hotplug_dev
,
1357 DeviceState
*dev
, Error
**errp
)
1359 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(hotplug_dev
);
1360 MachineClass
*mc
= MACHINE_GET_CLASS(lvms
);
1361 PlatformBusDevice
*pbus
;
1363 if (device_is_dynamic_sysbus(mc
, dev
)) {
1364 if (lvms
->platform_bus_dev
) {
1365 pbus
= PLATFORM_BUS_DEVICE(lvms
->platform_bus_dev
);
1366 platform_bus_link_device(pbus
, SYS_BUS_DEVICE(dev
));
1368 } else if (memhp_type_supported(dev
)) {
1369 virt_mem_plug(hotplug_dev
, dev
, errp
);
1373 static HotplugHandler
*virt_get_hotplug_handler(MachineState
*machine
,
1376 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
1378 if (device_is_dynamic_sysbus(mc
, dev
) ||
1379 object_dynamic_cast(OBJECT(dev
), TYPE_VIRTIO_IOMMU_PCI
) ||
1380 memhp_type_supported(dev
)) {
1381 return HOTPLUG_HANDLER(machine
);
1386 static const CPUArchIdList
*virt_possible_cpu_arch_ids(MachineState
*ms
)
1389 unsigned int max_cpus
= ms
->smp
.max_cpus
;
1391 if (ms
->possible_cpus
) {
1392 assert(ms
->possible_cpus
->len
== max_cpus
);
1393 return ms
->possible_cpus
;
1396 ms
->possible_cpus
= g_malloc0(sizeof(CPUArchIdList
) +
1397 sizeof(CPUArchId
) * max_cpus
);
1398 ms
->possible_cpus
->len
= max_cpus
;
1399 for (n
= 0; n
< ms
->possible_cpus
->len
; n
++) {
1400 ms
->possible_cpus
->cpus
[n
].type
= ms
->cpu_type
;
1401 ms
->possible_cpus
->cpus
[n
].arch_id
= n
;
1403 ms
->possible_cpus
->cpus
[n
].props
.has_socket_id
= true;
1404 ms
->possible_cpus
->cpus
[n
].props
.socket_id
=
1405 n
/ (ms
->smp
.cores
* ms
->smp
.threads
);
1406 ms
->possible_cpus
->cpus
[n
].props
.has_core_id
= true;
1407 ms
->possible_cpus
->cpus
[n
].props
.core_id
=
1408 n
/ ms
->smp
.threads
% ms
->smp
.cores
;
1409 ms
->possible_cpus
->cpus
[n
].props
.has_thread_id
= true;
1410 ms
->possible_cpus
->cpus
[n
].props
.thread_id
= n
% ms
->smp
.threads
;
1412 return ms
->possible_cpus
;
1415 static CpuInstanceProperties
virt_cpu_index_to_props(MachineState
*ms
,
1418 MachineClass
*mc
= MACHINE_GET_CLASS(ms
);
1419 const CPUArchIdList
*possible_cpus
= mc
->possible_cpu_arch_ids(ms
);
1421 assert(cpu_index
< possible_cpus
->len
);
1422 return possible_cpus
->cpus
[cpu_index
].props
;
1425 static int64_t virt_get_default_cpu_node_id(const MachineState
*ms
, int idx
)
1429 if (ms
->numa_state
->num_nodes
) {
1430 socket_id
= ms
->possible_cpus
->cpus
[idx
].props
.socket_id
;
1431 return socket_id
% ms
->numa_state
->num_nodes
;
1437 static void virt_class_init(ObjectClass
*oc
, void *data
)
1439 MachineClass
*mc
= MACHINE_CLASS(oc
);
1440 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(oc
);
1442 mc
->init
= virt_init
;
1443 mc
->default_cpu_type
= LOONGARCH_CPU_TYPE_NAME("la464");
1444 mc
->default_ram_id
= "loongarch.ram";
1445 mc
->desc
= "QEMU LoongArch Virtual Machine";
1446 mc
->max_cpus
= LOONGARCH_MAX_CPUS
;
1448 mc
->default_kernel_irqchip_split
= false;
1449 mc
->block_default_type
= IF_VIRTIO
;
1450 mc
->default_boot_order
= "c";
1452 mc
->possible_cpu_arch_ids
= virt_possible_cpu_arch_ids
;
1453 mc
->cpu_index_to_instance_props
= virt_cpu_index_to_props
;
1454 mc
->get_default_cpu_node_id
= virt_get_default_cpu_node_id
;
1455 mc
->numa_mem_supported
= true;
1456 mc
->auto_enable_numa_with_memhp
= true;
1457 mc
->auto_enable_numa_with_memdev
= true;
1458 mc
->get_hotplug_handler
= virt_get_hotplug_handler
;
1459 mc
->default_nic
= "virtio-net-pci";
1460 hc
->plug
= virt_device_plug_cb
;
1461 hc
->pre_plug
= virt_device_pre_plug
;
1462 hc
->unplug_request
= virt_device_unplug_request
;
1463 hc
->unplug
= virt_device_unplug
;
1465 object_class_property_add(oc
, "acpi", "OnOffAuto",
1466 virt_get_acpi
, virt_set_acpi
,
1468 object_class_property_set_description(oc
, "acpi",
1470 object_class_property_add(oc
, "v-eiointc", "OnOffAuto",
1471 virt_get_veiointc
, virt_set_veiointc
,
1473 object_class_property_set_description(oc
, "v-eiointc",
1474 "Enable Virt Extend I/O Interrupt Controller.");
1475 machine_class_allow_dynamic_sysbus_dev(mc
, TYPE_RAMFB_DEVICE
);
1477 machine_class_allow_dynamic_sysbus_dev(mc
, TYPE_TPM_TIS_SYSBUS
);
1481 static const TypeInfo virt_machine_types
[] = {
1483 .name
= TYPE_LOONGARCH_VIRT_MACHINE
,
1484 .parent
= TYPE_MACHINE
,
1485 .instance_size
= sizeof(LoongArchVirtMachineState
),
1486 .class_init
= virt_class_init
,
1487 .instance_init
= virt_initfn
,
1488 .interfaces
= (InterfaceInfo
[]) {
1489 { TYPE_HOTPLUG_HANDLER
},
1495 DEFINE_TYPES(virt_machine_types
)