From 6bd8a5162123641369b60d600c4906a472209183 Mon Sep 17 00:00:00 2001 From: Renbo Date: Tue, 27 Dec 2022 16:47:24 +0800 Subject: [PATCH 1/2] update to libvirt-8.0.0-10.module+el8.7.0+16689+53d59bc2 Signed-off-by: Renbo --- libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch | 49 + libvirt-Add-loongarch-support.patch | 1233 ----------------- ...storing-memlock-limit-on-destination.patch | 52 + ...-Introduce-memory-allocation-threads.patch | 6 +- ...nalMemlock-into-qemuDomainObjPrivate.patch | 91 ++ ...onf-virtiofs-add-thread_pool-element.patch | 151 ++ ...u64-rhel-for-host-model-and-baseline.patch | 6 +- ...ature-match-in-x86DecodeUseCandidate.patch | 6 +- ...nput-models-in-x86DecodeUseCandidate.patch | 6 +- ...ed-features-when-computing-CPU-model.patch | 6 +- ...-comparison-in-x86DecodeUseCandidate.patch | 6 +- ...t-Add-some-real-world-baseline-tests.patch | 6 +- ...p-some-old-artificial-baseline-tests.patch | 6 +- ...-Give-better-names-to-baseline-tests.patch | 6 +- ...ut-validation-of-disk-startup-policy.patch | 111 ++ ...n-counting-number-of-network-filters.patch | 55 + ...u-Add-qemuDomainSetMaxMemLock-helper.patch | 155 +++ ...emu-virtiofs-format-thread-pool-size.patch | 37 + ...y-backend-.prealloc-threads-property.patch | 6 +- ...d-Generate-prealloc-threads-property.patch | 6 +- ...qemuDomainObjPrivate-originalMemlock.patch | 55 + ...-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch | 120 ++ ...estore-original-memory-locking-limit.patch | 133 ++ ...igration-Use-qemuDomainSetMaxMemLock.patch | 53 + ...te-prealloc-threads-against-qemuCpas.patch | 6 +- ...abel-existing-mode-bind-UNIX-sockets.patch | 64 + ...or-messages-for-startupPolicy-checks.patch | 51 + ...rtupPolicy-Validate-disk-type-better.patch | 42 + ...ix-check-of-startupPolicy-definition.patch | 56 + ...upport-for-VIR_MIGRATE_ZEROCOPY-flag.patch | 80 ++ libvirt.spec | 87 +- 31 files changed, 1453 insertions(+), 1294 deletions(-) create mode 100644 libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch delete mode 100644 libvirt-Add-loongarch-support.patch create mode 100644 libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch create mode 100644 libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch create mode 100644 libvirt-conf-virtiofs-add-thread_pool-element.patch create mode 100644 libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch create mode 100644 libvirt-nwfilter-fix-crash-when-counting-number-of-network-filters.patch create mode 100644 libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch create mode 100644 libvirt-qemu-virtiofs-format-thread-pool-size.patch create mode 100644 libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch create mode 100644 libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch create mode 100644 libvirt-qemu_migration-Restore-original-memory-locking-limit.patch create mode 100644 libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch create mode 100644 libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch create mode 100644 libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch create mode 100644 libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch create mode 100644 libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch create mode 100644 libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch diff --git a/libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch b/libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch new file mode 100644 index 0000000..b65e479 --- /dev/null +++ b/libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch @@ -0,0 +1,49 @@ +From 9c2fd182a02d64004e30900c52e3fcdb550de0bd Mon Sep 17 00:00:00 2001 +Message-Id: <9c2fd182a02d64004e30900c52e3fcdb550de0bd@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 16:35:50 +0200 +Subject: [PATCH] Add VIR_MIGRATE_ZEROCOPY flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The flag can be used to enable zero-copy mechanism for migrating memory +pages. + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit 8744beecb36600e773c8a8c4823db2bf4b3e262d) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Conflicts: + include/libvirt/libvirt-domain.h + - post-copy recovery not backported + +Signed-off-by: Jiri Denemark +--- + include/libvirt/libvirt-domain.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 5f0a9b7572..792973ce2d 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -860,6 +860,14 @@ typedef enum { + */ + VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES = (1 << 18), + ++ /* Use zero-copy mechanism for migrating memory pages. For QEMU/KVM this ++ * means QEMU will be temporarily allowed to lock all guest pages in host's ++ * memory, although only those that are queued for transfer will be locked ++ * at the same time. ++ * ++ * Since: 8.5.0 ++ */ ++ VIR_MIGRATE_ZEROCOPY = (1 << 20), + } virDomainMigrateFlags; + + +-- +2.35.1 + diff --git a/libvirt-Add-loongarch-support.patch b/libvirt-Add-loongarch-support.patch deleted file mode 100644 index 94fd22a..0000000 --- a/libvirt-Add-loongarch-support.patch +++ /dev/null @@ -1,1233 +0,0 @@ -From da7befb4ce165d692f34156f740f4ea3ce2b7fec Mon Sep 17 00:00:00 2001 -From: zhaotianrui -Date: Sat, 3 Sep 2022 14:23:43 -0400 -Subject: [PATCH] Add loongarch support - -Signed-off-by: zhaotianrui -Change-Id: I8d245bc2fb914b08af4ade8e334d59ba3a5c2f01 ---- - po/POTFILES.in | 1 + - src/cpu/cpu.c | 3 +- - src/cpu/cpu.h | 3 +- - src/cpu/cpu_loongarch.c | 727 ++++++++++++++++++++++++++++++ - src/cpu/cpu_loongarch.h | 28 ++ - src/cpu/cpu_loongarch_data.h | 40 ++ - src/cpu/meson.build | 1 + - src/cpu_map/index.xml | 5 + - src/cpu_map/loongarch_vendors.xml | 3 + - src/cpu_map/ls_3a5000.xml | 6 + - src/cpu_map/meson.build | 2 + - src/qemu/qemu_capabilities.c | 5 + - src/qemu/qemu_conf.c | 4 +- - src/qemu/qemu_domain.c | 20 +- - src/qemu/qemu_domain.h | 1 + - src/qemu/qemu_domain_address.c | 58 +++ - src/qemu/qemu_validate.c | 3 +- - src/util/virarch.c | 3 + - src/util/virarch.h | 3 + - src/util/virhostcpu.c | 2 +- - src/util/virsysinfo.c | 2 +- - 21 files changed, 913 insertions(+), 7 deletions(-) - create mode 100644 src/cpu/cpu_loongarch.c - create mode 100644 src/cpu/cpu_loongarch.h - create mode 100644 src/cpu/cpu_loongarch_data.h - create mode 100644 src/cpu_map/loongarch_vendors.xml - create mode 100644 src/cpu_map/ls_3a5000.xml - -diff --git a/po/POTFILES.in b/po/POTFILES.in -index bf0a3b3529..1153e78265 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -68,6 +68,7 @@ - @SRCDIR@src/cpu/cpu_arm.c - @SRCDIR@src/cpu/cpu_map.c - @SRCDIR@src/cpu/cpu_ppc64.c -+@SRCDIR@src/cpu/cpu_loongarch.c - @SRCDIR@src/cpu/cpu_s390.c - @SRCDIR@src/cpu/cpu_x86.c - @SRCDIR@src/datatypes.c -diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c -index 285c7eee44..49527c3688 100644 ---- a/src/cpu/cpu.c -+++ b/src/cpu/cpu.c -@@ -31,7 +31,7 @@ - #include "cpu_arm.h" - #include "capabilities.h" - #include "virstring.h" -- -+#include "cpu_loongarch.h" - - #define VIR_FROM_THIS VIR_FROM_CPU - -@@ -42,6 +42,7 @@ static struct cpuArchDriver *drivers[] = { - &cpuDriverPPC64, - &cpuDriverS390, - &cpuDriverArm, -+ &cpuDriverLoongArch, - }; - - -diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h -index 071b33fe76..ce7aee4757 100644 ---- a/src/cpu/cpu.h -+++ b/src/cpu/cpu.h -@@ -28,7 +28,7 @@ - #include "cpu_x86_data.h" - #include "cpu_ppc64_data.h" - #include "cpu_arm_data.h" -- -+#include "cpu_loongarch_data.h" - - typedef struct _virCPUData virCPUData; - struct _virCPUData { -@@ -37,6 +37,7 @@ struct _virCPUData { - virCPUx86Data x86; - virCPUppc64Data ppc64; - virCPUarmData arm; -+ virCPULoongArchData loongarch; - /* generic driver needs no data */ - } data; - }; -diff --git a/src/cpu/cpu_loongarch.c b/src/cpu/cpu_loongarch.c -new file mode 100644 -index 0000000000..f7b4b85a44 ---- /dev/null -+++ b/src/cpu/cpu_loongarch.c -@@ -0,0 +1,727 @@ -+/* -+ * cpu_loongarch.c: CPU driver for 64-bit LOONGARCH CPUs -+ * -+ * Copyright (C) 2013 Red Hat, Inc. -+ * Copyright (C) IBM Corporation, 2010 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library. If not, see -+ * . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "virlog.h" -+#include "viralloc.h" -+#include "cpu.h" -+#include "virstring.h" -+#include "cpu_map.h" -+#include "virbuffer.h" -+#include "cpu_loongarch.h" -+#include "cpu_loongarch_data.h" -+ -+#define VIR_FROM_THIS VIR_FROM_CPU -+ -+VIR_LOG_INIT("cpu.cpu_loongarch"); -+ -+static const virArch archs[] = { VIR_ARCH_LOONGARCH64 }; -+ -+typedef struct _LoongArch_vendor LoongArch_vendor; -+struct _LoongArch_vendor { -+ char *name; -+}; -+ -+typedef struct _LoongArch_model LoongArch_model; -+struct _LoongArch_model { -+ char *name; -+ LoongArch_vendor *vendor; -+ virCPULoongArchData data; -+}; -+ -+typedef struct _LoongArch_map LoongArch_map; -+struct _LoongArch_map { -+ size_t nvendors; -+ LoongArch_vendor **vendors; -+ size_t nmodels; -+ LoongArch_model **models; -+}; -+ -+static void -+LoongArchDataClear(virCPULoongArchData *data) -+{ -+ if (!data) -+ return; -+ -+ g_free(data->prid); -+} -+ -+static int -+LoongArchDataCopy(virCPULoongArchData *dst, const virCPULoongArchData *src) -+{ -+ size_t i; -+ -+ dst->prid = g_new0(virCPULoongArchPrid, src->len); -+ dst->len = src->len; -+ -+ for (i = 0; i < src->len; i++) { -+ dst->prid[i].value = src->prid[i].value; -+ dst->prid[i].mask = src->prid[i].mask; -+ } -+ -+ return 0; -+} -+ -+static void -+LoongArchVendorFree(LoongArch_vendor *vendor) -+{ -+ if (!vendor) -+ return; -+ -+ g_free(vendor); -+} -+ -+static LoongArch_vendor * -+LoongArchVendorFind(LoongArch_map *map, -+ const char *name) -+{ -+ size_t i; -+ -+ for (i = 0; i < map->nvendors; i++) { -+ if (STREQ(map->vendors[i]->name, name)) -+ return map->vendors[i]; -+ } -+ -+ return NULL; -+} -+ -+static void -+LoongArchModelFree(LoongArch_model *model) -+{ -+ if (!model) -+ return; -+ -+ LoongArchDataClear(&model->data); -+ g_free(model->name); -+ g_free(model); -+} -+ -+static LoongArch_model * -+LoongArchModelCopy(LoongArch_model *model) -+{ -+ LoongArch_model *copy; -+ -+ copy = g_new0(LoongArch_model, 1); -+ copy->name = g_strdup(model->name); -+ -+ if (LoongArchDataCopy(©->data, &model->data) < 0) -+ goto error; -+ -+ copy->vendor = model->vendor; -+ -+ return copy; -+ -+ error: -+ LoongArchModelFree(copy); -+ return NULL; -+} -+ -+static LoongArch_model * -+LoongArchModelFind(LoongArch_map *map, -+ const char *name) -+{ -+ size_t i; -+ -+ for (i = 0; i < map->nmodels; i++) { -+ if (STREQ(map->models[i]->name, name)) -+ return map->models[i]; -+ } -+ -+ return NULL; -+} -+ -+static LoongArch_model * -+LoongArchModelFindPrid(LoongArch_map *map, -+ uint32_t prid) -+{ -+ size_t i; -+ size_t j; -+ -+ for (i = 0; i < map->nmodels; i++) { -+ LoongArch_model *model = map->models[i]; -+ for (j = 0; j < model->data.len; j++) { -+ if ((prid & model->data.prid[j].mask) == model->data.prid[j].value) -+ return model; -+ } -+ } -+ -+ return NULL; -+} -+ -+static LoongArch_model * -+LoongArchModelFromCPU(const virCPUDef *cpu, -+ LoongArch_map *map) -+{ -+ LoongArch_model *model; -+ -+ if (!cpu->model) { -+ virReportError(VIR_ERR_INVALID_ARG, "%s", -+ _("no CPU model specified")); -+ return NULL; -+ } -+ -+ if (!(model = LoongArchModelFind(map, cpu->model))) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Unknown CPU model %s"), cpu->model); -+ return NULL; -+ } -+ -+ return LoongArchModelCopy(model); -+} -+ -+static void -+LoongArchMapFree(LoongArch_map *map) -+{ -+ size_t i; -+ -+ if (!map) -+ return; -+ -+ for (i = 0; i < map->nmodels; i++) -+ LoongArchModelFree(map->models[i]); -+ g_free(map->models); -+ -+ for (i = 0; i < map->nvendors; i++) -+ LoongArchVendorFree(map->vendors[i]); -+ g_free(map->vendors); -+ -+ g_free(map); -+} -+ -+static int -+LoongArchVendorParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED, -+ const char *name, -+ void *data) -+{ -+ LoongArch_map *map = data; -+ LoongArch_vendor *vendor; -+ int ret = -1; -+ -+ vendor = g_new0(LoongArch_vendor, 1); -+ vendor->name = g_strdup(name); -+ -+ if (LoongArchVendorFind(map, vendor->name)) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("CPU vendor %s already defined"), vendor->name); -+ goto cleanup; -+ } -+ -+ VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor); -+ ret = 0; -+ -+ cleanup: -+ LoongArchVendorFree(vendor); -+ return ret; -+} -+ -+static int -+LoongArchModelParse(xmlXPathContextPtr ctxt, -+ const char *name, -+ void *data) -+{ -+ LoongArch_map *map = data; -+ LoongArch_model *model; -+ xmlNodePtr *nodes = NULL; -+ char *vendor = NULL; -+ unsigned long prid; -+ size_t i; -+ int n; -+ int ret = -1; -+ -+ model = g_new0(LoongArch_model, 1); -+ model->name = g_strdup(name); -+ -+ if (LoongArchModelFind(map, model->name)) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("CPU model %s already defined"), model->name); -+ goto cleanup; -+ } -+ -+ if (virXPathBoolean("boolean(./vendor)", ctxt)) { -+ vendor = virXPathString("string(./vendor/@name)", ctxt); -+ if (!vendor) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Invalid vendor element in CPU model %s"), -+ model->name); -+ goto cleanup; -+ } -+ -+ if (!(model->vendor = LoongArchVendorFind(map, vendor))) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Unknown vendor %s referenced by CPU model %s"), -+ vendor, model->name); -+ goto cleanup; -+ } -+ } -+ -+ if ((n = virXPathNodeSet("./prid", ctxt, &nodes)) <= 0) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Missing Prid information for CPU model %s"), -+ model->name); -+ goto cleanup; -+ } -+ -+ model->data.prid = g_new0(virCPULoongArchPrid, n); -+ model->data.len = n; -+ -+ for (i = 0; i < n; i++) { -+ ctxt->node = nodes[i]; -+ -+ if (virXPathULongHex("string(./@value)", ctxt, &prid) < 0) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Missing or invalid Prid value in CPU model %s"), -+ model->name); -+ goto cleanup; -+ } -+ model->data.prid[i].value = prid; -+ -+ if (virXPathULongHex("string(./@mask)", ctxt, &prid) < 0) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Missing or invalid PVR mask in CPU model %s"), -+ model->name); -+ goto cleanup; -+ } -+ model->data.prid[i].mask = prid; -+ } -+ -+ VIR_APPEND_ELEMENT(map->models, map->nmodels, model); -+ ret = 0; -+ -+ cleanup: -+ LoongArchModelFree(model); -+ g_free(vendor); -+ g_free(nodes); -+ return ret; -+} -+ -+static LoongArch_map * -+LoongArchLoadMap(void) -+{ -+ LoongArch_map *map; -+ -+ map = g_new0(LoongArch_map, 1); -+ if (cpuMapLoad("loongarch64", LoongArchVendorParse, NULL, LoongArchModelParse, map) < 0) -+ goto error; -+ -+ return map; -+ -+ error: -+ LoongArchMapFree(map); -+ return NULL; -+} -+ -+static virCPUData * -+LoongArchMakeCPUData(virArch arch, -+ virCPULoongArchData *data) -+{ -+ virCPUData *cpuData; -+ -+ cpuData = g_new0(virCPUData, 1); -+ cpuData->arch = arch; -+ -+ if (LoongArchDataCopy(&cpuData->data.loongarch, data) < 0) -+ g_free(cpuData); -+ -+ return cpuData; -+} -+ -+static virCPUCompareResult -+LoongArchCompute(virCPUDef *host, -+ const virCPUDef *other, -+ virCPUData *guestData, -+ char **message) -+{ -+ LoongArch_map *map = NULL; -+ LoongArch_model *host_model = NULL; -+ LoongArch_model *guest_model = NULL; -+ virCPUDef *cpu = NULL; -+ virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; -+ virArch arch; -+ size_t i; -+ -+ /* Ensure existing configurations are handled correctly */ -+ if (!(cpu = virCPUDefCopy(other))) -+ goto cleanup; -+ -+ if (cpu->arch != VIR_ARCH_NONE) { -+ bool found = false; -+ -+ for (i = 0; i < G_N_ELEMENTS(archs); i++) { -+ if (archs[i] == cpu->arch) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ VIR_DEBUG("CPU arch %s does not match host arch", -+ virArchToString(cpu->arch)); -+ if (message) { -+ *message = g_strdup_printf(_("CPU arch %s does not match host arch"), -+ virArchToString(cpu->arch)); -+ } -+ ret = VIR_CPU_COMPARE_INCOMPATIBLE; -+ goto cleanup; -+ } -+ arch = cpu->arch; -+ } else { -+ arch = host->arch; -+ } -+ -+ if (cpu->vendor && -+ (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) { -+ VIR_DEBUG("host CPU vendor does not match required CPU vendor %s", -+ cpu->vendor); -+ if (message) { -+ *message = g_strdup_printf(_("host CPU vendor does not match required " -+ "CPU vendor %s"), cpu->vendor); -+ } -+ ret = VIR_CPU_COMPARE_INCOMPATIBLE; -+ goto cleanup; -+ } -+ -+ if (!(map = LoongArchLoadMap())) -+ goto cleanup; -+ -+ /* Host CPU information */ -+ if (!(host_model = LoongArchModelFromCPU(host, map))) -+ goto cleanup; -+ -+ if (cpu->type == VIR_CPU_TYPE_GUEST) { -+ /* Guest CPU information */ -+ switch (cpu->mode) { -+ case VIR_CPU_MODE_HOST_MODEL: -+ case VIR_CPU_MODE_HOST_PASSTHROUGH: -+ /* host-model and host-passthrough: -+ * the guest CPU is the same as the host */ -+ guest_model = LoongArchModelCopy(host_model); -+ break; -+ -+ case VIR_CPU_MODE_CUSTOM: -+ /* custom: -+ * look up guest CPU information */ -+ guest_model = LoongArchModelFromCPU(cpu, map); -+ break; -+ } -+ } else { -+ /* Other host CPU information */ -+ guest_model = LoongArchModelFromCPU(cpu, map); -+ } -+ -+ if (!guest_model) -+ goto cleanup; -+ -+ if (STRNEQ(guest_model->name, host_model->name)) { -+ VIR_DEBUG("host CPU model does not match required CPU model %s", -+ guest_model->name); -+ if (message) { -+ *message = g_strdup_printf(_("host CPU model does not match required " -+ "CPU model %s"),guest_model->name); -+ } -+ ret = VIR_CPU_COMPARE_INCOMPATIBLE; -+ goto cleanup; -+ } -+ -+ if (guestData) -+ if (!(guestData = LoongArchMakeCPUData(arch, &guest_model->data))) -+ goto cleanup; -+ -+ ret = VIR_CPU_COMPARE_IDENTICAL; -+ -+ cleanup: -+ virCPUDefFree(cpu); -+ LoongArchMapFree(map); -+ LoongArchModelFree(host_model); -+ LoongArchModelFree(guest_model); -+ return ret; -+} -+ -+static virCPUCompareResult -+virCPULoongArchCompare(virCPUDef *host, -+ virCPUDef *cpu, -+ bool failIncompatible) -+{ -+ virCPUCompareResult ret; -+ char *message = NULL; -+ -+ if (!host || !host->model) { -+ if (failIncompatible) { -+ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", -+ _("unknown host CPU")); -+ } else { -+ VIR_WARN("unknown host CPU"); -+ ret = VIR_CPU_COMPARE_INCOMPATIBLE; -+ } -+ return -1; -+ } -+ -+ ret = LoongArchCompute(host, cpu, NULL, &message); -+ -+ if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) { -+ ret = VIR_CPU_COMPARE_ERROR; -+ if (message) { -+ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message); -+ } else { -+ virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); -+ } -+ } -+ g_free(message); -+ -+ return ret; -+} -+ -+static int -+LoongArchDriverDecode(virCPUDef *cpu, -+ const virCPUData *data, -+ virDomainCapsCPUModels *models) -+{ -+ int ret = -1; -+ LoongArch_map *map; -+ LoongArch_model *model; -+ -+ if (!data || !(map = LoongArchLoadMap())) -+ return -1; -+ -+ if (!(model = LoongArchModelFindPrid(map, data->data.loongarch.prid[0].value))) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("Cannot find CPU model with Prid 0x%08x"), -+ data->data.loongarch.prid[0].value); -+ goto cleanup; -+ } -+ -+ if (!virCPUModelIsAllowed(model->name, models)) { -+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -+ _("CPU model %s is not supported by hypervisor"), -+ model->name); -+ goto cleanup; -+ } -+ -+ cpu->model = g_strdup(model->name); -+ if (model->vendor) { -+ cpu->vendor = g_strdup(model->vendor->name); -+ } -+ ret = 0; -+ -+ cleanup: -+ LoongArchMapFree(map); -+ -+ return ret; -+} -+ -+static void -+virCPULoongArchDataFree(virCPUData *data) -+{ -+ if (!data) -+ return; -+ -+ LoongArchDataClear(&data->data.loongarch); -+ g_free(data); -+} -+ -+static int virCPULoongArchGetHostPRID(void) -+{ -+ return 0x14c010; -+} -+ -+static int -+virCPULoongArchGetHost(virCPUDef *cpu, -+ virDomainCapsCPUModels *models) -+{ -+ virCPUData *cpuData = NULL; -+ virCPULoongArchData *data; -+ int ret = -1; -+ -+ if (!(cpuData = virCPUDataNew(archs[0]))) -+ goto cleanup; -+ -+ data = &cpuData->data.loongarch; -+ -+ data->prid = g_new0(virCPULoongArchPrid, 1); -+ data->len = 1; -+ -+ data->prid[0].value = virCPULoongArchGetHostPRID(); -+ data->prid[0].mask = 0xffff00ul; -+ -+ ret = LoongArchDriverDecode(cpu, cpuData, models); -+ -+ cleanup: -+ virCPULoongArchDataFree(cpuData); -+ return ret; -+} -+ -+ -+static int -+virCPULoongArchUpdate(virCPUDef *guest, -+ const virCPUDef *host, -+ bool relative) -+{ -+ /* -+ * - host-passthrough doesn't even get here -+ * - host-model is used for host CPU running in a compatibility mode and -+ * it needs to remain unchanged -+ * - custom doesn't support any optional features, there's nothing to -+ * update -+ */ -+ VIR_DEBUG("host model %s, if relatived %d",host->model, relative); -+ if (guest->mode == VIR_CPU_MODE_CUSTOM) -+ guest->match = VIR_CPU_MATCH_EXACT; -+ -+ return 0; -+} -+ -+static virCPUDef * -+LoongArchDriverBaseline(virCPUDef **cpus, -+ unsigned int ncpus, -+ virDomainCapsCPUModels *models, -+ const char **features, -+ bool migratable) -+{ -+ LoongArch_map *map; -+ LoongArch_model *model; -+ LoongArch_vendor *vendor = NULL; -+ virCPUDef *cpu = NULL; -+ size_t i; -+ if (models && *features) { -+ VIR_DEBUG("migratable %d features %s",migratable, *features); -+ } -+ if (!(map = LoongArchLoadMap())) -+ goto error; -+ -+ if (!(model = LoongArchModelFind(map, cpus[0]->model))) { -+ virReportError(VIR_ERR_INTERNAL_ERROR, -+ _("Unknown CPU model %s"), cpus[0]->model); -+ goto error; -+ } -+ -+ for (i = 0; i < ncpus; i++) { -+ LoongArch_vendor *vnd; -+ -+ if (STRNEQ(cpus[i]->model, model->name)) { -+ virReportError(VIR_ERR_OPERATION_FAILED, "%s", -+ _("CPUs are incompatible")); -+ goto error; -+ } -+ -+ if (!cpus[i]->vendor) -+ continue; -+ -+ if (!(vnd = LoongArchVendorFind(map, cpus[i]->vendor))) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("Unknown CPU vendor %s"), cpus[i]->vendor); -+ goto error; -+ } -+ -+ if (model->vendor) { -+ if (model->vendor != vnd) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("CPU vendor %s of model %s differs from " -+ "vendor %s"), -+ model->vendor->name, model->name, -+ vnd->name); -+ goto error; -+ } -+ } else if (vendor) { -+ if (vendor != vnd) { -+ virReportError(VIR_ERR_OPERATION_FAILED, "%s", -+ _("CPU vendors do not match")); -+ goto error; -+ } -+ } else { -+ vendor = vnd; -+ } -+ } -+ -+ cpu = g_new0(virCPUDef ,1); -+ cpu->model = g_strdup(model->name); -+ if (vendor) { -+ cpu->vendor = g_strdup(vendor->name); -+ } -+ cpu->type = VIR_CPU_TYPE_GUEST; -+ cpu->match = VIR_CPU_MATCH_EXACT; -+ cpu->fallback = VIR_CPU_FALLBACK_FORBID; -+ -+ cleanup: -+ LoongArchMapFree(map); -+ -+ return cpu; -+ -+ error: -+ virCPUDefFree(cpu); -+ cpu = NULL; -+ goto cleanup; -+} -+ -+static int -+virCPULoongArchDriverGetModels(char ***models) -+{ -+ LoongArch_map *map; -+ size_t i; -+ int ret = -1; -+ -+ if (!(map = LoongArchLoadMap())) -+ goto error; -+ -+ if (models) { -+ *models = g_new0(char *, map->nmodels + 1); -+ for (i = 0; i < map->nmodels; i++) { -+ (*models)[i] = g_strdup(map->models[i]->name); -+ } -+ } -+ -+ ret = map->nmodels; -+ -+ cleanup: -+ LoongArchMapFree(map); -+ return ret; -+ -+ error: -+ if (models) { -+ g_strfreev(*models); -+ *models = NULL; -+ } -+ goto cleanup; -+} -+ -+struct cpuArchDriver cpuDriverLoongArch = { -+ .name = "LoongArch", -+ .arch = archs, -+ .narch = G_N_ELEMENTS(archs), -+ .compare = virCPULoongArchCompare, -+ .decode = LoongArchDriverDecode, -+ .encode = NULL, -+ .dataFree = virCPULoongArchDataFree, -+ .getHost = virCPULoongArchGetHost, -+ .baseline = LoongArchDriverBaseline, -+ .update = virCPULoongArchUpdate, -+ .getModels = virCPULoongArchDriverGetModels, -+}; -diff --git a/src/cpu/cpu_loongarch.h b/src/cpu/cpu_loongarch.h -new file mode 100644 -index 0000000000..1fde3b5162 ---- /dev/null -+++ b/src/cpu/cpu_loongarch.h -@@ -0,0 +1,28 @@ -+/* -+ * cpu_loongarch.h: CPU driver for 64-bit LOONGARCH CPUs -+ * -+ * Copyright (C) Copyright (C) IBM Corporation, 2010 -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library. If not, see -+ * . -+ */ -+ -+#ifndef __VIR_CPU_LOONGARCH_H__ -+# define __VIR_CPU_LOONGARCH_H__ -+ -+# include "cpu.h" -+ -+extern struct cpuArchDriver cpuDriverLoongArch; -+ -+#endif /* __VIR_CPU_LOONGARCH_H__ */ -diff --git a/src/cpu/cpu_loongarch_data.h b/src/cpu/cpu_loongarch_data.h -new file mode 100644 -index 0000000000..1a759e7d16 ---- /dev/null -+++ b/src/cpu/cpu_loongarch_data.h -@@ -0,0 +1,40 @@ -+/* -+ * cpu_loongarch_data.h: 64-bit LOONGARCH CPU specific data -+ * -+ * Copyright (C) 2012 IBM Corporation. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; If not, see -+ * . -+ */ -+ -+#ifndef __VIR_CPU_LOONGARCH_DATA_H__ -+# define __VIR_CPU_LOONGARCH_DATA_H__ -+ -+# include -+ -+typedef struct _virCPULoongArchPrid virCPULoongArchPrid; -+struct _virCPULoongArchPrid { -+ uint32_t value; -+ uint32_t mask; -+}; -+ -+# define VIR_CPU_LOONGARCH_DATA_INIT { 0 } -+ -+typedef struct _virCPULoongArchData virCPULoongArchData; -+struct _virCPULoongArchData { -+ size_t len; -+ virCPULoongArchPrid *prid; -+}; -+ -+#endif /* __VIR_CPU_MIPS64_DATA_H__ */ -diff --git a/src/cpu/meson.build b/src/cpu/meson.build -index b4ad95e46d..ad2f859fd8 100644 ---- a/src/cpu/meson.build -+++ b/src/cpu/meson.build -@@ -5,6 +5,7 @@ cpu_sources = [ - 'cpu_ppc64.c', - 'cpu_s390.c', - 'cpu_x86.c', -+ 'cpu_loongarch.c', - ] - - cpu_lib = static_library( -diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml -index ffe1fa91e5..d302de396a 100644 ---- a/src/cpu_map/index.xml -+++ b/src/cpu_map/index.xml -@@ -110,4 +110,9 @@ - - - -+ -+ -+ -+ -+ - -diff --git a/src/cpu_map/loongarch_vendors.xml b/src/cpu_map/loongarch_vendors.xml -new file mode 100644 -index 0000000000..c744654617 ---- /dev/null -+++ b/src/cpu_map/loongarch_vendors.xml -@@ -0,0 +1,3 @@ -+ -+ -+ -diff --git a/src/cpu_map/ls_3a5000.xml b/src/cpu_map/ls_3a5000.xml -new file mode 100644 -index 0000000000..f6fe3386f7 ---- /dev/null -+++ b/src/cpu_map/ls_3a5000.xml -@@ -0,0 +1,6 @@ -+ -+ -+ -+ -+ -+ -diff --git a/src/cpu_map/meson.build b/src/cpu_map/meson.build -index 013fc62a02..9657c5164e 100644 ---- a/src/cpu_map/meson.build -+++ b/src/cpu_map/meson.build -@@ -77,6 +77,8 @@ cpumap_data = [ - 'x86_vendors.xml', - 'x86_Westmere-IBRS.xml', - 'x86_Westmere.xml', -+ 'loongarch_vendors.xml', -+ 'ls_3a5000.xml', - ] - - install_data(cpumap_data, install_dir: pkgdatadir / 'cpu_map') -diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c -index c4f7db55c8..75668c6451 100644 ---- a/src/qemu/qemu_capabilities.c -+++ b/src/qemu/qemu_capabilities.c -@@ -2073,6 +2073,9 @@ bool virQEMUCapsHasPCIMultiBus(const virDomainDef *def) - if (ARCH_IS_X86(def->os.arch)) - return true; - -+ if (STRPREFIX(def->os.machine,"loongson7a")) -+ return true; -+ - /* PPC supports multibus on all machine types which have pci since qemu-2.0.0 */ - if (def->os.arch == VIR_ARCH_PPC || - ARCH_IS_PPC64(def->os.arch)) { -@@ -2690,6 +2693,7 @@ static const char *preferredMachines[] = - - "malta", /* VIR_ARCH_MIPS64 */ - "malta", /* VIR_ARCH_MIPS64EL */ -+ "loongson7a", /* VIR_ARCH_LOONGARCH64 */ - "or1k-sim", /* VIR_ARCH_OR32 */ - NULL, /* VIR_ARCH_PARISC (no QEMU impl) */ - NULL, /* VIR_ARCH_PARISC64 (no QEMU impl) */ -@@ -5115,6 +5119,7 @@ virQEMUCapsInitQMPBasicArch(virQEMUCaps *qemuCaps) - case VIR_ARCH_MIPSEL: - case VIR_ARCH_MIPS64: - case VIR_ARCH_MIPS64EL: -+ case VIR_ARCH_LOONGARCH64: - case VIR_ARCH_OR32: - case VIR_ARCH_PARISC: - case VIR_ARCH_PARISC64: -diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c -index a0b8076d6b..8cd03261ac 100644 ---- a/src/qemu/qemu_conf.c -+++ b/src/qemu/qemu_conf.c -@@ -101,7 +101,9 @@ qemuDriverUnlock(virQEMUDriver *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-kvm/loongarch_bios.bin:/usr/share/qemu-kvm/loongarch_bios.bin" -+ - #endif - - -diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c -index 40fe9985e6..814d8cb67d 100644 ---- a/src/qemu/qemu_domain.c -+++ b/src/qemu/qemu_domain.c -@@ -3668,6 +3668,10 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, - addPCIeRoot = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX); - break; - -+ case VIR_ARCH_LOONGARCH64: -+ addPCIeRoot = true; -+ break; -+ - case VIR_ARCH_PPC64: - case VIR_ARCH_PPC64LE: - addPCIRoot = true; -@@ -5065,6 +5069,11 @@ 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; -+ 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 */ -@@ -8324,6 +8333,13 @@ qemuDomainDefCheckABIStability(virQEMUDriver *driver, - } - - -+bool -+qemuDomainIsLoongson(const virDomainDef *def) -+{ -+ return (STRPREFIX(def->os.machine,"loongson3a") || STRPREFIX(def->os.machine,"loongson7a")); -+} -+ -+ - bool - qemuDomainCheckABIStability(virQEMUDriver *driver, - virDomainObj *vm, -@@ -8664,7 +8680,9 @@ qemuDomainMachineHasBuiltinIDE(const char *machine, - return qemuDomainMachineIsI440FX(machine, arch) || - STREQ(machine, "malta") || - STREQ(machine, "sun4u") || -- STREQ(machine, "g3beige"); -+ STREQ(machine, "g3beige") || -+ STREQ(machine, "loongson3a") || -+ STREQ(machine, "loongson7a"); - } - - -diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h -index e5046367e3..57f1f97348 100644 ---- a/src/qemu/qemu_domain.h -+++ b/src/qemu/qemu_domain.h -@@ -770,6 +770,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 18fc34d049..c3fac1c33b 100644 ---- a/src/qemu/qemu_domain_address.c -+++ b/src/qemu/qemu_domain_address.c -@@ -2026,6 +2026,59 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDef *def, - } - - -+static int -+qemuDomainValidateDevicePCISlotsLoongson(virDomainDef *def, -+ virDomainPCIAddressSet *addrs) -+{ -+ int ret = -1; -+ virPCIDeviceAddress tmp_addr; -+ char *addrStr = NULL; -+ virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_AUTOASSIGN -+ | 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) -+ goto cleanup; -+ } -+ -+ 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 */ -+ virDomainVideoDef *primaryVideo = def->videos[0]; -+ -+ if (virDeviceInfoPCIAddressIsWanted(&primaryVideo->info)) { -+ memset(&tmp_addr, 0, sizeof(tmp_addr)); -+ tmp_addr.slot = 2; -+ -+ if (!(addrStr = virPCIDeviceAddressAsString(&tmp_addr))) -+ goto cleanup; -+ if (!virDomainPCIAddressValidate(addrs, &tmp_addr, -+ addrStr, flags, true)) -+ goto cleanup; -+ -+ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { -+ if (qemuDomainPCIAddressReserveNextAddr(addrs, -+ &primaryVideo->info) < 0) -+ goto cleanup; -+ } else { -+ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) -+ goto cleanup; -+ primaryVideo->info.addr.pci = tmp_addr; -+ primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; -+ } -+ } -+ } -+ ret = 0; -+ cleanup: -+ VIR_FREE(addrStr); -+ return ret; -+} -+ -+ - static int - qemuDomainValidateDevicePCISlotsChipsets(virDomainDef *def, - virDomainPCIAddressSet *addrs) -@@ -2040,6 +2093,11 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDef *def, - return -1; - } - -+ if (qemuDomainIsLoongson(def) && -+ qemuDomainValidateDevicePCISlotsLoongson(def, addrs) < 0) { -+ return -1; -+ } -+ - return 0; - } - -diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c -index 7bc14293d6..7d01d31aaf 100644 ---- a/src/qemu/qemu_validate.c -+++ b/src/qemu/qemu_validate.c -@@ -186,7 +186,8 @@ qemuValidateDomainDefFeatures(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'"), -diff --git a/src/util/virarch.c b/src/util/virarch.c -index 2134dd6a9d..9f40a7110c 100644 ---- a/src/util/virarch.c -+++ b/src/util/virarch.c -@@ -59,6 +59,7 @@ static const struct virArchData { - - { "mips64", 64, VIR_ARCH_BIG_ENDIAN }, - { "mips64el", 64, VIR_ARCH_LITTLE_ENDIAN }, -+ { "loongarch64", 64, VIR_ARCH_LITTLE_ENDIAN }, - { "openrisc", 32, VIR_ARCH_BIG_ENDIAN }, - { "parisc", 32, VIR_ARCH_BIG_ENDIAN }, - { "parisc64", 64, VIR_ARCH_BIG_ENDIAN }, -@@ -222,6 +223,8 @@ virArch virArchFromHost(void) - arch = VIR_ARCH_X86_64; - } else if (STREQ(ut.machine, "arm64")) { - arch = VIR_ARCH_AARCH64; -+ } else if (STREQ(ut.machine, "loongarch64")) { -+ arch = VIR_ARCH_LOONGARCH64; - } else { - /* Otherwise assume the canonical name */ - if ((arch = virArchFromString(ut.machine)) == VIR_ARCH_NONE) { -diff --git a/src/util/virarch.h b/src/util/virarch.h -index 528f84f8a5..7d396f2fff 100644 ---- a/src/util/virarch.h -+++ b/src/util/virarch.h -@@ -44,6 +44,7 @@ typedef enum { - - VIR_ARCH_MIPS64, /* MIPS 64 BE https://en.wikipedia.org/wiki/MIPS_architecture */ - VIR_ARCH_MIPS64EL, /* MIPS 64 LE https://en.wikipedia.org/wiki/MIPS_architecture */ -+ VIR_ARCH_LOONGARCH64, - VIR_ARCH_OR32, /* OpenRisc 32 BE https://en.wikipedia.org/wiki/OpenRISC#QEMU_support */ - VIR_ARCH_PARISC, /* PA-Risc 32 BE https://en.wikipedia.org/wiki/PA-RISC */ - VIR_ARCH_PARISC64, /* PA-Risc 64 BE https://en.wikipedia.org/wiki/PA-RISC */ -@@ -98,6 +99,8 @@ typedef enum { - #define ARCH_IS_MIPS64(arch) ((arch) == VIR_ARCH_MIPS64 ||\ - (arch) == VIR_ARCH_MIPS64EL) - -+#define ARCH_IS_LOONGARCH(arch) ((arch) == VIR_ARCH_LOONGARCH64) -+ - typedef enum { - VIR_ARCH_LITTLE_ENDIAN, - VIR_ARCH_BIG_ENDIAN, -diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c -index 35f41daef2..137796ea07 100644 ---- a/src/util/virhostcpu.c -+++ b/src/util/virhostcpu.c -@@ -546,7 +546,7 @@ virHostCPUParseFrequency(FILE *cpuinfo, - char line[1024]; - - /* No sensible way to retrieve CPU frequency */ -- if (ARCH_IS_ARM(arch)) -+ if (ARCH_IS_ARM(arch) || ARCH_IS_LOONGARCH(arch)) - return 0; - - if (ARCH_IS_X86(arch)) -diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c -index af9e03c5ac..9577cf1910 100644 ---- a/src/util/virsysinfo.c -+++ b/src/util/virsysinfo.c -@@ -1247,7 +1247,7 @@ virSysinfoRead(void) - { - #if defined(__powerpc__) - return virSysinfoReadPPC(); --#elif defined(__arm__) || defined(__aarch64__) -+#elif defined(__arm__) || defined(__aarch64__) || defined(__loongarch__) - return virSysinfoReadARM(); - #elif defined(__s390__) || defined(__s390x__) - return virSysinfoReadS390(); --- -2.27.0 - diff --git a/libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch b/libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch new file mode 100644 index 0000000..985f693 --- /dev/null +++ b/libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch @@ -0,0 +1,52 @@ +From b6c1f9ca8eb0ca8f7603ab205c7dc95b9f07b5a0 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Jiri Denemark +Date: Mon, 18 Jul 2022 16:01:20 +0200 +Subject: [PATCH] RHEL: qemu_migration: Fix restoring memlock limit on + destination + +Restoring memory locking limit on the destination host only makes sense +when migration succeeded as otherwise the QEMU process will be killed +anyway. Specifically if the migration fails because the process died, +touching the limit would produce rather unhelpful error message instead +of the real issue: + + cannot get locked memory limit of process -1: No such file or + directory + +This patch is RHEL-only caused by misplacing the call to +qemuDomainSetMaxMemLock when the "qemu_migration: Restore original +memory locking limit" upstream patch was backported to an older code +base. + +https://bugzilla.redhat.com/show_bug.cgi?id=2107954 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index db5163e993..11f87296d6 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -5895,6 +5895,8 @@ qemuMigrationDstFinish(virQEMUDriver *driver, + */ + if (inPostCopy) + g_clear_pointer(&priv->job.completed, qemuDomainJobInfoFree); ++ ++ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + } + + qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, +@@ -5907,7 +5909,6 @@ qemuMigrationDstFinish(virQEMUDriver *driver, + cleanup: + g_clear_pointer(&jobInfo, qemuDomainJobInfoFree); + virPortAllocatorRelease(port); +- qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + if (priv->mon) + qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL); + VIR_FREE(priv->origname); +-- +2.35.1 + diff --git a/libvirt-conf-Introduce-memory-allocation-threads.patch b/libvirt-conf-Introduce-memory-allocation-threads.patch index 76bff0e..add140c 100644 --- a/libvirt-conf-Introduce-memory-allocation-threads.patch +++ b/libvirt-conf-Introduce-memory-allocation-threads.patch @@ -1,5 +1,5 @@ -From e60a964e51cb0aecb060f1a1cc2884586e00ddeb Mon Sep 17 00:00:00 2001 -Message-Id: +From 19f7e6dc950baf346738f462ac5c6b815c04edcc Mon Sep 17 00:00:00 2001 +Message-Id: <19f7e6dc950baf346738f462ac5c6b815c04edcc@dist-git> From: Michal Privoznik Date: Mon, 21 Mar 2022 16:49:25 +0100 Subject: [PATCH] conf: Introduce memory allocation threads @@ -18,7 +18,7 @@ only complicate things for a little or no benefit. Signed-off-by: Michal Privoznik Reviewed-by: Martin Kletzander (cherry picked from commit ba7f98126fa84d354ce72929b77cc111a9a557a9) -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2075569 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2067126 Signed-off-by: Michal Privoznik --- docs/formatdomain.rst | 8 +++++--- diff --git a/libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch b/libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch new file mode 100644 index 0000000..4edd02b --- /dev/null +++ b/libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch @@ -0,0 +1,91 @@ +From 00c5cab2b92b653edbf491d9ef60359578c3d59a Mon Sep 17 00:00:00 2001 +Message-Id: <00c5cab2b92b653edbf491d9ef60359578c3d59a@dist-git> +From: Michal Privoznik +Date: Wed, 11 May 2022 16:27:18 +0200 +Subject: [PATCH] conf: Move virDomainObj::originalMemlock into + qemuDomainObjPrivate + +Since v1.3.0-90-gafbe1d4c56 the original value of memlock limit +is stored inside virDomainObj struct directly (under +originalMemlock member). This is needless because the value is +used only inside QEMU driver and thus can reside in +qemuDomainObjPrivate struct. + +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +(cherry picked from commit 75df6d2c291c48d65c1e54dd93e3d2d3cb0712e7) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.h | 3 --- + src/qemu/qemu_domain.c | 9 +++++---- + src/qemu/qemu_domain.h | 3 +++ + 3 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index d0d0fdc815..45976beb2b 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -3031,9 +3031,6 @@ struct _virDomainObj { + int taint; + size_t ndeprecations; + char **deprecations; +- +- unsigned long long originalMemlock; /* Original RLIMIT_MEMLOCK, zero if no +- * restore will be required later */ + }; + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainObj, virObjectUnref); +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index 40fe9985e6..86d673dafa 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -9269,6 +9269,7 @@ int + qemuDomainAdjustMaxMemLock(virDomainObj *vm, + bool forceVFIO) + { ++ qemuDomainObjPrivate *priv = vm->privateData; + unsigned long long currentMemLock = 0; + unsigned long long desiredMemLock = 0; + +@@ -9281,8 +9282,8 @@ qemuDomainAdjustMaxMemLock(virDomainObj *vm, + /* If this is the first time adjusting the limit, save the current + * value so that we can restore it once memory locking is no longer + * required */ +- if (vm->originalMemlock == 0) { +- vm->originalMemlock = currentMemLock; ++ if (priv->originalMemlock == 0) { ++ priv->originalMemlock = currentMemLock; + } + } else { + /* If the limit is already high enough, we can assume +@@ -9295,8 +9296,8 @@ qemuDomainAdjustMaxMemLock(virDomainObj *vm, + } else { + /* Once memory locking is no longer required, we can restore the + * original, usually very low, limit */ +- desiredMemLock = vm->originalMemlock; +- vm->originalMemlock = 0; ++ desiredMemLock = priv->originalMemlock; ++ priv->originalMemlock = 0; + } + + if (desiredMemLock > 0 && +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index e5046367e3..e9497d20de 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -241,6 +241,9 @@ struct _qemuDomainObjPrivate { + GSList *dbusVMStateIds; + /* true if -object dbus-vmstate was added */ + bool dbusVMState; ++ ++ unsigned long long originalMemlock; /* Original RLIMIT_MEMLOCK, zero if no ++ * restore will be required later */ + }; + + #define QEMU_DOMAIN_PRIVATE(vm) \ +-- +2.35.1 + diff --git a/libvirt-conf-virtiofs-add-thread_pool-element.patch b/libvirt-conf-virtiofs-add-thread_pool-element.patch new file mode 100644 index 0000000..e03c66d --- /dev/null +++ b/libvirt-conf-virtiofs-add-thread_pool-element.patch @@ -0,0 +1,151 @@ +From 0c09e4225c511ce1b0ebe22e45962f83d5145e66 Mon Sep 17 00:00:00 2001 +Message-Id: <0c09e4225c511ce1b0ebe22e45962f83d5145e66@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 10 Jun 2022 15:10:29 +0200 +Subject: [PATCH] conf: virtiofs: add thread_pool element +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add an element to configure the thread pool size: + +... + + + +... + +https://bugzilla.redhat.com/show_bug.cgi?id=2072905 + +Signed-off-by: Ján Tomko +Reviewed-by: Michal Privoznik +(cherry picked from commit 0df2e7df80452f81edbfeb0ee355235b533346a9) +Signed-off-by: Ján Tomko + +https://bugzilla.redhat.com/show_bug.cgi?id=2079582 +--- + docs/formatdomain.rst | 6 ++++++ + docs/schemas/domaincommon.rng | 9 +++++++++ + src/conf/domain_conf.c | 15 +++++++++++++++ + src/conf/domain_conf.h | 1 + + .../qemuxml2argvdata/vhost-user-fs-fd-memory.xml | 1 + + 5 files changed, 32 insertions(+) + +diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst +index 17e89a0c0d..e6cf2ec083 100644 +--- a/docs/formatdomain.rst ++++ b/docs/formatdomain.rst +@@ -3316,6 +3316,7 @@ A directory on the host that can be accessed directly from the guest. + + + ++ + + + +@@ -3449,6 +3450,11 @@ A directory on the host that can be accessed directly from the guest. + ``chroot``, see the + `virtiofsd documentation `__ + for more details. ( :since:`Since 7.2.0` ) ++ Element ``thread_pool`` accepts one attribute ``size`` which defines the ++ maximum thread pool size. A value of "0" disables the pool. ++ The thread pool helps increase the number of requests in flight when used with ++ storage that has a higher latency. However, it has an overhead, and so for ++ fast, low latency filesystems, it may be best to turn it off. ( :since:`Since 8.5.0` ) + ``source`` + The resource on the host that is being accessed in the guest. The ``name`` + attribute must be used with ``type='template'``, and the ``dir`` attribute +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index c9c1529979..79c8979410 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -3064,6 +3064,15 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 92510973e6..95afd9226e 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -2447,6 +2447,8 @@ virDomainFSDefNew(virDomainXMLOption *xmlopt) + + ret->src = virStorageSourceNew(); + ++ ret->thread_pool_size = -1; ++ + if (xmlopt && + xmlopt->privateData.fsNew && + !(ret->privateData = xmlopt->privateData.fsNew())) +@@ -9869,6 +9871,7 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt, + if (def->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) { + g_autofree char *queue_size = virXPathString("string(./driver/@queue)", ctxt); + g_autofree char *binary = virXPathString("string(./binary/@path)", ctxt); ++ g_autofree char *thread_pool_size = virXPathString("string(./binary/thread_pool/@size)", ctxt); + g_autofree char *xattr = virXPathString("string(./binary/@xattr)", ctxt); + g_autofree char *cache = virXPathString("string(./binary/cache/@mode)", ctxt); + g_autofree char *sandbox = virXPathString("string(./binary/sandbox/@mode)", ctxt); +@@ -9883,6 +9886,14 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt, + goto error; + } + ++ if (thread_pool_size && ++ virStrToLong_i(thread_pool_size, NULL, 10, &def->thread_pool_size) < 0) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("cannot parse thread pool size '%s' for virtiofs"), ++ queue_size); ++ goto error; ++ } ++ + if (binary) + def->binary = virFileSanitizePath(binary); + +@@ -24205,6 +24216,10 @@ virDomainFSDefFormat(virBuffer *buf, + } + + virXMLFormatElement(&binaryBuf, "lock", &lockAttrBuf, NULL); ++ ++ if (def->thread_pool_size >= 0) ++ virBufferAsprintf(&binaryBuf, "\n", def->thread_pool_size); ++ + } + + virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio); +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 10af94e2e4..d0d0fdc815 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -892,6 +892,7 @@ struct _virDomainFSDef { + virTristateSwitch posix_lock; + virTristateSwitch flock; + virDomainFSSandboxMode sandbox; ++ int thread_pool_size; + virDomainVirtioOptions *virtio; + virObject *privateData; + }; +diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml +index abddf0870b..81de8c0dd7 100644 +--- a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml ++++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml +@@ -32,6 +32,7 @@ + + + ++ + + + +-- +2.35.1 + diff --git a/libvirt-cpu_map-Disable-cpu64-rhel-for-host-model-and-baseline.patch b/libvirt-cpu_map-Disable-cpu64-rhel-for-host-model-and-baseline.patch index ba16500..7711d3b 100644 --- a/libvirt-cpu_map-Disable-cpu64-rhel-for-host-model-and-baseline.patch +++ b/libvirt-cpu_map-Disable-cpu64-rhel-for-host-model-and-baseline.patch @@ -1,5 +1,5 @@ -From d03c369dd75c747f25ecc34af3b9d79adf92ea0c Mon Sep 17 00:00:00 2001 -Message-Id: +From 46f4cfe513f0f893c862dca7f02ed7d7932b2115 Mon Sep 17 00:00:00 2001 +Message-Id: <46f4cfe513f0f893c862dca7f02ed7d7932b2115@dist-git> From: Jiri Denemark Date: Tue, 26 Apr 2022 12:50:41 +0200 Subject: [PATCH] cpu_map: Disable cpu64-rhel* for host-model and baseline @@ -12,7 +12,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit d2e4d66be35cd04da72e5f5129a8a4da6a931505) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.patch b/libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.patch index dfd878b..2e9660e 100644 --- a/libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.patch +++ b/libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.patch @@ -1,5 +1,5 @@ -From e075af4319c7c30531421e6667845abd30cd28e9 Mon Sep 17 00:00:00 2001 -Message-Id: +From 99a298a4a0575bf0072f504c4b8e4551400c44c0 Mon Sep 17 00:00:00 2001 +Message-Id: <99a298a4a0575bf0072f504c4b8e4551400c44c0@dist-git> From: Jiri Denemark Date: Tue, 26 Apr 2022 11:58:07 +0200 Subject: [PATCH] cpu_x86: Consolidate signature match in x86DecodeUseCandidate @@ -12,7 +12,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit 35ce086667e68e8f546cf36473591dd7c19c72eb) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch b/libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch index 98c9364..e1b8a79 100644 --- a/libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch +++ b/libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch @@ -1,5 +1,5 @@ -From 5b5f684bfceeed923e1733931b6c4c75d5ed4149 Mon Sep 17 00:00:00 2001 -Message-Id: <5b5f684bfceeed923e1733931b6c4c75d5ed4149@dist-git> +From 752c74eeae67d41e7550991cb3bbe289984ec9d3 Mon Sep 17 00:00:00 2001 +Message-Id: <752c74eeae67d41e7550991cb3bbe289984ec9d3@dist-git> From: Jiri Denemark Date: Fri, 29 Apr 2022 10:35:02 +0200 Subject: [PATCH] cpu_x86: Ignore enabled features for input models in @@ -22,7 +22,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit bb6cedd2082599323257ee0df18c93a6e0551b0b) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch b/libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch index 59d8429..a778c81 100644 --- a/libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch +++ b/libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch @@ -1,5 +1,5 @@ -From 652e1798991dcb503abc9a2588b0f95c47b8e3df Mon Sep 17 00:00:00 2001 -Message-Id: <652e1798991dcb503abc9a2588b0f95c47b8e3df@dist-git> +From 5db9a525e3cec267544580d43554b2cf5779b6b9 Mon Sep 17 00:00:00 2001 +Message-Id: <5db9a525e3cec267544580d43554b2cf5779b6b9@dist-git> From: Jiri Denemark Date: Tue, 26 Apr 2022 15:06:30 +0200 Subject: [PATCH] cpu_x86: Penalize disabled features when computing CPU model @@ -39,8 +39,6 @@ Conflicts: tests/domaincapsdata/qemu_3.0.0-tcg.x86_64.xml - not supported upstream anymore -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 - Signed-off-by: Jiri Denemark --- src/cpu/cpu_x86.c | 44 ++++++++++++++++--- diff --git a/libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch b/libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch index caf14d8..24591e6 100644 --- a/libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch +++ b/libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch @@ -1,5 +1,5 @@ -From d9736516378d1fbac451dd80a93bf25c85e74b50 Mon Sep 17 00:00:00 2001 -Message-Id: +From 3d7a4041d31e403dc9e762b34f7faf36f7f20a28 Mon Sep 17 00:00:00 2001 +Message-Id: <3d7a4041d31e403dc9e762b34f7faf36f7f20a28@dist-git> From: Jiri Denemark Date: Tue, 26 Apr 2022 15:02:51 +0200 Subject: [PATCH] cpu_x86: Refactor feature list comparison in @@ -12,7 +12,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit 1d6ca40ac23c039abc4392b668f256d0eda33280) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cputest-Add-some-real-world-baseline-tests.patch b/libvirt-cputest-Add-some-real-world-baseline-tests.patch index 01a9d1b..6007a0f 100644 --- a/libvirt-cputest-Add-some-real-world-baseline-tests.patch +++ b/libvirt-cputest-Add-some-real-world-baseline-tests.patch @@ -1,5 +1,5 @@ -From 8f7e267c7b98b378e301519b10aa3d18f0ceb45c Mon Sep 17 00:00:00 2001 -Message-Id: <8f7e267c7b98b378e301519b10aa3d18f0ceb45c@dist-git> +From b37a398da4323407de24d19afac937eac80170cc Mon Sep 17 00:00:00 2001 +Message-Id: From: Jiri Denemark Date: Thu, 21 Apr 2022 18:25:15 +0200 Subject: [PATCH] cputest: Add some real world baseline tests @@ -8,7 +8,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit 63d633b9a4fc42da7e2acaf45501914607d968a5) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cputest-Drop-some-old-artificial-baseline-tests.patch b/libvirt-cputest-Drop-some-old-artificial-baseline-tests.patch index e602981..997dad8 100644 --- a/libvirt-cputest-Drop-some-old-artificial-baseline-tests.patch +++ b/libvirt-cputest-Drop-some-old-artificial-baseline-tests.patch @@ -1,5 +1,5 @@ -From 039e6627a7ee53973da64405b79cc0c0f6111fc7 Mon Sep 17 00:00:00 2001 -Message-Id: <039e6627a7ee53973da64405b79cc0c0f6111fc7@dist-git> +From 50d94f13286ca19ef1f457be72debdbf77547df6 Mon Sep 17 00:00:00 2001 +Message-Id: <50d94f13286ca19ef1f457be72debdbf77547df6@dist-git> From: Jiri Denemark Date: Wed, 4 May 2022 16:21:38 +0200 Subject: [PATCH] cputest: Drop some old artificial baseline tests @@ -8,7 +8,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit 6aff36019bbaf643f451779621c6c88cab0e64a7) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-cputest-Give-better-names-to-baseline-tests.patch b/libvirt-cputest-Give-better-names-to-baseline-tests.patch index a127f6a..ece2b12 100644 --- a/libvirt-cputest-Give-better-names-to-baseline-tests.patch +++ b/libvirt-cputest-Give-better-names-to-baseline-tests.patch @@ -1,5 +1,5 @@ -From 89272567fd9e2b87133333f5565c1d9e2befb350 Mon Sep 17 00:00:00 2001 -Message-Id: <89272567fd9e2b87133333f5565c1d9e2befb350@dist-git> +From 6cf9cd8f6d9e90eadd58d8a37129e7401876e4e8 Mon Sep 17 00:00:00 2001 +Message-Id: <6cf9cd8f6d9e90eadd58d8a37129e7401876e4e8@dist-git> From: Jiri Denemark Date: Wed, 4 May 2022 16:28:03 +0200 Subject: [PATCH] cputest: Give better names to baseline tests @@ -8,7 +8,7 @@ Signed-off-by: Jiri Denemark Reviewed-by: Michal Privoznik (cherry picked from commit 3daa68e26514dc114d71f4c44f7d728e93a53cd0) -https://bugzilla.redhat.com/show_bug.cgi?id=2084030 +https://bugzilla.redhat.com/show_bug.cgi?id=1851227 Signed-off-by: Jiri Denemark --- diff --git a/libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch b/libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch new file mode 100644 index 0000000..f9c61bb --- /dev/null +++ b/libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch @@ -0,0 +1,111 @@ +From 296343c5a950668d790f9cd5ebd7b466e8156d03 Mon Sep 17 00:00:00 2001 +Message-Id: <296343c5a950668d790f9cd5ebd7b466e8156d03@dist-git> +From: Peter Krempa +Date: Tue, 14 Jun 2022 13:23:29 +0200 +Subject: [PATCH] domain_validate: Split out validation of disk startup policy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move the code into 'virDomainDiskDefValidateStartupPolicy' which will be +later reused in the qemu driver. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit 3603a18bcec18842cedecbd8329723062b87795c) +https://bugzilla.redhat.com/show_bug.cgi?id=2095758 +--- + src/conf/domain_validate.c | 45 ++++++++++++++++++++++++-------------- + src/conf/domain_validate.h | 2 ++ + src/libvirt_private.syms | 1 + + 3 files changed, 31 insertions(+), 17 deletions(-) + +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index 452742e67c..bfff7339ef 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -598,6 +598,32 @@ virDomainDiskDefSourceLUNValidate(const virStorageSource *src) + } + + ++int ++virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk) ++{ ++ if (disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_DEFAULT) ++ return 0; ++ ++ if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("disk startupPolicy '%s' is not allowed for disk of '%s' type"), ++ virDomainStartupPolicyTypeToString(disk->startupPolicy), ++ virStorageTypeToString(disk->src->type)); ++ return -1; ++ } ++ ++ if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM && ++ disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY && ++ disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ + static int + virDomainDiskDefValidate(const virDomainDef *def, + const virDomainDiskDef *disk) +@@ -775,23 +801,8 @@ virDomainDiskDefValidate(const virDomainDef *def, + return -1; + } + +- if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) { +- if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { +- virReportError(VIR_ERR_XML_ERROR, +- _("disk startupPolicy '%s' is not allowed for disk of '%s' type"), +- virDomainStartupPolicyTypeToString(disk->startupPolicy), +- virStorageTypeToString(disk->src->type)); +- return -1; +- } +- +- if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM && +- disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY && +- disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy")); +- return -1; +- } +- } ++ if (virDomainDiskDefValidateStartupPolicy(disk) < 0) ++ return -1; + + if (disk->wwn && !virValidateWWN(disk->wwn)) + return -1; +diff --git a/src/conf/domain_validate.h b/src/conf/domain_validate.h +index 430d61fd3c..07b99195e3 100644 +--- a/src/conf/domain_validate.h ++++ b/src/conf/domain_validate.h +@@ -41,4 +41,6 @@ int virDomainDeviceDefValidate(const virDomainDeviceDef *dev, + + int virDomainDiskDefValidateSource(const virStorageSource *src); + ++int virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk); ++ + int virDomainDiskDefSourceLUNValidate(const virStorageSource *src); +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 2c42e2a5e8..5b7a056151 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -777,6 +777,7 @@ virDomainActualNetDefValidate; + virDomainDefValidate; + virDomainDeviceValidateAliasForHotplug; + virDomainDiskDefSourceLUNValidate; ++virDomainDiskDefValidateStartupPolicy; + + + # conf/interface_conf.h +-- +2.35.1 + diff --git a/libvirt-nwfilter-fix-crash-when-counting-number-of-network-filters.patch b/libvirt-nwfilter-fix-crash-when-counting-number-of-network-filters.patch new file mode 100644 index 0000000..3e5c4f3 --- /dev/null +++ b/libvirt-nwfilter-fix-crash-when-counting-number-of-network-filters.patch @@ -0,0 +1,55 @@ +From dc6ab8b51ff53ba22abfb84f24641aa87320038a Mon Sep 17 00:00:00 2001 +Message-Id: +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Tue, 8 Mar 2022 17:28:38 +0000 +Subject: [PATCH] nwfilter: fix crash when counting number of network filters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The virNWFilterObjListNumOfNWFilters method iterates over the +driver->nwfilters, accessing virNWFilterObj instances. As such +it needs to be protected against concurrent modification of +the driver->nwfilters object. + +This API allows unprivileged users to connect, so users with +read-only access to libvirt can cause a denial of service +crash if they are able to race with a call of virNWFilterUndefine. +Since network filters are usually statically defined, this is +considered a low severity problem. + +This is assigned CVE-2022-0897. + +Reviewed-by: Eric Blake +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit a4947e8f63c3e6b7b067b444f3d6cf674c0d7f36) +https://bugzilla.redhat.com/show_bug.cgi?id=2063902 +--- + src/nwfilter/nwfilter_driver.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c +index 200451d6b1..956aca6421 100644 +--- a/src/nwfilter/nwfilter_driver.c ++++ b/src/nwfilter/nwfilter_driver.c +@@ -478,11 +478,15 @@ nwfilterLookupByName(virConnectPtr conn, + static int + nwfilterConnectNumOfNWFilters(virConnectPtr conn) + { ++ int ret; + if (virConnectNumOfNWFiltersEnsureACL(conn) < 0) + return -1; + +- return virNWFilterObjListNumOfNWFilters(driver->nwfilters, conn, +- virConnectNumOfNWFiltersCheckACL); ++ nwfilterDriverLock(); ++ ret = virNWFilterObjListNumOfNWFilters(driver->nwfilters, conn, ++ virConnectNumOfNWFiltersCheckACL); ++ nwfilterDriverUnlock(); ++ return ret; + } + + +-- +2.35.1 + diff --git a/libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch b/libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch new file mode 100644 index 0000000..1bb549c --- /dev/null +++ b/libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch @@ -0,0 +1,155 @@ +From 2595c7716b19214b2729b41b86656f96a2cd18bc Mon Sep 17 00:00:00 2001 +Message-Id: <2595c7716b19214b2729b41b86656f96a2cd18bc@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 15:21:30 +0200 +Subject: [PATCH] qemu: Add qemuDomainSetMaxMemLock helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +qemuDomainAdjustMaxMemLock combined computing the desired limit with +applying it. This patch separates the code to apply a memory locking +limit to a new qemuDomainSetMaxMemLock helper for better reusability. + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit dff51c7f5760ded8235076f55d082fe4363f2f78) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_domain.c | 95 ++++++++++++++++++++++++++---------------- + src/qemu/qemu_domain.h | 3 ++ + 2 files changed, 61 insertions(+), 37 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index ee7d310903..a81789f194 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -9261,6 +9261,61 @@ qemuDomainGetMemLockLimitBytes(virDomainDef *def, + } + + ++/** ++ * qemuDomainSetMaxMemLock: ++ * @vm: domain ++ * @limit: the desired memory locking limit ++ * @origPtr: where to store (or load from) the original value of the limit ++ * ++ * Set the memory locking limit for @vm unless it's already big enough. If ++ * @origPtr is non-NULL, the original value of the limit will be store there ++ * and can be restored by calling this function with @limit == 0. ++ * ++ * Returns: 0 on success, -1 otherwise. ++ */ ++int ++qemuDomainSetMaxMemLock(virDomainObj *vm, ++ unsigned long long limit, ++ unsigned long long *origPtr) ++{ ++ unsigned long long current = 0; ++ ++ if (virProcessGetMaxMemLock(vm->pid, ¤t) < 0) ++ return -1; ++ ++ if (limit > 0) { ++ VIR_DEBUG("Requested memory lock limit: %llu", limit); ++ /* If the limit is already high enough, we can assume ++ * that some external process is taking care of managing ++ * process limits and we shouldn't do anything ourselves: ++ * we're probably running in a containerized environment ++ * where we don't have enough privilege anyway */ ++ if (current >= limit) { ++ VIR_DEBUG("Current limit %llu is big enough", current); ++ return 0; ++ } ++ ++ /* If this is the first time adjusting the limit, save the current ++ * value so that we can restore it once memory locking is no longer ++ * required */ ++ if (origPtr && *origPtr == 0) ++ *origPtr = current; ++ } else { ++ /* Once memory locking is no longer required, we can restore the ++ * original, usually very low, limit. But only if we actually stored ++ * the original limit before. */ ++ if (!origPtr || *origPtr == 0) ++ return 0; ++ ++ limit = *origPtr; ++ *origPtr = 0; ++ VIR_DEBUG("Resetting memory lock limit back to %llu", limit); ++ } ++ ++ return virProcessSetMaxMemLock(vm->pid, limit); ++} ++ ++ + /** + * qemuDomainAdjustMaxMemLock: + * @vm: domain +@@ -9282,43 +9337,9 @@ int + qemuDomainAdjustMaxMemLock(virDomainObj *vm, + bool forceVFIO) + { +- qemuDomainObjPrivate *priv = vm->privateData; +- unsigned long long currentMemLock = 0; +- unsigned long long desiredMemLock = 0; +- +- desiredMemLock = qemuDomainGetMemLockLimitBytes(vm->def, forceVFIO); +- if (virProcessGetMaxMemLock(vm->pid, ¤tMemLock) < 0) +- return -1; +- +- if (desiredMemLock > 0) { +- if (currentMemLock < desiredMemLock) { +- /* If this is the first time adjusting the limit, save the current +- * value so that we can restore it once memory locking is no longer +- * required */ +- if (priv->originalMemlock == 0) { +- priv->originalMemlock = currentMemLock; +- } +- } else { +- /* If the limit is already high enough, we can assume +- * that some external process is taking care of managing +- * process limits and we shouldn't do anything ourselves: +- * we're probably running in a containerized environment +- * where we don't have enough privilege anyway */ +- desiredMemLock = 0; +- } +- } else { +- /* Once memory locking is no longer required, we can restore the +- * original, usually very low, limit */ +- desiredMemLock = priv->originalMemlock; +- priv->originalMemlock = 0; +- } +- +- if (desiredMemLock > 0 && +- virProcessSetMaxMemLock(vm->pid, desiredMemLock) < 0) { +- return -1; +- } +- +- return 0; ++ return qemuDomainSetMaxMemLock(vm, ++ qemuDomainGetMemLockLimitBytes(vm->def, forceVFIO), ++ &QEMU_DOMAIN_PRIVATE(vm)->originalMemlock); + } + + +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index e9497d20de..6d1d23439a 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -789,6 +789,9 @@ int qemuDomainAdjustMaxMemLock(virDomainObj *vm, + bool forceVFIO); + int qemuDomainAdjustMaxMemLockHostdev(virDomainObj *vm, + virDomainHostdevDef *hostdev); ++int qemuDomainSetMaxMemLock(virDomainObj *vm, ++ unsigned long long limit, ++ unsigned long long *origPtr); + + int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, + const virDomainMemoryDef *mem); +-- +2.35.1 + diff --git a/libvirt-qemu-virtiofs-format-thread-pool-size.patch b/libvirt-qemu-virtiofs-format-thread-pool-size.patch new file mode 100644 index 0000000..afda4b8 --- /dev/null +++ b/libvirt-qemu-virtiofs-format-thread-pool-size.patch @@ -0,0 +1,37 @@ +From 44f83782ba882f9eb037a54fb75231c305d98712 Mon Sep 17 00:00:00 2001 +Message-Id: <44f83782ba882f9eb037a54fb75231c305d98712@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 10 Jun 2022 15:25:00 +0200 +Subject: [PATCH] qemu: virtiofs: format --thread-pool-size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://bugzilla.redhat.com/show_bug.cgi?id=2079582 + +Signed-off-by: Ján Tomko +Reviewed-by: Michal Privoznik +(cherry picked from commit 2753eba20ce76d3d8785b23a6e940574ca12fe3c) +Signed-off-by: Ján Tomko +--- + src/qemu/qemu_virtiofs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c +index 1b853a5a59..1ee3781286 100644 +--- a/src/qemu/qemu_virtiofs.c ++++ b/src/qemu/qemu_virtiofs.c +@@ -163,6 +163,10 @@ qemuVirtioFSBuildCommandLine(virQEMUDriverConfig *cfg, + virBufferAddLit(&opts, ",no_posix_lock"); + + virCommandAddArgBuffer(cmd, &opts); ++ ++ if (fs->thread_pool_size >= 0) ++ virCommandAddArgFormat(cmd, "--thread-pool-size=%i", fs->thread_pool_size); ++ + if (cfg->virtiofsdDebug) + virCommandAddArg(cmd, "-d"); + +-- +2.35.1 + diff --git a/libvirt-qemu_capabilities-Detect-memory-backend-.prealloc-threads-property.patch b/libvirt-qemu_capabilities-Detect-memory-backend-.prealloc-threads-property.patch index 91d50fc..4916fd9 100644 --- a/libvirt-qemu_capabilities-Detect-memory-backend-.prealloc-threads-property.patch +++ b/libvirt-qemu_capabilities-Detect-memory-backend-.prealloc-threads-property.patch @@ -1,5 +1,5 @@ -From 9f9fcbc842846c6f2579ca52190f506060e191d8 Mon Sep 17 00:00:00 2001 -Message-Id: <9f9fcbc842846c6f2579ca52190f506060e191d8@dist-git> +From c387e7680c07d7dbb934dbe972e99ab78cebad28 Mon Sep 17 00:00:00 2001 +Message-Id: From: Michal Privoznik Date: Mon, 21 Mar 2022 16:55:05 +0100 Subject: [PATCH] qemu_capabilities: Detect memory-backend-*.prealloc-threads @@ -36,7 +36,7 @@ tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2075569 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2067126 Signed-off-by: Michal Privoznik --- src/qemu/qemu_capabilities.c | 2 ++ diff --git a/libvirt-qemu_command-Generate-prealloc-threads-property.patch b/libvirt-qemu_command-Generate-prealloc-threads-property.patch index 16b656c..0a7bc32 100644 --- a/libvirt-qemu_command-Generate-prealloc-threads-property.patch +++ b/libvirt-qemu_command-Generate-prealloc-threads-property.patch @@ -1,5 +1,5 @@ -From f9c8097e8a836052239c51552d943a76b8164de3 Mon Sep 17 00:00:00 2001 -Message-Id: +From e52b12a986de8ac469b98135b2c1d2a8a63b9052 Mon Sep 17 00:00:00 2001 +Message-Id: From: Michal Privoznik Date: Mon, 21 Mar 2022 17:10:15 +0100 Subject: [PATCH] qemu_command: Generate prealloc-threads property @@ -16,7 +16,7 @@ tests/qemuxml2argvdata/memfd-memory-numa.x86_64-latest.args: Upstream has moved some cmd line arguments (v8.0.0-260-gaf23241cfe) but that is not backported. -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2075569 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2067126 Signed-off-by: Michal Privoznik --- src/qemu/qemu_command.c | 5 ++++- diff --git a/libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch b/libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch new file mode 100644 index 0000000..d35edd1 --- /dev/null +++ b/libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch @@ -0,0 +1,55 @@ +From b221b3ab6d881efedc544e0e0ed9c507e21fd178 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Wed, 11 May 2022 16:37:27 +0200 +Subject: [PATCH] qemu_domain: Format qemuDomainObjPrivate::originalMemlock + +Now that qemuDomainObjPrivate struct gained new member format it +into XML and parse it so that the value is preserved across +daemon restarts. + +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +(cherry picked from commit 21aec91790ae14d24512856b20cff49764ede637) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_domain.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index 86d673dafa..ee7d310903 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -2383,6 +2383,12 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf, + if (qemuDomainObjPrivateXMLFormatBackups(buf, vm) < 0) + return -1; + ++ if (priv->originalMemlock > 0) { ++ virBufferAsprintf(buf, ++ "%llu\n", ++ priv->originalMemlock); ++ } ++ + return 0; + } + +@@ -3104,6 +3110,13 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, + + priv->memPrealloc = virXPathBoolean("boolean(./memPrealloc)", ctxt) == 1; + ++ if (virXPathULongLong("string(./originalMemlock)", ++ ctxt, &priv->originalMemlock) == -2) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to parse original memlock size")); ++ goto error; ++ } ++ + return 0; + + error: +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch b/libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch new file mode 100644 index 0000000..0f91c7d --- /dev/null +++ b/libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch @@ -0,0 +1,120 @@ +From 35f06623b82d99dd380340eef465394975dd1c80 Mon Sep 17 00:00:00 2001 +Message-Id: <35f06623b82d99dd380340eef465394975dd1c80@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 16:37:31 +0200 +Subject: [PATCH] qemu_migration: Implement VIR_MIGRATE_ZEROCOPY flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://gitlab.com/libvirt/libvirt/-/issues/306 + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit d375993ab314a41bca7ef6c846e07afc18c37774) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Conflicts: + src/qemu/qemu_migration.c + src/qemu/qemu_migration.h + - post-copy recovery not bacported + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 21 +++++++++++++++++++++ + src/qemu/qemu_migration.h | 1 + + src/qemu/qemu_migration_params.c | 6 ++++++ + src/qemu/qemu_migration_params.h | 1 + + 4 files changed, 29 insertions(+) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 35ad201580..db5163e993 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2366,6 +2366,12 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver, + return NULL; + } + ++ if (flags & VIR_MIGRATE_ZEROCOPY && !(flags & VIR_MIGRATE_PARALLEL)) { ++ virReportError(VIR_ERR_OPERATION_INVALID, "%s", ++ _("zero-copy is only available for parallel migration")); ++ return NULL; ++ } ++ + if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)) { + if (flags & VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) { +@@ -4137,6 +4143,21 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + migParams) < 0) + goto error; + ++ if (flags & VIR_MIGRATE_ZEROCOPY) { ++ /* Zero-copy requires pages in transfer to be locked in host memory. ++ * Unfortunately, we have no reliable way of computing how many pages ++ * will need to be locked at the same time. Thus we set the limit to ++ * the whole guest memory and reset it back once migration is done. */ ++ unsigned long long limit; ++ ++ if (virMemoryLimitIsSet(vm->def->mem.hard_limit)) ++ limit = vm->def->mem.hard_limit; ++ else ++ limit = virDomainDefGetMemoryTotal(vm->def); ++ ++ if (qemuDomainSetMaxMemLock(vm, limit << 10, &priv->preMigrationMemlock) < 0) ++ goto error; ++ } + + if (storageMigration) { + if (mig->nbd) { +diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h +index b233358a51..6f737f7b4c 100644 +--- a/src/qemu/qemu_migration.h ++++ b/src/qemu/qemu_migration.h +@@ -60,6 +60,7 @@ + VIR_MIGRATE_TLS | \ + VIR_MIGRATE_PARALLEL | \ + VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES | \ ++ VIR_MIGRATE_ZEROCOPY | \ + 0) + + /* All supported migration parameters and their types. */ +diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c +index 7b225fdf4b..c985583861 100644 +--- a/src/qemu/qemu_migration_params.c ++++ b/src/qemu/qemu_migration_params.c +@@ -96,6 +96,7 @@ VIR_ENUM_IMPL(qemuMigrationCapability, + "multifd", + "dirty-bitmaps", + "return-path", ++ "zero-copy-send", + ); + + +@@ -177,6 +178,11 @@ static const qemuMigrationParamsFlagMapItem qemuMigrationParamsFlagMap[] = { + VIR_MIGRATE_TUNNELLED, + QEMU_MIGRATION_CAP_RETURN_PATH, + QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION}, ++ ++ {QEMU_MIGRATION_FLAG_REQUIRED, ++ VIR_MIGRATE_ZEROCOPY, ++ QEMU_MIGRATION_CAP_ZERO_COPY_SEND, ++ QEMU_MIGRATION_SOURCE}, + }; + + /* Translation from VIR_MIGRATE_PARAM_* typed parameters to +diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h +index b4de8dda7b..caa5e47f0f 100644 +--- a/src/qemu/qemu_migration_params.h ++++ b/src/qemu/qemu_migration_params.h +@@ -41,6 +41,7 @@ typedef enum { + QEMU_MIGRATION_CAP_MULTIFD, + QEMU_MIGRATION_CAP_BLOCK_DIRTY_BITMAPS, + QEMU_MIGRATION_CAP_RETURN_PATH, ++ QEMU_MIGRATION_CAP_ZERO_COPY_SEND, + + QEMU_MIGRATION_CAP_LAST + } qemuMigrationCapability; +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Restore-original-memory-locking-limit.patch b/libvirt-qemu_migration-Restore-original-memory-locking-limit.patch new file mode 100644 index 0000000..c8afc02 --- /dev/null +++ b/libvirt-qemu_migration-Restore-original-memory-locking-limit.patch @@ -0,0 +1,133 @@ +From 8cccd9634ecd91a5b7343eddc037e0fa7de2f9f6 Mon Sep 17 00:00:00 2001 +Message-Id: <8cccd9634ecd91a5b7343eddc037e0fa7de2f9f6@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 16:12:02 +0200 +Subject: [PATCH] qemu_migration: Restore original memory locking limit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For RDMA migration we update memory locking limit, but never set it back +once migration finishes (on the destination host) or aborts (on the +source host). + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit d4d3bb813031275c2c7cf72724b83c97ce82ab7a) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Conflicts: + src/qemu/qemu_migration.c + - post-copy resovery not backported + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_domain.c | 12 ++++++++++++ + src/qemu/qemu_domain.h | 3 +++ + src/qemu/qemu_migration.c | 10 ++++++++-- + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index a81789f194..c24d1e4d53 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -2389,6 +2389,11 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf, + priv->originalMemlock); + } + ++ if (priv->preMigrationMemlock > 0) { ++ virBufferAsprintf(buf, "%llu\n", ++ priv->preMigrationMemlock); ++ } ++ + return 0; + } + +@@ -3117,6 +3122,13 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, + goto error; + } + ++ if (virXPathULongLong("string(./preMigrationMemlock)", ctxt, ++ &priv->preMigrationMemlock) == -2) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to parse pre-migration memlock limit")); ++ return -1; ++ } ++ + return 0; + + error: +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index 6d1d23439a..d6e8a7a0fb 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -146,6 +146,9 @@ struct _qemuDomainObjPrivate { + int nbdPort; /* Port used for migration with NBD */ + unsigned short migrationPort; + int preMigrationState; ++ unsigned long long preMigrationMemlock; /* Original RLIMIT_MEMLOCK in case ++ it was changed for the current ++ migration job. */ + + virChrdevs *devs; + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 10338f8e87..35ad201580 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2974,7 +2974,8 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver, + + if (STREQ_NULLABLE(protocol, "rdma") && + vm->def->mem.hard_limit > 0 && +- qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) { ++ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, ++ &priv->preMigrationMemlock) < 0) { + goto stopjob; + } + +@@ -3451,6 +3452,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriver *driver, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + virObjectEventStateQueue(driver->domainEventState, event); + qemuDomainEventEmitJobCompleted(driver, vm); ++ priv->preMigrationMemlock = 0; + } else { + virErrorPtr orig_err; + int reason; +@@ -3471,6 +3473,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriver *driver, + + qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, + jobPriv->migParams, priv->job.apiFlags); ++ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + + qemuDomainSaveStatus(vm); + } +@@ -4224,7 +4227,8 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + case MIGRATION_DEST_HOST: + if (STREQ(spec->dest.host.protocol, "rdma") && + vm->def->mem.hard_limit > 0 && +- qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) { ++ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, ++ &priv->preMigrationMemlock) < 0) { + goto exit_monitor; + } + rc = qemuMonitorMigrateToHost(priv->mon, migrate_flags, +@@ -5408,6 +5412,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriver *driver, + if (ret < 0) { + qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, + jobPriv->migParams, priv->job.apiFlags); ++ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + qemuMigrationJobFinish(driver, vm); + } else { + qemuMigrationJobContinue(vm); +@@ -5881,6 +5886,7 @@ qemuMigrationDstFinish(virQEMUDriver *driver, + cleanup: + g_clear_pointer(&jobInfo, qemuDomainJobInfoFree); + virPortAllocatorRelease(port); ++ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock); + if (priv->mon) + qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL); + VIR_FREE(priv->origname); +-- +2.35.1 + diff --git a/libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch b/libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch new file mode 100644 index 0000000..88a871b --- /dev/null +++ b/libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch @@ -0,0 +1,53 @@ +From 8354fa1d2e471699331961272bc38f5e4cfe7cb8 Mon Sep 17 00:00:00 2001 +Message-Id: <8354fa1d2e471699331961272bc38f5e4cfe7cb8@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 09:04:04 +0200 +Subject: [PATCH] qemu_migration: Use qemuDomainSetMaxMemLock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This helper will not try to set the limit if it is already big enough, +which may be useful when libvirt daemon is running in a containerized +environment and is not allowed to change memory locking limit. + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit 22ee8cbf090c45f999b76e3f8dc7a45065fc9edf) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Conflicts: + src/qemu/qemu_migration.c + - refactoring for post-copy recovery not backported + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index 2635ef1162..10338f8e87 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -2974,7 +2974,7 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver, + + if (STREQ_NULLABLE(protocol, "rdma") && + vm->def->mem.hard_limit > 0 && +- virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) { ++ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) { + goto stopjob; + } + +@@ -4224,7 +4224,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, + case MIGRATION_DEST_HOST: + if (STREQ(spec->dest.host.protocol, "rdma") && + vm->def->mem.hard_limit > 0 && +- virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) { ++ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) { + goto exit_monitor; + } + rc = qemuMonitorMigrateToHost(priv->mon, migrate_flags, +-- +2.35.1 + diff --git a/libvirt-qemu_validate-Validate-prealloc-threads-against-qemuCpas.patch b/libvirt-qemu_validate-Validate-prealloc-threads-against-qemuCpas.patch index 979286d..0f8d752 100644 --- a/libvirt-qemu_validate-Validate-prealloc-threads-against-qemuCpas.patch +++ b/libvirt-qemu_validate-Validate-prealloc-threads-against-qemuCpas.patch @@ -1,5 +1,5 @@ -From d1a1a95343946fbe0736a14073b63831320d55d2 Mon Sep 17 00:00:00 2001 -Message-Id: +From 088ba382d7a099ddbebe37e5486ce648e24266db Mon Sep 17 00:00:00 2001 +Message-Id: <088ba382d7a099ddbebe37e5486ce648e24266db@dist-git> From: Michal Privoznik Date: Mon, 21 Mar 2022 17:09:40 +0100 Subject: [PATCH] qemu_validate: Validate prealloc threads against qemuCpas @@ -10,7 +10,7 @@ preallocation threads. Validate this assumption. Signed-off-by: Michal Privoznik Reviewed-by: Martin Kletzander (cherry picked from commit 75a4e0165ef199809974e97b507d3953e1de01d1) -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2075569 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2067126 Signed-off-by: Michal Privoznik --- src/qemu/qemu_validate.c | 7 +++++++ diff --git a/libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch b/libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch new file mode 100644 index 0000000..8332ee9 --- /dev/null +++ b/libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch @@ -0,0 +1,64 @@ +From 07fb786e0d17bd395333d276ebbaad42c72ee358 Mon Sep 17 00:00:00 2001 +Message-Id: <07fb786e0d17bd395333d276ebbaad42c72ee358@dist-git> +From: David Michael +Date: Tue, 28 Jun 2022 08:33:41 -0400 +Subject: [PATCH] security_selinux.c: Relabel existing mode="bind" UNIX sockets + +This supports sockets created by libvirt and passed by FD using the +same method as in security_dac.c. + +Signed-off-by: David Michael +Signed-off-by: Michal Privoznik +Reviewed-by: Michal Privoznik +(cherry picked from commit 9f13f54a6348b54170f7de3595039c99b9da72c7) + +https://bugzilla.redhat.com/show_bug.cgi?id=2101575 + +Signed-off-by: Michal Privoznik +--- + src/security/security_selinux.c | 9 +++++++-- + tests/securityselinuxlabeldata/chardev.txt | 2 +- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index 0952431064..b90e819fd2 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -2545,7 +2545,12 @@ virSecuritySELinuxSetChardevLabel(virSecurityManager *mgr, + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: +- if (!dev_source->data.nix.listen) { ++ if (!dev_source->data.nix.listen || ++ (dev_source->data.nix.path && ++ virFileExists(dev_source->data.nix.path))) { ++ /* Also label mode='bind' sockets if they exist, ++ * e.g. because they were created by libvirt ++ * and passed via FD */ + if (virSecuritySELinuxSetFilecon(mgr, + dev_source->data.nix.path, + imagelabel, +@@ -2622,7 +2627,7 @@ virSecuritySELinuxRestoreChardevLabel(virSecurityManager *mgr, + case VIR_DOMAIN_CHR_TYPE_UNIX: + if (!dev_source->data.nix.listen) { + if (virSecuritySELinuxRestoreFileLabel(mgr, +- dev_source->data.file.path, ++ dev_source->data.nix.path, + true) < 0) + goto done; + } +diff --git a/tests/securityselinuxlabeldata/chardev.txt b/tests/securityselinuxlabeldata/chardev.txt +index 3f4b6302b9..bdb367f7a5 100644 +--- a/tests/securityselinuxlabeldata/chardev.txt ++++ b/tests/securityselinuxlabeldata/chardev.txt +@@ -2,6 +2,6 @@ + /plain.dev;system_u:object_r:svirt_image_t:s0:c41,c264 + /plain.fifo;system_u:object_r:svirt_image_t:s0:c41,c264 + /nolabel.sock; +-/plain.sock; ++/plain.sock;system_u:object_r:svirt_image_t:s0:c41,c264 + /yeslabel.sock;system_u:object_r:svirt_image_t:s0:c41,c264 + /altlabel.sock;system_u:object_r:svirt_image_custom_t:s0:c41,c264 +-- +2.35.1 + diff --git a/libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch b/libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch new file mode 100644 index 0000000..a6076a1 --- /dev/null +++ b/libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch @@ -0,0 +1,51 @@ +From 41247c87fd47f2e55825d62c697da810ba5062f5 Mon Sep 17 00:00:00 2001 +Message-Id: <41247c87fd47f2e55825d62c697da810ba5062f5@dist-git> +From: Peter Krempa +Date: Tue, 14 Jun 2022 13:13:48 +0200 +Subject: [PATCH] virDomainDiskDefValidate: Improve error messages for + 'startupPolicy' checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove linebreak and mention the attribute name. Also prepare the error +messages for future by substituting the type of offending access. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit 9a480737c8adf92c332aa850c5269191ceb04eb9) +https://bugzilla.redhat.com/show_bug.cgi?id=2095758 +--- + src/conf/domain_validate.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index a4271f1247..452742e67c 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -778,9 +778,9 @@ virDomainDiskDefValidate(const virDomainDef *def, + if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) { + if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { + virReportError(VIR_ERR_XML_ERROR, +- _("Setting disk %s is not allowed for " +- "disk of network type"), +- virDomainStartupPolicyTypeToString(disk->startupPolicy)); ++ _("disk startupPolicy '%s' is not allowed for disk of '%s' type"), ++ virDomainStartupPolicyTypeToString(disk->startupPolicy), ++ virStorageTypeToString(disk->src->type)); + return -1; + } + +@@ -788,8 +788,7 @@ virDomainDiskDefValidate(const virDomainDef *def, + disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY && + disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) { + virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Setting disk 'requisite' is allowed only for " +- "cdrom or floppy")); ++ _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy")); + return -1; + } + } +-- +2.35.1 + diff --git a/libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch b/libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch new file mode 100644 index 0000000..f57195b --- /dev/null +++ b/libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch @@ -0,0 +1,42 @@ +From 26daf647925213a05509cc302d9151fe4525febb Mon Sep 17 00:00:00 2001 +Message-Id: <26daf647925213a05509cc302d9151fe4525febb@dist-git> +From: Peter Krempa +Date: Tue, 14 Jun 2022 14:07:47 +0200 +Subject: [PATCH] virDomainDiskDefValidateStartupPolicy: Validate disk type + better +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Our startup policy checkers work only for local paths, so disk sources +such as NVMe, or vhost-user can't be used with startup policy. + +Unfortunately the validation did not catch these cases. Fix it. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit b90d0f0a1e4ee52c828fb683c14c14e241e6fcbb) +https://bugzilla.redhat.com/show_bug.cgi?id=2095758 +--- + src/conf/domain_validate.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index bfff7339ef..55759af9f8 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -604,7 +604,10 @@ virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk) + if (disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_DEFAULT) + return 0; + +- if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { ++ /* We want to allow any startup policy for un-translated _TYPE_VOLUME disks. ++ * virStorageSourceGetActualType returns _TYPE_VOLUME in such case */ ++ if (virStorageSourceGetActualType(disk->src) != VIR_STORAGE_TYPE_VOLUME && ++ !virStorageSourceIsLocalStorage(disk->src)) { + virReportError(VIR_ERR_XML_ERROR, + _("disk startupPolicy '%s' is not allowed for disk of '%s' type"), + virDomainStartupPolicyTypeToString(disk->startupPolicy), +-- +2.35.1 + diff --git a/libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch b/libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch new file mode 100644 index 0000000..d8ab75e --- /dev/null +++ b/libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch @@ -0,0 +1,56 @@ +From 2ea89fb18aa9d2dac1e651869736fede7a2ec434 Mon Sep 17 00:00:00 2001 +Message-Id: <2ea89fb18aa9d2dac1e651869736fede7a2ec434@dist-git> +From: Peter Krempa +Date: Tue, 14 Jun 2022 14:21:33 +0200 +Subject: [PATCH] virDomainDiskTranslateSourcePool: Fix check of + 'startupPolicy' definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The check was historically done only for _TYPE_VOLUME disks, but +refactors to allow _TYPE_VOLUME disks in the backing chain caused a +regression where we'd reject startupPolicy also for _TYPE_BLOCK disks +which historically worked well. + +Fix it by using the 'virDomainDiskDefValidateStartupPolicy' helper and +use it only when the top level image is a _TYPE_VOLUME as in other cases +it was already validated. This also allows _TYPE_BLOCK volumes to use +startup policy. + +Fixes: 37f01262eed9f37dd5eb7de8b83edd2fea741054 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2095758 +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit ed8984306e1cd44c424fda3ed412a4177dd7b84d) +--- + src/conf/domain_conf.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 805a15848e..92510973e6 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -31311,13 +31311,13 @@ virDomainDiskTranslateSourcePool(virDomainDiskDef *def) + + if (virDomainStorageSourceTranslateSourcePool(n, conn) < 0) + return -1; +- } + +- if (def->startupPolicy != 0 && +- virStorageSourceGetActualType(def->src) != VIR_STORAGE_TYPE_FILE) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("'startupPolicy' is only valid for 'file' type volume")); +- return -1; ++ /* The validity of 'startupPolicy' setting is checked only for the top ++ * level image. For any other subsequent images we honour it only if ++ * possible */ ++ if (n == def->src && ++ virDomainDiskDefValidateStartupPolicy(def) < 0) ++ return -1; + } + + return 0; +-- +2.35.1 + diff --git a/libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch b/libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch new file mode 100644 index 0000000..c16422a --- /dev/null +++ b/libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch @@ -0,0 +1,80 @@ +From 20c1c86f96dd7293734888ef6f8b75c11cda5fae Mon Sep 17 00:00:00 2001 +Message-Id: <20c1c86f96dd7293734888ef6f8b75c11cda5fae@dist-git> +From: Jiri Denemark +Date: Wed, 22 Jun 2022 16:36:53 +0200 +Subject: [PATCH] virsh: Add support for VIR_MIGRATE_ZEROCOPY flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +(cherry picked from commit efa3baeae70fbdf4ab032ca485cb9272ee96bd50) + +https://bugzilla.redhat.com/show_bug.cgi?id=2089433 + +Conflicts: + docs/manpages/virsh.rst + tools/virsh-domain.c + - post-copy recovery not backported + +Signed-off-by: Jiri Denemark +--- + docs/manpages/virsh.rst | 8 +++++++- + tools/virsh-domain.c | 7 +++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst +index dd534c10cb..d24e7774a6 100644 +--- a/docs/manpages/virsh.rst ++++ b/docs/manpages/virsh.rst +@@ -3225,7 +3225,8 @@ migrate + migrate [--live] [--offline] [--direct] [--p2p [--tunnelled]] + [--persistent] [--undefinesource] [--suspend] [--copy-storage-all] + [--copy-storage-inc] [--change-protection] [--unsafe] [--verbose] +- [--rdma-pin-all] [--abort-on-error] [--postcopy] [--postcopy-after-precopy] ++ [--rdma-pin-all] [--abort-on-error] [--postcopy] ++ [--postcopy-after-precopy] [--zerocopy] + domain desturi [migrateuri] [graphicsuri] [listen-address] [dname] + [--timeout seconds [--timeout-suspend | --timeout-postcopy]] + [--xml file] [--migrate-disks disk-list] [--disks-port port] +@@ -3298,6 +3299,11 @@ high (and thus allowing the domain to lock most of the host's memory). Doing so + may be dangerous to both the domain and the host itself since the host's kernel + may run out of memory. + ++*--zerocopy* requests zero-copy mechanism to be used for migrating memory pages. ++For QEMU/KVM this means QEMU will be temporarily allowed to lock all guest ++pages in host's memory, although only those that are queued for transfer will ++be locked at the same time. ++ + ``Note``: Individual hypervisors usually do not support all possible types of + migration. For example, QEMU does not support direct migration. + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index b56f6a90f5..c5bade1dbf 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -10730,6 +10730,10 @@ static const vshCmdOptDef opts_migrate[] = { + .type = VSH_OT_BOOL, + .help = N_("automatically switch to post-copy migration after one pass of pre-copy") + }, ++ {.name = "zerocopy", ++ .type = VSH_OT_BOOL, ++ .help = N_("use zero-copy mechanism for migrating memory pages") ++ }, + {.name = "migrateuri", + .type = VSH_OT_STRING, + .completer = virshCompleteEmpty, +@@ -11133,6 +11137,9 @@ doMigrate(void *opaque) + if (vshCommandOptBool(cmd, "postcopy")) + flags |= VIR_MIGRATE_POSTCOPY; + ++ if (vshCommandOptBool(cmd, "zerocopy")) ++ flags |= VIR_MIGRATE_ZEROCOPY; ++ + if (vshCommandOptBool(cmd, "tls")) + flags |= VIR_MIGRATE_TLS; + +-- +2.35.1 + diff --git a/libvirt.spec b/libvirt.spec index 248656f..530b2cb 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -6,16 +6,16 @@ %define min_rhel 8 %define min_fedora 33 -%define arches_qemu_kvm %{ix86} x86_64 %{power64} %{arm} aarch64 s390x loongarch64 +%define arches_qemu_kvm %{ix86} x86_64 %{power64} %{arm} aarch64 s390x %if 0%{?rhel} %if 0%{?rhel} > 8 - %define arches_qemu_kvm x86_64 aarch64 s390x loongarch64 + %define arches_qemu_kvm x86_64 aarch64 s390x %else - %define arches_qemu_kvm x86_64 %{power64} aarch64 s390x loongarch64 + %define arches_qemu_kvm x86_64 %{power64} aarch64 s390x %endif %endif -%define arches_64bit x86_64 %{power64} aarch64 s390x riscv64 loongarch64 +%define arches_64bit x86_64 %{power64} aarch64 s390x riscv64 %define arches_x86 %{ix86} x86_64 %define arches_systemtap_64bit %{arches_64bit} @@ -23,9 +23,9 @@ %define arches_xen %{arches_x86} aarch64 %define arches_vbox %{arches_x86} %define arches_ceph %{arches_64bit} -%define arches_zfs %{arches_x86} %{power64} %{arm} loongarch64 -%define arches_numactl %{arches_x86} %{power64} aarch64 s390x loongarch64 -%define arches_numad %{arches_x86} %{power64} aarch64 loongarch64 +%define arches_zfs %{arches_x86} %{power64} %{arm} +%define arches_numactl %{arches_x86} %{power64} aarch64 s390x +%define arches_numad %{arches_x86} %{power64} aarch64 # The hypervisor drivers that run in libvirtd %define with_qemu 0%{!?_without_qemu:1} @@ -210,7 +210,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 8.0.0 -Release: 5.2%{?dist}%{?extra_release} +Release: 10%{?dist}%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -250,7 +250,23 @@ Patch27: libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.pa Patch28: libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch Patch29: libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch Patch30: libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch -Patch31: libvirt-Add-loongarch-support.patch +Patch31: libvirt-nwfilter-fix-crash-when-counting-number-of-network-filters.patch +Patch32: libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch +Patch33: libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch +Patch34: libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch +Patch35: libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch +Patch36: libvirt-conf-virtiofs-add-thread_pool-element.patch +Patch37: libvirt-qemu-virtiofs-format-thread-pool-size.patch +Patch38: libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch +Patch39: libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch +Patch40: libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch +Patch41: libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch +Patch42: libvirt-qemu_migration-Restore-original-memory-locking-limit.patch +Patch43: libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch +Patch44: libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch +Patch45: libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch +Patch46: libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch +Patch47: libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2124,21 +2140,44 @@ exit 0 %changelog -* Tue May 17 2022 Jiri Denemark - 8.0.0-5.2.el8 -- cpu_map: Disable cpu64-rhel* for host-model and baseline (rhbz#2084030) -- cputest: Drop some old artificial baseline tests (rhbz#2084030) -- cputest: Give better names to baseline tests (rhbz#2084030) -- cputest: Add some real world baseline tests (rhbz#2084030) -- cpu_x86: Consolidate signature match in x86DecodeUseCandidate (rhbz#2084030) -- cpu_x86: Refactor feature list comparison in x86DecodeUseCandidate (rhbz#2084030) -- cpu_x86: Penalize disabled features when computing CPU model (rhbz#2084030) -- cpu_x86: Ignore enabled features for input models in x86DecodeUseCandidate (rhbz#2084030) - -* Wed Apr 27 2022 Jiri Denemark - 8.0.0-5.1.el8 -- conf: Introduce memory allocation threads (rhbz#2075569) -- qemu_capabilities: Detect memory-backend-*.prealloc-threads property (rhbz#2075569) -- qemu_validate: Validate prealloc threads against qemuCpas (rhbz#2075569) -- qemu_command: Generate prealloc-threads property (rhbz#2075569) +* Mon Jul 25 2022 Jiri Denemark - 8.0.0-10 +- security_selinux.c: Relabel existing mode="bind" UNIX sockets (rhbz#2101575) +- RHEL: qemu_migration: Fix restoring memlock limit on destination (rhbz#2107954) + +* Thu Jun 30 2022 Jiri Denemark - 8.0.0-9 +- conf: virtiofs: add thread_pool element (rhbz#2079582) +- qemu: virtiofs: format --thread-pool-size (rhbz#2079582) +- conf: Move virDomainObj::originalMemlock into qemuDomainObjPrivate (rhbz#2089433) +- qemu_domain: Format qemuDomainObjPrivate::originalMemlock (rhbz#2089433) +- qemu: Add qemuDomainSetMaxMemLock helper (rhbz#2089433) +- qemu_migration: Use qemuDomainSetMaxMemLock (rhbz#2089433) +- qemu_migration: Restore original memory locking limit (rhbz#2089433) +- Add VIR_MIGRATE_ZEROCOPY flag (rhbz#2089433) +- virsh: Add support for VIR_MIGRATE_ZEROCOPY flag (rhbz#2089433) +- qemu_migration: Implement VIR_MIGRATE_ZEROCOPY flag (rhbz#2089433) + +* Wed Jun 15 2022 Jiri Denemark - 8.0.0-8 +- nwfilter: fix crash when counting number of network filters (CVE-2022-0897, rhbz#2063902) +- virDomainDiskDefValidate: Improve error messages for 'startupPolicy' checks (rhbz#2095758) +- domain_validate: Split out validation of disk startup policy (rhbz#2095758) +- virDomainDiskDefValidateStartupPolicy: Validate disk type better (rhbz#2095758) +- virDomainDiskTranslateSourcePool: Fix check of 'startupPolicy' definition (rhbz#2095758) + +* Tue May 17 2022 Jiri Denemark - 8.0.0-7 +- cpu_map: Disable cpu64-rhel* for host-model and baseline (rhbz#1851227) +- cputest: Drop some old artificial baseline tests (rhbz#1851227) +- cputest: Give better names to baseline tests (rhbz#1851227) +- cputest: Add some real world baseline tests (rhbz#1851227) +- cpu_x86: Consolidate signature match in x86DecodeUseCandidate (rhbz#1851227) +- cpu_x86: Refactor feature list comparison in x86DecodeUseCandidate (rhbz#1851227) +- cpu_x86: Penalize disabled features when computing CPU model (rhbz#1851227) +- cpu_x86: Ignore enabled features for input models in x86DecodeUseCandidate (rhbz#1851227) + +* Wed Apr 27 2022 Jiri Denemark - 8.0.0-6 +- conf: Introduce memory allocation threads (rhbz#2067126) +- qemu_capabilities: Detect memory-backend-*.prealloc-threads property (rhbz#2067126) +- qemu_validate: Validate prealloc threads against qemuCpas (rhbz#2067126) +- qemu_command: Generate prealloc-threads property (rhbz#2067126) * Fri Feb 25 2022 Jiri Denemark - 8.0.0-5 - node_device: Rework udevKludgeStorageType() (rhbz#2056673) -- Gitee From 1d9651ab80be81851d1bd95c48a3e586114f3532 Mon Sep 17 00:00:00 2001 From: zhaotianrui Date: Thu, 8 Sep 2022 09:28:25 -0400 Subject: [PATCH 2/2] Add loongarch support Signed-off-by: zhaotianrui --- libvirt-Add-loongarch-support.patch | 1233 +++++++++++++++++++++++++++ libvirt.spec | 15 +- 2 files changed, 1241 insertions(+), 7 deletions(-) create mode 100644 libvirt-Add-loongarch-support.patch diff --git a/libvirt-Add-loongarch-support.patch b/libvirt-Add-loongarch-support.patch new file mode 100644 index 0000000..94fd22a --- /dev/null +++ b/libvirt-Add-loongarch-support.patch @@ -0,0 +1,1233 @@ +From da7befb4ce165d692f34156f740f4ea3ce2b7fec Mon Sep 17 00:00:00 2001 +From: zhaotianrui +Date: Sat, 3 Sep 2022 14:23:43 -0400 +Subject: [PATCH] Add loongarch support + +Signed-off-by: zhaotianrui +Change-Id: I8d245bc2fb914b08af4ade8e334d59ba3a5c2f01 +--- + po/POTFILES.in | 1 + + src/cpu/cpu.c | 3 +- + src/cpu/cpu.h | 3 +- + src/cpu/cpu_loongarch.c | 727 ++++++++++++++++++++++++++++++ + src/cpu/cpu_loongarch.h | 28 ++ + src/cpu/cpu_loongarch_data.h | 40 ++ + src/cpu/meson.build | 1 + + src/cpu_map/index.xml | 5 + + src/cpu_map/loongarch_vendors.xml | 3 + + src/cpu_map/ls_3a5000.xml | 6 + + src/cpu_map/meson.build | 2 + + src/qemu/qemu_capabilities.c | 5 + + src/qemu/qemu_conf.c | 4 +- + src/qemu/qemu_domain.c | 20 +- + src/qemu/qemu_domain.h | 1 + + src/qemu/qemu_domain_address.c | 58 +++ + src/qemu/qemu_validate.c | 3 +- + src/util/virarch.c | 3 + + src/util/virarch.h | 3 + + src/util/virhostcpu.c | 2 +- + src/util/virsysinfo.c | 2 +- + 21 files changed, 913 insertions(+), 7 deletions(-) + create mode 100644 src/cpu/cpu_loongarch.c + create mode 100644 src/cpu/cpu_loongarch.h + create mode 100644 src/cpu/cpu_loongarch_data.h + create mode 100644 src/cpu_map/loongarch_vendors.xml + create mode 100644 src/cpu_map/ls_3a5000.xml + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index bf0a3b3529..1153e78265 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -68,6 +68,7 @@ + @SRCDIR@src/cpu/cpu_arm.c + @SRCDIR@src/cpu/cpu_map.c + @SRCDIR@src/cpu/cpu_ppc64.c ++@SRCDIR@src/cpu/cpu_loongarch.c + @SRCDIR@src/cpu/cpu_s390.c + @SRCDIR@src/cpu/cpu_x86.c + @SRCDIR@src/datatypes.c +diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c +index 285c7eee44..49527c3688 100644 +--- a/src/cpu/cpu.c ++++ b/src/cpu/cpu.c +@@ -31,7 +31,7 @@ + #include "cpu_arm.h" + #include "capabilities.h" + #include "virstring.h" +- ++#include "cpu_loongarch.h" + + #define VIR_FROM_THIS VIR_FROM_CPU + +@@ -42,6 +42,7 @@ static struct cpuArchDriver *drivers[] = { + &cpuDriverPPC64, + &cpuDriverS390, + &cpuDriverArm, ++ &cpuDriverLoongArch, + }; + + +diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h +index 071b33fe76..ce7aee4757 100644 +--- a/src/cpu/cpu.h ++++ b/src/cpu/cpu.h +@@ -28,7 +28,7 @@ + #include "cpu_x86_data.h" + #include "cpu_ppc64_data.h" + #include "cpu_arm_data.h" +- ++#include "cpu_loongarch_data.h" + + typedef struct _virCPUData virCPUData; + struct _virCPUData { +@@ -37,6 +37,7 @@ struct _virCPUData { + virCPUx86Data x86; + virCPUppc64Data ppc64; + virCPUarmData arm; ++ virCPULoongArchData loongarch; + /* generic driver needs no data */ + } data; + }; +diff --git a/src/cpu/cpu_loongarch.c b/src/cpu/cpu_loongarch.c +new file mode 100644 +index 0000000000..f7b4b85a44 +--- /dev/null ++++ b/src/cpu/cpu_loongarch.c +@@ -0,0 +1,727 @@ ++/* ++ * cpu_loongarch.c: CPU driver for 64-bit LOONGARCH CPUs ++ * ++ * Copyright (C) 2013 Red Hat, Inc. ++ * Copyright (C) IBM Corporation, 2010 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see ++ * . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "virlog.h" ++#include "viralloc.h" ++#include "cpu.h" ++#include "virstring.h" ++#include "cpu_map.h" ++#include "virbuffer.h" ++#include "cpu_loongarch.h" ++#include "cpu_loongarch_data.h" ++ ++#define VIR_FROM_THIS VIR_FROM_CPU ++ ++VIR_LOG_INIT("cpu.cpu_loongarch"); ++ ++static const virArch archs[] = { VIR_ARCH_LOONGARCH64 }; ++ ++typedef struct _LoongArch_vendor LoongArch_vendor; ++struct _LoongArch_vendor { ++ char *name; ++}; ++ ++typedef struct _LoongArch_model LoongArch_model; ++struct _LoongArch_model { ++ char *name; ++ LoongArch_vendor *vendor; ++ virCPULoongArchData data; ++}; ++ ++typedef struct _LoongArch_map LoongArch_map; ++struct _LoongArch_map { ++ size_t nvendors; ++ LoongArch_vendor **vendors; ++ size_t nmodels; ++ LoongArch_model **models; ++}; ++ ++static void ++LoongArchDataClear(virCPULoongArchData *data) ++{ ++ if (!data) ++ return; ++ ++ g_free(data->prid); ++} ++ ++static int ++LoongArchDataCopy(virCPULoongArchData *dst, const virCPULoongArchData *src) ++{ ++ size_t i; ++ ++ dst->prid = g_new0(virCPULoongArchPrid, src->len); ++ dst->len = src->len; ++ ++ for (i = 0; i < src->len; i++) { ++ dst->prid[i].value = src->prid[i].value; ++ dst->prid[i].mask = src->prid[i].mask; ++ } ++ ++ return 0; ++} ++ ++static void ++LoongArchVendorFree(LoongArch_vendor *vendor) ++{ ++ if (!vendor) ++ return; ++ ++ g_free(vendor); ++} ++ ++static LoongArch_vendor * ++LoongArchVendorFind(LoongArch_map *map, ++ const char *name) ++{ ++ size_t i; ++ ++ for (i = 0; i < map->nvendors; i++) { ++ if (STREQ(map->vendors[i]->name, name)) ++ return map->vendors[i]; ++ } ++ ++ return NULL; ++} ++ ++static void ++LoongArchModelFree(LoongArch_model *model) ++{ ++ if (!model) ++ return; ++ ++ LoongArchDataClear(&model->data); ++ g_free(model->name); ++ g_free(model); ++} ++ ++static LoongArch_model * ++LoongArchModelCopy(LoongArch_model *model) ++{ ++ LoongArch_model *copy; ++ ++ copy = g_new0(LoongArch_model, 1); ++ copy->name = g_strdup(model->name); ++ ++ if (LoongArchDataCopy(©->data, &model->data) < 0) ++ goto error; ++ ++ copy->vendor = model->vendor; ++ ++ return copy; ++ ++ error: ++ LoongArchModelFree(copy); ++ return NULL; ++} ++ ++static LoongArch_model * ++LoongArchModelFind(LoongArch_map *map, ++ const char *name) ++{ ++ size_t i; ++ ++ for (i = 0; i < map->nmodels; i++) { ++ if (STREQ(map->models[i]->name, name)) ++ return map->models[i]; ++ } ++ ++ return NULL; ++} ++ ++static LoongArch_model * ++LoongArchModelFindPrid(LoongArch_map *map, ++ uint32_t prid) ++{ ++ size_t i; ++ size_t j; ++ ++ for (i = 0; i < map->nmodels; i++) { ++ LoongArch_model *model = map->models[i]; ++ for (j = 0; j < model->data.len; j++) { ++ if ((prid & model->data.prid[j].mask) == model->data.prid[j].value) ++ return model; ++ } ++ } ++ ++ return NULL; ++} ++ ++static LoongArch_model * ++LoongArchModelFromCPU(const virCPUDef *cpu, ++ LoongArch_map *map) ++{ ++ LoongArch_model *model; ++ ++ if (!cpu->model) { ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("no CPU model specified")); ++ return NULL; ++ } ++ ++ if (!(model = LoongArchModelFind(map, cpu->model))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown CPU model %s"), cpu->model); ++ return NULL; ++ } ++ ++ return LoongArchModelCopy(model); ++} ++ ++static void ++LoongArchMapFree(LoongArch_map *map) ++{ ++ size_t i; ++ ++ if (!map) ++ return; ++ ++ for (i = 0; i < map->nmodels; i++) ++ LoongArchModelFree(map->models[i]); ++ g_free(map->models); ++ ++ for (i = 0; i < map->nvendors; i++) ++ LoongArchVendorFree(map->vendors[i]); ++ g_free(map->vendors); ++ ++ g_free(map); ++} ++ ++static int ++LoongArchVendorParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED, ++ const char *name, ++ void *data) ++{ ++ LoongArch_map *map = data; ++ LoongArch_vendor *vendor; ++ int ret = -1; ++ ++ vendor = g_new0(LoongArch_vendor, 1); ++ vendor->name = g_strdup(name); ++ ++ if (LoongArchVendorFind(map, vendor->name)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("CPU vendor %s already defined"), vendor->name); ++ goto cleanup; ++ } ++ ++ VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor); ++ ret = 0; ++ ++ cleanup: ++ LoongArchVendorFree(vendor); ++ return ret; ++} ++ ++static int ++LoongArchModelParse(xmlXPathContextPtr ctxt, ++ const char *name, ++ void *data) ++{ ++ LoongArch_map *map = data; ++ LoongArch_model *model; ++ xmlNodePtr *nodes = NULL; ++ char *vendor = NULL; ++ unsigned long prid; ++ size_t i; ++ int n; ++ int ret = -1; ++ ++ model = g_new0(LoongArch_model, 1); ++ model->name = g_strdup(name); ++ ++ if (LoongArchModelFind(map, model->name)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("CPU model %s already defined"), model->name); ++ goto cleanup; ++ } ++ ++ if (virXPathBoolean("boolean(./vendor)", ctxt)) { ++ vendor = virXPathString("string(./vendor/@name)", ctxt); ++ if (!vendor) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Invalid vendor element in CPU model %s"), ++ model->name); ++ goto cleanup; ++ } ++ ++ if (!(model->vendor = LoongArchVendorFind(map, vendor))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown vendor %s referenced by CPU model %s"), ++ vendor, model->name); ++ goto cleanup; ++ } ++ } ++ ++ if ((n = virXPathNodeSet("./prid", ctxt, &nodes)) <= 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Missing Prid information for CPU model %s"), ++ model->name); ++ goto cleanup; ++ } ++ ++ model->data.prid = g_new0(virCPULoongArchPrid, n); ++ model->data.len = n; ++ ++ for (i = 0; i < n; i++) { ++ ctxt->node = nodes[i]; ++ ++ if (virXPathULongHex("string(./@value)", ctxt, &prid) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Missing or invalid Prid value in CPU model %s"), ++ model->name); ++ goto cleanup; ++ } ++ model->data.prid[i].value = prid; ++ ++ if (virXPathULongHex("string(./@mask)", ctxt, &prid) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Missing or invalid PVR mask in CPU model %s"), ++ model->name); ++ goto cleanup; ++ } ++ model->data.prid[i].mask = prid; ++ } ++ ++ VIR_APPEND_ELEMENT(map->models, map->nmodels, model); ++ ret = 0; ++ ++ cleanup: ++ LoongArchModelFree(model); ++ g_free(vendor); ++ g_free(nodes); ++ return ret; ++} ++ ++static LoongArch_map * ++LoongArchLoadMap(void) ++{ ++ LoongArch_map *map; ++ ++ map = g_new0(LoongArch_map, 1); ++ if (cpuMapLoad("loongarch64", LoongArchVendorParse, NULL, LoongArchModelParse, map) < 0) ++ goto error; ++ ++ return map; ++ ++ error: ++ LoongArchMapFree(map); ++ return NULL; ++} ++ ++static virCPUData * ++LoongArchMakeCPUData(virArch arch, ++ virCPULoongArchData *data) ++{ ++ virCPUData *cpuData; ++ ++ cpuData = g_new0(virCPUData, 1); ++ cpuData->arch = arch; ++ ++ if (LoongArchDataCopy(&cpuData->data.loongarch, data) < 0) ++ g_free(cpuData); ++ ++ return cpuData; ++} ++ ++static virCPUCompareResult ++LoongArchCompute(virCPUDef *host, ++ const virCPUDef *other, ++ virCPUData *guestData, ++ char **message) ++{ ++ LoongArch_map *map = NULL; ++ LoongArch_model *host_model = NULL; ++ LoongArch_model *guest_model = NULL; ++ virCPUDef *cpu = NULL; ++ virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; ++ virArch arch; ++ size_t i; ++ ++ /* Ensure existing configurations are handled correctly */ ++ if (!(cpu = virCPUDefCopy(other))) ++ goto cleanup; ++ ++ if (cpu->arch != VIR_ARCH_NONE) { ++ bool found = false; ++ ++ for (i = 0; i < G_N_ELEMENTS(archs); i++) { ++ if (archs[i] == cpu->arch) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ VIR_DEBUG("CPU arch %s does not match host arch", ++ virArchToString(cpu->arch)); ++ if (message) { ++ *message = g_strdup_printf(_("CPU arch %s does not match host arch"), ++ virArchToString(cpu->arch)); ++ } ++ ret = VIR_CPU_COMPARE_INCOMPATIBLE; ++ goto cleanup; ++ } ++ arch = cpu->arch; ++ } else { ++ arch = host->arch; ++ } ++ ++ if (cpu->vendor && ++ (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) { ++ VIR_DEBUG("host CPU vendor does not match required CPU vendor %s", ++ cpu->vendor); ++ if (message) { ++ *message = g_strdup_printf(_("host CPU vendor does not match required " ++ "CPU vendor %s"), cpu->vendor); ++ } ++ ret = VIR_CPU_COMPARE_INCOMPATIBLE; ++ goto cleanup; ++ } ++ ++ if (!(map = LoongArchLoadMap())) ++ goto cleanup; ++ ++ /* Host CPU information */ ++ if (!(host_model = LoongArchModelFromCPU(host, map))) ++ goto cleanup; ++ ++ if (cpu->type == VIR_CPU_TYPE_GUEST) { ++ /* Guest CPU information */ ++ switch (cpu->mode) { ++ case VIR_CPU_MODE_HOST_MODEL: ++ case VIR_CPU_MODE_HOST_PASSTHROUGH: ++ /* host-model and host-passthrough: ++ * the guest CPU is the same as the host */ ++ guest_model = LoongArchModelCopy(host_model); ++ break; ++ ++ case VIR_CPU_MODE_CUSTOM: ++ /* custom: ++ * look up guest CPU information */ ++ guest_model = LoongArchModelFromCPU(cpu, map); ++ break; ++ } ++ } else { ++ /* Other host CPU information */ ++ guest_model = LoongArchModelFromCPU(cpu, map); ++ } ++ ++ if (!guest_model) ++ goto cleanup; ++ ++ if (STRNEQ(guest_model->name, host_model->name)) { ++ VIR_DEBUG("host CPU model does not match required CPU model %s", ++ guest_model->name); ++ if (message) { ++ *message = g_strdup_printf(_("host CPU model does not match required " ++ "CPU model %s"),guest_model->name); ++ } ++ ret = VIR_CPU_COMPARE_INCOMPATIBLE; ++ goto cleanup; ++ } ++ ++ if (guestData) ++ if (!(guestData = LoongArchMakeCPUData(arch, &guest_model->data))) ++ goto cleanup; ++ ++ ret = VIR_CPU_COMPARE_IDENTICAL; ++ ++ cleanup: ++ virCPUDefFree(cpu); ++ LoongArchMapFree(map); ++ LoongArchModelFree(host_model); ++ LoongArchModelFree(guest_model); ++ return ret; ++} ++ ++static virCPUCompareResult ++virCPULoongArchCompare(virCPUDef *host, ++ virCPUDef *cpu, ++ bool failIncompatible) ++{ ++ virCPUCompareResult ret; ++ char *message = NULL; ++ ++ if (!host || !host->model) { ++ if (failIncompatible) { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", ++ _("unknown host CPU")); ++ } else { ++ VIR_WARN("unknown host CPU"); ++ ret = VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ return -1; ++ } ++ ++ ret = LoongArchCompute(host, cpu, NULL, &message); ++ ++ if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) { ++ ret = VIR_CPU_COMPARE_ERROR; ++ if (message) { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message); ++ } else { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); ++ } ++ } ++ g_free(message); ++ ++ return ret; ++} ++ ++static int ++LoongArchDriverDecode(virCPUDef *cpu, ++ const virCPUData *data, ++ virDomainCapsCPUModels *models) ++{ ++ int ret = -1; ++ LoongArch_map *map; ++ LoongArch_model *model; ++ ++ if (!data || !(map = LoongArchLoadMap())) ++ return -1; ++ ++ if (!(model = LoongArchModelFindPrid(map, data->data.loongarch.prid[0].value))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Cannot find CPU model with Prid 0x%08x"), ++ data->data.loongarch.prid[0].value); ++ goto cleanup; ++ } ++ ++ if (!virCPUModelIsAllowed(model->name, models)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("CPU model %s is not supported by hypervisor"), ++ model->name); ++ goto cleanup; ++ } ++ ++ cpu->model = g_strdup(model->name); ++ if (model->vendor) { ++ cpu->vendor = g_strdup(model->vendor->name); ++ } ++ ret = 0; ++ ++ cleanup: ++ LoongArchMapFree(map); ++ ++ return ret; ++} ++ ++static void ++virCPULoongArchDataFree(virCPUData *data) ++{ ++ if (!data) ++ return; ++ ++ LoongArchDataClear(&data->data.loongarch); ++ g_free(data); ++} ++ ++static int virCPULoongArchGetHostPRID(void) ++{ ++ return 0x14c010; ++} ++ ++static int ++virCPULoongArchGetHost(virCPUDef *cpu, ++ virDomainCapsCPUModels *models) ++{ ++ virCPUData *cpuData = NULL; ++ virCPULoongArchData *data; ++ int ret = -1; ++ ++ if (!(cpuData = virCPUDataNew(archs[0]))) ++ goto cleanup; ++ ++ data = &cpuData->data.loongarch; ++ ++ data->prid = g_new0(virCPULoongArchPrid, 1); ++ data->len = 1; ++ ++ data->prid[0].value = virCPULoongArchGetHostPRID(); ++ data->prid[0].mask = 0xffff00ul; ++ ++ ret = LoongArchDriverDecode(cpu, cpuData, models); ++ ++ cleanup: ++ virCPULoongArchDataFree(cpuData); ++ return ret; ++} ++ ++ ++static int ++virCPULoongArchUpdate(virCPUDef *guest, ++ const virCPUDef *host, ++ bool relative) ++{ ++ /* ++ * - host-passthrough doesn't even get here ++ * - host-model is used for host CPU running in a compatibility mode and ++ * it needs to remain unchanged ++ * - custom doesn't support any optional features, there's nothing to ++ * update ++ */ ++ VIR_DEBUG("host model %s, if relatived %d",host->model, relative); ++ if (guest->mode == VIR_CPU_MODE_CUSTOM) ++ guest->match = VIR_CPU_MATCH_EXACT; ++ ++ return 0; ++} ++ ++static virCPUDef * ++LoongArchDriverBaseline(virCPUDef **cpus, ++ unsigned int ncpus, ++ virDomainCapsCPUModels *models, ++ const char **features, ++ bool migratable) ++{ ++ LoongArch_map *map; ++ LoongArch_model *model; ++ LoongArch_vendor *vendor = NULL; ++ virCPUDef *cpu = NULL; ++ size_t i; ++ if (models && *features) { ++ VIR_DEBUG("migratable %d features %s",migratable, *features); ++ } ++ if (!(map = LoongArchLoadMap())) ++ goto error; ++ ++ if (!(model = LoongArchModelFind(map, cpus[0]->model))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown CPU model %s"), cpus[0]->model); ++ goto error; ++ } ++ ++ for (i = 0; i < ncpus; i++) { ++ LoongArch_vendor *vnd; ++ ++ if (STRNEQ(cpus[i]->model, model->name)) { ++ virReportError(VIR_ERR_OPERATION_FAILED, "%s", ++ _("CPUs are incompatible")); ++ goto error; ++ } ++ ++ if (!cpus[i]->vendor) ++ continue; ++ ++ if (!(vnd = LoongArchVendorFind(map, cpus[i]->vendor))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Unknown CPU vendor %s"), cpus[i]->vendor); ++ goto error; ++ } ++ ++ if (model->vendor) { ++ if (model->vendor != vnd) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("CPU vendor %s of model %s differs from " ++ "vendor %s"), ++ model->vendor->name, model->name, ++ vnd->name); ++ goto error; ++ } ++ } else if (vendor) { ++ if (vendor != vnd) { ++ virReportError(VIR_ERR_OPERATION_FAILED, "%s", ++ _("CPU vendors do not match")); ++ goto error; ++ } ++ } else { ++ vendor = vnd; ++ } ++ } ++ ++ cpu = g_new0(virCPUDef ,1); ++ cpu->model = g_strdup(model->name); ++ if (vendor) { ++ cpu->vendor = g_strdup(vendor->name); ++ } ++ cpu->type = VIR_CPU_TYPE_GUEST; ++ cpu->match = VIR_CPU_MATCH_EXACT; ++ cpu->fallback = VIR_CPU_FALLBACK_FORBID; ++ ++ cleanup: ++ LoongArchMapFree(map); ++ ++ return cpu; ++ ++ error: ++ virCPUDefFree(cpu); ++ cpu = NULL; ++ goto cleanup; ++} ++ ++static int ++virCPULoongArchDriverGetModels(char ***models) ++{ ++ LoongArch_map *map; ++ size_t i; ++ int ret = -1; ++ ++ if (!(map = LoongArchLoadMap())) ++ goto error; ++ ++ if (models) { ++ *models = g_new0(char *, map->nmodels + 1); ++ for (i = 0; i < map->nmodels; i++) { ++ (*models)[i] = g_strdup(map->models[i]->name); ++ } ++ } ++ ++ ret = map->nmodels; ++ ++ cleanup: ++ LoongArchMapFree(map); ++ return ret; ++ ++ error: ++ if (models) { ++ g_strfreev(*models); ++ *models = NULL; ++ } ++ goto cleanup; ++} ++ ++struct cpuArchDriver cpuDriverLoongArch = { ++ .name = "LoongArch", ++ .arch = archs, ++ .narch = G_N_ELEMENTS(archs), ++ .compare = virCPULoongArchCompare, ++ .decode = LoongArchDriverDecode, ++ .encode = NULL, ++ .dataFree = virCPULoongArchDataFree, ++ .getHost = virCPULoongArchGetHost, ++ .baseline = LoongArchDriverBaseline, ++ .update = virCPULoongArchUpdate, ++ .getModels = virCPULoongArchDriverGetModels, ++}; +diff --git a/src/cpu/cpu_loongarch.h b/src/cpu/cpu_loongarch.h +new file mode 100644 +index 0000000000..1fde3b5162 +--- /dev/null ++++ b/src/cpu/cpu_loongarch.h +@@ -0,0 +1,28 @@ ++/* ++ * cpu_loongarch.h: CPU driver for 64-bit LOONGARCH CPUs ++ * ++ * Copyright (C) Copyright (C) IBM Corporation, 2010 ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see ++ * . ++ */ ++ ++#ifndef __VIR_CPU_LOONGARCH_H__ ++# define __VIR_CPU_LOONGARCH_H__ ++ ++# include "cpu.h" ++ ++extern struct cpuArchDriver cpuDriverLoongArch; ++ ++#endif /* __VIR_CPU_LOONGARCH_H__ */ +diff --git a/src/cpu/cpu_loongarch_data.h b/src/cpu/cpu_loongarch_data.h +new file mode 100644 +index 0000000000..1a759e7d16 +--- /dev/null ++++ b/src/cpu/cpu_loongarch_data.h +@@ -0,0 +1,40 @@ ++/* ++ * cpu_loongarch_data.h: 64-bit LOONGARCH CPU specific data ++ * ++ * Copyright (C) 2012 IBM Corporation. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; If not, see ++ * . ++ */ ++ ++#ifndef __VIR_CPU_LOONGARCH_DATA_H__ ++# define __VIR_CPU_LOONGARCH_DATA_H__ ++ ++# include ++ ++typedef struct _virCPULoongArchPrid virCPULoongArchPrid; ++struct _virCPULoongArchPrid { ++ uint32_t value; ++ uint32_t mask; ++}; ++ ++# define VIR_CPU_LOONGARCH_DATA_INIT { 0 } ++ ++typedef struct _virCPULoongArchData virCPULoongArchData; ++struct _virCPULoongArchData { ++ size_t len; ++ virCPULoongArchPrid *prid; ++}; ++ ++#endif /* __VIR_CPU_MIPS64_DATA_H__ */ +diff --git a/src/cpu/meson.build b/src/cpu/meson.build +index b4ad95e46d..ad2f859fd8 100644 +--- a/src/cpu/meson.build ++++ b/src/cpu/meson.build +@@ -5,6 +5,7 @@ cpu_sources = [ + 'cpu_ppc64.c', + 'cpu_s390.c', + 'cpu_x86.c', ++ 'cpu_loongarch.c', + ] + + cpu_lib = static_library( +diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml +index ffe1fa91e5..d302de396a 100644 +--- a/src/cpu_map/index.xml ++++ b/src/cpu_map/index.xml +@@ -110,4 +110,9 @@ + + + ++ ++ ++ ++ ++ + +diff --git a/src/cpu_map/loongarch_vendors.xml b/src/cpu_map/loongarch_vendors.xml +new file mode 100644 +index 0000000000..c744654617 +--- /dev/null ++++ b/src/cpu_map/loongarch_vendors.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +diff --git a/src/cpu_map/ls_3a5000.xml b/src/cpu_map/ls_3a5000.xml +new file mode 100644 +index 0000000000..f6fe3386f7 +--- /dev/null ++++ b/src/cpu_map/ls_3a5000.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/meson.build b/src/cpu_map/meson.build +index 013fc62a02..9657c5164e 100644 +--- a/src/cpu_map/meson.build ++++ b/src/cpu_map/meson.build +@@ -77,6 +77,8 @@ cpumap_data = [ + 'x86_vendors.xml', + 'x86_Westmere-IBRS.xml', + 'x86_Westmere.xml', ++ 'loongarch_vendors.xml', ++ 'ls_3a5000.xml', + ] + + install_data(cpumap_data, install_dir: pkgdatadir / 'cpu_map') +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index c4f7db55c8..75668c6451 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -2073,6 +2073,9 @@ bool virQEMUCapsHasPCIMultiBus(const virDomainDef *def) + if (ARCH_IS_X86(def->os.arch)) + return true; + ++ if (STRPREFIX(def->os.machine,"loongson7a")) ++ return true; ++ + /* PPC supports multibus on all machine types which have pci since qemu-2.0.0 */ + if (def->os.arch == VIR_ARCH_PPC || + ARCH_IS_PPC64(def->os.arch)) { +@@ -2690,6 +2693,7 @@ static const char *preferredMachines[] = + + "malta", /* VIR_ARCH_MIPS64 */ + "malta", /* VIR_ARCH_MIPS64EL */ ++ "loongson7a", /* VIR_ARCH_LOONGARCH64 */ + "or1k-sim", /* VIR_ARCH_OR32 */ + NULL, /* VIR_ARCH_PARISC (no QEMU impl) */ + NULL, /* VIR_ARCH_PARISC64 (no QEMU impl) */ +@@ -5115,6 +5119,7 @@ virQEMUCapsInitQMPBasicArch(virQEMUCaps *qemuCaps) + case VIR_ARCH_MIPSEL: + case VIR_ARCH_MIPS64: + case VIR_ARCH_MIPS64EL: ++ case VIR_ARCH_LOONGARCH64: + case VIR_ARCH_OR32: + case VIR_ARCH_PARISC: + case VIR_ARCH_PARISC64: +diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c +index a0b8076d6b..8cd03261ac 100644 +--- a/src/qemu/qemu_conf.c ++++ b/src/qemu/qemu_conf.c +@@ -101,7 +101,9 @@ qemuDriverUnlock(virQEMUDriver *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-kvm/loongarch_bios.bin:/usr/share/qemu-kvm/loongarch_bios.bin" ++ + #endif + + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index 40fe9985e6..814d8cb67d 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -3668,6 +3668,10 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, + addPCIeRoot = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX); + break; + ++ case VIR_ARCH_LOONGARCH64: ++ addPCIeRoot = true; ++ break; ++ + case VIR_ARCH_PPC64: + case VIR_ARCH_PPC64LE: + addPCIRoot = true; +@@ -5065,6 +5069,11 @@ 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; ++ 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 */ +@@ -8324,6 +8333,13 @@ qemuDomainDefCheckABIStability(virQEMUDriver *driver, + } + + ++bool ++qemuDomainIsLoongson(const virDomainDef *def) ++{ ++ return (STRPREFIX(def->os.machine,"loongson3a") || STRPREFIX(def->os.machine,"loongson7a")); ++} ++ ++ + bool + qemuDomainCheckABIStability(virQEMUDriver *driver, + virDomainObj *vm, +@@ -8664,7 +8680,9 @@ qemuDomainMachineHasBuiltinIDE(const char *machine, + return qemuDomainMachineIsI440FX(machine, arch) || + STREQ(machine, "malta") || + STREQ(machine, "sun4u") || +- STREQ(machine, "g3beige"); ++ STREQ(machine, "g3beige") || ++ STREQ(machine, "loongson3a") || ++ STREQ(machine, "loongson7a"); + } + + +diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h +index e5046367e3..57f1f97348 100644 +--- a/src/qemu/qemu_domain.h ++++ b/src/qemu/qemu_domain.h +@@ -770,6 +770,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 18fc34d049..c3fac1c33b 100644 +--- a/src/qemu/qemu_domain_address.c ++++ b/src/qemu/qemu_domain_address.c +@@ -2026,6 +2026,59 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDef *def, + } + + ++static int ++qemuDomainValidateDevicePCISlotsLoongson(virDomainDef *def, ++ virDomainPCIAddressSet *addrs) ++{ ++ int ret = -1; ++ virPCIDeviceAddress tmp_addr; ++ char *addrStr = NULL; ++ virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_AUTOASSIGN ++ | 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) ++ goto cleanup; ++ } ++ ++ 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 */ ++ virDomainVideoDef *primaryVideo = def->videos[0]; ++ ++ if (virDeviceInfoPCIAddressIsWanted(&primaryVideo->info)) { ++ memset(&tmp_addr, 0, sizeof(tmp_addr)); ++ tmp_addr.slot = 2; ++ ++ if (!(addrStr = virPCIDeviceAddressAsString(&tmp_addr))) ++ goto cleanup; ++ if (!virDomainPCIAddressValidate(addrs, &tmp_addr, ++ addrStr, flags, true)) ++ goto cleanup; ++ ++ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { ++ if (qemuDomainPCIAddressReserveNextAddr(addrs, ++ &primaryVideo->info) < 0) ++ goto cleanup; ++ } else { ++ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, 0) < 0) ++ goto cleanup; ++ primaryVideo->info.addr.pci = tmp_addr; ++ primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; ++ } ++ } ++ } ++ ret = 0; ++ cleanup: ++ VIR_FREE(addrStr); ++ return ret; ++} ++ ++ + static int + qemuDomainValidateDevicePCISlotsChipsets(virDomainDef *def, + virDomainPCIAddressSet *addrs) +@@ -2040,6 +2093,11 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDef *def, + return -1; + } + ++ if (qemuDomainIsLoongson(def) && ++ qemuDomainValidateDevicePCISlotsLoongson(def, addrs) < 0) { ++ return -1; ++ } ++ + return 0; + } + +diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c +index 7bc14293d6..7d01d31aaf 100644 +--- a/src/qemu/qemu_validate.c ++++ b/src/qemu/qemu_validate.c +@@ -186,7 +186,8 @@ qemuValidateDomainDefFeatures(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'"), +diff --git a/src/util/virarch.c b/src/util/virarch.c +index 2134dd6a9d..9f40a7110c 100644 +--- a/src/util/virarch.c ++++ b/src/util/virarch.c +@@ -59,6 +59,7 @@ static const struct virArchData { + + { "mips64", 64, VIR_ARCH_BIG_ENDIAN }, + { "mips64el", 64, VIR_ARCH_LITTLE_ENDIAN }, ++ { "loongarch64", 64, VIR_ARCH_LITTLE_ENDIAN }, + { "openrisc", 32, VIR_ARCH_BIG_ENDIAN }, + { "parisc", 32, VIR_ARCH_BIG_ENDIAN }, + { "parisc64", 64, VIR_ARCH_BIG_ENDIAN }, +@@ -222,6 +223,8 @@ virArch virArchFromHost(void) + arch = VIR_ARCH_X86_64; + } else if (STREQ(ut.machine, "arm64")) { + arch = VIR_ARCH_AARCH64; ++ } else if (STREQ(ut.machine, "loongarch64")) { ++ arch = VIR_ARCH_LOONGARCH64; + } else { + /* Otherwise assume the canonical name */ + if ((arch = virArchFromString(ut.machine)) == VIR_ARCH_NONE) { +diff --git a/src/util/virarch.h b/src/util/virarch.h +index 528f84f8a5..7d396f2fff 100644 +--- a/src/util/virarch.h ++++ b/src/util/virarch.h +@@ -44,6 +44,7 @@ typedef enum { + + VIR_ARCH_MIPS64, /* MIPS 64 BE https://en.wikipedia.org/wiki/MIPS_architecture */ + VIR_ARCH_MIPS64EL, /* MIPS 64 LE https://en.wikipedia.org/wiki/MIPS_architecture */ ++ VIR_ARCH_LOONGARCH64, + VIR_ARCH_OR32, /* OpenRisc 32 BE https://en.wikipedia.org/wiki/OpenRISC#QEMU_support */ + VIR_ARCH_PARISC, /* PA-Risc 32 BE https://en.wikipedia.org/wiki/PA-RISC */ + VIR_ARCH_PARISC64, /* PA-Risc 64 BE https://en.wikipedia.org/wiki/PA-RISC */ +@@ -98,6 +99,8 @@ typedef enum { + #define ARCH_IS_MIPS64(arch) ((arch) == VIR_ARCH_MIPS64 ||\ + (arch) == VIR_ARCH_MIPS64EL) + ++#define ARCH_IS_LOONGARCH(arch) ((arch) == VIR_ARCH_LOONGARCH64) ++ + typedef enum { + VIR_ARCH_LITTLE_ENDIAN, + VIR_ARCH_BIG_ENDIAN, +diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c +index 35f41daef2..137796ea07 100644 +--- a/src/util/virhostcpu.c ++++ b/src/util/virhostcpu.c +@@ -546,7 +546,7 @@ virHostCPUParseFrequency(FILE *cpuinfo, + char line[1024]; + + /* No sensible way to retrieve CPU frequency */ +- if (ARCH_IS_ARM(arch)) ++ if (ARCH_IS_ARM(arch) || ARCH_IS_LOONGARCH(arch)) + return 0; + + if (ARCH_IS_X86(arch)) +diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c +index af9e03c5ac..9577cf1910 100644 +--- a/src/util/virsysinfo.c ++++ b/src/util/virsysinfo.c +@@ -1247,7 +1247,7 @@ virSysinfoRead(void) + { + #if defined(__powerpc__) + return virSysinfoReadPPC(); +-#elif defined(__arm__) || defined(__aarch64__) ++#elif defined(__arm__) || defined(__aarch64__) || defined(__loongarch__) + return virSysinfoReadARM(); + #elif defined(__s390__) || defined(__s390x__) + return virSysinfoReadS390(); +-- +2.27.0 + diff --git a/libvirt.spec b/libvirt.spec index 530b2cb..1cdca14 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -6,16 +6,16 @@ %define min_rhel 8 %define min_fedora 33 -%define arches_qemu_kvm %{ix86} x86_64 %{power64} %{arm} aarch64 s390x +%define arches_qemu_kvm %{ix86} x86_64 %{power64} %{arm} aarch64 s390x loongarch64 %if 0%{?rhel} %if 0%{?rhel} > 8 - %define arches_qemu_kvm x86_64 aarch64 s390x + %define arches_qemu_kvm x86_64 aarch64 s390x loongarch64 %else - %define arches_qemu_kvm x86_64 %{power64} aarch64 s390x + %define arches_qemu_kvm x86_64 %{power64} aarch64 s390x loongarch64 %endif %endif -%define arches_64bit x86_64 %{power64} aarch64 s390x riscv64 +%define arches_64bit x86_64 %{power64} aarch64 s390x riscv64 loongarch64 %define arches_x86 %{ix86} x86_64 %define arches_systemtap_64bit %{arches_64bit} @@ -23,9 +23,9 @@ %define arches_xen %{arches_x86} aarch64 %define arches_vbox %{arches_x86} %define arches_ceph %{arches_64bit} -%define arches_zfs %{arches_x86} %{power64} %{arm} -%define arches_numactl %{arches_x86} %{power64} aarch64 s390x -%define arches_numad %{arches_x86} %{power64} aarch64 +%define arches_zfs %{arches_x86} %{power64} %{arm} loongarch64 +%define arches_numactl %{arches_x86} %{power64} aarch64 s390x loongarch64 +%define arches_numad %{arches_x86} %{power64} aarch64 loongarch64 # The hypervisor drivers that run in libvirtd %define with_qemu 0%{!?_without_qemu:1} @@ -267,6 +267,7 @@ Patch44: libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch Patch45: libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch Patch46: libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch Patch47: libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch +Patch1000: libvirt-Add-loongarch-support.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} -- Gitee