From nobody Thu Dec 18 17:57:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1732043718968555.2200640122102; Tue, 19 Nov 2024 11:15:18 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 996) id CD4991B0E; Tue, 19 Nov 2024 14:15:17 -0500 (EST) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 775C51404; Tue, 19 Nov 2024 13:52:00 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 996) id 2250A13F5; Tue, 19 Nov 2024 13:51:49 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 5400E14B6 for ; Tue, 19 Nov 2024 13:51:09 -0500 (EST) Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-679-fO-vPIoyMme8CllWEOx5xQ-1; Tue, 19 Nov 2024 13:50:40 -0500 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7AFB319541BE for ; Tue, 19 Nov 2024 18:50:39 +0000 (UTC) Received: from orkuz (unknown [10.45.226.13]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F2E0B1956054 for ; Tue, 19 Nov 2024 18:50:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732042269; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lGA1LgD/UMfnHznYjfOzQBbsyxFjtfdp4yaz8A6sO6c=; b=Bx/FmfjbOYCJTcdrPw6iJMTCiG1ykx4M4GHUbDzk4VTP5izrVFPm1QduF7uPYZ8vRj+bSh 5SeoKyi41NmYaGopmiBsEmP5igexZk+5VvT+7uZmXsQHDK2CL0LgvvV4I6p6zGwvSVoArm SsNZh0jQAAClWBVzoh780ggnE8uzWRQ= X-MC-Unique: fO-vPIoyMme8CllWEOx5xQ-1 X-Mimecast-MFC-AGG-ID: fO-vPIoyMme8CllWEOx5xQ From: Jiri Denemark To: devel@lists.libvirt.org Subject: [PATCH 13/32] qemu: Canonicalize CPU models Date: Tue, 19 Nov 2024 19:49:49 +0100 Message-ID: <5884f33638c2eba69bfa9c8550a0cebf163b9a2b.1732039836.git.jdenemar@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: JqunaVCvPwC6k5o5R5Dsoz4nkyFGX09suZuRfVQSp_I_1732042239 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: JXR4YC4MQFVDA46FCLNXQ7ELLWVGVDGS X-Message-ID-Hash: JXR4YC4MQFVDA46FCLNXQ7ELLWVGVDGS X-MailFrom: jdenemar@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1732043720501116600 Content-Type: text/plain; charset="utf-8" When parsing a domain XML which uses a non-versioned CPU model we want to replace it with the appropriate version variant similarly to what we do with machine types. Theoretically QEMU supports per machine type specification of a version with which a non-versioned CPU model is replaced, but this is always 1 for all machine types and the query-machines QMP command does not even report the value. Luckily after talking to Igor, having a single number per machine type does not really allow for setting it to anything but 1 as CPU models have different number of versions. Each machine type would need to define a specific version for each CPU model, which would be a maintenance nightmare. For this reason there's no desire to ever resolve non-versioned CPU models to anything but v1 in QEMU and the per machine type setting will most likely even be removed completely. Thus it is safe for us to always use v1 as the canonical CPU model. Some non-versioned CPU models, however, are actually aliases to specific versions of a base model rather than being base models themselves. These are the old CPU model variants before model versions were introduced, e.g., -noTSX, -IBRS, etc. The mapping of these names to versions is hardcoded and will never change. We do not translate such CPU models to the corresponding versioned names. This allows us to introduce the corresponding -v* variants that match the QEMU models rather than the existing definitions in our CPU map. The guest CPU will be the same either way, but the way libvirt checks the CPU model compatibility with the host will be different. The old "partial" check done by libvirt using the definition from CPU map will still be used for the old names (we can't change this for compatibility reasons), but the corresponding versioned variants (as well as all other versions that do not have a non-versioned alias) will benefit from the recently introduced new "partial" check which uses only the information we get from QEMU to check whether a specific CPU definition is usable on the host. Signed-off-by: Jiri Denemark --- src/qemu/qemu_capabilities.c | 53 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_capabilities.h | 3 ++ src/qemu/qemu_domain.c | 6 ++++ src/qemu/qemu_postparse.c | 19 +++++++++++++ 4 files changed, 81 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5ac9f306f5..455fb5acbe 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2379,6 +2379,59 @@ virQEMUCapsGetCanonicalMachine(virQEMUCaps *qemuCaps, } =20 =20 +/** + * virQEMUCapsGetCanonicalCPU: + * @qemuCaps: QEMU capabilities + * @type: virtualization type + * @model: CPU model name + * + * Resolve a CPU model without explicit version to its versioned twin. We = only + * replace a base CPU model with its -v1 variant as that's what QEMU is do= ing. + * Theoretically they have a per machine type configuration of the default= CPU + * version to be used if no explicit version is specified, but it's always= 1 + * and they will not change it. And they do not report the default CPU ver= sion + * via QMP anyway. + * + * The old named variants of other CPU models (-noTSX, -IBRS, etc.) are ig= nored + * as they are hardcoded aliases to specific versions and not "dynamically" + * resolved. + * + * Returns the canonical versioned name of the CPU model or NULL if the CPU + * model should stay unchanged. The pointer (which must never be freed by = the + * caller) is valid as long as the caller holds a reference to the qemuCaps + * object. + */ +const char * +virQEMUCapsGetCanonicalCPU(virQEMUCaps *qemuCaps, + virDomainVirtType type, + const char *model) +{ + qemuMonitorCPUDefs *models; + size_t i; + + if (!ARCH_IS_X86(qemuCaps->arch) || !model) + return NULL; + + models =3D virQEMUCapsGetAccel(qemuCaps, type)->cpuModels; + if (!models) + return NULL; + + for (i =3D 0; i < models->ncpus; i++) { + qemuMonitorCPUDefInfo *cpu =3D models->cpus + i; + const char *p =3D STRSKIP(cpu->name, model); + + if (p && STREQ(p, "-v1")) { + if (virCPUCheckModel(qemuCaps->arch, cpu->name)) + return cpu->name; + + break; + } + } + + return NULL; +} + + int virQEMUCapsGetMachineMaxCpus(virQEMUCaps *qemuCaps, virDomainVirtType virtType, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 48e4530c95..7decf31b97 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -778,6 +778,9 @@ bool virQEMUCapsIsCPUModeSupported(virQEMUCaps *qemuCap= s, const char *virQEMUCapsGetCanonicalMachine(virQEMUCaps *qemuCaps, virDomainVirtType virtType, const char *name); +const char *virQEMUCapsGetCanonicalCPU(virQEMUCaps *qemuCaps, + virDomainVirtType type, + const char *model); bool virQEMUCapsIsMachineSupported(virQEMUCaps *qemuCaps, virDomainVirtType virtType, const char *canonical_machine) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 153bd56e86..d922f482c2 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5057,6 +5057,12 @@ qemuDomainMakeCPUMigratable(virArch arch, !ARCH_IS_X86(arch)) return 0; =20 + /* Strip -v1 suffix from the CPU model for backward compatibility with + * libvirt releases that do not support versioned CPU models. + */ + if (g_str_has_suffix(cpu->model, "-v1")) + cpu->model[strlen(cpu->model) - 3] =3D '\0'; + if (STREQ(cpu->model, "Icelake-Server")) { /* Originally Icelake-Server CPU model contained pconfig CPU featu= re. * It was never actually enabled and thus it was removed. To enable diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index 03b5ef825a..d3d85de11c 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -1656,6 +1656,23 @@ qemuDomainDefVcpusPostParse(virDomainDef *def) } =20 =20 +static void +qemuDomainCanonicalizeCPU(virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + const char *model; + + model =3D virQEMUCapsGetCanonicalCPU(qemuCaps, def->virtType, def->cpu= ->model); + if (!model) + return; + + VIR_DEBUG("Replacing CPU model '%1$s' with '%2$s'", def->cpu->model, m= odel); + + g_free(def->cpu->model); + def->cpu->model =3D g_strdup(model); +} + + static int qemuDomainDefCPUPostParse(virDomainDef *def, virQEMUCaps *qemuCaps) @@ -1667,6 +1684,8 @@ qemuDomainDefCPUPostParse(virDomainDef *def, if (!def->cpu) return 0; =20 + qemuDomainCanonicalizeCPU(def, qemuCaps); + for (i =3D 0; i < def->cpu->nfeatures; i++) { virCPUFeatureDef *feature =3D &def->cpu->features[i]; =20 --=20 2.47.0