From 3243783c32b1e3a5cfbe792ef4fd15b4a3a912d6 Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Thu, 21 Mar 2024 11:30:27 +0800 Subject: [PATCH] Support for loongarch64 in the QEMU driver Implement support for loongarch64 in the QEMU driver. Signed-off-by: Xianglai Li Reviewed-by: Andrea Bolognani --- src/qemu/qemu_capabilities.c | 7 +++--- src/qemu/qemu_command.c | 6 +++-- src/qemu/qemu_domain.c | 43 ++++++++++++++++++++++++++++++++---- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_validate.c | 1 + 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index fe008d170c..21f93c6774 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1146,7 +1146,8 @@ virQEMUCapsInitGuestFromBinary(virCaps *caps, NULL, NULL, 0, NULL); } - if ((ARCH_IS_X86(guestarch) || guestarch == VIR_ARCH_AARCH64)) + if (ARCH_IS_X86(guestarch) || guestarch == VIR_ARCH_AARCH64 || + ARCH_IS_LOONGARCH(guestarch)) virCapabilitiesAddGuestFeatureWithToggle(guest, VIR_CAPS_GUEST_FEATURE_TYPE_ACPI, true, true); @@ -2696,7 +2697,7 @@ static const char *preferredMachines[] = NULL, /* VIR_ARCH_ITANIUM (doesn't exist in QEMU any more) */ "lm32-evr", /* VIR_ARCH_LM32 */ - NULL, /* VIR_ARCH_LOONGARCH64 */ + "virt", /* VIR_ARCH_LOONGARCH64 */ "mcf5208evb", /* VIR_ARCH_M68K */ "petalogix-s3adsp1800", /* VIR_ARCH_MICROBLAZE */ "petalogix-s3adsp1800", /* VIR_ARCH_MICROBLAZEEL */ @@ -3771,7 +3772,7 @@ virQEMUCapsInitCPUModel(virQEMUCaps *qemuCaps, } else if (ARCH_IS_X86(qemuCaps->arch)) { ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, modelInfo, cpu, migratable); - } else if (ARCH_IS_ARM(qemuCaps->arch)) { + } else if (ARCH_IS_ARM(qemuCaps->arch) || ARCH_IS_LOONGARCH(qemuCaps->arch)) { ret = 2; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2bb1b6a0e7..0ca77bc9d7 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9186,9 +9186,11 @@ qemuChrIsPlatformDevice(const virDomainDef *def, } } - if (ARCH_IS_RISCV(def->os.arch)) { + if (ARCH_IS_RISCV(def->os.arch) || + ARCH_IS_LOONGARCH(def->os.arch)) { - /* 16550a (used by riscv/virt guests) is a platform device */ + /* 16550a (used by the virt machine type on some architectures) + * is a platform device */ if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL && chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM && chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A) { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4e98b06529..6b869797a8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -4117,7 +4117,7 @@ qemuDomainGetSCSIControllerModel(const virDomainDef *def, if (qemuDomainIsPSeries(def)) return VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI; - if (ARCH_IS_S390(def->os.arch)) + if (ARCH_IS_S390(def->os.arch) || qemuDomainIsLoongArchVirt(def)) return VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI; if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) return VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC; @@ -4263,10 +4263,13 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, addPCIRoot = true; break; + case VIR_ARCH_LOONGARCH64: + addPCIeRoot = true; + break; + case VIR_ARCH_CRIS: case VIR_ARCH_ITANIUM: case VIR_ARCH_LM32: - case VIR_ARCH_LOONGARCH64: case VIR_ARCH_M68K: case VIR_ARCH_MICROBLAZE: case VIR_ARCH_MICROBLAZEEL: @@ -5437,6 +5440,7 @@ qemuDomainDefaultNetModel(const virDomainDef *def, /* When there are no backwards compatibility concerns getting in * the way, virtio is a good default */ if (ARCH_IS_S390(def->os.arch) || + qemuDomainIsLoongArchVirt(def) || qemuDomainIsRISCVVirt(def)) { return VIR_DOMAIN_NET_MODEL_VIRTIO; } @@ -5680,6 +5684,9 @@ qemuDomainControllerDefPostParse(virDomainControllerDef *cont, cont->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI; else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NEC_USB_XHCI)) cont->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI; + } else if (ARCH_IS_LOONGARCH(def->os.arch)) { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_QEMU_XHCI)) + cont->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI; } } /* forbid usb model 'qusb1' and 'qusb2' in this kind of hyperviosr */ @@ -5779,7 +5786,9 @@ qemuDomainChrDefPostParse(virDomainChrDef *chr, chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA; } else if (qemuDomainIsPSeries(def)) { chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO; - } else if (qemuDomainIsARMVirt(def) || qemuDomainIsRISCVVirt(def)) { + } else if (qemuDomainIsARMVirt(def) || + qemuDomainIsLoongArchVirt(def) || + qemuDomainIsRISCVVirt(def)) { chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM; } else if (ARCH_IS_S390(def->os.arch)) { chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP; @@ -5805,7 +5814,8 @@ qemuDomainChrDefPostParse(virDomainChrDef *chr, case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM: if (qemuDomainIsARMVirt(def)) { chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011; - } else if (qemuDomainIsRISCVVirt(def)) { + } else if (qemuDomainIsLoongArchVirt(def) || + qemuDomainIsRISCVVirt(def)) { chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A; } break; @@ -5977,6 +5987,7 @@ qemuDomainDefaultVideoDevice(const virDomainDef *def, if (ARCH_IS_PPC64(def->os.arch)) return VIR_DOMAIN_VIDEO_TYPE_VGA; if (qemuDomainIsARMVirt(def) || + qemuDomainIsLoongArchVirt(def) || qemuDomainIsRISCVVirt(def) || ARCH_IS_S390(def->os.arch)) { return VIR_DOMAIN_VIDEO_TYPE_VIRTIO; @@ -9030,6 +9041,22 @@ qemuDomainMachineIsPSeries(const char *machine, } +static bool +qemuDomainMachineIsLoongArchVirt(const char *machine, + const virArch arch) +{ + if (!ARCH_IS_LOONGARCH(arch)) + return false; + + if (STREQ(machine, "virt") || + STRPREFIX(machine, "virt-")) { + return true; + } + + return false; +} + + static bool qemuDomainMachineIsMipsMalta(const char *machine, const virArch arch) @@ -9123,6 +9150,13 @@ qemuDomainIsMipsMalta(const virDomainDef *def) } +bool +qemuDomainIsLoongArchVirt(const virDomainDef *def) +{ + return qemuDomainMachineIsLoongArchVirt(def->os.machine, def->os.arch); +} + + bool qemuDomainHasPCIRoot(const virDomainDef *def) { @@ -9209,6 +9243,7 @@ qemuDomainSupportsPCIMultibus(const virDomainDef *def) /* In some cases, support for multibus is limited to some machine * types */ if (qemuDomainIsARMVirt(def) || + qemuDomainIsLoongArchVirt(def) || qemuDomainIsRISCVVirt(def)) { return true; } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 626df6338f..bd37cb245a 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -828,6 +828,7 @@ bool qemuDomainIsQ35(const virDomainDef *def); bool qemuDomainIsI440FX(const virDomainDef *def); bool qemuDomainIsS390CCW(const virDomainDef *def); bool qemuDomainIsARMVirt(const virDomainDef *def); +bool qemuDomainIsLoongArchVirt(const virDomainDef *def); bool qemuDomainIsRISCVVirt(const virDomainDef *def); bool qemuDomainIsPSeries(const virDomainDef *def); bool qemuDomainIsMipsMalta(const virDomainDef *def); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 6a73d02050..b096312d1c 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2064,6 +2064,7 @@ qemuValidateDomainChrDef(const virDomainChrDef *dev, isCompatible = false; } if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A && + !qemuDomainIsLoongArchVirt(def) && !qemuDomainIsRISCVVirt(def)) { isCompatible = false; }