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"
41 static void create_fdt(LoongArchMachineState
*lams
)
43 MachineState
*ms
= MACHINE(lams
);
45 ms
->fdt
= create_device_tree(&lams
->fdt_size
);
47 error_report("create_device_tree() failed");
52 qemu_fdt_setprop_string(ms
->fdt
, "/", "compatible",
53 "linux,dummy-loongson3");
54 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#address-cells", 0x2);
55 qemu_fdt_setprop_cell(ms
->fdt
, "/", "#size-cells", 0x2);
58 static void fdt_add_cpu_nodes(const LoongArchMachineState
*lams
)
61 const MachineState
*ms
= MACHINE(lams
);
62 int smp_cpus
= ms
->smp
.cpus
;
64 qemu_fdt_add_subnode(ms
->fdt
, "/cpus");
65 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#address-cells", 0x1);
66 qemu_fdt_setprop_cell(ms
->fdt
, "/cpus", "#size-cells", 0x0);
69 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
70 char *nodename
= g_strdup_printf("/cpus/cpu@%d", num
);
71 LoongArchCPU
*cpu
= LOONGARCH_CPU(qemu_get_cpu(num
));
73 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
74 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "cpu");
75 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "compatible",
77 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "reg", num
);
78 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "phandle",
79 qemu_fdt_alloc_phandle(ms
->fdt
));
84 qemu_fdt_add_subnode(ms
->fdt
, "/cpus/cpu-map");
86 for (num
= smp_cpus
- 1; num
>= 0; num
--) {
87 char *cpu_path
= g_strdup_printf("/cpus/cpu@%d", num
);
90 if (ms
->smp
.threads
> 1) {
91 map_path
= g_strdup_printf(
92 "/cpus/cpu-map/socket%d/core%d/thread%d",
93 num
/ (ms
->smp
.cores
* ms
->smp
.threads
),
94 (num
/ ms
->smp
.threads
) % ms
->smp
.cores
,
95 num
% ms
->smp
.threads
);
97 map_path
= g_strdup_printf(
98 "/cpus/cpu-map/socket%d/core%d",
100 num
% ms
->smp
.cores
);
102 qemu_fdt_add_path(ms
->fdt
, map_path
);
103 qemu_fdt_setprop_phandle(ms
->fdt
, map_path
, "cpu", cpu_path
);
110 static void fdt_add_fw_cfg_node(const LoongArchMachineState
*lams
)
113 hwaddr base
= VIRT_FWCFG_BASE
;
114 const MachineState
*ms
= MACHINE(lams
);
116 nodename
= g_strdup_printf("/fw_cfg@%" PRIx64
, base
);
117 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
118 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
119 "compatible", "qemu,fw-cfg-mmio");
120 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
122 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
126 static void fdt_add_pcie_node(const LoongArchMachineState
*lams
)
129 hwaddr base_mmio
= LS7A_PCI_MEM_BASE
;
130 hwaddr size_mmio
= LS7A_PCI_MEM_SIZE
;
131 hwaddr base_pio
= LS7A_PCI_IO_BASE
;
132 hwaddr size_pio
= LS7A_PCI_IO_SIZE
;
133 hwaddr base_pcie
= LS_PCIECFG_BASE
;
134 hwaddr size_pcie
= LS_PCIECFG_SIZE
;
135 hwaddr base
= base_pcie
;
137 const MachineState
*ms
= MACHINE(lams
);
139 nodename
= g_strdup_printf("/pcie@%" PRIx64
, base
);
140 qemu_fdt_add_subnode(ms
->fdt
, nodename
);
141 qemu_fdt_setprop_string(ms
->fdt
, nodename
,
142 "compatible", "pci-host-ecam-generic");
143 qemu_fdt_setprop_string(ms
->fdt
, nodename
, "device_type", "pci");
144 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#address-cells", 3);
145 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "#size-cells", 2);
146 qemu_fdt_setprop_cell(ms
->fdt
, nodename
, "linux,pci-domain", 0);
147 qemu_fdt_setprop_cells(ms
->fdt
, nodename
, "bus-range", 0,
148 PCIE_MMCFG_BUS(LS_PCIECFG_SIZE
- 1));
149 qemu_fdt_setprop(ms
->fdt
, nodename
, "dma-coherent", NULL
, 0);
150 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "reg",
151 2, base_pcie
, 2, size_pcie
);
152 qemu_fdt_setprop_sized_cells(ms
->fdt
, nodename
, "ranges",
153 1, FDT_PCI_RANGE_IOPORT
, 2, LS7A_PCI_IO_OFFSET
,
154 2, base_pio
, 2, size_pio
,
155 1, FDT_PCI_RANGE_MMIO
, 2, base_mmio
,
156 2, base_mmio
, 2, size_mmio
);
158 qemu_fdt_dumpdtb(ms
->fdt
, lams
->fdt_size
);
162 #define PM_BASE 0x10080000
163 #define PM_SIZE 0x100
166 static void virt_build_smbios(LoongArchMachineState
*lams
)
168 MachineState
*ms
= MACHINE(lams
);
169 MachineClass
*mc
= MACHINE_GET_CLASS(lams
);
170 uint8_t *smbios_tables
, *smbios_anchor
;
171 size_t smbios_tables_len
, smbios_anchor_len
;
172 const char *product
= "QEMU Virtual Machine";
178 smbios_set_defaults("QEMU", product
, mc
->name
, false,
179 true, SMBIOS_ENTRY_POINT_TYPE_64
);
181 smbios_get_tables(ms
, NULL
, 0, &smbios_tables
, &smbios_tables_len
,
182 &smbios_anchor
, &smbios_anchor_len
, &error_fatal
);
185 fw_cfg_add_file(lams
->fw_cfg
, "etc/smbios/smbios-tables",
186 smbios_tables
, smbios_tables_len
);
187 fw_cfg_add_file(lams
->fw_cfg
, "etc/smbios/smbios-anchor",
188 smbios_anchor
, smbios_anchor_len
);
192 static void virt_machine_done(Notifier
*notifier
, void *data
)
194 LoongArchMachineState
*lams
= container_of(notifier
,
195 LoongArchMachineState
, machine_done
);
196 virt_build_smbios(lams
);
197 loongarch_acpi_setup(lams
);
200 struct memmap_entry
{
207 static struct memmap_entry
*memmap_table
;
208 static unsigned memmap_entries
;
210 static void memmap_add_entry(uint64_t address
, uint64_t length
, uint32_t type
)
212 /* Ensure there are no duplicate entries. */
213 for (unsigned i
= 0; i
< memmap_entries
; i
++) {
214 assert(memmap_table
[i
].address
!= address
);
217 memmap_table
= g_renew(struct memmap_entry
, memmap_table
,
219 memmap_table
[memmap_entries
].address
= cpu_to_le64(address
);
220 memmap_table
[memmap_entries
].length
= cpu_to_le64(length
);
221 memmap_table
[memmap_entries
].type
= cpu_to_le32(type
);
222 memmap_table
[memmap_entries
].reserved
= 0;
227 * This is a placeholder for missing ACPI,
228 * and will eventually be replaced.
230 static uint64_t loongarch_virt_pm_read(void *opaque
, hwaddr addr
, unsigned size
)
235 static void loongarch_virt_pm_write(void *opaque
, hwaddr addr
,
236 uint64_t val
, unsigned size
)
238 if (addr
!= PM_CTRL
) {
244 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET
);
247 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN
);
254 static const MemoryRegionOps loongarch_virt_pm_ops
= {
255 .read
= loongarch_virt_pm_read
,
256 .write
= loongarch_virt_pm_write
,
257 .endianness
= DEVICE_NATIVE_ENDIAN
,
259 .min_access_size
= 1,
264 static struct _loaderparams
{
266 const char *kernel_filename
;
267 const char *kernel_cmdline
;
268 const char *initrd_filename
;
271 static uint64_t cpu_loongarch_virt_to_phys(void *opaque
, uint64_t addr
)
273 return addr
& 0x1fffffffll
;
276 static int64_t load_kernel_info(void)
278 uint64_t kernel_entry
, kernel_low
, kernel_high
;
281 kernel_size
= load_elf(loaderparams
.kernel_filename
, NULL
,
282 cpu_loongarch_virt_to_phys
, NULL
,
283 &kernel_entry
, &kernel_low
,
284 &kernel_high
, NULL
, 0,
287 if (kernel_size
< 0) {
288 error_report("could not load kernel '%s': %s",
289 loaderparams
.kernel_filename
,
290 load_elf_strerror(kernel_size
));
296 static DeviceState
*create_acpi_ged(DeviceState
*pch_pic
, LoongArchMachineState
*lams
)
299 MachineState
*ms
= MACHINE(lams
);
300 uint32_t event
= ACPI_GED_PWR_DOWN_EVT
;
303 event
|= ACPI_GED_MEM_HOTPLUG_EVT
;
305 dev
= qdev_new(TYPE_ACPI_GED
);
306 qdev_prop_set_uint32(dev
, "ged-event", event
);
309 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, VIRT_GED_EVT_ADDR
);
311 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 1, VIRT_GED_MEM_ADDR
);
312 /* ged regs used for reset and power down */
313 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 2, VIRT_GED_REG_ADDR
);
315 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0,
316 qdev_get_gpio_in(pch_pic
, LS7A_SCI_IRQ
- PCH_PIC_IRQ_OFFSET
));
317 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
321 static void loongarch_devices_init(DeviceState
*pch_pic
, LoongArchMachineState
*lams
)
323 DeviceState
*gpex_dev
;
326 MemoryRegion
*ecam_alias
, *ecam_reg
, *pio_alias
, *pio_reg
;
327 MemoryRegion
*mmio_alias
, *mmio_reg
, *pm_mem
;
330 gpex_dev
= qdev_new(TYPE_GPEX_HOST
);
331 d
= SYS_BUS_DEVICE(gpex_dev
);
332 sysbus_realize_and_unref(d
, &error_fatal
);
333 pci_bus
= PCI_HOST_BRIDGE(gpex_dev
)->bus
;
335 /* Map only part size_ecam bytes of ECAM space */
336 ecam_alias
= g_new0(MemoryRegion
, 1);
337 ecam_reg
= sysbus_mmio_get_region(d
, 0);
338 memory_region_init_alias(ecam_alias
, OBJECT(gpex_dev
), "pcie-ecam",
339 ecam_reg
, 0, LS_PCIECFG_SIZE
);
340 memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE
,
343 /* Map PCI mem space */
344 mmio_alias
= g_new0(MemoryRegion
, 1);
345 mmio_reg
= sysbus_mmio_get_region(d
, 1);
346 memory_region_init_alias(mmio_alias
, OBJECT(gpex_dev
), "pcie-mmio",
347 mmio_reg
, LS7A_PCI_MEM_BASE
, LS7A_PCI_MEM_SIZE
);
348 memory_region_add_subregion(get_system_memory(), LS7A_PCI_MEM_BASE
,
351 /* Map PCI IO port space. */
352 pio_alias
= g_new0(MemoryRegion
, 1);
353 pio_reg
= sysbus_mmio_get_region(d
, 2);
354 memory_region_init_alias(pio_alias
, OBJECT(gpex_dev
), "pcie-io", pio_reg
,
355 LS7A_PCI_IO_OFFSET
, LS7A_PCI_IO_SIZE
);
356 memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE
,
359 for (i
= 0; i
< GPEX_NUM_IRQS
; i
++) {
360 sysbus_connect_irq(d
, i
,
361 qdev_get_gpio_in(pch_pic
, 16 + i
));
362 gpex_set_irq_num(GPEX_HOST(gpex_dev
), i
, 16 + i
);
365 serial_mm_init(get_system_memory(), LS7A_UART_BASE
, 0,
366 qdev_get_gpio_in(pch_pic
,
367 LS7A_UART_IRQ
- PCH_PIC_IRQ_OFFSET
),
368 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN
);
371 for (i
= 0; i
< nb_nics
; i
++) {
372 NICInfo
*nd
= &nd_table
[i
];
375 nd
->model
= g_strdup("virtio");
378 pci_nic_init_nofail(nd
, pci_bus
, nd
->model
, NULL
);
382 pci_vga_init(pci_bus
);
385 * There are some invalid guest memory access.
386 * Create some unimplemented devices to emulate this.
388 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
389 sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE
,
390 qdev_get_gpio_in(pch_pic
,
391 LS7A_RTC_IRQ
- PCH_PIC_IRQ_OFFSET
));
393 pm_mem
= g_new(MemoryRegion
, 1);
394 memory_region_init_io(pm_mem
, NULL
, &loongarch_virt_pm_ops
,
395 NULL
, "loongarch_virt_pm", PM_SIZE
);
396 memory_region_add_subregion(get_system_memory(), PM_BASE
, pm_mem
);
398 lams
->acpi_ged
= create_acpi_ged(pch_pic
, lams
);
401 static void loongarch_irq_init(LoongArchMachineState
*lams
)
403 MachineState
*ms
= MACHINE(lams
);
404 DeviceState
*pch_pic
, *pch_msi
, *cpudev
;
405 DeviceState
*ipi
, *extioi
;
408 CPULoongArchState
*env
;
412 ipi
= qdev_new(TYPE_LOONGARCH_IPI
);
413 sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi
), &error_fatal
);
415 extioi
= qdev_new(TYPE_LOONGARCH_EXTIOI
);
416 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi
), &error_fatal
);
419 * The connection of interrupts:
420 * +-----+ +---------+ +-------+
421 * | IPI |--> | CPUINTC | <-- | Timer |
422 * +-----+ +---------+ +-------+
430 * +---------+ +---------+
431 * | PCH-PIC | | PCH-MSI |
432 * +---------+ +---------+
435 * +--------+ +---------+ +---------+
436 * | UARTs | | Devices | | Devices |
437 * +--------+ +---------+ +---------+
439 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
440 cpu_state
= qemu_get_cpu(cpu
);
441 cpudev
= DEVICE(cpu_state
);
442 lacpu
= LOONGARCH_CPU(cpu_state
);
445 /* connect ipi irq to cpu irq */
446 qdev_connect_gpio_out(ipi
, cpu
, qdev_get_gpio_in(cpudev
, IRQ_IPI
));
447 /* IPI iocsr memory region */
448 memory_region_add_subregion(&env
->system_iocsr
, SMP_IPI_MAILBOX
,
449 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
),
451 memory_region_add_subregion(&env
->system_iocsr
, MAIL_SEND_ADDR
,
452 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi
),
454 /* extioi iocsr memory region */
455 memory_region_add_subregion(&env
->system_iocsr
, APIC_BASE
,
456 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi
),
461 * connect ext irq to the cpu irq
462 * cpu_pin[9:2] <= intc_pin[7:0]
464 for (cpu
= 0; cpu
< ms
->smp
.cpus
; cpu
++) {
465 cpudev
= DEVICE(qemu_get_cpu(cpu
));
466 for (pin
= 0; pin
< LS3A_INTC_IP
; pin
++) {
467 qdev_connect_gpio_out(extioi
, (cpu
* 8 + pin
),
468 qdev_get_gpio_in(cpudev
, pin
+ 2));
472 pch_pic
= qdev_new(TYPE_LOONGARCH_PCH_PIC
);
473 d
= SYS_BUS_DEVICE(pch_pic
);
474 sysbus_realize_and_unref(d
, &error_fatal
);
475 memory_region_add_subregion(get_system_memory(), LS7A_IOAPIC_REG_BASE
,
476 sysbus_mmio_get_region(d
, 0));
477 memory_region_add_subregion(get_system_memory(),
478 LS7A_IOAPIC_REG_BASE
+ PCH_PIC_ROUTE_ENTRY_OFFSET
,
479 sysbus_mmio_get_region(d
, 1));
480 memory_region_add_subregion(get_system_memory(),
481 LS7A_IOAPIC_REG_BASE
+ PCH_PIC_INT_STATUS_LO
,
482 sysbus_mmio_get_region(d
, 2));
484 /* Connect 64 pch_pic irqs to extioi */
485 for (int i
= 0; i
< PCH_PIC_IRQ_NUM
; i
++) {
486 qdev_connect_gpio_out(DEVICE(d
), i
, qdev_get_gpio_in(extioi
, i
));
489 pch_msi
= qdev_new(TYPE_LOONGARCH_PCH_MSI
);
490 qdev_prop_set_uint32(pch_msi
, "msi_irq_base", PCH_MSI_IRQ_START
);
491 d
= SYS_BUS_DEVICE(pch_msi
);
492 sysbus_realize_and_unref(d
, &error_fatal
);
493 sysbus_mmio_map(d
, 0, LS7A_PCH_MSI_ADDR_LOW
);
494 for (i
= 0; i
< PCH_MSI_IRQ_NUM
; i
++) {
495 /* Connect 192 pch_msi irqs to extioi */
496 qdev_connect_gpio_out(DEVICE(d
), i
,
497 qdev_get_gpio_in(extioi
, i
+ PCH_MSI_IRQ_START
));
500 loongarch_devices_init(pch_pic
, lams
);
503 static void loongarch_firmware_init(LoongArchMachineState
*lams
)
505 char *filename
= MACHINE(lams
)->firmware
;
506 char *bios_name
= NULL
;
509 lams
->bios_loaded
= false;
511 bios_name
= qemu_find_file(QEMU_FILE_TYPE_BIOS
, filename
);
513 error_report("Could not find ROM image '%s'", filename
);
517 bios_size
= load_image_targphys(bios_name
, VIRT_BIOS_BASE
, VIRT_BIOS_SIZE
);
519 error_report("Could not load ROM image '%s'", bios_name
);
525 memory_region_init_ram(&lams
->bios
, NULL
, "loongarch.bios",
526 VIRT_BIOS_SIZE
, &error_fatal
);
527 memory_region_set_readonly(&lams
->bios
, true);
528 memory_region_add_subregion(get_system_memory(), VIRT_BIOS_BASE
, &lams
->bios
);
529 lams
->bios_loaded
= true;
534 static void reset_load_elf(void *opaque
)
536 LoongArchCPU
*cpu
= opaque
;
537 CPULoongArchState
*env
= &cpu
->env
;
541 cpu_set_pc(CPU(cpu
), env
->elf_address
);
545 /* Load an image file into an fw_cfg entry identified by key. */
546 static void load_image_to_fw_cfg(FWCfgState
*fw_cfg
, uint16_t size_key
,
547 uint16_t data_key
, const char *image_name
,
553 if (image_name
== NULL
) {
557 if (try_decompress
) {
558 size
= load_image_gzipped_buffer(image_name
,
559 LOAD_IMAGE_MAX_GUNZIP_BYTES
, &data
);
562 if (size
== (size_t)-1) {
566 if (!g_file_get_contents(image_name
, &contents
, &length
, NULL
)) {
567 error_report("failed to load \"%s\"", image_name
);
571 data
= (uint8_t *)contents
;
574 fw_cfg_add_i32(fw_cfg
, size_key
, size
);
575 fw_cfg_add_bytes(fw_cfg
, data_key
, data
, size
);
578 static void fw_cfg_add_kernel_info(FWCfgState
*fw_cfg
)
581 * Expose the kernel, the command line, and the initrd in fw_cfg.
582 * We don't process them here at all, it's all left to the
585 load_image_to_fw_cfg(fw_cfg
,
586 FW_CFG_KERNEL_SIZE
, FW_CFG_KERNEL_DATA
,
587 loaderparams
.kernel_filename
,
590 if (loaderparams
.initrd_filename
) {
591 load_image_to_fw_cfg(fw_cfg
,
592 FW_CFG_INITRD_SIZE
, FW_CFG_INITRD_DATA
,
593 loaderparams
.initrd_filename
, false);
596 if (loaderparams
.kernel_cmdline
) {
597 fw_cfg_add_i32(fw_cfg
, FW_CFG_CMDLINE_SIZE
,
598 strlen(loaderparams
.kernel_cmdline
) + 1);
599 fw_cfg_add_string(fw_cfg
, FW_CFG_CMDLINE_DATA
,
600 loaderparams
.kernel_cmdline
);
604 static void loongarch_firmware_boot(LoongArchMachineState
*lams
)
606 fw_cfg_add_kernel_info(lams
->fw_cfg
);
609 static void loongarch_direct_kernel_boot(LoongArchMachineState
*lams
)
611 MachineState
*machine
= MACHINE(lams
);
612 int64_t kernel_addr
= 0;
616 kernel_addr
= load_kernel_info();
617 if (!machine
->firmware
) {
618 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
619 lacpu
= LOONGARCH_CPU(qemu_get_cpu(i
));
620 lacpu
->env
.load_elf
= true;
621 lacpu
->env
.elf_address
= kernel_addr
;
626 static void loongarch_init(MachineState
*machine
)
629 const char *cpu_model
= machine
->cpu_type
;
630 ram_addr_t offset
= 0;
631 ram_addr_t ram_size
= machine
->ram_size
;
632 uint64_t highram_size
= 0;
633 MemoryRegion
*address_space_mem
= get_system_memory();
634 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(machine
);
638 cpu_model
= LOONGARCH_CPU_TYPE_NAME("la464");
641 if (!strstr(cpu_model
, "la464")) {
642 error_report("LoongArch/TCG needs cpu type la464");
646 if (ram_size
< 1 * GiB
) {
647 error_report("ram_size must be greater than 1G.");
652 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
653 cpu_create(machine
->cpu_type
);
655 fdt_add_cpu_nodes(lams
);
656 /* Add memory region */
657 memory_region_init_alias(&lams
->lowmem
, NULL
, "loongarch.lowram",
658 machine
->ram
, 0, 256 * MiB
);
659 memory_region_add_subregion(address_space_mem
, offset
, &lams
->lowmem
);
661 memmap_add_entry(0, 256 * MiB
, 1);
662 highram_size
= ram_size
- 256 * MiB
;
663 memory_region_init_alias(&lams
->highmem
, NULL
, "loongarch.highmem",
664 machine
->ram
, offset
, highram_size
);
665 memory_region_add_subregion(address_space_mem
, 0x90000000, &lams
->highmem
);
666 memmap_add_entry(0x90000000, highram_size
, 1);
667 /* Add isa io region */
668 memory_region_init_alias(&lams
->isa_io
, NULL
, "isa-io",
669 get_system_io(), 0, LOONGARCH_ISA_IO_SIZE
);
670 memory_region_add_subregion(address_space_mem
, LOONGARCH_ISA_IO_BASE
,
672 /* load the BIOS image. */
673 loongarch_firmware_init(lams
);
676 lams
->fw_cfg
= loongarch_fw_cfg_init(ram_size
, machine
);
677 rom_set_fw(lams
->fw_cfg
);
678 if (lams
->fw_cfg
!= NULL
) {
679 fw_cfg_add_file(lams
->fw_cfg
, "etc/memmap",
681 sizeof(struct memmap_entry
) * (memmap_entries
));
683 fdt_add_fw_cfg_node(lams
);
684 loaderparams
.ram_size
= ram_size
;
685 loaderparams
.kernel_filename
= machine
->kernel_filename
;
686 loaderparams
.kernel_cmdline
= machine
->kernel_cmdline
;
687 loaderparams
.initrd_filename
= machine
->initrd_filename
;
688 /* load the kernel. */
689 if (loaderparams
.kernel_filename
) {
690 if (lams
->bios_loaded
) {
691 loongarch_firmware_boot(lams
);
693 loongarch_direct_kernel_boot(lams
);
696 /* register reset function */
697 for (i
= 0; i
< machine
->smp
.cpus
; i
++) {
698 lacpu
= LOONGARCH_CPU(qemu_get_cpu(i
));
699 qemu_register_reset(reset_load_elf
, lacpu
);
701 /* Initialize the IO interrupt subsystem */
702 loongarch_irq_init(lams
);
703 lams
->machine_done
.notify
= virt_machine_done
;
704 qemu_add_machine_init_done_notifier(&lams
->machine_done
);
705 fdt_add_pcie_node(lams
);
708 MemoryRegion
*fdt_rom
= g_new(MemoryRegion
, 1);
709 memory_region_init_rom(fdt_rom
, NULL
, "fdt", LA_FDT_SIZE
, &error_fatal
);
710 memory_region_add_subregion(get_system_memory(), LA_FDT_BASE
, fdt_rom
);
711 rom_add_blob_fixed("fdt", machine
->fdt
, lams
->fdt_size
, LA_FDT_BASE
);
714 bool loongarch_is_acpi_enabled(LoongArchMachineState
*lams
)
716 if (lams
->acpi
== ON_OFF_AUTO_OFF
) {
722 static void loongarch_get_acpi(Object
*obj
, Visitor
*v
, const char *name
,
723 void *opaque
, Error
**errp
)
725 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
726 OnOffAuto acpi
= lams
->acpi
;
728 visit_type_OnOffAuto(v
, name
, &acpi
, errp
);
731 static void loongarch_set_acpi(Object
*obj
, Visitor
*v
, const char *name
,
732 void *opaque
, Error
**errp
)
734 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
736 visit_type_OnOffAuto(v
, name
, &lams
->acpi
, errp
);
739 static void loongarch_machine_initfn(Object
*obj
)
741 LoongArchMachineState
*lams
= LOONGARCH_MACHINE(obj
);
743 lams
->acpi
= ON_OFF_AUTO_AUTO
;
744 lams
->oem_id
= g_strndup(ACPI_BUILD_APPNAME6
, 6);
745 lams
->oem_table_id
= g_strndup(ACPI_BUILD_APPNAME8
, 8);
748 static void loongarch_class_init(ObjectClass
*oc
, void *data
)
750 MachineClass
*mc
= MACHINE_CLASS(oc
);
752 mc
->desc
= "Loongson-3A5000 LS7A1000 machine";
753 mc
->init
= loongarch_init
;
754 mc
->default_ram_size
= 1 * GiB
;
755 mc
->default_cpu_type
= LOONGARCH_CPU_TYPE_NAME("la464");
756 mc
->default_ram_id
= "loongarch.ram";
757 mc
->max_cpus
= LOONGARCH_MAX_VCPUS
;
759 mc
->default_kernel_irqchip_split
= false;
760 mc
->block_default_type
= IF_VIRTIO
;
761 mc
->default_boot_order
= "c";
764 object_class_property_add(oc
, "acpi", "OnOffAuto",
765 loongarch_get_acpi
, loongarch_set_acpi
,
767 object_class_property_set_description(oc
, "acpi",
771 static const TypeInfo loongarch_machine_types
[] = {
773 .name
= TYPE_LOONGARCH_MACHINE
,
774 .parent
= TYPE_MACHINE
,
775 .instance_size
= sizeof(LoongArchMachineState
),
776 .class_init
= loongarch_class_init
,
777 .instance_init
= loongarch_machine_initfn
,
781 DEFINE_TYPES(loongarch_machine_types
)