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.h"
13 #include "sysemu/sysemu.h"
14 #include "sysemu/qtest.h"
15 #include "sysemu/runstate.h"
16 #include "sysemu/reset.h"
17 #include "sysemu/rtc.h"
18 #include "hw/loongarch/virt.h"
19 #include "exec/address-spaces.h"
22 #include "hw/loader.h"
24 #include "hw/intc/loongarch_ipi.h"
25 #include "hw/intc/loongarch_extioi.h"
26 #include "hw/intc/loongarch_pch_pic.h"
27 #include "hw/intc/loongarch_pch_msi.h"
28 #include "hw/pci-host/ls7a.h"
29 #include "hw/pci-host/gpex.h"
30 #include "hw/misc/unimp.h"
31 #include "hw/loongarch/fw_cfg.h"
32 #include "target/loongarch/cpu.h"
33 #include "hw/firmware/smbios.h"
34 #include "hw/acpi/aml-build.h"
35 #include "qapi/qapi-visit-common.h"
36 #include "hw/acpi/generic_event_device.h"
37 #include "hw/mem/nvdimm.h"
38 #include "sysemu/device_tree.h"
40 #include "hw/core/sysbus-fdt.h"
41 #include "hw/platform-bus.h"
43 static void create_fdt(LoongArchMachineState
*lams
)
45 MachineState
*ms
= MACHINE(lams
);
47 ms
->fdt
= create_device_tree(&lams
->fdt_size
);
49 error_report("create_device_tree() failed");
54 qemu_fdt_setprop_string(ms
->fdt
, "/", "compatible",
55 "linux,dummy-loongson3");
56 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#address-cells", 0x2);
57 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#size-cells", 0x2);
60 static void fdt_add_cpu_nodes(const LoongArchMachineState
*lams
)
63 const MachineState
*ms
= MACHINE(lams
);
64 int smp_cpus
= ms
->smp
.cpus
;
66 qemu_fdt_add_subnode(ms
->fdt
, "/cpus");
67 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#address-cells", 0x1);
68 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#size-cells", 0x0);
71 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
72 char *nodename
= g_strdup_printf("/cpus/cpu@%d", num
);
73 LoongArchCPU
*cpu
= LOONGARCH_CPU(qemu_get_cpu(num
));
75 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
76 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "cpu");
77 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
79 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "reg", num
);
80 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle",
81 qemu_fdt_alloc_phandle(ms
->fdt
));
86 qemu_fdt_add_subnode(ms
->fdt
, "/cpus/cpu-map");
88 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
89 char *cpu_path
= g_strdup_printf("/cpus/cpu@%d", num
);
92 if (ms
->smp
.threads
> 1) {
93 map_path
= g_strdup_printf(
94 "/cpus/cpu-map/socket%d/core%d/thread%d",
95 num
/ (ms
->smp
.cores
* ms
->smp
.threads
),
96 (num
/ ms
->smp
.threads
) % ms
->smp
.cores
,
97 num
% ms
->smp
.threads
);
99 map_path
= g_strdup_printf(
100 "/cpus/cpu-map/socket%d/core%d",
102 num
% ms
->smp
.cores
);
104 qemu_fdt_add_path(ms
->fdt
, map_path
);
105 qemu_fdt_setprop_phandle(ms
->fdt
, map_path
, "cpu", cpu_path
);
112 static void fdt_add_fw_cfg_node(const LoongArchMachineState
*lams
)
115 hwaddr base
= VIRT_FWCFG_BASE
;
116 const MachineState
*ms
= MACHINE(lams
);
118 nodename
= g_strdup_printf("/fw_cfg@%" PRIx64
, base
);
119 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
120 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
121 "compatible", "qemu,fw-cfg-mmio");
122 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
124 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
128 static void fdt_add_pcie_node(const LoongArchMachineState
*lams
)
131 hwaddr base_mmio
= VIRT_PCI_MEM_BASE
;
132 hwaddr size_mmio
= VIRT_PCI_MEM_SIZE
;
133 hwaddr base_pio
= VIRT_PCI_IO_BASE
;
134 hwaddr size_pio
= VIRT_PCI_IO_SIZE
;
135 hwaddr base_pcie
= VIRT_PCI_CFG_BASE
;
136 hwaddr size_pcie
= VIRT_PCI_CFG_SIZE
;
137 hwaddr base
= base_pcie
;
139 const MachineState
*ms
= MACHINE(lams
);
141 nodename
= g_strdup_printf("/pcie@%" PRIx64
, base
);
142 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
143 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
144 "compatible", "pci-host-ecam-generic");
145 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "pci");
146 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#address-cells", 3);
147 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#size-cells", 2);
148 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "linux,pci-domain", 0);
149 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "bus-range", 0,
150 PCIE_MMCFG_BUS(VIRT_PCI_CFG_SIZE
- 1));
151 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
152 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
153 2, base_pcie
, 2, size_pcie
);
154 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "ranges",
155 1, FDT_PCI_RANGE_IOPORT
, 2, VIRT_PCI_IO_OFFSET
,
156 2, base_pio
, 2, size_pio
,
157 1, FDT_PCI_RANGE_MMIO
, 2, base_mmio
,
158 2, base_mmio
, 2, size_mmio
);
160 qemu_fdt_dumpdtb(ms
->fdt
, lams
->fdt_size
);
163 static void fdt_add_irqchip_node(LoongArchMachineState
*lams
)
165 MachineState
*ms
= MACHINE(lams
);
167 uint32_t irqchip_phandle
;
169 irqchip_phandle
= qemu_fdt_alloc_phandle(ms
->fdt
);
170 qemu_fdt_setprop_cell(ms
->fdt
, "/", "interrupt-parent", irqchip_phandle
);
172 nodename
= g_strdup_printf("/intc@%lx", VIRT_IOAPIC_REG_BASE
);
173 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
174 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#interrupt-cells", 3);
175 qemu_fdt_setprop(ms
->fdt
, nodename
, "interrupt-controller", NULL
, 0);
176 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#address-cells", 0x2);
177 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#size-cells", 0x2);
178 qemu_fdt_setprop(ms
->fdt
, nodename
, "ranges", NULL
, 0);
180 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
183 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
184 2, VIRT_IOAPIC_REG_BASE
,
185 2, PCH_PIC_ROUTE_ENTRY_OFFSET
);
187 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle", irqchip_phandle
);
191 #define PM_BASE 0x10080000
192 #define PM_SIZE 0x100
195 static void virt_build_smbios(LoongArchMachineState
*lams
)
197 MachineState
*ms
= MACHINE(lams
);
198 MachineClass
*mc
= MACHINE_GET_CLASS(lams
);
199 uint8_t *smbios_tables
, *smbios_anchor
;
200 size_t smbios_tables_len
, smbios_anchor_len
;
201 const char *product
= "QEMU Virtual Machine";
207 smbios_set_defaults("QEMU", product
, mc
->name
, false,
208 true, SMBIOS_ENTRY_POINT_TYPE_64
);
210 smbios_get_tables(ms
, NULL
, 0, &smbios_tables
, &smbios_tables_len
,
211 &smbios_anchor
, &smbios_anchor_len
, &error_fatal
);
214 fw_cfg_add_file(lams
->fw_cfg
, "etc/smbios/smbios-tables",
215 smbios_tables
, smbios_tables_len
);
216 fw_cfg_add_file(lams
->fw_cfg
, "etc/smbios/smbios-anchor",
217 smbios_anchor
, smbios_anchor_len
);
221 static void virt_machine_done(Notifier
*notifier
, void *data
)
223 LoongArchMachineState
*lams
= container_of(notifier
,
224 LoongArchMachineState
, machine_done
);
225 virt_build_smbios(lams
);
226 loongarch_acpi_setup(lams
);
229 struct memmap_entry
{
236 static struct memmap_entry
*memmap_table
;
237 static unsigned memmap_entries
;
239 static void memmap_add_entry(uint64_t address
, uint64_t length
, uint32_t type
)
241 /* Ensure there are no duplicate entries. */
242 for (unsigned i
= 0; i
< memmap_entries
; i
++) {
243 assert(memmap_table
[i
].address
!= address
);
246 memmap_table
= g_renew(struct memmap_entry
, memmap_table
,
248 memmap_table
[memmap_entries
].address
= cpu_to_le64(address
);
249 memmap_table
[memmap_entries
].length
= cpu_to_le64(length
);
250 memmap_table
[memmap_entries
].type
= cpu_to_le32(type
);
251 memmap_table
[memmap_entries
].reserved
= 0;
256 * This is a placeholder for missing ACPI,
257 * and will eventually be replaced.
259 static uint64_t loongarch_virt_pm_read(void *opaque
, hwaddr addr
, unsigned size
)
264 static void loongarch_virt_pm_write(void *opaque
, hwaddr addr
,
265 uint64_t val
, unsigned size
)
267 if (addr
!= PM_CTRL
) {
273 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET
);
276 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN
);
283 static const MemoryRegionOps loongarch_virt_pm_ops
= {
284 .read
= loongarch_virt_pm_read
,
285 .write
= loongarch_virt_pm_write
,
286 .endianness
= DEVICE_NATIVE_ENDIAN
,
288 .min_access_size
= 1,
293 static struct _loaderparams
{
295 const char *kernel_filename
;
296 const char *kernel_cmdline
;
297 const char *initrd_filename
;
300 static uint64_t cpu_loongarch_virt_to_phys(void *opaque
, uint64_t addr
)
302 return addr
& 0x1fffffffll
;
305 static int64_t load_kernel_info(void)
307 uint64_t kernel_entry
, kernel_low
, kernel_high
;
310 kernel_size
= load_elf(loaderparams
.kernel_filename
, NULL
,
311 cpu_loongarch_virt_to_phys
, NULL
,
312 &kernel_entry
, &kernel_low
,
313 &kernel_high
, NULL
, 0,
316 if (kernel_size
< 0) {
317 error_report("could not load kernel '%s': %s",
318 loaderparams
.kernel_filename
,
319 load_elf_strerror(kernel_size
));
325 static DeviceState
*create_acpi_ged(DeviceState
*pch_pic
, LoongArchMachineState
*lams
)
328 MachineState
*ms
= MACHINE(lams
);
329 uint32_t event
= ACPI_GED_PWR_DOWN_EVT
;
332 event
|= ACPI_GED_MEM_HOTPLUG_EVT
;
334 dev
= qdev_new(TYPE_ACPI_GED
);
335 qdev_prop_set_uint32(dev
, "ged-event", event
);
338 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, VIRT_GED_EVT_ADDR
);
340 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 1, VIRT_GED_MEM_ADDR
);
341 /* ged regs used for reset and power down */
342 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 2, VIRT_GED_REG_ADDR
);
344 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0,
345 qdev_get_gpio_in(pch_pic
, VIRT_SCI_IRQ
- PCH_PIC_IRQ_OFFSET
));
346 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
350 static DeviceState
*create_platform_bus(DeviceState
*pch_pic
)
353 SysBusDevice
*sysbus
;
355 MemoryRegion
*sysmem
= get_system_memory();
357 dev
= qdev_new(TYPE_PLATFORM_BUS_DEVICE
);
358 dev
->id
= g_strdup(TYPE_PLATFORM_BUS_DEVICE
);
359 qdev_prop_set_uint32(dev
, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS
);
360 qdev_prop_set_uint32(dev
, "mmio_size", VIRT_PLATFORM_BUS_SIZE
);
361 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
363 sysbus
= SYS_BUS_DEVICE(dev
);
364 for (i
= 0; i
< VIRT_PLATFORM_BUS_NUM_IRQS
; i
++) {
365 irq
= VIRT_PLATFORM_BUS_IRQ
- PCH_PIC_IRQ_OFFSET
+ i
;
366 sysbus_connect_irq(sysbus
, i
, qdev_get_gpio_in(pch_pic
, irq
));
369 memory_region_add_subregion(sysmem
,
370 VIRT_PLATFORM_BUS_BASEADDRESS
,
371 sysbus_mmio_get_region(sysbus
, 0));
375 static void loongarch_devices_init(DeviceState
*pch_pic
, LoongArchMachineState
*lams
)
377 DeviceState
*gpex_dev
;
380 MemoryRegion
*ecam_alias
, *ecam_reg
, *pio_alias
, *pio_reg
;
381 MemoryRegion
*mmio_alias
, *mmio_reg
, *pm_mem
;
384 gpex_dev
= qdev_new(TYPE_GPEX_HOST
);
385 d
= SYS_BUS_DEVICE(gpex_dev
);
386 sysbus_realize_and_unref(d
, &error_fatal
);
387 pci_bus
= PCI_HOST_BRIDGE(gpex_dev
)->bus
;
389 /* Map only part size_ecam bytes of ECAM space */
390 ecam_alias
= g_new0(MemoryRegion
, 1);
391 ecam_reg
= sysbus_mmio_get_region(d
, 0);
392 memory_region_init_alias(ecam_alias
, OBJECT(gpex_dev
), "pcie-ecam",
393 ecam_reg
, 0, VIRT_PCI_CFG_SIZE
);
394 memory_region_add_subregion(get_system_memory(), VIRT_PCI_CFG_BASE
,
397 /* Map PCI mem space */
398 mmio_alias
= g_new0(MemoryRegion
, 1);
399 mmio_reg
= sysbus_mmio_get_region(d
, 1);
400 memory_region_init_alias(mmio_alias
, OBJECT(gpex_dev
), "pcie-mmio",
401 mmio_reg
, VIRT_PCI_MEM_BASE
, VIRT_PCI_MEM_SIZE
);
402 memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE
,
405 /* Map PCI IO port space. */
406 pio_alias
= g_new0(MemoryRegion
, 1);
407 pio_reg
= sysbus_mmio_get_region(d
, 2);
408 memory_region_init_alias(pio_alias
, OBJECT(gpex_dev
), "pcie-io", pio_reg
,
409 VIRT_PCI_IO_OFFSET
, VIRT_PCI_IO_SIZE
);
410 memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE
,
413 for (i
= 0; i
< GPEX_NUM_IRQS
; i
++) {
414 sysbus_connect_irq(d
, i
,
415 qdev_get_gpio_in(pch_pic
, 16 + i
));
416 gpex_set_irq_num(GPEX_HOST(gpex_dev
), i
, 16 + i
);
419 serial_mm_init(get_system_memory(), VIRT_UART_BASE
, 0,
420 qdev_get_gpio_in(pch_pic
,
421 VIRT_UART_IRQ
- PCH_PIC_IRQ_OFFSET
),
422 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN
);
425 for (i
= 0; i
< nb_nics
; i
++) {
426 NICInfo
*nd
= &nd_table
[i
];
429 nd
->model
= g_strdup("virtio");
432 pci_nic_init_nofail(nd
, pci_bus
, nd
->model
, NULL
);
436 * There are some invalid guest memory access.
437 * Create some unimplemented devices to emulate this.
439 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
440 sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE
,
441 qdev_get_gpio_in(pch_pic
,
442 VIRT_RTC_IRQ
- PCH_PIC_IRQ_OFFSET
));
444 pm_mem
= g_new(MemoryRegion
, 1);
445 memory_region_init_io(pm_mem
, NULL
, &loongarch_virt_pm_ops
,
446 NULL
, "loongarch_virt_pm", PM_SIZE
);
447 memory_region_add_subregion(get_system_memory(), PM_BASE
, pm_mem
);
449 lams
->acpi_ged
= create_acpi_ged(pch_pic
, lams
);
451 lams
->platform_bus_dev
= create_platform_bus(pch_pic
);
454 static void loongarch_irq_init(LoongArchMachineState
*lams
)
456 MachineState
*ms
= MACHINE(lams
);
457 DeviceState
*pch_pic
, *pch_msi
, *cpudev
;
458 DeviceState
*ipi
, *extioi
;
461 CPULoongArchState
*env
;
465 ipi
= qdev_new(TYPE_LOONGARCH_IPI
);
466 sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi
), &error_fatal
);
468 extioi
= qdev_new(TYPE_LOONGARCH_EXTIOI
);
469 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi
), &error_fatal
);
472 * The connection of interrupts:
473 * +-----+ +---------+ +-------+
474 * | IPI |--> | CPUINTC | <-- | Timer |
475 * +-----+ +---------+ +-------+
483 * +---------+ +---------+
484 * | PCH-PIC | | PCH-MSI |
485 * +---------+ +---------+
488 * +--------+ +---------+ +---------+
489 * | UARTs | | Devices | | Devices |
490 * +--------+ +---------+ +---------+
492 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
493 cpu_state
= qemu_get_cpu(cpu
);
494 cpudev
= DEVICE(cpu_state
);
495 lacpu
= LOONGARCH_CPU(cpu_state
);
498 /* connect ipi irq to cpu irq */
499 qdev_connect_gpio_out(ipi
, cpu
, qdev_get_gpio_in(cpudev
, IRQ_IPI
));
500 /* IPI iocsr memory region */
501 memory_region_add_subregion(&env
->system_iocsr
, SMP_IPI_MAILBOX
,
502 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
),
504 memory_region_add_subregion(&env
->system_iocsr
, MAIL_SEND_ADDR
,
505 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
),
507 /* extioi iocsr memory region */
508 memory_region_add_subregion(&env
->system_iocsr
, APIC_BASE
,
509 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi
),
514 * connect ext irq to the cpu irq
515 * cpu_pin[9:2] <= intc_pin[7:0]
517 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
518 cpudev
= DEVICE(qemu_get_cpu(cpu
));
519 for (pin
= 0; pin
< LS3A_INTC_IP
; pin
++) {
520 qdev_connect_gpio_out(extioi
, (cpu
* 8 + pin
),
521 qdev_get_gpio_in(cpudev
, pin
+ 2));
525 pch_pic
= qdev_new(TYPE_LOONGARCH_PCH_PIC
);
526 d
= SYS_BUS_DEVICE(pch_pic
);
527 sysbus_realize_and_unref(d
, &error_fatal
);
528 memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE
,
529 sysbus_mmio_get_region(d
, 0));
530 memory_region_add_subregion(get_system_memory(),
531 VIRT_IOAPIC_REG_BASE
+ PCH_PIC_ROUTE_ENTRY_OFFSET
,
532 sysbus_mmio_get_region(d
, 1));
533 memory_region_add_subregion(get_system_memory(),
534 VIRT_IOAPIC_REG_BASE
+ PCH_PIC_INT_STATUS_LO
,
535 sysbus_mmio_get_region(d
, 2));
537 /* Connect 64 pch_pic irqs to extioi */
538 for (int i
= 0; i
< PCH_PIC_IRQ_NUM
; i
++) {
539 qdev_connect_gpio_out(DEVICE(d
), i
, qdev_get_gpio_in(extioi
, i
));
542 pch_msi
= qdev_new(TYPE_LOONGARCH_PCH_MSI
);
543 qdev_prop_set_uint32(pch_msi
, "msi_irq_base", PCH_MSI_IRQ_START
);
544 d
= SYS_BUS_DEVICE(pch_msi
);
545 sysbus_realize_and_unref(d
, &error_fatal
);
546 sysbus_mmio_map(d
, 0, VIRT_PCH_MSI_ADDR_LOW
);
547 for (i
= 0; i
< PCH_MSI_IRQ_NUM
; i
++) {
548 /* Connect 192 pch_msi irqs to extioi */
549 qdev_connect_gpio_out(DEVICE(d
), i
,
550 qdev_get_gpio_in(extioi
, i
+ PCH_MSI_IRQ_START
));
553 loongarch_devices_init(pch_pic
, lams
);
556 static void loongarch_firmware_init(LoongArchMachineState
*lams
)
558 char *filename
= MACHINE(lams
)->firmware
;
559 char *bios_name
= NULL
;
562 lams
->bios_loaded
= false;
564 bios_name
= qemu_find_file(QEMU_FILE_TYPE_BIOS
, filename
);
566 error_report("Could not find ROM image '%s'", filename
);
570 bios_size
= load_image_targphys(bios_name
, VIRT_BIOS_BASE
, VIRT_BIOS_SIZE
);
572 error_report("Could not load ROM image '%s'", bios_name
);
578 memory_region_init_ram(&lams
->bios
, NULL
, "loongarch.bios",
579 VIRT_BIOS_SIZE
, &error_fatal
);
580 memory_region_set_readonly(&lams
->bios
, true);
581 memory_region_add_subregion(get_system_memory(), VIRT_BIOS_BASE
, &lams
->bios
);
582 lams
->bios_loaded
= true;
587 static void reset_load_elf(void *opaque
)
589 LoongArchCPU
*cpu
= opaque
;
590 CPULoongArchState
*env
= &cpu
->env
;
594 cpu_set_pc(CPU(cpu
), env
->elf_address
);
598 /* Load an image file into an fw_cfg entry identified by key. */
599 static void load_image_to_fw_cfg(FWCfgState
*fw_cfg
, uint16_t size_key
,
600 uint16_t data_key
, const char *image_name
,
606 if (image_name
== NULL
) {
610 if (try_decompress
) {
611 size
= load_image_gzipped_buffer(image_name
,
612 LOAD_IMAGE_MAX_GUNZIP_BYTES
, &data
);
615 if (size
== (size_t)-1) {
619 if (!g_file_get_contents(image_name
, &contents
, &length
, NULL
)) {
620 error_report("failed to load \"%s\"", image_name
);
624 data
= (uint8_t *)contents
;
627 fw_cfg_add_i32(fw_cfg
, size_key
, size
);
628 fw_cfg_add_bytes(fw_cfg
, data_key
, data
, size
);
631 static void fw_cfg_add_kernel_info(FWCfgState
*fw_cfg
)
634 * Expose the kernel, the command line, and the initrd in fw_cfg.
635 * We don't process them here at all, it's all left to the
638 load_image_to_fw_cfg(fw_cfg
,
639 FW_CFG_KERNEL_SIZE
, FW_CFG_KERNEL_DATA
,
640 loaderparams
.kernel_filename
,
643 if (loaderparams
.initrd_filename
) {
644 load_image_to_fw_cfg(fw_cfg
,
645 FW_CFG_INITRD_SIZE
, FW_CFG_INITRD_DATA
,
646 loaderparams
.initrd_filename
, false);
649 if (loaderparams
.kernel_cmdline
) {
650 fw_cfg_add_i32(fw_cfg
, FW_CFG_CMDLINE_SIZE
,
651 strlen(loaderparams
.kernel_cmdline
) + 1);
652 fw_cfg_add_string(fw_cfg
, FW_CFG_CMDLINE_DATA
,
653 loaderparams
.kernel_cmdline
);
657 static void loongarch_firmware_boot(LoongArchMachineState
*lams
)
659 fw_cfg_add_kernel_info(lams
->fw_cfg
);
662 static void loongarch_direct_kernel_boot(LoongArchMachineState
*lams
)
664 MachineState
*machine
= MACHINE(lams
);
665 int64_t kernel_addr
= 0;
669 kernel_addr
= load_kernel_info();
670 if (!machine
->firmware
) {
671 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
672 lacpu
= LOONGARCH_CPU(qemu_get_cpu(i
));
673 lacpu
->env
.load_elf
= true;
674 lacpu
->env
.elf_address
= kernel_addr
;
679 static void loongarch_init(MachineState
*machine
)
682 const char *cpu_model
= machine
->cpu_type
;
683 ram_addr_t offset
= 0;
684 ram_addr_t ram_size
= machine
->ram_size
;
685 uint64_t highram_size
= 0;
686 MemoryRegion
*address_space_mem
= get_system_memory();
687 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(machine
);
691 cpu_model
= LOONGARCH_CPU_TYPE_NAME("la464");
694 if (!strstr(cpu_model
, "la464")) {
695 error_report("LoongArch/TCG needs cpu type la464");
699 if (ram_size
< 1 * GiB
) {
700 error_report("ram_size must be greater than 1G.");
705 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
706 cpu_create(machine
->cpu_type
);
708 fdt_add_cpu_nodes(lams
);
709 /* Add memory region */
710 memory_region_init_alias(&lams
->lowmem
, NULL
, "loongarch.lowram",
711 machine
->ram
, 0, 256 * MiB
);
712 memory_region_add_subregion(address_space_mem
, offset
, &lams
->lowmem
);
714 memmap_add_entry(0, 256 * MiB
, 1);
715 highram_size
= ram_size
- 256 * MiB
;
716 memory_region_init_alias(&lams
->highmem
, NULL
, "loongarch.highmem",
717 machine
->ram
, offset
, highram_size
);
718 memory_region_add_subregion(address_space_mem
, 0x90000000, &lams
->highmem
);
719 memmap_add_entry(0x90000000, highram_size
, 1);
720 /* Add isa io region */
721 memory_region_init_alias(&lams
->isa_io
, NULL
, "isa-io",
722 get_system_io(), 0, VIRT_ISA_IO_SIZE
);
723 memory_region_add_subregion(address_space_mem
, VIRT_ISA_IO_BASE
,
725 /* load the BIOS image. */
726 loongarch_firmware_init(lams
);
729 lams
->fw_cfg
= loongarch_fw_cfg_init(ram_size
, machine
);
730 rom_set_fw(lams
->fw_cfg
);
731 if (lams
->fw_cfg
!= NULL
) {
732 fw_cfg_add_file(lams
->fw_cfg
, "etc/memmap",
734 sizeof(struct memmap_entry
) * (memmap_entries
));
736 fdt_add_fw_cfg_node(lams
);
737 loaderparams
.ram_size
= ram_size
;
738 loaderparams
.kernel_filename
= machine
->kernel_filename
;
739 loaderparams
.kernel_cmdline
= machine
->kernel_cmdline
;
740 loaderparams
.initrd_filename
= machine
->initrd_filename
;
741 /* load the kernel. */
742 if (loaderparams
.kernel_filename
) {
743 if (lams
->bios_loaded
) {
744 loongarch_firmware_boot(lams
);
746 loongarch_direct_kernel_boot(lams
);
749 /* register reset function */
750 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
751 lacpu
= LOONGARCH_CPU(qemu_get_cpu(i
));
752 qemu_register_reset(reset_load_elf
, lacpu
);
754 /* Initialize the IO interrupt subsystem */
755 loongarch_irq_init(lams
);
756 fdt_add_irqchip_node(lams
);
757 platform_bus_add_all_fdt_nodes(machine
->fdt
, "/intc",
758 VIRT_PLATFORM_BUS_BASEADDRESS
,
759 VIRT_PLATFORM_BUS_SIZE
,
760 VIRT_PLATFORM_BUS_IRQ
);
761 lams
->machine_done
.notify
= virt_machine_done
;
762 qemu_add_machine_init_done_notifier(&lams
->machine_done
);
763 fdt_add_pcie_node(lams
);
766 MemoryRegion
*fdt_rom
= g_new(MemoryRegion
, 1);
767 memory_region_init_rom(fdt_rom
, NULL
, "fdt", VIRT_FDT_SIZE
, &error_fatal
);
768 memory_region_add_subregion(get_system_memory(), VIRT_FDT_BASE
, fdt_rom
);
769 rom_add_blob_fixed("fdt", machine
->fdt
, lams
->fdt_size
, VIRT_FDT_BASE
);
772 bool loongarch_is_acpi_enabled(LoongArchMachineState
*lams
)
774 if (lams
->acpi
== ON_OFF_AUTO_OFF
) {
780 static void loongarch_get_acpi(Object
*obj
, Visitor
*v
, const char *name
,
781 void *opaque
, Error
**errp
)
783 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
784 OnOffAuto acpi
= lams
->acpi
;
786 visit_type_OnOffAuto(v
, name
, &acpi
, errp
);
789 static void loongarch_set_acpi(Object
*obj
, Visitor
*v
, const char *name
,
790 void *opaque
, Error
**errp
)
792 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
794 visit_type_OnOffAuto(v
, name
, &lams
->acpi
, errp
);
797 static void loongarch_machine_initfn(Object
*obj
)
799 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
801 lams
->acpi
= ON_OFF_AUTO_AUTO
;
802 lams
->oem_id
= g_strndup(ACPI_BUILD_APPNAME6
, 6);
803 lams
->oem_table_id
= g_strndup(ACPI_BUILD_APPNAME8
, 8);
806 static void loongarch_machine_device_plug_cb(HotplugHandler
*hotplug_dev
,
807 DeviceState
*dev
, Error
**errp
)
809 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(hotplug_dev
);
810 MachineClass
*mc
= MACHINE_GET_CLASS(lams
);
812 if (device_is_dynamic_sysbus(mc
, dev
)) {
813 if (lams
->platform_bus_dev
) {
814 platform_bus_link_device(PLATFORM_BUS_DEVICE(lams
->platform_bus_dev
),
815 SYS_BUS_DEVICE(dev
));
820 static HotplugHandler
*virt_machine_get_hotplug_handler(MachineState
*machine
,
823 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
825 if (device_is_dynamic_sysbus(mc
, dev
)) {
826 return HOTPLUG_HANDLER(machine
);
831 static void loongarch_class_init(ObjectClass
*oc
, void *data
)
833 MachineClass
*mc
= MACHINE_CLASS(oc
);
834 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(oc
);
836 mc
->desc
= "Loongson-3A5000 LS7A1000 machine";
837 mc
->init
= loongarch_init
;
838 mc
->default_ram_size
= 1 * GiB
;
839 mc
->default_cpu_type
= LOONGARCH_CPU_TYPE_NAME("la464");
840 mc
->default_ram_id
= "loongarch.ram";
841 mc
->max_cpus
= LOONGARCH_MAX_VCPUS
;
843 mc
->default_kernel_irqchip_split
= false;
844 mc
->block_default_type
= IF_VIRTIO
;
845 mc
->default_boot_order
= "c";
847 mc
->get_hotplug_handler
= virt_machine_get_hotplug_handler
;
848 hc
->plug
= loongarch_machine_device_plug_cb
;
850 object_class_property_add(oc
, "acpi", "OnOffAuto",
851 loongarch_get_acpi
, loongarch_set_acpi
,
853 object_class_property_set_description(oc
, "acpi",
857 static const TypeInfo loongarch_machine_types
[] = {
859 .name
= TYPE_LOONGARCH_MACHINE
,
860 .parent
= TYPE_MACHINE
,
861 .instance_size
= sizeof(LoongArchMachineState
),
862 .class_init
= loongarch_class_init
,
863 .instance_init
= loongarch_machine_initfn
,
864 .interfaces
= (InterfaceInfo
[]) {
865 { TYPE_HOTPLUG_HANDLER
},
871 DEFINE_TYPES(loongarch_machine_types
)