264 lines
10 KiB
Diff
264 lines
10 KiB
Diff
From 4b7f6284eaa3e3b15360e25848fc68b37ee6c768 Mon Sep 17 00:00:00 2001
|
|
From: zhaotianrui <zhaotianrui@loongson.cn>
|
|
Date: Wed, 11 Jan 2023 11:56:03 -0500
|
|
Subject: [PATCH 3/4] Config some capabilities for loongarch virt machine
|
|
|
|
Config some capabilities for loongarch virt machine such as
|
|
PCI multi bus and the path of loongarch uefi binary.
|
|
|
|
Signed-off-by: zhaotianrui <zhaotianrui@loongson.cn>
|
|
---
|
|
src/qemu/qemu.conf | 3 +-
|
|
src/qemu/qemu_capabilities.c | 4 ++
|
|
src/qemu/qemu_conf.c | 3 +-
|
|
src/qemu/qemu_domain.c | 31 ++++++++++-
|
|
src/qemu/qemu_domain.h | 1 +
|
|
src/qemu/qemu_domain_address.c | 86 ++++++++++++++++++++++++++++++
|
|
src/qemu/test_libvirtd_qemu.aug.in | 1 +
|
|
7 files changed, 125 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
|
|
index abdbf07fec..3856087248 100644
|
|
--- a/src/qemu/qemu.conf
|
|
+++ b/src/qemu/qemu.conf
|
|
@@ -771,7 +771,8 @@
|
|
# "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd",
|
|
# "/usr/share/OVMF/OVMF_CODE.secboot.fd:/usr/share/OVMF/OVMF_VARS.fd",
|
|
# "/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd",
|
|
-# "/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd"
|
|
+# "/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd",
|
|
+# "/usr/share/qemu/loongarch_bios.bin:/usr/share/qemu/loongarch_vars.bin"
|
|
#]
|
|
|
|
# The backend to use for handling stdout/stderr output from
|
|
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
|
index 0c3eb148b2..21b477cd4d 100644
|
|
--- a/src/qemu/qemu_capabilities.c
|
|
+++ b/src/qemu/qemu_capabilities.c
|
|
@@ -1983,6 +1983,10 @@ bool virQEMUCapsHasPCIMultiBus(virQEMUCapsPtr qemuCaps,
|
|
* since forever */
|
|
if (ARCH_IS_SW64(def->os.arch))
|
|
return true;
|
|
+ /* loongarch64 support PCI-multibus on all machine types
|
|
+ * since forever */
|
|
+ if (ARCH_IS_LOONGARCH(def->os.arch))
|
|
+ return true;
|
|
|
|
if (def->os.arch == VIR_ARCH_PPC ||
|
|
ARCH_IS_PPC64(def->os.arch)) {
|
|
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
|
|
index 28319a1baf..3253875d6e 100644
|
|
--- a/src/qemu/qemu_conf.c
|
|
+++ b/src/qemu/qemu_conf.c
|
|
@@ -98,7 +98,8 @@ qemuDriverUnlock(virQEMUDriverPtr driver)
|
|
"/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd:" \
|
|
"/usr/share/OVMF/OVMF_CODE.secboot.fd:/usr/share/OVMF/OVMF_VARS.fd:" \
|
|
"/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd:" \
|
|
- "/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd"
|
|
+ "/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd:" \
|
|
+ "/usr/share/qemu/loongarch_bios.bin:/usr/share/qemu/loongarch_vars.bin"
|
|
#endif
|
|
|
|
|
|
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
index 37dac3694b..152c8615d5 100644
|
|
--- a/src/qemu/qemu_domain.c
|
|
+++ b/src/qemu/qemu_domain.c
|
|
@@ -5186,7 +5186,7 @@ qemuDomainDefValidateFeatures(const virDomainDef *def,
|
|
switch ((virDomainFeature) i) {
|
|
case VIR_DOMAIN_FEATURE_IOAPIC:
|
|
if (def->features[i] != VIR_DOMAIN_IOAPIC_NONE) {
|
|
- if (!ARCH_IS_X86(def->os.arch)) {
|
|
+ if (!ARCH_IS_X86(def->os.arch) && !ARCH_IS_LOONGARCH(def->os.arch)) {
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
_("The '%s' feature is not supported for "
|
|
"architecture '%s' or machine type '%s'"),
|
|
@@ -9089,6 +9089,11 @@ qemuDomainControllerDefPostParse(virDomainControllerDefPtr 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;
|
|
+ else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NEC_USB_XHCI))
|
|
+ cont->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI;
|
|
}
|
|
}
|
|
/* forbid usb model 'qusb1' and 'qusb2' in this kind of hyperviosr */
|
|
@@ -12985,6 +12990,20 @@ qemuDomainMachineIsPSeries(const char *machine,
|
|
return false;
|
|
}
|
|
|
|
+static bool
|
|
+qemuDomainMachineIsLoongson(const char *machine,
|
|
+ const virArch arch)
|
|
+{
|
|
+ if (!ARCH_IS_LOONGARCH(arch))
|
|
+ return false;
|
|
+
|
|
+ if (STREQ(machine, "loongson7a") ||
|
|
+ STRPREFIX(machine, "loongson7a-")) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
|
|
/* You should normally avoid this function and use
|
|
* qemuDomainHasBuiltinIDE() instead. */
|
|
@@ -12996,7 +13015,8 @@ qemuDomainMachineHasBuiltinIDE(const char *machine,
|
|
STREQ(machine, "malta") ||
|
|
STREQ(machine, "sun4u") ||
|
|
STREQ(machine, "core3") ||
|
|
- STREQ(machine, "g3beige");
|
|
+ STREQ(machine, "g3beige") ||
|
|
+ STREQ(machine, "loongson7a");
|
|
}
|
|
|
|
|
|
@@ -13066,6 +13086,13 @@ qemuDomainIsPSeries(const virDomainDef *def)
|
|
}
|
|
|
|
|
|
+bool
|
|
+qemuDomainIsLoongson(const virDomainDef *def)
|
|
+{
|
|
+ return qemuDomainMachineIsLoongson(def->os.machine, def->os.arch);
|
|
+}
|
|
+
|
|
+
|
|
bool
|
|
qemuDomainHasPCIRoot(const virDomainDef *def)
|
|
{
|
|
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
index 7603724ccd..368fc4030f 100644
|
|
--- a/src/qemu/qemu_domain.h
|
|
+++ b/src/qemu/qemu_domain.h
|
|
@@ -999,6 +999,7 @@ bool qemuDomainIsS390CCW(const virDomainDef *def);
|
|
bool qemuDomainIsARMVirt(const virDomainDef *def);
|
|
bool qemuDomainIsRISCVVirt(const virDomainDef *def);
|
|
bool qemuDomainIsPSeries(const virDomainDef *def);
|
|
+bool qemuDomainIsLoongson(const virDomainDef *def);
|
|
bool qemuDomainHasPCIRoot(const virDomainDef *def);
|
|
bool qemuDomainHasPCIeRoot(const virDomainDef *def);
|
|
bool qemuDomainHasBuiltinIDE(const virDomainDef *def);
|
|
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
|
|
index ab6bce19f4..7f48773832 100644
|
|
--- a/src/qemu/qemu_domain_address.c
|
|
+++ b/src/qemu/qemu_domain_address.c
|
|
@@ -2078,6 +2078,87 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
|
|
return 0;
|
|
}
|
|
|
|
+static int
|
|
+qemuDomainValidateDevicePCISlotsLoongson(virDomainDefPtr def,
|
|
+ virQEMUCapsPtr qemuCaps,
|
|
+ virDomainPCIAddressSetPtr addrs)
|
|
+{
|
|
+ int ret = -1;
|
|
+ virPCIDeviceAddress tmp_addr;
|
|
+ bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
|
|
+ g_autofree char *addrStr = NULL;
|
|
+ virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
|
|
+
|
|
+ if (addrs->nbuses) {
|
|
+ memset(&tmp_addr, 0, sizeof(tmp_addr));
|
|
+ tmp_addr.slot = 1;
|
|
+ /* pci-ohci at 00:01.0 */
|
|
+ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (def->nvideos > 0 &&
|
|
+ def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_NONE &&
|
|
+ def->videos[0]->type != VIR_DOMAIN_VIDEO_TYPE_RAMFB) {
|
|
+ /* reserve slot 2 for vga device */
|
|
+ virDomainVideoDefPtr primaryVideo = def->videos[0];
|
|
+
|
|
+ if (virDeviceInfoPCIAddressIsWanted(&primaryVideo->info)) {
|
|
+ memset(&tmp_addr, 0, sizeof(tmp_addr));
|
|
+ tmp_addr.slot = 2;
|
|
+
|
|
+ if (!(addrStr = virPCIDeviceAddressAsString(&tmp_addr)))
|
|
+ return -1;
|
|
+ if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
|
|
+ addrStr, flags, true))
|
|
+ return ret;
|
|
+
|
|
+ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
|
|
+ if (qemuDeviceVideoUsable) {
|
|
+ if (qemuDomainPCIAddressReserveNextAddr(addrs,
|
|
+ &primaryVideo->info) < 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ } else {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
+ _("PCI address 0:0:2.0 is in use, "
|
|
+ "QEMU needs it for primary video"));
|
|
+ return ret;
|
|
+ }
|
|
+ } else {
|
|
+ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0)
|
|
+ return ret;
|
|
+ primaryVideo->info.addr.pci = tmp_addr;
|
|
+ primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
|
|
+ }
|
|
+ } else if (!qemuDeviceVideoUsable) {
|
|
+ if (primaryVideo->info.addr.pci.domain != 0 ||
|
|
+ primaryVideo->info.addr.pci.bus != 0 ||
|
|
+ primaryVideo->info.addr.pci.slot != 2 ||
|
|
+ primaryVideo->info.addr.pci.function != 0) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
+ _("Primary video card must have PCI address 0:0:2.0"));
|
|
+ return ret;
|
|
+ }
|
|
+ /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function
|
|
+ * has already reserved the address, so we must skip */
|
|
+ }
|
|
+ } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
|
|
+ memset(&tmp_addr, 0, sizeof(tmp_addr));
|
|
+ tmp_addr.slot = 2;
|
|
+
|
|
+ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
|
|
+ VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video"
|
|
+ " device will not be possible without manual"
|
|
+ " intervention");
|
|
+ } else if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) {
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ret = 0;
|
|
+ return ret;
|
|
+}
|
|
|
|
static int
|
|
qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def,
|
|
@@ -2094,6 +2175,11 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def,
|
|
return -1;
|
|
}
|
|
|
|
+ if (qemuDomainIsLoongson(def) &&
|
|
+ qemuDomainValidateDevicePCISlotsLoongson(def, qemuCaps, addrs) < 0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
|
|
index 19da591aae..caa06a45cb 100644
|
|
--- a/src/qemu/test_libvirtd_qemu.aug.in
|
|
+++ b/src/qemu/test_libvirtd_qemu.aug.in
|
|
@@ -95,6 +95,7 @@ module Test_libvirtd_qemu =
|
|
{ "2" = "/usr/share/OVMF/OVMF_CODE.secboot.fd:/usr/share/OVMF/OVMF_VARS.fd" }
|
|
{ "3" = "/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd" }
|
|
{ "4" = "/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd" }
|
|
+ { "5" = "/usr/share/qemu/loongarch_bios.bin:/usr/share/qemu/loongarch_vars.bin" }
|
|
}
|
|
{ "stdio_handler" = "logd" }
|
|
{ "gluster_debug_level" = "9" }
|
|
--
|
|
2.25.1
|
|
|