From nobody Thu Nov 12 15:08:52 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; 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 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1794227538; cv=none; d=zohomail.com; s=zohoarc; b=SwuyoJtbmll34b/YzVOjohg8giiFjJDZMvYwY+pbL75smysg5YNXCxENnOqjQ9vJkl04s9+yk3GMdGRf3zWViB6vJJDWqcUd+lyfPRTAOnAVUnyLvzQpUmaOAQoFRwMO0kG1KMr0+8TsL/QmXV4SUf0skp08OiLfNC1iMiXvimE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1794227538; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:Subject:Subject:To:To:Message-Id; bh=imc75ggnC+RWD+ow+eAK6lY8OqYfnYU1IUnpB2ZMz8w=; b=HAeQozjnNxopA5/YMu01i2z21kbLsrSwHysMAp4XmaqE2w7KntUbkCLUXwxoJAcGX5qSk6wa8Z4RtmxM2pXC4INPI9Vm/XuqKyeVJKxqSNIcoIrYfk+ijovaBSwj1JcbdX/1xAB25jQp9MV66hb/iv1RVD8ikMKMZvxuogr6E+I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1794227538060132.42028479057024; Mon, 9 Nov 2026 04:32:18 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id B1F6F41BB7; Mon, 9 Nov 2026 07:32:16 -0500 (EST) Received: from [172.19.199.22] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 0AB1541C4A; Mon, 9 Nov 2026 07:27:31 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 6D5494195D; Fri, 6 Nov 2026 09:53:08 -0500 (EST) Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 0D9AB3F289 for ; Fri, 6 Nov 2026 09:53:05 -0500 (EST) Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-48df4f540ebso458389f8f.3 for ; Fri, 06 Nov 2026 06:53:05 -0800 (PST) Received: from athena.sw.ru ([2a06:5b06:b600:300:1488:8e51:f958:9448]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-492d7701cf9sm3548009f8f.39.2026.11.06.06.53.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 06:53:04 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1793976785; x=1794581585; darn=lists.libvirt.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=imc75ggnC+RWD+ow+eAK6lY8OqYfnYU1IUnpB2ZMz8w=; b=gNzUZoTGR8xmiJLcYUfMJ025HQFzgdH6MU+q7zxA0Lgvfgv5rkKBCtuif8gmrEdpSk z8U6oXSa9RqOrptZkz1Ne9bG0b2YMVDJVnwD+Cc8IHMfZ8FkM19rmvWSwwvMP6YfzEXZ uJyh6uGg83s+nlcjxQ7oJPJqTtz5D+N2ZV9EJZbJo2WnfJSZG7+CfuCNXUa5B/0kT0+h 1gqwhGkN/KoC/OFk6qxO7BgrX4u8kTo+j8Ewukwhq4bILgPFe0w4UQVLcPc79v8g8S8w VyV+IGwUtRqz+H+FIQx09cL/7ma/uvEL1SVKH37ftKmpGCogyKZXuCYzDBj7YHMW6FiI bK8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793976785; x=1794581585; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=imc75ggnC+RWD+ow+eAK6lY8OqYfnYU1IUnpB2ZMz8w=; b=xCgInkJz0Aekwo4Bkw8/B06gakxQNR7s6thB5pY8snKFkN/ee49ijaTybx5tyZnmHd Ab6vmyb+fTflVkbNmkIxir6AyhxauztNCHMWVY/MuF88kd6e2OrzijIA7QQMG8MRlTx5 1Ri3M6ytsvbulz4u2hRLvLsQVDa5/5/zqiY26gxtvLr8CBlxlE76pNRTDfOZ92fmM7l+ RQ0MCZWKGWqqjXjO1atp6LLlLQqCYAKLadg5VJ028zlDAou5ISl1yZYT/oI78wmbQrrK G9fMi6IHlvvdgtpqEn4YpY1hN3H70SprhfovIYYI8vY6Eqefu3EOcwalRcYtiDa5rFjk BYgg== X-Gm-Message-State: APuU4Z/DFwtxfnDOj+abDjvncX/BeRX96d0kGJaigt/pT4sJ7QdutWIo P/69Wk9H7X1QIGXgnSc9moN44WD5P69PDTjs5KOaw8ifhDa30h/HK+foH7WkKj9PSPP/GRSOTIC jELFm X-Gm-Gg: AYBFou18Sym39hRrx7qci6qLTagKqosWRmUzL76ahHygpv9TkyPbJQqkbi2Axf1UMZf 6SxFEIvDo01QJ7FDNbLBORUvpYqJQKOnFo/lZsXcwdyxr+CzkNNW1LF6cSFUExmPbp+/KsFIyXz OvVMok57Tpndov7dSfu3c0o3esmlfCs92foK59avhsQ6KYVrCdPEcCVuy8/Wd9YBPxhObrUEZ2q lqV5epRgujt+xooFpseiAipqTb6CxPB8rFRSJef4w9ZFbKqVyDplvFjleGwNibrtBQzsE6Yekc+ 5u4IWo/kHvTe2b1Yj8ppv96X/qFidQG6YwjPmFOVu2+kDuEVkmfyUoi6iP9ihE9okrZWUjZ3evp ctoR0rNgbfGIzXks6xQYGFfhdHrWt5CUT2VIXJ8cFhHB5XNupAJeaiLBPIpadeOfOO8IASfha28 PxdV+jkCXPsUaPdm28+Z1qyGzIO3zFqfUYCe29t4sx+BrRx6kXbby01GBdEKoUa9NwQGVhBOCK3 LRuXTaeGuArv8kiuKunRwSkv1ZCWyWcEL3MXZB0Ofv52yewAuUctwj3U3K6pZNh+TJWqqrHFbSP uW0p6QmwPu1QiElGZePS++2xWg== X-Received: by 2002:a05:6000:25ea:b0:48d:f39b:83de with SMTP id ffacd0b85a97d-492732dc7edmr5656130f8f.3.1793976784415; Fri, 06 Nov 2026 06:53:04 -0800 (PST) To: devel@lists.libvirt.org Subject: [PATCH v2 1/2] cpu_x86: let AMD guests drop spec-ctrl instead of failing Date: Fri, 6 Nov 2026 15:52:59 +0100 Message-ID: <20261106145300.3953928-2-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261106145300.3953928-1-den@openvz.org> References: <20261026190654.791689-1-den@openvz.org> <20261106145300.3953928-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-MailFrom: den@openvz.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation Message-ID-Hash: DGNSPIPPHXTR2MEKLPJ74W7PVAOIN5XF X-Message-ID-Hash: DGNSPIPPHXTR2MEKLPJ74W7PVAOIN5XF X-Mailman-Approved-At: Mon, 09 Nov 2026 12:27:22 +0000 CC: den@openvz.org X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "Denis V. Lunev via Devel" Reply-To: "Denis V. Lunev" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1794227542583158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev Since Linux kernel commit de572491a975 ("KVM: x86: AMD's IBPB is not equivalent to Intel's IBPB") KVM offers spec-ctrl on AMD hosts only when the CPU enumerates IBPB_RET, which Zen 1-3 do not. A host-model guest started on such a CPU under an older kernel has spec-ctrl in its live definition. On a destination with the newer kernel QEMU filters the feature out and the incoming migration fails: guest CPU doesn't match specification: missing features: spec-ctrl Restoring a save image or reverting a snapshot fails the same way, so the guest cannot be moved to the new kernel without a restart. Dropping the bit in libvirt costs the guest nothing beyond what KVM already withholds. KVM grants PRED_CMD for spec-ctrl or ibpb and SPEC_CTRL for spec-ctrl or any of ibrs, amd-stibp and amd-ssbd (kernel commit 39485ed95d6b), and checks the values written to SPEC_CTRL against the host, not the guest CPUID (kernel commit 841c2be09fe4). Both predate de572491a975. Since kernel commit e592ec657d84 KVM also ignores guest CPUID bits it does not support, so a host without IBPB_RET treats the guest as lacking spec-ctrl even if the bit stayed. QEMU drops the bit either way; libvirt only decides whether the guest survives. When a domain is started (fresh start, incoming migration, restore, snapshot revert) and the hypervisor dropped a required spec-ctrl while providing ibpb and one of ibrs, amd-stibp and amd-ssbd, virCPUUpdateLive() disables spec-ctrl in the live definition and logs it at VIR_INFO. spec-ctrl is also removed from the features QEMU reports as filtered, because check=3D'full' fails on any filtered feature whatever the definition says. Any other missing or extra feature still fails with check=3D'full'. Signed-off-by: Denis V. Lunev --- src/cpu/cpu_x86.c | 93 ++++++++++++++++++- tests/cputest.c | 15 +++ ...PYC-7713-64-Core-no-spec-ctrl-disabled.xml | 4 + ...EPYC-7713-64-Core-no-spec-ctrl-enabled.xml | 11 +++ ...d-EPYC-7713-64-Core-no-spec-ctrl-guest.xml | 56 +++++++++++ ...id-EPYC-7713-64-Core-no-spec-ctrl-json.xml | 56 +++++++++++ ...-64-Core-no-spec-ctrl-no-ibpb-disabled.xml | 4 + ...3-64-Core-no-spec-ctrl-no-ibpb-enabled.xml | 11 +++ ...713-64-Core-no-spec-ctrl-no-ibpb-guest.xml | 56 +++++++++++ 9 files changed, 302 insertions(+), 4 deletions(-) create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-no-ibpb-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-no-ibpb-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-no-ibpb-guest.xml diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 18c5756ef9..3e89d5ef0a 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -3144,6 +3144,88 @@ virCPUx86Update(virCPUDef *guest, } =20 =20 +/* + * Since kernel commit de572491a975 KVM no longer offers spec-ctrl on AMD + * hosts without IBPB_RET. The MSRs it stands for are still available to + * the guest through ibpb and any of ibrs, amd-stibp and amd-ssbd. + */ +static int +x86SpecCtrlDroppable(const virCPUDef *cpu G_GNUC_UNUSED, + virCPUx86Map *map, + const virCPUx86Data *enabled) +{ + const char *specCtrlMSR[] =3D { "ibrs", "amd-stibp", "amd-ssbd" }; + size_t i; + int rc; + + if ((rc =3D x86FeatureInData("ibpb", enabled, map)) <=3D 0) + return rc; + + for (i =3D 0; i < G_N_ELEMENTS(specCtrlMSR); i++) { + if ((rc =3D x86FeatureInData(specCtrlMSR[i], enabled, map)) !=3D 0) + return rc; + } + + return 0; +} + + +static const struct { + const char *name; + int (*droppable)(const virCPUDef *cpu, + virCPUx86Map *map, + const virCPUx86Data *enabled); +} x86DroppableFeatures[] =3D { + { "spec-ctrl", x86SpecCtrlDroppable }, +}; + + +/* + * Newer KVM may stop offering a feature a guest started elsewhere already + * requires, although the guest loses nothing without it. Disable such + * features rather than failing the check. + */ +static int +x86UpdateLiveDroppable(virCPUDef *cpu, + virCPUx86Map *map, + const virCPUx86Data *enabled, + virCPUx86Data *disabled) +{ + size_t i; + + for (i =3D 0; i < G_N_ELEMENTS(x86DroppableFeatures); i++) { + const char *name =3D x86DroppableFeatures[i].name; + virCPUFeatureDef *feature; + virCPUx86Feature *x86Feature; + int rc; + + if (!(feature =3D virCPUDefFindFeature(cpu, name)) || + feature->policy !=3D VIR_CPU_FEATURE_REQUIRE) + continue; + + if ((rc =3D x86FeatureInData(name, enabled, map)) < 0) + return -1; + + if (rc =3D=3D 1) + continue; + + if ((rc =3D x86DroppableFeatures[i].droppable(cpu, map, enabled)) = < 0) + return -1; + + if (rc =3D=3D 0) + continue; + + VIR_INFO("Hypervisor does not provide '%s', disabling it in the gu= est CPU", + name); + virCPUDefUpdateFeature(cpu, name, VIR_CPU_FEATURE_DISABLE); + if ((x86Feature =3D x86FeatureFind(map, name))) + x86DataSubtract(disabled, &x86Feature->data); + } + + return 0; +} + + static int virCPUx86UpdateLive(virCPUDef *cpu, virCPUData *dataEnabled, @@ -3165,16 +3247,19 @@ virCPUx86UpdateLive(virCPUDef *cpu, if (!(map =3D virCPUx86GetMap())) return -1; =20 - if (!(model =3D x86ModelFromCPU(cpu, map, -1)) || - !(modelDisabled =3D x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_DISA= BLE))) - return -1; - if (dataEnabled) x86DataCopy(&enabled, &dataEnabled->data.x86); =20 if (dataDisabled) x86DataCopy(&disabled, &dataDisabled->data.x86); =20 + if (x86UpdateLiveDroppable(cpu, map, &enabled, &disabled) < 0) + return -1; + + if (!(model =3D x86ModelFromCPU(cpu, map, -1)) || + !(modelDisabled =3D x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_DISA= BLE))) + return -1; + for (i =3D 0; i < map->nfeatures; i++) { virCPUx86Feature *feature =3D map->features[i]; virCPUFeaturePolicy expected =3D VIR_CPU_FEATURE_LAST; diff --git a/tests/cputest.c b/tests/cputest.c index e29c81cb8e..35b426155e 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -857,6 +857,15 @@ cpuTestUpdateLive(const void *arg) !(disabledData =3D virCPUDataParse(disabled))) return -1; =20 + if (data->result =3D=3D -1) { + if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) = =3D=3D 0) { + VIR_TEST_VERBOSE("virCPUUpdateLive succeeded unexpectedly"); + return -1; + } + virResetLastError(); + return 0; + } + expectedFile =3D g_strdup_printf("cpuid-%s-json", data->host); if (!(expected =3D cpuTestLoadXML(data->arch, expectedFile, data->existingTestCases))) { @@ -1110,6 +1119,10 @@ mymain(void) } \ } while (0) =20 +#define DO_TEST_UPDATE_LIVE(arch, host, result) \ + DO_TEST(arch, cpuTestUpdateLive, host, host, \ + NULL, NULL, 0, NULL, 0, result) + #define DO_TEST_CPUID_BASELINE(arch, label, cpu1, cpu2) \ do { \ const char *cpus[] =3D {cpu1, cpu2}; \ @@ -1270,6 +1283,8 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core-ibpb", JSON_MODELS_R= EQUIRED); DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7502-32-Core", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7713-64-Core", JSON_MODELS); + DO_TEST_UPDATE_LIVE(VIR_ARCH_X86_64, "EPYC-7713-64-Core-no-spec-ctrl",= 0); + DO_TEST_UPDATE_LIVE(VIR_ARCH_X86_64, "EPYC-7713-64-Core-no-spec-ctrl-n= o-ibpb", -1); DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-9334-32-Core", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "FX-8150", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-1352", JSON_NONE); diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= disabled.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctr= l-disabled.xml new file mode 100644 index 0000000000..d29d62bcad --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-disable= d.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= enabled.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl= -enabled.xml new file mode 100644 index 0000000000..6c7b14cd6f --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-enabled= .xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= guest.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-g= uest.xml new file mode 100644 index 0000000000..546896260f --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-guest.x= ml @@ -0,0 +1,56 @@ + + EPYC-Milan + AMD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= json.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-js= on.xml new file mode 100644 index 0000000000..d68763d61b --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-json.xml @@ -0,0 +1,56 @@ + + EPYC-Milan + AMD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= no-ibpb-disabled.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-= spec-ctrl-no-ibpb-disabled.xml new file mode 100644 index 0000000000..d29d62bcad --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-no-ibpb= -disabled.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= no-ibpb-enabled.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-s= pec-ctrl-no-ibpb-enabled.xml new file mode 100644 index 0000000000..0662433a08 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-no-ibpb= -enabled.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-= no-ibpb-guest.xml b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spe= c-ctrl-no-ibpb-guest.xml new file mode 100644 index 0000000000..546896260f --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-EPYC-7713-64-Core-no-spec-ctrl-no-ibpb= -guest.xml @@ -0,0 +1,56 @@ + + EPYC-Milan + AMD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --=20 2.53.0 From nobody Thu Nov 12 15:08:52 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; 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 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1794227708; cv=none; d=zohomail.com; s=zohoarc; b=IY1IK7PPS3BXRwjazFJPSmr6oO51xbjRgoLtuEJRkO9Acb9R9McTo+fBDk/QbAYVDUWgyvk/rji9YFRDZir2k1sbJvEM6d6TaK7uO4eong3vw9V2R2eohsel+zpCYYcgPmRglZcuNVsxxGOh+9txFvHWSL++E92xw22mYHMkpe0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1794227708; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:Subject:Subject:To:To:Message-Id; bh=c86hvk6JfUn1Pz/HM9j2LR7sUkubcHc7vqO0YjIBHzs=; b=La96L9vg0xqEgNbP+U/kgwucxfqQuoy/Iye45uYTHE90jhjDODbH6WnQhMWn+s4KOUouRm3QdV1pwwY5iaWUgiOGUMAWiMDsBCrfDPPRv03dTya2L/64Uk0caq3qvx3zxH/XSG38pE9FFJqCHE8SxC+waaHxzy8xBM80vpVMbdc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1794227708003837.3136551032819; Mon, 9 Nov 2026 04:35:08 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 9E8773F2EF; Mon, 9 Nov 2026 07:35:06 -0500 (EST) Received: from [172.19.199.22] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 49CB341CD5; Mon, 9 Nov 2026 07:27:44 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id C1D143F289; Fri, 6 Nov 2026 09:53:08 -0500 (EST) Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A10CD3F292 for ; Fri, 6 Nov 2026 09:53:06 -0500 (EST) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4a5177d78c7so7002495e9.2 for ; Fri, 06 Nov 2026 06:53:06 -0800 (PST) Received: from athena.sw.ru ([2a06:5b06:b600:300:1488:8e51:f958:9448]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-492d7701cf9sm3548009f8f.39.2026.11.06.06.53.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 06:53:05 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1793976785; x=1794581585; darn=lists.libvirt.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=c86hvk6JfUn1Pz/HM9j2LR7sUkubcHc7vqO0YjIBHzs=; b=s2EMAHprjyNU7/DmkTIj7a2mN5fXWKN7zHJQ1OuRv6K2eUVdtoDcgvA9njCe6dW5J7 nXPTL3VI/tPKAtUm8oczi8joi20IzPrYPmtZZsObPXSZtJx24BN9BeBXHsygivAWfAQE eTL5zEL4SU5iUW/nwh/QaRryxLMS1en/Hd2BYFPweXjco4AB+QIiKxHFVg/nquQVZP3o xBkrBS+AlIL4mrk/R2aCX/+lkiqhVD7AkX4OC5yR1t+S3L6KD0GyP0ZZxIk7cnRiZ61Y eoZgM+pTM+U5S8iVw6gG14oPf/I64Obm3c6v5doLBPlSvcomiILrFN0nLySpCxKlQfFV 3Q2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793976785; x=1794581585; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=c86hvk6JfUn1Pz/HM9j2LR7sUkubcHc7vqO0YjIBHzs=; b=mkad7szk/Rp8w2uWy2AAWnNS+ODypUjp9yrDIVo3CtHoyS3eFu/9fMr7GxtKVc82LM wFBmRsxyE+13MqnDb6zhf7TT6YJ+l2ZuBT/+bnsrlyCq9n7g2Pj25D/WLx2LQD4RxRL6 HiEwAqr6b0GdVS9KRggiG8wtQe8SuK+HaYshNMTj3M8S2QiZjwAdY3VZx+ELB+NBFinx GNDBTgfG9U7DDV1zK/faxdjysgaccyZgwnM9pWYKi3BRmpPhyxep7frL6ONX2IcFPwdt FjBRde55T34bcPqGUWLKQwFENrnOH627wQ4JnY4Ohl7B3ln3vfSdwnthyPeXzgh9/CtF ralw== X-Gm-Message-State: APuU4Z87YMeNK1G/4qVG7gfEB2AoUN0tXSZas+dQG3QIcpZfw637Uq19 Qzqew113s9rbXffPfi5oNYWW82RGpoGr/rVgVTOIOBhdjdBNxear6qTlSVAwIo5QqnZw/TBZYTE 6PUJw X-Gm-Gg: AYBFou3a/c+galPPdIlS4tTmEmmQ+RvjnGKFokFyrG+KMEh0n8QUG5DmFEbhKZ5ghyv z/OQJK32z2jawUxsGsaMN4RfIkyQodxw6m2RJ929a/s6zGCfOOlSiiEC1hNp+hZXL6JFvKyiPEd sizFipm5aG+tvr3gwxPg6wzHovcOe99Ko4kVJwyj6s0kQwMME4KmWg4G4EdUDr2eakf7uBZUjkH s/2BjW7d6pIwrl6Q8wM1L0WxXX/p0GBQ5k0X0sXBsO4x0Xl//36rbYBsXIybmuvMh1Zih9ITSQD 7wVpPtmYbUIZND6Huke/aSB6Zxe4w7eU83vY+Ub4g3KX9eFco7R78q2acl06BqNmiwv+PWcJo/v BgeO12umFRFweKUSytFEO59Ce9k/TmyT7+Tzh8eCQSgX0GzNdeIb8BePlUK35F7rmPL2WXB6Whv 8yE2+HrvPe8h3qjrY2bbVAGHXZgX9Gc1OW8D61p16OwAmY8xj2GS0zcLQwJoaCDOpp2D9kHhKhM yIOexK8jCBHkoimZMu2RqYjZRf19JZE4H664sptQoBc9j1W1HSb31bTyn7B7SF2YyueaARKs+Uc 6wvIIFZMzmmMdXbDTRMY5xu1ng== X-Received: by 2002:a05:600c:1c1c:b0:4a1:ac66:6ac6 with SMTP id 5b1f17b1804b1-4b6dfbac6eamr51431035e9.26.1793976785417; Fri, 06 Nov 2026 06:53:05 -0800 (PST) To: devel@lists.libvirt.org Subject: [PATCH v2 2/2] cpu_x86: let AMD guests drop bus-lock-detect instead of failing Date: Fri, 6 Nov 2026 15:53:00 +0100 Message-ID: <20261106145300.3953928-3-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261106145300.3953928-1-den@openvz.org> References: <20261026190654.791689-1-den@openvz.org> <20261106145300.3953928-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-MailFrom: den@openvz.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation Message-ID-Hash: VUDR34EZEAUWUT654CQ2JS27ONCN2YUR X-Message-ID-Hash: VUDR34EZEAUWUT654CQ2JS27ONCN2YUR X-Mailman-Approved-At: Mon, 09 Nov 2026 12:27:36 +0000 CC: den@openvz.org X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "Denis V. Lunev via Devel" Reply-To: "Denis V. Lunev" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1794227710502158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev Kernel commit 76ea438b4afc ("KVM: X86: Expose bus lock debug exception to guest") made KVM offer bus-lock-detect on every host that enumerates it, AMD Zen 5 included. Kernel commit 54950bfe2b69 ("KVM: SVM: Don't advertise Bus Lock Detect to guest if SVM support is missing"), marked for stable, stopped offering it on AMD. A host-model guest started on Zen 5 under an older kernel has bus-lock-detect in its live definition. On a destination with the newer kernel QEMU filters the feature out and the incoming migration fails: guest CPU doesn't match specification: missing features: bus-lock-detect Restoring a save image or reverting a snapshot fails the same way, so the guest cannot be moved to the new kernel without a restart. Dropping the bit in libvirt costs the guest nothing. Bus lock detection is enabled through DEBUGCTL, which SVM loads for the guest only with LBR virtualization active, and 54950bfe2b69 says the guest could not use the feature despite the CPUID bit. QEMU does not migrate DEBUGCTL, so the guest resumes with bus lock detection off. A Linux guest since kernel commit 408eb7417a92 ("x86/bus_lock: Add support for AMD") sets DEBUGCTL.BLD again only when it brings a CPU online; with LBR virtualization enabled, the default, kernels since 5ecdb48dd918 ("KVM: SVM: Treat DEBUGCTL[5:2] as reserved") answer that write with #GP, which Linux reports as an "unchecked MSR access error" warning and carries on, and older kernels ignore the bit. QEMU drops the bit either way; libvirt only decides whether the guest survives. Kernel commit 62ad461079e7 ("KVM: SVM: Add support for virtualizating Bus Lock Detect") lets KVM offer the feature on AMD again with LBR virtualization. A guest started there and moved to a host without it loses the bus lock #DB, which Linux uses only to warn about or throttle tasks that cause bus locks. Add bus-lock-detect next to spec-ctrl in the table of droppable features, for CPU models whose vendor is AMD: when the hypervisor dropped it, virCPUUpdateLive() disables it in the live definition and removes it from the features QEMU reports as filtered. Intel keeps failing: VMX has virtualized bus lock detection since 76ea438b4afc, so a missing bit there is a real loss. Signed-off-by: Denis V. Lunev --- src/cpu/cpu_x86.c | 21 +++++++ tests/cputest.c | 2 + ...e-i7-1365U-no-bus-lock-detect-disabled.xml | 4 ++ ...re-i7-1365U-no-bus-lock-detect-enabled.xml | 21 +++++++ ...Core-i7-1365U-no-bus-lock-detect-guest.xml | 61 +++++++++++++++++++ ...0X-16-Core-no-bus-lock-detect-disabled.xml | 4 ++ ...50X-16-Core-no-bus-lock-detect-enabled.xml | 14 +++++ ...9950X-16-Core-no-bus-lock-detect-guest.xml | 45 ++++++++++++++ ...-9950X-16-Core-no-bus-lock-detect-json.xml | 45 ++++++++++++++ 9 files changed, 217 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-loc= k-detect-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-loc= k-detect-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-loc= k-detect-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no= -bus-lock-detect-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no= -bus-lock-detect-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no= -bus-lock-detect-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no= -bus-lock-detect-json.xml diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 3e89d5ef0a..7f6d29b447 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -3170,6 +3170,26 @@ x86SpecCtrlDroppable(const virCPUDef *cpu G_GNUC_UNU= SED, } =20 =20 +/* + * KVM offered bus-lock-detect on AMD hosts until kernel commit + * 54950bfe2b69 although SVM never let the guest use it. + */ +static int +x86BusLockDetectDroppable(const virCPUDef *cpu, + virCPUx86Map *map, + const virCPUx86Data *enabled G_GNUC_UNUSED) +{ + virCPUx86Model *model; + + if (!cpu->model || + !(model =3D x86ModelFind(map, cpu->model)) || + !model->vendor) + return 0; + + return STREQ(model->vendor->name, "AMD"); +} + + static const struct { const char *name; int (*droppable)(const virCPUDef *cpu, @@ -3177,6 +3197,7 @@ static const struct { const virCPUx86Data *enabled); } x86DroppableFeatures[] =3D { { "spec-ctrl", x86SpecCtrlDroppable }, + { "bus-lock-detect", x86BusLockDetectDroppable }, }; =20 =20 diff --git a/tests/cputest.c b/tests/cputest.c index 35b426155e..6c15d71365 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1262,6 +1262,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-1270P", JSON_MODELS_REQUIRED); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-1365U", JSON_MODELS_REQUIRED); + DO_TEST_UPDATE_LIVE(VIR_ARCH_X86_64, "Core-i7-1365U-no-bus-lock-detect= ", -1); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600-xsaveopt", JSON_MODELS_RE= QUIRED); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3520M", JSON_NONE); @@ -1297,6 +1298,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-9-3900X-12-Core", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-9-9950X-16-Core", JSON_MODELS); + DO_TEST_UPDATE_LIVE(VIR_ARCH_X86_64, "Ryzen-9-9950X-16-Core-no-bus-loc= k-detect", 0); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-6731E", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-6788P", JSON_MODELS_REQUIRED); diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detec= t-disabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-d= etect-disabled.xml new file mode 100644 index 0000000000..e97a5ab0c5 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detect-disab= led.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detec= t-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-de= tect-enabled.xml new file mode 100644 index 0000000000..1f6363183c --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detect-enabl= ed.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detec= t-guest.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-dete= ct-guest.xml new file mode 100644 index 0000000000..268d5484a4 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-1365U-no-bus-lock-detect-guest= .xml @@ -0,0 +1,61 @@ + + SierraForest + Intel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lo= ck-detect-disabled.xml b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Co= re-no-bus-lock-detect-disabled.xml new file mode 100644 index 0000000000..e97a5ab0c5 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lock-dete= ct-disabled.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lo= ck-detect-enabled.xml b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Cor= e-no-bus-lock-detect-enabled.xml new file mode 100644 index 0000000000..281971e99f --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lock-dete= ct-enabled.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lo= ck-detect-guest.xml b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-= no-bus-lock-detect-guest.xml new file mode 100644 index 0000000000..174ac2293f --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lock-dete= ct-guest.xml @@ -0,0 +1,45 @@ + + EPYC-Turin + AMD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lo= ck-detect-json.xml b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-n= o-bus-lock-detect-json.xml new file mode 100644 index 0000000000..533b04903a --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Ryzen-9-9950X-16-Core-no-bus-lock-dete= ct-json.xml @@ -0,0 +1,45 @@ + + EPYC-Turin + AMD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --=20 2.53.0