diff --git a/docs/system/loongarch/loongson3.rst b/docs/system/loongarch/virt.rst similarity index 51% rename from docs/system/loongarch/loongson3.rst rename to docs/system/loongarch/virt.rst index 489ea20f8f..c37268b404 100644 --- a/docs/system/loongarch/loongson3.rst +++ b/docs/system/loongarch/virt.rst @@ -19,14 +19,14 @@ The ``virt`` machine supports: - Fw_cfg device - PCI/PCIe devices - Memory device -- CPU device. Type: la464-loongarch-cpu. +- CPU device. Type: la464. CPU and machine Type -------------------- The ``qemu-system-loongarch64`` provides emulation for virt machine. You can specify the machine type ``virt`` and -cpu type ``la464-loongarch-cpu``. +cpu type ``la464``. Boot options ------------ @@ -35,95 +35,74 @@ We can boot the LoongArch virt machine by specifying the uefi bios, initrd, and linux kernel. And those source codes and binary files can be accessed by following steps. -(1) booting command: +(1) Build qemu-system-loongarch64: .. code-block:: bash - $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464-loongarch-cpu \ - -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd initrd.img \ - -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \ - --nographic - -Note: The running speed may be a little slow, as the performance of our -qemu and uefi bios is not perfect, and it is being fixed. - -(2) cross compiler tools: - -.. code-block:: bash - - wget https://github.com/loongson/build-tools/releases/download/ \ - 2022.05.29/loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz - - tar -vxf loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz - -(3) qemu compile configure option: - -.. code-block:: bash - - ./configure --disable-rdma --disable-pvrdma --prefix=usr \ + ./configure --disable-rdma --disable-pvrdma --prefix=/usr \ --target-list="loongarch64-softmmu" \ --disable-libiscsi --disable-libnfs --disable-libpmem \ --disable-glusterfs --enable-libusb --enable-usb-redir \ --disable-opengl --disable-xen --enable-spice \ --enable-debug --disable-capstone --disable-kvm \ --enable-profiler - make + make -j8 -(4) uefi bios source code and compile method: +(2) Set cross tools: .. code-block:: bash - git clone https://github.com/loongson/edk2-LoongarchVirt.git + wget https://github.com/loongson/build-tools/releases/download/2022.09.06/loongarch64-clfs-6.3-cross-tools-gcc-glibc.tar.xz - cd edk2-LoongarchVirt + tar -vxf loongarch64-clfs-6.3-cross-tools-gcc-glibc.tar.xz -C /opt - git submodule update --init + export PATH=/opt/cross-tools/bin:$PATH + export LD_LIBRARY_PATH=/opt/cross-tools/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH=/opt/cross-tools/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH - export PATH=$YOUR_COMPILER_PATH/bin:$PATH +Note: You need get the latest cross-tools at https://github.com/loongson/build-tools - export WORKSPACE=`pwd` +(3) Build BIOS: - export PACKAGES_PATH=$WORKSPACE/edk2-LoongarchVirt + See: https://github.com/tianocore/edk2-platforms/tree/master/Platform/Loongson/LoongArchQemuPkg#readme - export GCC5_LOONGARCH64_PREFIX=loongarch64-unknown-linux-gnu- +Note: To build the release version of the bios, set --buildtarget=RELEASE, + the bios file path: Build/LoongArchQemu/RELEASE_GCC5/FV/QEMU_EFI.fd - edk2-LoongarchVirt/edksetup.sh - - make -C edk2-LoongarchVirt/BaseTools - - build --buildtarget=DEBUG --tagname=GCC5 --arch=LOONGARCH64 --platform=OvmfPkg/LoongArchQemu/Loongson.dsc - - build --buildtarget=RELEASE --tagname=GCC5 --arch=LOONGARCH64 --platform=OvmfPkg/LoongArchQemu/Loongson.dsc - -The efi binary file path: - - Build/LoongArchQemu/DEBUG_GCC5/FV/QEMU_EFI.fd - - Build/LoongArchQemu/RELEASE_GCC5/FV/QEMU_EFI.fd - -(5) linux kernel source code and compile method: +(4) Build kernel: .. code-block:: bash git clone https://github.com/loongson/linux.git - export PATH=$YOUR_COMPILER_PATH/bin:$PATH + cd linux - export LD_LIBRARY_PATH=$YOUR_COMPILER_PATH/lib:$LD_LIBRARY_PATH - - export LD_LIBRARY_PATH=$YOUR_COMPILER_PATH/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH + git checkout loongarch-next make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- loongson3_defconfig - make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- - - make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- install - - make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- modules_install + make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- -j32 Note: The branch of linux source code is loongarch-next. + the kernel file: arch/loongarch/boot/vmlinuz.efi -(6) initrd file: +(5) Get initrd: You can use busybox tool and the linux modules to make a initrd file. Or you can access the binary files: https://github.com/yangxiaojuan-loongson/qemu-binary + +.. code-block:: bash + + git clone https://github.com/yangxiaojuan-loongson/qemu-binary + +Note: the initrd file is ramdisk + +(6) Booting LoongArch: + +.. code-block:: bash + + $ ./build/qemu-system-loongarch64 -machine virt -m 4G -cpu la464 \ + -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd ramdisk \ + -serial stdio -monitor telnet:localhost:4495,server,nowait \ + -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \ + --nographic diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index f551296a0e..6cb2472d33 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -260,6 +260,7 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine) AML_SYSTEM_MEMORY, VIRT_GED_MEM_ADDR); } + acpi_dsdt_add_power_button(dsdt); } static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) @@ -271,7 +272,7 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) .pio.size = VIRT_PCI_IO_SIZE, .ecam.base = VIRT_PCI_CFG_BASE, .ecam.size = VIRT_PCI_CFG_SIZE, - .irq = PCH_PIC_IRQ_OFFSET + VIRT_DEVICE_IRQS, + .irq = VIRT_GSI_BASE + VIRT_DEVICE_IRQS, .bus = lams->pci_bus, }; diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 66be925068..38ef7cc49f 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -316,6 +316,14 @@ static void virt_machine_done(Notifier *notifier, void *data) loongarch_acpi_setup(lams); } +static void virt_powerdown_req(Notifier *notifier, void *opaque) +{ + LoongArchMachineState *s = container_of(notifier, + LoongArchMachineState, powerdown_notifier); + + acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS); +} + struct memmap_entry { uint64_t address; uint64_t length; @@ -432,7 +440,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, - qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET)); + qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - VIRT_GSI_BASE)); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return dev; } @@ -452,7 +460,7 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic) sysbus = SYS_BUS_DEVICE(dev); for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) { - irq = VIRT_PLATFORM_BUS_IRQ - PCH_PIC_IRQ_OFFSET + i; + irq = VIRT_PLATFORM_BUS_IRQ - VIRT_GSI_BASE + i; sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(pch_pic, irq)); } @@ -509,7 +517,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0, qdev_get_gpio_in(pch_pic, - VIRT_UART_IRQ - PCH_PIC_IRQ_OFFSET), + VIRT_UART_IRQ - VIRT_GSI_BASE), 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); fdt_add_uart_node(lams); @@ -531,7 +539,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4); sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE, qdev_get_gpio_in(pch_pic, - VIRT_RTC_IRQ - PCH_PIC_IRQ_OFFSET)); + VIRT_RTC_IRQ - VIRT_GSI_BASE)); fdt_add_rtc_node(lams); pm_mem = g_new(MemoryRegion, 1); @@ -859,6 +867,10 @@ static void loongarch_init(MachineState *machine) VIRT_PLATFORM_BUS_IRQ); lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); + /* connect powerdown request */ + lams->powerdown_notifier.notify = virt_powerdown_req; + qemu_register_powerdown_notifier(&lams->powerdown_notifier); + fdt_add_pcie_node(lams); /* * Since lowmem region starts from 0 and Linux kernel legacy start address diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index f5f818894e..7ae8a91229 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -45,6 +45,7 @@ struct LoongArchMachineState { /* State for other subsystems/APIs: */ FWCfgState *fw_cfg; Notifier machine_done; + Notifier powerdown_notifier; OnOffAuto acpi; char *oem_id; char *oem_table_id; diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index ff4b979912..e753449593 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -26,24 +26,25 @@ #define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL /* - * According to the kernel pch irq start from 64 offset - * 0 ~ 16 irqs used for non-pci device while 16 ~ 64 irqs - * used for pci device. + * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot + * 0 - 15 GSI for ISA devices even if there is no ISA devices + * 16 - 63 GSI for CPU devices such as timers/perf monitor etc + * 64 - GSI for external devices */ #define VIRT_PCH_PIC_IRQ_NUM 32 -#define PCH_PIC_IRQ_OFFSET 64 +#define VIRT_GSI_BASE 64 #define VIRT_DEVICE_IRQS 16 -#define VIRT_UART_IRQ (PCH_PIC_IRQ_OFFSET + 2) +#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2) #define VIRT_UART_BASE 0x1fe001e0 #define VIRT_UART_SIZE 0X100 -#define VIRT_RTC_IRQ (PCH_PIC_IRQ_OFFSET + 3) +#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 3) #define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000) #define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) #define VIRT_RTC_LEN 0x100 -#define VIRT_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4) +#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 4) #define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 #define VIRT_PLATFORM_BUS_SIZE 0x2000000 #define VIRT_PLATFORM_BUS_NUM_IRQS 2 -#define VIRT_PLATFORM_BUS_IRQ 69 +#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 5) #endif diff --git a/qemu-options.hx b/qemu-options.hx index beeb4475ba..d42f60fb91 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2585,7 +2585,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " specify SMBIOS type 17 fields\n" "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n" " specify SMBIOS type 41 fields\n", - QEMU_ARCH_I386 | QEMU_ARCH_ARM) + QEMU_ARCH_I386 | QEMU_ARCH_ARM | QEMU_ARCH_LOONGARCH) SRST ``-smbios file=binary`` Load SMBIOS entry from binary file. diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index d6513f2d9d..97e6579f6a 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -546,6 +546,8 @@ static void loongarch_qemu_write(void *opaque, hwaddr addr, static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) { switch (addr) { + case VERSION_REG: + return 0x11ULL; case FEATURE_REG: return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI | 1ULL << IOCSRF_CSRIPI; diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index d60693fafe..e11c875188 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -28,6 +28,7 @@ #define IOCSRF_GMOD 9 #define IOCSRF_VM 11 +#define VERSION_REG 0x0 #define FEATURE_REG 0x8 #define VENDOR_REG 0x10 #define CPUNAME_REG 0x20