From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8ED3134D3B9; Wed, 27 May 2026 23:47:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925640; cv=none; b=VptEjXRvGCnLhQBeusuGghDGre3cKlkHdbh5QITOtSmceIkCTUBcLGVrtq/DKIrC05XTs8x8Fpt+yQDOjNCsxPT2Gy1QaaP6PfRYMaaBWmYF5yOQE3YpHQxops0HoemWWC6jzhAkkLSvsIoQl+7lgT/isnTYL+GnmMmg9a/Ci1k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925640; c=relaxed/simple; bh=kiJB+hqQYj7xhnhJjwxYAUz132raL+ulTgPrrJKnIvQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l5MZUdGai5paQmVeZyCLLSGKjHtMjH0x4E1ITTC4gOT3hQj8AP0Ay0myOZe95lr8rfkAcETd6EHro6f4EaTUoGbQzDSYbkIF9SK+rSXiHDnOLRY5pA12RXTGIgiH4Uu+3lOvYdkUFglu62UmjOma/oqpNVqI37ArpL6AJc09IhU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aOyDbYGw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aOyDbYGw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D61F51F00ACA; Wed, 27 May 2026 23:47:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925639; bh=FyGd/1uAOo7TXsMQ15W37emnMrwKdTILk7667NP3Jy4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aOyDbYGwv/tKnAuFQJKMrkrGBJz8a61PfQ2fhvhrmsaluaVoaHf+CYSVwcVec3AHv JiiNa4SN5rbPctQNBRUzoxk1taR+PgaUujM5eVHafAIevTx3UevQyMhlWbtIbo55Bk mdMsesyTKB++XPvWD1A5oZnvue+cffkbrGjk24VW5DY/Ye9k+ADWIqpTTPcMcC5S8U HGfu5tfiUelQ895fFFV9jz8To/lFSbcURG02fN4cCB0ajdDI3vGb0VrAjvXSIVjxnM PoIcMkylSu/Zrrj7HhLVyKp2a7h1syC7dQSDnncu3c+gnBadALhEaskmnzKFIb3Z0p TVTmNG03WdpUA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 01/17] KVM: nSVM: Stop leaking single-stepping on VMRUN into L2 Date: Wed, 27 May 2026 23:46:55 +0000 Message-ID: <20260527234711.4175166-2-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" According to the APM, TF on VMRUN causes a #DB after VMRUN completes on the _host_ side. However, KVM injects a #DB in L2 context instead (or exits to userspace if KVM_GUESTDBG_SINGLESTEP is set) in kvm_skip_emulated_instruction(). Avoid single-step handling on VMRUN by open-coding the rest of kvm_skip_emulated_instruction() in nested_svm_vmrun(). This doesn't look pretty, but following changes will need to open-code kvm_pmu_instruction_retired() anyway, and will cleanup the code. This ignores TF on VMRUN instead of injecting a spurious exception into L2. Document this virtualization hole with a FIXME. Note that a failed VMRUN would have been correctly single-stepped, but now TF is always ignored for consistency and simplicity purposes. VMX does not support TF on a successful VMLAUNCH/VMRESUME, so it's unlikely that single-stepping VMRUN properly is important, especially if it's only for failed VMRUNs. Fixes: c8e16b78c614 ("x86: KVM: svm: eliminate hardcoded RIP advancement fr= om vmrun_interception()") Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 18 +++++++++++++++--- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/svm/svm.h | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 28ac5d5c990dd..01e3e6fa8bbb1 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -30,6 +30,7 @@ #include "lapic.h" #include "svm.h" #include "hyperv.h" +#include "pmu.h" =20 #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK =20 @@ -1145,11 +1146,22 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); =20 /* Advance RIP past VMRUN as part of the nested #VMEXIT. */ - return kvm_skip_emulated_instruction(vcpu); + if (!svm_skip_emulated_instruction(vcpu)) + return 0; + + kvm_pmu_instruction_retired(vcpu); + return 1; } =20 - /* At this point, VMRUN is guaranteed to not fault; advance RIP. */ - ret =3D kvm_skip_emulated_instruction(vcpu); + /* + * At this point, VMRUN is guaranteed to not fault; advance RIP. + * + * FIXME: If TF is set on VMRUN should inject a #DB (or handle guest + * debugging) right after #VMEXIT, right now it's just ignored. + */ + ret =3D svm_skip_emulated_instruction(vcpu); + if (ret) + kvm_pmu_instruction_retired(vcpu); =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index e74fcde6155ec..183e577802301 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -333,7 +333,7 @@ static int __svm_skip_emulated_instruction(struct kvm_v= cpu *vcpu, return 1; } =20 -static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu) +int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu) { return __svm_skip_emulated_instruction(vcpu, EMULTYPE_SKIP, true); } diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 2b6733dffd76f..e5d9984ef6320 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -832,6 +832,8 @@ static inline void svm_enable_intercept_for_msr(struct = kvm_vcpu *vcpu, svm_set_intercept_for_msr(vcpu, msr, type, true); } =20 +int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu); + /* nested.c */ =20 #define NESTED_EXIT_HOST 0 /* Exit handled on host level */ --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5180334F25C; Wed, 27 May 2026 23:47:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925641; cv=none; b=IwGKjjHyGTSvisRQV0j0TRn1tbwM5g5HOjMxVe2sQo/8MHbBOUivlqUOcSy+FCPhQUEqEQCkXsyrEWSJkxl3ptPhtyAuGuASjRs12ae+QMswVs/XZV8j78s06FPERjr9dZVu9gAQHgJR08qH6vJjdnVQ1ISXlpoZk2oyXkLLhgI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925641; c=relaxed/simple; bh=C9d8yBO9J4yCFc/5Ebpn1RJ2Ik8xbZ2fKHIem+1Jrfk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O1jkr1sqQ9z/P6l6ANadF1Kcg1OitCf1fZXi7PnydftA8L3FgRVuIz1+vLPdN0MHn0LaPEjVdurc7PRFPGEKdbWiie26aqHrFcd/2zA9rPYBT9kR0XjmdQ5CYVJ2FL0jULN0XKZGznxMXaBjTORG5Zl+vJeVTn/cM94PUko8xkM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kpH1tB9+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kpH1tB9+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8EAF51F00A3E; Wed, 27 May 2026 23:47:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925640; bh=maLHjx7aDGBVMG08GXms4oRWNwyzEpbFcX9pn3DcEuM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kpH1tB9+amOS97K1xAosJjekTsWqCCeaT5ajP4wbS8lWGZaywHOD0Jut8B4ir6V+q 0oGj6bLQymoBep4HeV2pyDPZNulOtwBPsc78UrhEJXjPwkRznhSsiDgpVcj29ZUuS7 WCDMVksZqvdBVTMOYEKnFLHBEv9FSl5T8hpasP+xYln8399kmsF9JaX7dKZqCnuI+C 9xhXvdx2XuoRCReYAS9mBoUJJSpJjRQe4uwPhIBpyBbg3Sks7CZr2x+QsSy/kdQdDY ObQW+9Bn5Zyzi55dLZSWNP48HZcmrrdPSrgPJevg3VC0FZ8ohQc2ddHLxDqcFmxKBS OO22sKbIFiacw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 02/17] KVM: nSVM: Bail early out of VMRUN emulation if advancing RIP fails Date: Wed, 27 May 2026 23:46:56 +0000 Message-ID: <20260527234711.4175166-3-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If svm_skip_emulation_instruction() fails, then RIP could not be advanced correctly (e.g. decode failure when NextRIP is not available). KVM will exit to userspace to handle the emulation failure, but only after stuffing the wrong RIP into vmcb01 and entering guest mode. Bail early and exit to userspace before committing any side-effects of emulating the VMRUN (e.g. entering guest mode). Fixes: c8e16b78c614 ("x86: KVM: svm: eliminate hardcoded RIP advancement fr= om vmrun_interception()") Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 01e3e6fa8bbb1..ddf18a6daf823 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1159,9 +1159,10 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) * FIXME: If TF is set on VMRUN should inject a #DB (or handle guest * debugging) right after #VMEXIT, right now it's just ignored. */ - ret =3D svm_skip_emulated_instruction(vcpu); - if (ret) - kvm_pmu_instruction_retired(vcpu); + if (!svm_skip_emulated_instruction(vcpu)) + return 0; + + kvm_pmu_instruction_retired(vcpu); =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1191,7 +1192,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_svm_vmexit(svm); } =20 - return ret; + return 1; } =20 /* Copy state save area fields which are handled by VMRUN */ --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E975B3B4E8F; Wed, 27 May 2026 23:47:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925642; cv=none; b=sp3KtL0It33NUQZfeVJoYixlnJW+uXDsSX4n9NBNEyZV1W+FFbTglRYBPtmJTugjVR/l4ccCDwdcZEy6GCMUIM6XlCkFC5cfPa+Y3dI2yATg3liVhpty6/bekwVDC2W4sMWMmPMU10VlyboLupmI0ttiU1H+gvFuKiRC/FjfMws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925642; c=relaxed/simple; bh=7+Tv4NBVSbknMRguQ3kWdxSF/aC1JK7bBli793XgeAw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qEXbrc+CjtJ66RyNXBlX/CpxnNr8gEnGl3V60i35X12Wqame+2IeQwRYxdx9tfnPvzZKpRGSWjllCK4d/d5aCjls8OBi27hkXNccmNzXj0D3X4gzNpqkWSBMoTHnNnothA/xbu8Q1LVeLC8pNXm5wxatkequICwsqcyKpZX3WEI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K2+uvpF6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="K2+uvpF6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 477191F00ACF; Wed, 27 May 2026 23:47:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925640; bh=saBqk30OK+NzxA4VKs1MZapGHjQQor0woe2RYxM3Ypw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=K2+uvpF6tWV3DXtSI/2ctukogJEe/XfmcMBaWtxwXFIFMi26WS+1bhnS+fklPAIdI LYrAMDn48v95LNwMrkgbKSUVCPkloxPBJ1AEv7jkM+YLjPUXK23ZpMbDtNECMJQCjH LFsyPCPhb2UCsy08VevkoEnIBISuWDeQJacCi4k72H8ODavdnI+3qJ/GTdfRDJlAq1 +Dq4OyQXF3B5cMuMic1Vb2UVl95OQrYsVtDsCR4lkFJ0oE3wKa3z5tFoo4zWmt0Qmk ETSV3DrUdiOaN6iXIL3Lb2E3X0ztFoe33+R7BOZ/y6h+Z7U1YuyDMsr95EcmT8PjTJ 5+WipdzZo3LAg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 03/17] KVM: nSVM: Unify RIP and PMU handling calls when emulating VMRUN Date: Wed, 27 May 2026 23:46:57 +0000 Message-ID: <20260527234711.4175166-4-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The code paths for advancing RIP and retiring the instruction for RIP are very similar whether or not caching vmcb12 succeeds. The only difference is handling mapping failures (i.e. EFAULT). Pull the mapping failure handling out and unify the calls to svm_skip_emulated_instruction() and kvm_pmu_instruction_retired(), but return immediately after if copying and caching vmcb12 failed. A nice side effect of this is that the FIXME comment is now above the only code path calling svm_skip_emulated_instruction(). Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index ddf18a6daf823..0063ccbd327bc 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1141,20 +1141,13 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) } =20 ret =3D nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa); - if (ret) { - if (ret =3D=3D -EFAULT) - return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); - - /* Advance RIP past VMRUN as part of the nested #VMEXIT. */ - if (!svm_skip_emulated_instruction(vcpu)) - return 0; - - kvm_pmu_instruction_retired(vcpu); - return 1; - } + if (ret =3D=3D -EFAULT) + return kvm_handle_memory_failure(vcpu, X86EMUL_IO_NEEDED, NULL); =20 /* - * At this point, VMRUN is guaranteed to not fault; advance RIP. + * At this point, VMRUN is guaranteed to not fault; advance RIP. If + * caching vmcb12 failed for other reasons, return immediately afterward + * as a nested #VMEXIT was already set up. * * FIXME: If TF is set on VMRUN should inject a #DB (or handle guest * debugging) right after #VMEXIT, right now it's just ignored. @@ -1164,6 +1157,9 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) =20 kvm_pmu_instruction_retired(vcpu); =20 + if (ret) + return 1; + /* * Since vmcb01 is not in use, we can use it to store some of the L1 * state. --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C98B33D16F5; Wed, 27 May 2026 23:47:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925643; cv=none; b=FteetzO81qIYIaBAWEdYw6h/qKhv3uF3EHPwPRPAbWfVF75AyhEPB8WAWLSX4FQhOIcNLQCQnf9hN3rNotd5kZjXXj9t9s/Tw2fjeY+JO/LrTq/N7MndU4nsqS5lZDYZulKVydtwi8/IogQRxImQBbJ+JXVSWlWW81UehDuq8TY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925643; c=relaxed/simple; bh=G/MiT6wcqobLrSddK4gBSbHHxNnlmJDSsQGVQLMbiZc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KAeGleFq/opjsAry1ZbKj1kAHEMLKk7gtnx+pU43OAAsOTv+3/MazDVL1u4Lplr7S9BPG2dD8zBuLXcrrB82NNzdE88sExe4vdIkXsKqDISdWzjNYZivNZkPZTy9XwWiNGV5qEhLqmKPzhMkiSaKc8j8U786VPRfoYo0lF0mOSQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EM6Bcuek; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EM6Bcuek" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 006DA1F00ACA; Wed, 27 May 2026 23:47:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925641; bh=wRywIKLjaYBvGlLXm2ij6Kp5db8CtObLdxRCXVphEG4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=EM6BcuekQV9D2dWJru8TMMHyT+4yLm3ksJOSsCdFodM6krxvGb2cqPpcti2sy/Gwd KRunu9SuPVuE4vUeXQ7QJ7L34iMglp84plFnASptpjopywbz6NlRQguSyH1VGqRdV0 ZwEyNHb7gz1LfSjrpFBPLao7H3N+6cEPHfz7H4nNz9vN3Wj+QiMcs0k1ZdjqnNMmXB 7xWqiCVCk9QVFZyaQ4FA9ue6SmQBx2hq7JDeMa06laUETHcicFaYiAEPN86A0IVq26 1doOYbkmsQIhPmsDXZXLA8oDYquVrXQbhgTdrL4WTxvjHzBaIQfdQhK0DT2jYyDXvo ReJVNbusDRDHw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 04/17] KVM: nSVM: Move VMRUN instruction retirement after entering guest mode Date: Wed, 27 May 2026 23:46:58 +0000 Message-ID: <20260527234711.4175166-5-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A successful VMRUN retires in guest mode and should be counted by the PMU as a guest instruction. Move the call to kvm_pmu_instruction_retired() after potentially entering guest mode, such that VMRUN is counted correctly. The PMU event will be matched against L2's CPL, but otherwise this does not change the behavior in terms of guest vs. host, because KVM does not virtualize Host-Only/Guest-Only PMC controls yet, so all instructions are counted regardless of the vCPU's host/guest state. But this change is needed for the incoming support for Host-Only/Guest-Only controls to count VMRUN correctly. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 0063ccbd327bc..7456cacde296c 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1155,10 +1155,8 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) if (!svm_skip_emulated_instruction(vcpu)) return 0; =20 - kvm_pmu_instruction_retired(vcpu); - if (ret) - return 1; + goto insn_retired; =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1188,6 +1186,12 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) nested_svm_vmexit(svm); } =20 +insn_retired: + /* + * A successful VMRUN is counted by the PMU in guest mode, so only + * retire the instruction after potentially entering guest mode. + */ + kvm_pmu_instruction_retired(vcpu); return 1; } =20 --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 56F263D25CC; Wed, 27 May 2026 23:47:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925643; cv=none; b=lPM773zSAe4yDzLvHaWsUOKNbdm+qrDvRyygfAIMK31D0SAxnajkXuW8iq4NAbD5EkfKQSBCfsBEVk/tnT4h0tWF1wXIuYJxEl9VK2R24S17fG8ML1SoufRXpZXpNn6n9R9njrzvG4QYPE6VNGPIFLJrFHPGhsMWMaO1eQHshA8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925643; c=relaxed/simple; bh=fKy5YCuj1HhVHXrB6k9r2l+HIsSNpTjnXLIix3FgnsM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WkGlLV0LRhBNAMETv6IDQn7snLM2nfNntNycDJVPyFV/VYhj2Ni3ETwxsLXVnPEK8dxqS8125Ph6YIbaRjU2qVPzVZ8orq5IN3qzgCJbifSXDXCfhXDKuLQXc2nh/QCDRMimuMKBG3JEBjr6a9ls58RpCVeyaj3Ag2uPKcr/pgE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FiPaT3qT; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FiPaT3qT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ACBC71F000E9; Wed, 27 May 2026 23:47:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925642; bh=gGILxze6ukmeEu8hVvjw9FiDyUkak6Xcqt2eg77NxBk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FiPaT3qTz5biIsHXCi5rECym4Ses2KamO26CiVFP6AWOP/FFLslSqp4PwE7wK7f/l h8D2z1pFF7oGoM0oINUY4nyqVSyLoHUtzfqmJFygVAdOLpdvq1+V3Mklw5Ic+QkUg8 PQJmuIMKTjU+bnhlE9K15KZzMZqzD7leJB5sMcp3BDHCwGhJC0TLioYl3NF773n4i/ tVGVUZkM4lC6kzY9mwLYtwMGR1TyY2/q9+ZrwwYMvO3wXwtuO4KELJzbS+l945jyOL IqjVZv+nTV9A/2/FjCQTYeLVVbpWsfjL9jDiji0EQ6fE5EIWRJ1IkKX6zRkn+0mPLz 2xp6y/uagrPBA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 05/17] KVM: x86: Move enable_pmu/enable_mediated_pmu to pmu.h and pmu.c Date: Wed, 27 May 2026 23:46:59 +0000 Message-ID: <20260527234711.4175166-6-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The declaration and definition of enable_pmu/enable_mediated_pmu semantically belongs in pmu.h and pmu.c, and more importantly, pmu.h uses enable_mediated_pmu and relies on the caller including x86.h. There is already precedence for other module params defined outside of x86.c, so move enable_pmu/enable_mediated_pmu to pmu.c. No functional change intended. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 10 ++++++++++ arch/x86/kvm/pmu.h | 3 +++ arch/x86/kvm/x86.c | 9 --------- arch/x86/kvm/x86.h | 3 --- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index e218352e34231..d6ac3c55fce55 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "x86.h" @@ -33,6 +34,15 @@ static struct x86_pmu_capability __read_mostly kvm_host_= pmu; struct x86_pmu_capability __read_mostly kvm_pmu_cap; EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_pmu_cap); =20 +/* Enable/disable PMU virtualization */ +bool __read_mostly enable_pmu =3D true; +EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_pmu); +module_param(enable_pmu, bool, 0444); + +/* Enable/disabled mediated PMU virtualization. */ +bool __read_mostly enable_mediated_pmu; +EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_mediated_pmu); + struct kvm_pmu_emulated_event_selectors { u64 INSTRUCTIONS_RETIRED; u64 BRANCH_INSTRUCTIONS_RETIRED; diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 0925246731cb1..b1f2418e960ac 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -53,6 +53,9 @@ struct kvm_pmu_ops { const u32 MSR_STRIDE; }; =20 +extern bool enable_pmu; +extern bool enable_mediated_pmu; + void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops); =20 void kvm_handle_guest_mediated_pmi(void); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1578c0ecbbd1b..cbe740dca5d21 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -181,15 +181,6 @@ module_param(force_emulation_prefix, int, 0644); int __read_mostly pi_inject_timer =3D -1; module_param(pi_inject_timer, bint, 0644); =20 -/* Enable/disable PMU virtualization */ -bool __read_mostly enable_pmu =3D true; -EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_pmu); -module_param(enable_pmu, bool, 0444); - -/* Enable/disabled mediated PMU virtualization. */ -bool __read_mostly enable_mediated_pmu; -EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_mediated_pmu); - bool __read_mostly eager_page_split =3D true; module_param(eager_page_split, bool, 0644); =20 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 38a905fa86de2..30a69effc81e2 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -490,9 +490,6 @@ fastpath_t handle_fastpath_invd(struct kvm_vcpu *vcpu); extern struct kvm_caps kvm_caps; extern struct kvm_host_values kvm_host; =20 -extern bool enable_pmu; -extern bool enable_mediated_pmu; - void kvm_setup_xss_caps(void); =20 /* --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DE703D811F; Wed, 27 May 2026 23:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925645; cv=none; b=pJXmqmfKzvBZewQOXRcVvHNSf7iFj+kH9gculSmyTtcC78XS4rOGza50AqONH8IpWbJdMtfe28qIFFR/HTsZ7YproYQ2/fNPkj1ORo7x2qKPnBZUavvlzQ+FMyRo9GYbWcoKo950SEGfwOWTbzL8RHm179n1Rnj+GiLQ6leA3hg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925645; c=relaxed/simple; bh=RH39PNn/B2K1ju7y7kb3Q9hqqhSA+ENKgCm8lSkjoDc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AZhBPjqjifYLJZqYcAJPXldj/gA84tctSjnByDA28EXm59vnp9/44VLmctl+w+AiGDZag9uTssMcdH0aoxlgsLVBOP5dFLf1v7/I13Xk7x260QaqDGSMMloaEiVqUNRl5M+d695yjmRrs3rPBdo+imcVyoAFdfhYEQ86oFXl8AQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SklgLZYh; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SklgLZYh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 65E7F1F00A3D; Wed, 27 May 2026 23:47:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925643; bh=Q3xofZqOzvu5Onur3sOZTMIEKlsNXZMa7Z/7OwCz1yM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SklgLZYh+Phi3oRi8jAtnZb88ZB3ZoukK8PiG5i+nvX/9z90vkE0eVip1Yb5KokXa iJG7lJyEHWoq4x0ECRXUvkOidmeHIpgjpaHjZUYVB/nHfg0z7QYxDIVDhvPyH2Y/OT YiX7yKiKrzhiBs6wT7/F1hZNgi3falAcR+039wqXlf1duHBK9SQONS2GjAAdgandT7 ZKDCs29/x1yrkQ/L5J+2+XDvEMMmXXUwKtCQ8ww1vQ6TYayft1YbSb38kQCAiC0Btf Xok0e+p3j81Im4bwcOVEEiuV5R6Uw0GJzghnbM78WP0w9IJkBinyjTv/Et0locxJYh V4vgYWIptN2Gw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 06/17] KVM: x86/pmu: Rename reprogram_counters() to clarify usage Date: Wed, 27 May 2026 23:47:00 +0000 Message-ID: <20260527234711.4175166-7-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rename reprogram_counters() to kvm_pmu_request_counters_reprogram() clarifying that it is more similar to kvm_pmu_request_counter_reprogram(), and less similar to reprogram_counter(). The kvm_pmu_* prefix is also appropriate as the function is exposed in the header. Opportunistically rename the argument from 'diff' to 'counters'. No functional change intended. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 2 +- arch/x86/kvm/pmu.h | 7 ++++--- arch/x86/kvm/vmx/pmu_intel.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index d6ac3c55fce55..afbc731e72174 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -889,7 +889,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_d= ata *msr_info) if (pmu->global_ctrl !=3D data) { diff =3D pmu->global_ctrl ^ data; pmu->global_ctrl =3D data; - reprogram_counters(pmu, diff); + kvm_pmu_request_counters_reprogram(pmu, diff); } /* * Unconditionally forward writes to vendor code, i.e. to the diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index b1f2418e960ac..f8286067722b0 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -210,14 +210,15 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) kvm_make_request(KVM_REQ_PMU, pmc->vcpu); } =20 -static inline void reprogram_counters(struct kvm_pmu *pmu, u64 diff) +static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, + u64 counters) { int bit; =20 - if (!diff) + if (!counters) return; =20 - for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX) + for_each_set_bit(bit, (unsigned long *)&counters, X86_PMC_IDX_MAX) set_bit(bit, pmu->reprogram_pmi); kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); } diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 27eb76e6b6a03..9bd77843d8da2 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -391,7 +391,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, str= uct msr_data *msr_info) if (pmu->pebs_enable !=3D data) { diff =3D pmu->pebs_enable ^ data; pmu->pebs_enable =3D data; - reprogram_counters(pmu, diff); + kvm_pmu_request_counters_reprogram(pmu, diff); } break; case MSR_IA32_DS_AREA: --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8F703D6487; Wed, 27 May 2026 23:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925644; cv=none; b=TRwuaywgwzzRH9DB+PumsxIa2nhREm+wb6aiJskAoQV1ZTW1w85WyjVPxpl7fL2auH0Oi9mL9JTkoJ0ymnE1vSjjoJm0vp203ylINirE7rH+xU2if5goG9kyiw17phmKR9GeTChImmQPwdPN4PlyP7/s3MwBCaCRhWnvmukxkcA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925644; c=relaxed/simple; bh=ySStj5wTCcL5x3zBqamnC6pC0mLKKke+qmjS5ARZM+M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=urjZTkqBENDhcBt9intzdL0rPTMMDZybnTVVSGmZKyeK7TUcnVmN/Nx0pwLSK2AX6T0+RdmQb/pp2B82u1LdlCNYAkb7dg3wELTED92FNNnLiSintcWu6pQBzXwhiB2+RS0XhWhMInOBVSteRfzpU683Zd32JwZqYHlzYwAxaLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SnqYEMG7; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SnqYEMG7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E0211F00ACA; Wed, 27 May 2026 23:47:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925643; bh=/4xqYTAetiwpn4T1YrIUcTJoj2l0gLO6N9btuBFDewo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SnqYEMG7g8wE3UZjMPzR4O6sLTT/HZVrX8R0GhYU3Vnq9yEqX0F3qAkH16sFAk3tz OrgSagZ6hAIbcGxQQqeZjF69xgHYNW8Q7ChcNjqxjLTsCELPaXEZtgiwSfN8P5zUT9 rY/ip5NXghapEH13Vl+PoZohr+nomGh3sgM8HyvgFuhFoQJtOYEPszzH/hpFLGIXf2 scWVLda+lwY4XKvnoSTfu2ZpjltoyerbL2cyO0vseaefG9yKL+GNdB5UwR5eXiFspq 5k4xHIIrqMRa3pzgKNgDgAgr7MQyNNzISTkQdgloyYwiFyyl9p9IRgUpYRrUhqld4t yCX3gw+Y5cZuA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 07/17] KVM: x86/pmu: Do a single atomic OR when reprogramming counters Date: Wed, 27 May 2026 23:47:01 +0000 Message-ID: <20260527234711.4175166-8-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Do a single atomic OR using the atomic overlay of reprogram_pmi bitmask, instead of one atomic set_bit() call per counter. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index f8286067722b0..0e99022168a85 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -213,13 +213,10 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, u64 counters) { - int bit; - if (!counters) return; =20 - for_each_set_bit(bit, (unsigned long *)&counters, X86_PMC_IDX_MAX) - set_bit(bit, pmu->reprogram_pmi); + atomic64_or(counters, &pmu->__reprogram_pmi); kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); } =20 --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 729653DA5B2; Wed, 27 May 2026 23:47:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925645; cv=none; b=lfJoKJSnLjs+lYNNDfTRCgs+LxCZdye5UE07yTILuYqloCehx0J4sqCoS6SHaVvVzQTedB8vgaMZDMudW854w9T59M36XcgE4gA+OWMaGpNdQbOKp7lQic3Lf9Ygmq7q/ShDqq1a+SJjnQ2j8qlW8Rz5m7PGh7Nrwdx8uUZ+Sdk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925645; c=relaxed/simple; bh=/FJ/pHWRgLiuSDRymygjv3hpBEpE82SbBkGfJgNq6pQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DPi3MGaIPwrfWCVMzlIqbsf4A9prDZH+5cVj8JETqUzuG1RQIV+Eesw65dfW/X58Y3sWW4NXL7bYs2dxhGy3jd9WYS3UE6MWqfUe6vyrH3syiOXvFa9ZAaX8dxiCRgtn79L42wIi5jsFfS8r/YRorPPGTvplu/VbR4kJS9wLSTc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jZbn4nU1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jZbn4nU1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA65F1F000E9; Wed, 27 May 2026 23:47:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925644; bh=jwzvNaDhgxzGSMGoezFqYQOSgXb6nd5oUPgLydEYQFA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=jZbn4nU1G6XdC/6AERLGYW4R5i1ELcIYVPPxDB5dDTH6vDFsHoYEdwZAjqSExJdZs Kucae8vJgbsd63T9Q3NCrwG7FErZvkriy1OaEzvnXZc6w+wRHB7dFCUvgRkY61Esau NNBD10oK9HpGWm/snq+XtbQn/MlwRq215dTim35gi/kHPT/5EBCysuFae4DZn+5mHi 8YUlQNk0AF9G7cwybe02P2K7QEhO/4aoxC6n2xV9gOk6IOsfUC9ob4iwUC8EzfYFkx hx8jor3aP7OTKPXaC9wzJXOoLO21BSeZDoSIPSZyD0RWQA+mjYYIc06vtED4TI7EEa glk1kwpICSE1w== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 08/17] KVM: x86/pmu: Check mediated PMU counter enablement before event filters Date: Wed, 27 May 2026 23:47:02 +0000 Message-ID: <20260527234711.4175166-9-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If the guest disables the counter (by clearing ARCH_PERFMON_EVENTSEL_ENABLE), KVM still performs the PMU filter lookup, even though it doesn't end up changing eventsel_hw. Check if the counter is enabled by the guest before doing the potentially expensive PMU filter lookup. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index afbc731e72174..67dbbd4c73036 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -532,7 +532,7 @@ static bool pmc_is_event_allowed(struct kvm_pmc *pmc) =20 static void kvm_mediated_pmu_refresh_event_filter(struct kvm_pmc *pmc) { - bool allowed =3D pmc_is_event_allowed(pmc); + bool allowed =3D pmc_is_locally_enabled(pmc) && pmc_is_event_allowed(pmc); struct kvm_pmu *pmu =3D pmc_to_pmu(pmc); =20 if (pmc_is_gp(pmc)) { --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2BAC93DD531; Wed, 27 May 2026 23:47:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925646; cv=none; b=pyi5/WNC1Vg4sQKKPVgMn9LiS6Rfw5/SqTF0L0K3mCUfcuhQgEMyUKWEdMpXgUEfpuVw341sbL5uEsc/x1pd384Q5avX36JpwIVuKoRDSvYUtyGulop64XliZw93B26jDhShqlGOPnaK32v54+TUQJ1nz2lCQ+QIQjw6mxVCoy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925646; c=relaxed/simple; bh=wfc7o0YVNYcCd4DlwXP/cWzxBWndg/FDvjk9nEW1Wuc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kZl134uEbVzP57pK6rPB9fxqcBBfh935lReRnFELlSOsRHCaKzctpiGcZ5EjTA5DMANHgPsQyeqq2XyLNc61JIEbti++Wf331c/53zuxAj7pbGVE7QY/yh9FtCyfkEuOdATlaskgfMgrGmaqvQIFTZTlC+OgZ7o1phUcZteri8M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Qc1UGngZ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Qc1UGngZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 842021F00A3E; Wed, 27 May 2026 23:47:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925645; bh=MB81YlG2FDhoDL/Ufj59rhXsq8NtjHGVGEmFXI3z9pk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Qc1UGngZOAG0dAvkUwPSVSe1CXidaFPR5GFgJq+JuQ20ruq9HLZQkyWoVPUUIBHhd SgEcMtPIjPnNLlSjMGftwPktaBYDxawgvhlUEQv4xAOX2VOU1+Pom2iTq8DGZ4pPpA nD1LxKfwG8PDvLSc9hz9Dxw9HBze5D8iJAJY13ZmdjUKr4ilwsA5ynV7RSl8ATfVbV 9EsoZIXmhBdvjrre9pPP/Y2RUcbgQzU1wXKyBLurqA5Puhj5CdCvl7c/HOMcUXI5kk SbBT1hmILJz5BNWuvdOcGTxx+wTTdJ/P9jhALoFIvQrpd0Ng2XmWcm960EblIOPurQ nkUanF05xCeTg== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 09/17] KVM: x86/pmu: Add support for KVM_X86_PMU_OP_OPTIONAL_RET0 Date: Wed, 27 May 2026 23:47:03 +0000 Message-ID: <20260527234711.4175166-10-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add definitions for KVM_X86_PMU_OP_OPTIONAL_RET0() to resolve to __static_call_return0, similar to KVM_X86_OP_OPTIONAL_RET0(). Move the definition of kvm_pmu_call() to pmu.h, and add declarations for the static PMU calls in the header to allow making callbacks from the header in following changes. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm-x86-pmu-ops.h | 4 +++- arch/x86/include/asm/kvm_host.h | 1 - arch/x86/kvm/pmu.c | 4 ++++ arch/x86/kvm/pmu.h | 8 ++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/= kvm-x86-pmu-ops.h index d5452b3433b7d..0616243c84cf9 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #if !defined(KVM_X86_PMU_OP) || \ - !defined(KVM_X86_PMU_OP_OPTIONAL) + !defined(KVM_X86_PMU_OP_OPTIONAL) || \ + !defined(KVM_X86_PMU_OP_OPTIONAL_RET0) #error Missing one or more KVM_X86_PMU_OP #defines #else =20 @@ -31,3 +32,4 @@ KVM_X86_PMU_OP(mediated_put) =20 #undef KVM_X86_PMU_OP #undef KVM_X86_PMU_OP_OPTIONAL +#undef KVM_X86_PMU_OP_OPTIONAL_RET0 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index d72051150bac9..0f3cbf9fc1ae1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -2068,7 +2068,6 @@ extern bool __read_mostly enable_device_posted_irqs; extern struct kvm_x86_ops kvm_x86_ops; =20 #define kvm_x86_call(func) static_call(kvm_x86_##func) -#define kvm_pmu_call(func) static_call(kvm_x86_pmu_##func) =20 #define KVM_X86_OP(func) \ DECLARE_STATIC_CALL(kvm_x86_##func, *(((struct kvm_x86_ops *)0)->func)); diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 67dbbd4c73036..9b7e39610be22 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -98,6 +98,7 @@ static struct kvm_pmu_ops kvm_pmu_ops __read_mostly; DEFINE_STATIC_CALL_NULL(kvm_x86_pmu_##func, \ *(((struct kvm_pmu_ops *)0)->func)); #define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP #include =20 void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops) @@ -109,6 +110,9 @@ void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_o= ps) #define KVM_X86_PMU_OP(func) \ WARN_ON(!kvm_pmu_ops.func); __KVM_X86_PMU_OP(func) #define KVM_X86_PMU_OP_OPTIONAL __KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0(func) \ + static_call_update(kvm_x86_pmu_##func, (void *)kvm_pmu_ops.func ? : \ + (void *)__static_call_return0); #include #undef __KVM_X86_PMU_OP } diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 0e99022168a85..a062f0bc3dbb1 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -53,6 +53,14 @@ struct kvm_pmu_ops { const u32 MSR_STRIDE; }; =20 +#define kvm_pmu_call(func) static_call(kvm_x86_pmu_##func) + +#define KVM_X86_PMU_OP(func) \ + DECLARE_STATIC_CALL(kvm_x86_pmu_##func, *(((struct kvm_pmu_ops *)0)->func= )); +#define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP +#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP +#include + extern bool enable_pmu; extern bool enable_mediated_pmu; =20 --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D71E33DEAC6; Wed, 27 May 2026 23:47:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925647; cv=none; b=oKXrBXnZhaPwA0JpEwSuBvQYJJpl6TexrHgCXd2XehYudwjdBaZzxOQkv6FvBoaEfW2UNSMFTm1ex8AmQcHo+1erSyqfnsgFORFNw/gwZOGSJ1agi7uRYzPWBP/p977aBc6xU5s92eAxBQizXTy8Eu1v9vQR7nof3cmeHdfhacI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925647; c=relaxed/simple; bh=JoMlUFmX74jbQ64/XP+QU4/uNTvzkHL/jAskHT1N/S8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pookPEWSvZ9dm3+uYtXdMEMznJYbyRxn5oFulxyUw2eEHn9IOvpf4z6PWNldTiLPoC3FpBT6yVzy6ztrdHLh1kVKglbESch/BaU3foYaeNRN4LwLgZDpRVkZ5UoWgEeHDljCtIo3FA8Q7kWjVAZF50pYFYvwtYrtRSRqi1I4ABM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g32tugSV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g32tugSV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3CBA01F00A3F; Wed, 27 May 2026 23:47:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925645; bh=GMF37vL88d77+IcP6BqJ3vXPZdpI8CTUZdelKUkc8zE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=g32tugSVz2UJbYc4khgM5F2r95hfr+v3dkVSkZrqf5xiLJU1kRlwuwHiYir0pR4Sa Pc860p1q1GZPqvO+0h5LXSUaSbFdSu2hmt4RwJW41/AtwwhM5Z/kcIuxJDn+htUNDg k6muE5HA5mZUgtwiV76O3aaDiudv1P/Y2x3jx1adMoeJy4Gu4P7NLMvIDfuhC/27XO iNYFsB33YLTTI7pNvnIDtpJf0Ay51qI3X3m7esWfRwcfAA7ESDwPf3J+4SxRYP5HZR HbjCbVadpxn5VRRPvwxHzGu2NCxnswI4blkMRqLzWwVTxxbmumntVA/nun6OxkHmy3 UxXDMteMKLYyw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 10/17] KVM: x86/pmu: Disable counters based on Host-Only/Guest-Only bits in SVM Date: Wed, 27 May 2026 23:47:04 +0000 Message-ID: <20260527234711.4175166-11-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce an optional per-vendor PMU callback for checking if a counter is disabled in the current mode, and register a callback on AMD to disable a counter based on the vCPU's setting of Host-Only or Guest-Only EVENT_SELECT bits with the mediated PMU. If EFER.SVME is set, all events are counted if both bits are set or cleared. If only one bit is set, the counter is disabled if the vCPU context does not match the set bit. If EFER.SVME is cleared, the counter is disabled if any of the bits is set, otherwise all events are counted. Note that a Linux guest correctly handles this and clears Host-Only when EFER.SVME is cleared, see commit 1018faa6cf23 ("perf/x86/kvm: Fix Host-Only/Guest-Only counting with SVM disabled"). The callback is made from pmc_is_locally_enabled(), which is used for the mediated PMU when updating eventsel_hw in kvm_mediated_pmu_refresh_eventsel_hw(), as well as when checking what PMCs count instructions/branches for emulation in kvm_pmu_recalc_pmc_emulation(). Host-Only and Guest-Only bits are currently reserved, so this change is a noop, but the bits will be allowed with mediated PMU in a following change when fully supported. Originally-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm-x86-pmu-ops.h | 1 + arch/x86/include/asm/perf_event.h | 2 ++ arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 4 +++- arch/x86/kvm/svm/pmu.c | 32 ++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/= kvm-x86-pmu-ops.h index 0616243c84cf9..4a223c2793e3f 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -24,6 +24,7 @@ KVM_X86_PMU_OP(init) KVM_X86_PMU_OP_OPTIONAL(reset) KVM_X86_PMU_OP_OPTIONAL(deliver_pmi) KVM_X86_PMU_OP_OPTIONAL(cleanup) +KVM_X86_PMU_OP_OPTIONAL_RET0(pmc_is_disabled_in_current_mode) =20 KVM_X86_PMU_OP_OPTIONAL(write_global_ctrl) KVM_X86_PMU_OP(mediated_load) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_= event.h index 752cb319d5eab..1eb13673e889f 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -60,6 +60,8 @@ #define AMD64_EVENTSEL_INT_CORE_ENABLE (1ULL << 36) #define AMD64_EVENTSEL_GUESTONLY (1ULL << 40) #define AMD64_EVENTSEL_HOSTONLY (1ULL << 41) +#define AMD64_EVENTSEL_HOST_GUEST_MASK \ + (AMD64_EVENTSEL_HOSTONLY | AMD64_EVENTSEL_GUESTONLY) =20 #define AMD64_EVENTSEL_INT_CORE_SEL_SHIFT 37 #define AMD64_EVENTSEL_INT_CORE_SEL_MASK \ diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 9b7e39610be22..8159b07e9bc20 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -100,6 +100,7 @@ static struct kvm_pmu_ops kvm_pmu_ops __read_mostly; #define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP #define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP #include +EXPORT_STATIC_CALL_GPL(kvm_x86_pmu_pmc_is_disabled_in_current_mode); =20 void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops) { diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index a062f0bc3dbb1..cc7f55d4a78b4 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -36,6 +36,7 @@ struct kvm_pmu_ops { void (*reset)(struct kvm_vcpu *vcpu); void (*deliver_pmi)(struct kvm_vcpu *vcpu); void (*cleanup)(struct kvm_vcpu *vcpu); + bool (*pmc_is_disabled_in_current_mode)(struct kvm_pmc *pmc); =20 bool (*is_mediated_pmu_supported)(struct x86_pmu_capability *host_pmu); void (*mediated_load)(struct kvm_vcpu *vcpu); @@ -201,7 +202,8 @@ static inline bool pmc_is_locally_enabled(struct kvm_pm= c *pmc) pmc->idx - KVM_FIXED_PMC_BASE_IDX) & (INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER); =20 - return pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE; + return (pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) && + !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); } =20 extern struct x86_pmu_capability kvm_pmu_cap; diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 7aa298eeb0721..41ee6532290e9 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -260,6 +260,37 @@ static void amd_mediated_pmu_put(struct kvm_vcpu *vcpu) wrmsrq(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, pmu->global_status); } =20 +static bool amd_pmc_is_disabled_in_current_mode(struct kvm_pmc *pmc) +{ + struct kvm_vcpu *vcpu =3D pmc->vcpu; + u64 host_guest_bits; + + if (!kvm_vcpu_has_mediated_pmu(vcpu)) + return false; + + /* Common code is supposed to check the common enable bit */ + if (WARN_ON_ONCE(!(pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE))) + return false; + + /* If both bits are cleared, the counter is always enabled */ + host_guest_bits =3D pmc->eventsel & AMD64_EVENTSEL_HOST_GUEST_MASK; + if (!host_guest_bits) + return false; + + /* If EFER.SVME=3D0 and either bit is set, the counter is disabled */ + if (!(vcpu->arch.efer & EFER_SVME)) + return true; + + /* + * If EFER.SVME=3D1, the counter is disabled iff only one of the bits is + * set AND the set bit doesn't match the vCPU mode. + */ + if (host_guest_bits =3D=3D AMD64_EVENTSEL_HOST_GUEST_MASK) + return false; + + return !!(host_guest_bits & AMD64_EVENTSEL_GUESTONLY) !=3D is_guest_mode(= vcpu); +} + struct kvm_pmu_ops amd_pmu_ops __initdata =3D { .rdpmc_ecx_to_pmc =3D amd_rdpmc_ecx_to_pmc, .msr_idx_to_pmc =3D amd_msr_idx_to_pmc, @@ -269,6 +300,7 @@ struct kvm_pmu_ops amd_pmu_ops __initdata =3D { .set_msr =3D amd_pmu_set_msr, .refresh =3D amd_pmu_refresh, .init =3D amd_pmu_init, + .pmc_is_disabled_in_current_mode =3D amd_pmc_is_disabled_in_current_mode, =20 .is_mediated_pmu_supported =3D amd_pmu_is_mediated_pmu_supported, .mediated_load =3D amd_mediated_pmu_load, --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EC7F3DFC94; Wed, 27 May 2026 23:47:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925647; cv=none; b=fAGSEuFvy8fzArQbvxqIA3cGBKI2u3tpDAm8Mkd6l36KP3f6FBCB2S7Z4uKyqdzvG5NP9thmlw0BY8Og//FakQKbVfEt7BlZV/dJsjE+lTXEgv4iyjxN+0lg46TsAWHGzJx44zZPajLRqWCNeQaS4UXLiVOxh+En7haBsV1GTLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925647; c=relaxed/simple; bh=1OjvkToNiF7PIOdJwlONk0WyJNtFLGgXSS4wYXS2+Ds=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=avMllXdoYI9zuMEYdILrwx2RmGFvRLLHDr2H0/tgIMOotg7hqeXiLgxGlV1FqZtCGqfioNF5cDWuCig2WBZxCBB8F3XII2RGRroMHnJiuYGd9kZiMIpc8zhsMe/NUsstcz5Uz1sWTWnrgM1V31hBpHqhz1gwTA6a2Ro5wB6EuUs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MszNCFk7; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MszNCFk7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E884F1F000E9; Wed, 27 May 2026 23:47:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925646; bh=zIGTWLcUYHa8BBkPNoQV8lYXGIV+Jsa5WbC4uAOIHik=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=MszNCFk7zliXmge1CJbZmFYVg3RkpyNAnCWJbFtnVPOXn9fn+QbsQNqOK/eZ88R6L gx+NfVQ96rNUuefgSfL5uvxVQgWw82Tew0/xZhi9q1bS3fb9AthQpiA037orE2Qia2 LqdSfy0L/dTKlgFndDc0sBpleL7KfXa9P1RTNVNgWaXPW+lNimGnYwBz7MqWNzRiLG tFIcpYqNWJv+R1VerMDIkph3rnBvJc2y56RNgp1C2CjndJj315JU717WwadN48V7UE hDkyJkD5oBHeubnRAEsxNzRx4GKYoj9Bh1PyHArs/CeJDz2y6PgOAbUJBsIx/4Mbc4 L8vzZy6xhwwVQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 11/17] KVM: x86/pmu: Track mediated PMU counters with mode-specific enables Date: Wed, 27 May 2026 23:47:05 +0000 Message-ID: <20260527234711.4175166-12-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Instead of always checking of a counter needs to be disabled for mode-specific reasons (e.g. Host-Only/Guest-Only bits in SVM), add a bitmap to track such counters. Set the bit for counters using either Host-Only or Guest-Only bits in EVENTSEL on SVM. This bitmap will also be reused in following changes to selectively apply changes to such counters. Signed-off-by: Yosry Ahmed --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 9 +++++++-- arch/x86/kvm/svm/pmu.c | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 0f3cbf9fc1ae1..32a413182a751 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -615,6 +615,8 @@ struct kvm_pmu { DECLARE_BITMAP(pmc_counting_instructions, X86_PMC_IDX_MAX); DECLARE_BITMAP(pmc_counting_branches, X86_PMC_IDX_MAX); =20 + DECLARE_BITMAP(pmc_has_mode_specific_enables, X86_PMC_IDX_MAX); + u64 ds_area; u64 pebs_enable; u64 pebs_enable_rsvd; diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 8159b07e9bc20..84c834ad2cd47 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -936,6 +936,7 @@ static void kvm_pmu_reset(struct kvm_vcpu *vcpu) pmu->need_cleanup =3D false; =20 bitmap_zero(pmu->reprogram_pmi, X86_PMC_IDX_MAX); + bitmap_zero(pmu->pmc_has_mode_specific_enables, X86_PMC_IDX_MAX); =20 kvm_for_each_pmc(pmu, pmc, i, pmu->all_valid_pmc_idx) { pmc_stop_counter(pmc); diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index cc7f55d4a78b4..34c3c6913ef62 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -202,8 +202,13 @@ static inline bool pmc_is_locally_enabled(struct kvm_p= mc *pmc) pmc->idx - KVM_FIXED_PMC_BASE_IDX) & (INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER); =20 - return (pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) && - !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); + if (!(pmc->eventsel & ARCH_PERFMON_EVENTSEL_ENABLE)) + return false; + + if (!test_bit(pmc->idx, pmu->pmc_has_mode_specific_enables)) + return true; + + return !kvm_pmu_call(pmc_is_disabled_in_current_mode)(pmc); } =20 extern struct x86_pmu_capability kvm_pmu_cap; diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 41ee6532290e9..b892a25ea4ca9 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -168,6 +168,12 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, stru= ct msr_data *msr_info) pmc->eventsel =3D data; pmc->eventsel_hw =3D (data & ~AMD64_EVENTSEL_HOSTONLY) | AMD64_EVENTSEL_GUESTONLY; + + if (data & AMD64_EVENTSEL_HOST_GUEST_MASK) + __set_bit(pmc->idx, pmu->pmc_has_mode_specific_enables); + else + __clear_bit(pmc->idx, pmu->pmc_has_mode_specific_enables); + kvm_pmu_request_counter_reprogram(pmc); } return 0; --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 468693E1701; Wed, 27 May 2026 23:47:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925648; cv=none; b=sXOjdXSNcXgtD7UukU4USCIvIz1Wk7+8h9FqdwHWH2EO0i27k9883t9wJ0ZseI2cMEcGx0zol0/pMGOik4DYElsXrlrNSwunoLUjOxC1fEnusFNSr8+pF8oqcKbPHkjaE1eGmq2RaWSm9HZsvwJzHqLpcmNKA6kbnID5kqAEXuM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925648; c=relaxed/simple; bh=206mIqF3fci4HH6D2sBWKZdC2Yk2DRzwHTjFG6TdwJo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DZmRAT7uhFw7uIVfBazrw8lJgd4ktJUg4tfI/66xDr5JcdVAxWuXhBFlAwnHInWYln0H1Vnvmlf4O0rLCaIlhbAANDJX4VQq5mlLcvkls2oY6oKfEPCijoQdmtfqYj4MoVcNbSpq+d22ODZv21zEEo+9vVUC7OarTKctis9mdvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N+kxsHCa; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N+kxsHCa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A01FB1F0155A; Wed, 27 May 2026 23:47:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925647; bh=Lkyxj+w/QFGgBjgywi/rJa7BtIb05sbN5pFHjSM+i4Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=N+kxsHCauNXnb/KgbBoT6DfK4Cu+CgfV/KQbvYMoPO6zsITQSKW9ty+3jifIimRso 8kx9HWhdaMZGihPe+ph9HGzmSbsvshKrhcg3cPNfXr4wfggOk2PB6TO3M2rUBBWTb5 Q25nP3zsHZQl3zaMfV7//Jz2nw1lGeMEYfgt1O5Q4qPdatVcjtyCDPCB1WPb4ilFjH cL39M5oi5jjPZlMObhvkvtG26R20oqKZyLV6H3Nu9AGFkt6nwrg/cqGcst8Xmtjml4 Wn+jp50JmF6LhgYBMN2CMn4EnV0mD9N39JBxctIG0Y6dl1irBUnf+z1LuXkXl0GB14 9x7ydbvUiNnFw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 12/17] KVM: x86/pmu: Reprogram Host/Guest-Only counters on nested transitions Date: Wed, 27 May 2026 23:47:06 +0000 Message-ID: <20260527234711.4175166-13-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Reprogram PMU counters on nested transitions for the mediated PMU, to re-evaluate Host-Only and Guest-Only bits and enable/disable the PMU counters accordingly. For example, if Host-Only is set and Guest-Only is cleared, a counter should be disabled when entering guest mode and enabled when exiting guest mode. According to the APM, when EFER.SVME is cleared, setting Host-Only or Guest-Only disables the counter, so also trigger counter reprogramming when EFER.SVME is toggled. Counters setting any of Host-Only and Guest-Only bits are already being tracked in pmc_has_mode_specific_enables, use the bitmap to reprogram these counters. Reprogram the counters synchronously on nested VMRUN/#VMEXIT and EFER.SVME toggling. This is necessary as these instructions are counted based on the new CPU state (after the instruction is retired in hardware). Hence, the PMU needs to be updated before instruction emulation is completed and kvm_pmu_instruction_retired() is called. Defer reprogramming the counters when force leaving guest mode through svm_leave_nested() to avoid potentially reading stale state (e.g. incorrect EFER). All flows force leaving nested are not architectural, so precision is not a priority. Refactor a helper out of kvm_pmu_request_reprogram_counters() that accepts a boolean allowing synchronous vs deferred reprogramming, and use that from SVM code to support both scenarios. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/pmu.c | 1 + arch/x86/kvm/pmu.h | 18 ++++++++++++++---- arch/x86/kvm/svm/nested.c | 12 ++++++++++++ arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/svm/svm.h | 22 ++++++++++++++++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 84c834ad2cd47..b92dd2e583356 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -685,6 +685,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu) kvm_for_each_pmc(pmu, pmc, bit, bitmap) kvm_pmu_recalc_pmc_emulation(pmu, pmc); } +EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_pmu_handle_event); =20 int kvm_pmu_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx) { diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 34c3c6913ef62..a5821d7c87f93 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -216,6 +216,7 @@ extern struct x86_pmu_capability kvm_pmu_cap; void kvm_init_pmu_capability(struct kvm_pmu_ops *pmu_ops); =20 void kvm_pmu_recalc_pmc_emulation(struct kvm_pmu *pmu, struct kvm_pmc *pmc= ); +void kvm_pmu_handle_event(struct kvm_vcpu *vcpu); =20 static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc) { @@ -225,14 +226,24 @@ static inline void kvm_pmu_request_counter_reprogram(= struct kvm_pmc *pmc) kvm_make_request(KVM_REQ_PMU, pmc->vcpu); } =20 -static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, - u64 counters) +static inline void __kvm_pmu_reprogram_counters(struct kvm_pmu *pmu, + u64 counters, + bool defer) { if (!counters) return; =20 atomic64_or(counters, &pmu->__reprogram_pmi); - kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); + if (defer) + kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); + else + kvm_pmu_handle_event(pmu_to_vcpu(pmu)); +} + +static inline void kvm_pmu_request_counters_reprogram(struct kvm_pmu *pmu, + u64 counters) +{ + __kvm_pmu_reprogram_counters(pmu, counters, true); } =20 /* @@ -261,7 +272,6 @@ static inline bool kvm_pmu_is_fastpath_emulation_allowe= d(struct kvm_vcpu *vcpu) } =20 void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu); -void kvm_pmu_handle_event(struct kvm_vcpu *vcpu); int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data); int kvm_pmu_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx); bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr); diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 7456cacde296c..ef093c7ae091f 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -860,6 +860,7 @@ static void nested_vmcb02_prepare_control(struct vcpu_s= vm *svm) =20 /* Enter Guest-Mode */ enter_guest_mode(vcpu); + svm_pmu_handle_nested_transition(svm); =20 /* * Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info, @@ -1325,6 +1326,8 @@ void nested_svm_vmexit(struct vcpu_svm *svm) =20 /* Exit Guest-Mode */ leave_guest_mode(vcpu); + svm_pmu_handle_nested_transition(svm); + svm->nested.vmcb12_gpa =3D 0; =20 kvm_warn_on_nested_run_pending(vcpu); @@ -1536,6 +1539,15 @@ void svm_leave_nested(struct kvm_vcpu *vcpu) =20 leave_guest_mode(vcpu); =20 + /* + * Force leaving nested is a non-architectural flow so precision + * is not a priority. Defer updating the PMU until the next vCPU + * run, potentially tolerating some imprecision to avoid poking + * into PMU state from arbitrary contexts (e.g. KVM may end up + * using stale state). + */ + __svm_pmu_handle_nested_transition(svm, true); + svm_switch_vmcb(svm, &svm->vmcb01); =20 nested_svm_uninit_mmu_context(vcpu); diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 183e577802301..717af5c4d0571 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -265,6 +265,7 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) set_exception_intercept(svm, GP_VECTOR); } =20 + svm_pmu_handle_nested_transition(svm); kvm_make_request(KVM_REQ_RECALC_INTERCEPTS, vcpu); } =20 diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index e5d9984ef6320..43e7323dcb23f 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -25,6 +25,7 @@ #include "cpuid.h" #include "kvm_cache_regs.h" #include "x86.h" +#include "pmu.h" =20 /* * Helpers to convert to/from physical addresses for pages whose address is @@ -897,6 +898,27 @@ void nested_copy_vmcb_save_to_cache(struct vcpu_svm *s= vm, void nested_sync_control_from_vmcb02(struct vcpu_svm *svm); void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vm= cb); =20 + +static inline void __svm_pmu_handle_nested_transition(struct vcpu_svm *svm= , bool defer) +{ + struct kvm_pmu *pmu =3D vcpu_to_pmu(&svm->vcpu); + u64 counters =3D *(u64 *)pmu->pmc_has_mode_specific_enables; + + __kvm_pmu_reprogram_counters(pmu, counters, defer); +} + +static inline void svm_pmu_handle_nested_transition(struct vcpu_svm *svm) +{ + /* + * Do NOT defer reprogramming the counters by default. Instructions + * causing a state change are counted based on the _new_ CPU state + * (e.g. a successful VMRUN is counted in guest mode). Hence, the + * counters should be reprogrammed with the new state _before_ the + * instruction is potentially counted upon emulation completion. + */ + __svm_pmu_handle_nested_transition(svm, false); +} + extern struct kvm_x86_nested_ops svm_nested_ops; =20 /* avic.c */ --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F36C83C9890; Wed, 27 May 2026 23:47:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925649; cv=none; b=tf9P6fc+gYe8xNUBo/5YZcGHNJujjiZAkBUsheD6FIACcuRMjGFtgXQaQcxl/j+66CIuhL5Ci86x36uE7zTkpgVVqsZnEkcaQy5Txz8tvfOB7kygEkZadOsLAsrKv9BQFeVhVYNC+VHZlwyLGKHzwWchWRc4gJZ4eTeMkO8+wUg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925649; c=relaxed/simple; bh=V8BIKaq66vQ/UDXTvrEVR48q0FJMy+iJC3s2mvcGFUo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j/Hadp5z9P005Fu8oev0SRbPQJaFsZ5ufIWg3rKPJTSR10vlHX472n3Y5SzS4CVEUNZcBvXBXRW87pDxxahmD+ND6uinMLOzIGiBgVWAXPCtrrPE9XKSxdxsKSsmrSRU0XmgLObVV9e5ICC9JQzQt785GnVjPdKk2whLM1Vpd4o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l4ksVVrY; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l4ksVVrY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57DD91F00A3D; Wed, 27 May 2026 23:47:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925647; bh=dOoldtVY2Gku7aJgZIqdcLHChMYQnv835HrQuauIHFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=l4ksVVrYveE+S77KquiOc6w8NBzalwBlMO69u/FCa+MFIDACDT40A74gyMaSsUV/V wZpTE/C1TEg91ExPBCqGwRPs6UExqQjOxC0ZeRDzJ0cOv/h1DBLQv1jmzJ7y+TAjVS M2QWm7FGTlC7onC98VUYFlWtC2qLY/C+veqpGRqKqzAReRE1lSGPRZZfYVRGhalQkN m6Z+CtHWNmSkETzE0YDL0yFXCuokhrSkht4lonftbLiw5udazWII/gobvLswJiAfSO MerwkzpFyPuneJIlBq9EdUF5hb/EU1RZEDldJ5OeU+j8CevDCIm+Lt33ZS1WbPaA5C WomND3wfXEgiA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 13/17] KVM: x86/pmu: Allow Host-Only/Guest-Only bits with nSVM and mediated PMU Date: Wed, 27 May 2026 23:47:07 +0000 Message-ID: <20260527234711.4175166-14-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jim Mattson Now that KVM correctly handles Host-Only and Guest-Only bits in the event selector MSRs, allow the guest to set them if the vCPU advertises SVM and uses the mediated PMU. Signed-off-by: Jim Mattson Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/pmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index b892a25ea4ca9..c18286545a7ac 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -213,7 +213,11 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) } =20 pmu->counter_bitmask[KVM_PMC_GP] =3D BIT_ULL(48) - 1; + pmu->reserved_bits =3D 0xfffffff000280000ull; + if (guest_cpu_cap_has(vcpu, X86_FEATURE_SVM) && kvm_vcpu_has_mediated_pmu= (vcpu)) + pmu->reserved_bits &=3D ~AMD64_EVENTSEL_HOST_GUEST_MASK; + pmu->raw_event_mask =3D AMD64_RAW_EVENT_MASK; /* not applicable to AMD; but clean them to prevent any fall out */ pmu->counter_bitmask[KVM_PMC_FIXED] =3D 0; --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA6643E3C67; Wed, 27 May 2026 23:47:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925649; cv=none; b=Mi4DjT4hqkO9CM8mE4w4CGrW0DEsSqq2Hd6MXM/xRb/q5EeMPH4HjeAizhPtNVzMkLBU97aS0UR6+l4ozatfje+dyLci2ez6Wa/PkiYhUSlFSlLbWvujQwT2UsoUXsybHbZDvt5wLo+l0FGwijZx9mB92gv3WJuuirOcPg9+byo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925649; c=relaxed/simple; bh=OI+xfgAyuNI9hANCEwWyv7RuIVole8DA9b84kwMlNug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M9iax7f+M+pY5ngEWt7raYdRVLiQJNNAgqtZBHS0WHsBBkUVuZrpvXiPgNq9HJrd44S/dWU0RVY1UgBeM1wRZFgRu18u3JljM1CDiGpLWRGyoX4GuSikM78bJYQwB6ZenVjJW5gMtKH32XW1Qc1IluQNv96PNCewuWrrSeTE6O8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RIJItrc5; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RIJItrc5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0FCD71F00ACA; Wed, 27 May 2026 23:47:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925648; bh=0lACjNcIpZ/rfwqoS4imDme5ztaTLdxIhnFZ+jb8Clc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=RIJItrc5XCA5LYwvsPhVI1F6vq6Gzd3mYkpLpmpdFwu2N7KHcnDPFVU3bXfq3+PmS rQZPu5VcFVY+qkvOgvQ/3+4ax8vfUEWGfhQc3bioh6TTBNQqU+RAbTSDW1cA/O+Ngo TxR4NlnyPYN7mqSiw2nu1r5Ob/31hjbmbsYE0rZRoq7OIlWeHl71N+2BIh3W4DUebj nF1SYy11JirTTrysnLZMIb8Cbn86Gd9uqXr6ye+ECNTqUL4nwhy9Ti3mfSJvmYWJwb A/Zubpby0q4wEYXgp6ISEDJDmSbwmaDgbdpw6DrtTikFZQZ2AgEYV4OsPbrPhD9wDh uJ10qyGks9QQw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 14/17] KVM: selftests: Refactor allocating guest stack into a helper Date: Wed, 27 May 2026 23:47:08 +0000 Message-ID: <20260527234711.4175166-15-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for reusing the logic to allocate stacks for nested guests, refactoring allocating a guest stack and aligning RSP into a helper. No functional change intended. Signed-off-by: Yosry Ahmed --- .../testing/selftests/kvm/lib/x86/processor.c | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 4ca48de7a926d..9393bb580a58e 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -778,6 +778,30 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vc= pu) REPORT_GUEST_ASSERT(uc); } =20 +static gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) +{ + int size =3D nr_pages * getpagesize(); + gva_t stack_gva; + + stack_gva =3D __vm_alloc(vm, size, DEFAULT_GUEST_STACK_VADDR_MIN, MEM_REG= ION_DATA); + stack_gva +=3D size; + + /* + * Align stack to match calling sequence requirements in section "The + * Stack Frame" of the System V ABI AMD64 Architecture Processor + * Supplement, which requires the value (%rsp + 8) to be a multiple of + * 16 when control is transferred to the function entry point. + * + * If this code is ever used to launch a vCPU with 32-bit entry point it + * may need to subtract 4 bytes instead of 8 bytes. + */ + TEST_ASSERT(IS_ALIGNED(stack_gva, PAGE_SIZE), + "__vm_alloc() did not provide a page-aligned address"); + stack_gva -=3D 8; + + return stack_gva; +} + void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus) { int r; @@ -820,27 +844,8 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u= 32 vcpu_id) { struct kvm_mp_state mp_state; struct kvm_regs regs; - gva_t stack_gva; struct kvm_vcpu *vcpu; =20 - stack_gva =3D __vm_alloc(vm, DEFAULT_STACK_PGS * getpagesize(), - DEFAULT_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA); - - stack_gva +=3D DEFAULT_STACK_PGS * getpagesize(); - - /* - * Align stack to match calling sequence requirements in section "The - * Stack Frame" of the System V ABI AMD64 Architecture Processor - * Supplement, which requires the value (%rsp + 8) to be a multiple of - * 16 when control is transferred to the function entry point. - * - * If this code is ever used to launch a vCPU with 32-bit entry point it - * may need to subtract 4 bytes instead of 8 bytes. - */ - TEST_ASSERT(IS_ALIGNED(stack_gva, PAGE_SIZE), - "__vm_alloc() did not provide a page-aligned address"); - stack_gva -=3D 8; - vcpu =3D __vm_vcpu_add(vm, vcpu_id); vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); vcpu_init_sregs(vm, vcpu); @@ -849,7 +854,7 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u3= 2 vcpu_id) /* Setup guest general purpose registers */ vcpu_regs_get(vcpu, ®s); regs.rflags =3D regs.rflags | X86_EFLAGS_FIXED; - regs.rsp =3D stack_gva; + regs.rsp =3D vm_alloc_stack(vm, DEFAULT_STACK_PGS); vcpu_regs_set(vcpu, ®s); =20 /* Setup the MP state */ --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C6E83C942C; Wed, 27 May 2026 23:47:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925651; cv=none; b=R/SyhfjbM3izzHT99sUrC+sSorSaMsLl7/N7sFjBYmREM9h/Thhgz3IF6uFrFI87m6rdeCeHbjmr28yYSsVqytodBYjk8/8/XBzTG6lPW1HqJCtzfkNgik9MUTwKf24+deU2k+YU9kRydv9WgeDy1ffO3cm1UsKat0gk8txgXZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925651; c=relaxed/simple; bh=ppFOZXZp1mhQpfCJoAgjRVpQNQTAzRUCth7GOcUVJmE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vC5rvv5k/LbJszOkcADGjA3KxsvhG/x/LrsH9Q4FbzGRZYJVvT9kg5T9LikK67716lf2pHHlf+bLZvDsmKJ/97G3H+0lifvYzg/D14npyc1JqwlQ8P8jSchrQdimlyZfTAyk6MHBrtqJJ9lLC9/e7uVhdoJO9JD46W+2jjtglKQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eH5Z5QXh; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eH5Z5QXh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBBA91F00ACF; Wed, 27 May 2026 23:47:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925649; bh=bIfcOFpv8y9d0c5rMhhhwZKzXQTjrLMLbf8k9VBsVWA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=eH5Z5QXh19bZmnUFts3iF80FH+Wx+9fvJK+dXIbZer89lOEesbIrNaPcmyLoL2+Hk zXZtRcjZXNYlbWqx4XLfp3VSykLM24XbkoV+aAk70ZwBeCqy3n+x+5LVjXJywAD3nX lzb93rkuHPQqBVInCdtfqWjzSzdc/iLAleLT9qhoYXO7WbpPhbMxruPBpcTqK/YeI3 faWtpweuD0kqdmxCpmEvP7gXA4Q4hrZLjhZWV6r0c6BjZl5asfYGrQUvab5iKJ8nUM HMGzJLd+B3+eMxvOKneIMhgJJ01db4lgOTronwVMdMGoRLRy4NfjMdG1My/L/RxsCr R5Bbif20/rcWA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 15/17] KVM: selftests: Allocate a dedicated guest page for x86 L2 guest stack Date: Wed, 27 May 2026 23:47:09 +0000 Message-ID: <20260527234711.4175166-16-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Instead of relying on the L1-provided stack for L2, which is usually an array on L1's own stack, allocate a dedicated page of VM memory for the L2 stack in vcpu_alloc_{vmx/svm}() and use that as L2's RSP in the VMCS/VMCB instead of the L1-provided value. Most L1 guest code does not do anything with the L2 stack other than stuff it in RSP, so this change is transparent and the L1-provided stack is silently ignored. The only exception is memstress nested L1 code which puts the vCPU index on L2's stack, so update this code to use the newly allocated stack. L1-provided stacks will be dropped and cleaned up separately. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/processor.h | 2 ++ tools/testing/selftests/kvm/include/x86/svm_util.h | 3 +++ tools/testing/selftests/kvm/include/x86/vmx.h | 2 ++ tools/testing/selftests/kvm/lib/x86/memstress.c | 5 ++--- tools/testing/selftests/kvm/lib/x86/processor.c | 2 +- tools/testing/selftests/kvm/lib/x86/svm.c | 4 +++- tools/testing/selftests/kvm/lib/x86/vmx.c | 4 +++- 7 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 06878e7c73479..e918237c3c208 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -1225,6 +1225,8 @@ struct idt_entry { void vm_install_exception_handler(struct kvm_vm *vm, int vector, void (*handler)(struct ex_regs *)); =20 +gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages); + /* * Exception fixup morphs #DE to an arbitrary magic vector so that '0' can= be * used to signal "no expcetion". diff --git a/tools/testing/selftests/kvm/include/x86/svm_util.h b/tools/tes= ting/selftests/kvm/include/x86/svm_util.h index 6c013eb838beb..3b1cc484fba1c 100644 --- a/tools/testing/selftests/kvm/include/x86/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86/svm_util.h @@ -28,6 +28,9 @@ struct svm_test_data { void *msr_hva; u64 msr_gpa; =20 + /* Stack */ + void *stack; /* gva */ + /* NPT */ u64 ncr3_gpa; }; diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 90fffaf915958..1dcb9b86d33d3 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -524,6 +524,8 @@ struct vmx_pages { u64 apic_access_gpa; void *apic_access; =20 + void *stack; + u64 eptp_gpa; }; =20 diff --git a/tools/testing/selftests/kvm/lib/x86/memstress.c b/tools/testin= g/selftests/kvm/lib/x86/memstress.c index 61cf952cd2dc2..fa07ef037cad1 100644 --- a/tools/testing/selftests/kvm/lib/x86/memstress.c +++ b/tools/testing/selftests/kvm/lib/x86/memstress.c @@ -43,7 +43,7 @@ static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_i= d) GUEST_ASSERT(ept_1g_pages_supported()); =20 rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; - *rsp =3D vcpu_id; + *(u64 *)vmx->stack =3D vcpu_id; prepare_vmcs(vmx, memstress_l2_guest_entry, rsp); =20 GUEST_ASSERT(!vmlaunch()); @@ -56,9 +56,8 @@ static void l1_svm_code(struct svm_test_data *svm, u64 vc= pu_id) unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; unsigned long *rsp; =20 - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; - *rsp =3D vcpu_id; + *(u64 *)svm->stack =3D vcpu_id; generic_svm_setup(svm, memstress_l2_guest_entry, rsp); =20 run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 9393bb580a58e..ef56dcefe0119 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -778,7 +778,7 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcp= u) REPORT_GUEST_ASSERT(uc); } =20 -static gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) +gva_t vm_alloc_stack(struct kvm_vm *vm, int nr_pages) { int size =3D nr_pages * getpagesize(); gva_t stack_gva; diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 3b01605ab016c..4e9c37f8d1a61 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -46,6 +46,8 @@ vcpu_alloc_svm(struct kvm_vm *vm, gva_t *p_svm_gva) svm->msr_gpa =3D addr_gva2gpa(vm, (uintptr_t)svm->msr); memset(svm->msr_hva, 0, getpagesize()); =20 + svm->stack =3D (void *)vm_alloc_stack(vm, 1); + if (vm->stage2_mmu.pgd_created) svm->ncr3_gpa =3D vm->stage2_mmu.pgd; =20 @@ -122,7 +124,7 @@ void generic_svm_setup(struct svm_test_data *svm, void = *guest_rip, void *guest_r ctrl->msrpm_base_pa =3D svm->msr_gpa; =20 vmcb->save.rip =3D (u64)guest_rip; - vmcb->save.rsp =3D (u64)guest_rsp; + vmcb->save.rsp =3D (u64)svm->stack; guest_regs.rdi =3D (u64)svm; =20 if (svm->ncr3_gpa) { diff --git a/tools/testing/selftests/kvm/lib/x86/vmx.c b/tools/testing/self= tests/kvm/lib/x86/vmx.c index 7c10ba6e6fb40..36aa108088ddd 100644 --- a/tools/testing/selftests/kvm/lib/x86/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86/vmx.c @@ -116,6 +116,8 @@ vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva) vmx->vmwrite_gpa =3D addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite); memset(vmx->vmwrite_hva, 0, getpagesize()); =20 + vmx->stack =3D (void *)vm_alloc_stack(vm, 1); + if (vm->stage2_mmu.pgd_created) vmx->eptp_gpa =3D vm->stage2_mmu.pgd; =20 @@ -370,7 +372,7 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_ri= p, void *guest_rsp) { init_vmcs_control_fields(vmx); init_vmcs_host_state(); - init_vmcs_guest_state(guest_rip, guest_rsp); + init_vmcs_guest_state(guest_rip, vmx->stack); } =20 bool kvm_cpu_has_ept(void) --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25E9B3E51D9; Wed, 27 May 2026 23:47:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925652; cv=none; b=SONAQH3sqVB5dUWVjF/Ex9su/Y8nU5cj1kcKAP2dPaApN9Tl+npkfly6i1awgZ0t1Rk3+9gT0q3TmWYK2D62yL1fYgzGFYWucM8iOoHC0h8AbzKfQbHCKE3imtx60ClLqSshuyMbb1nlvUHnU7kuTPP4Cs1LeyU+TmO5HeknA1g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925652; c=relaxed/simple; bh=aIqL2WXQ5uLzhqLNDMI48KfxLSHxnTrVdMAAaMMszHg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s0JEzQVP0gOyTkp/UZZntd7BFm2bb7lcCD3xl0R87hFROA/aobwLhojgeU/5knrsNIBRfJ6IQJzAAlKJuIElhd1Myy69p12THqXnz3SH0S1svPr0VmRz4bx+yZ515W1zYTvpFkEWvEqbMdPqmN2hie2h0eG0SPL6/808y0+H2IA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M/PvHuth; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="M/PvHuth" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 746BA1F00A3E; Wed, 27 May 2026 23:47:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925650; bh=7FXM196uRj+2OTzYY1sbjs8L95g52YScDFZWbiYjMRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=M/PvHuthoddW3frulFaWKM1rbuFAYNAFJwRz/QYezyt/RqAHg8arzkPPFdGkGvAw2 eBmZNLl6AuJFQ00YApLBjGefWqDAZVXGxz0AqACfdXCfnGPMiQE7hjbJx99vz4vsla wLbEHORLVLwBGUcuoQR5yX54Cecv7PbN4J89QgougQ37pcz3tYETxds50EU5TSRGZv Wi/bMVM+U/M+vPdfEi64j1Cv9A1r/bZHldhfs1u8WsS+vbqZkue1flHR0ovvR+vWpU WgyB7kKhPM7Q/JEtruGplscQkPpsLZphC0n+FaZ0zYvo0NUxbIq2EXZs8vjC+pt80q 2x3YmAN1+fYjQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 16/17] KVM: selftests: Drop L1-provided stacks for L2 guests on x86 Date: Wed, 27 May 2026 23:47:10 +0000 Message-ID: <20260527234711.4175166-17-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that a dedicated page is allocated for L2's stack and stuffed in RSP, the L1-provided stack is unused. Drop the stacks allocated by L1 guest code for L2 in all x86 tests. Suggested-by: Sean Christopherson Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/svm_util.h | 2 +- tools/testing/selftests/kvm/include/x86/vmx.h | 2 +- tools/testing/selftests/kvm/lib/x86/memstress.c | 14 ++------------ tools/testing/selftests/kvm/lib/x86/svm.c | 2 +- tools/testing/selftests/kvm/lib/x86/vmx.c | 2 +- tools/testing/selftests/kvm/x86/aperfmperf_test.c | 9 ++------- .../selftests/kvm/x86/evmcs_smm_controls_test.c | 5 +---- tools/testing/selftests/kvm/x86/hyperv_evmcs.c | 6 +----- tools/testing/selftests/kvm/x86/hyperv_svm_test.c | 6 +----- tools/testing/selftests/kvm/x86/kvm_buslock_test.c | 9 ++------- .../selftests/kvm/x86/nested_close_kvm_test.c | 12 ++---------- .../selftests/kvm/x86/nested_dirty_log_test.c | 8 ++------ .../selftests/kvm/x86/nested_emulation_test.c | 4 ++-- .../selftests/kvm/x86/nested_exceptions_test.c | 9 ++------- .../selftests/kvm/x86/nested_invalid_cr3_test.c | 10 ++-------- .../selftests/kvm/x86/nested_tdp_fault_test.c | 9 ++------- .../selftests/kvm/x86/nested_tsc_adjust_test.c | 10 ++-------- .../selftests/kvm/x86/nested_tsc_scaling_test.c | 10 ++-------- .../selftests/kvm/x86/nested_vmsave_vmload_test.c | 6 +----- tools/testing/selftests/kvm/x86/smm_test.c | 8 ++------ tools/testing/selftests/kvm/x86/state_test.c | 11 ++--------- tools/testing/selftests/kvm/x86/svm_int_ctl_test.c | 5 +---- .../selftests/kvm/x86/svm_lbr_nested_state.c | 6 +----- .../selftests/kvm/x86/svm_nested_clear_efer_svme.c | 7 +------ .../selftests/kvm/x86/svm_nested_shutdown_test.c | 5 +---- .../kvm/x86/svm_nested_soft_inject_test.c | 6 +----- .../selftests/kvm/x86/svm_nested_vmcb12_gpa.c | 13 ++++--------- tools/testing/selftests/kvm/x86/svm_vmcall_test.c | 5 +---- .../selftests/kvm/x86/triple_fault_event_test.c | 9 ++------- .../selftests/kvm/x86/vmx_apic_access_test.c | 5 +---- .../selftests/kvm/x86/vmx_apicv_updates_test.c | 4 +--- .../kvm/x86/vmx_invalid_nested_guest_state.c | 6 +----- .../selftests/kvm/x86/vmx_nested_la57_state_test.c | 5 +---- .../selftests/kvm/x86/vmx_preemption_timer_test.c | 5 +---- 34 files changed, 51 insertions(+), 184 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/svm_util.h b/tools/tes= ting/selftests/kvm/include/x86/svm_util.h index 3b1cc484fba1c..c201c30485e72 100644 --- a/tools/testing/selftests/kvm/include/x86/svm_util.h +++ b/tools/testing/selftests/kvm/include/x86/svm_util.h @@ -60,7 +60,7 @@ static inline void vmmcall(void) ) =20 struct svm_test_data *vcpu_alloc_svm(struct kvm_vm *vm, gva_t *p_svm_gva); -void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *g= uest_rsp); +void generic_svm_setup(struct svm_test_data *svm, void *guest_rip); void run_guest(struct vmcb *vmcb, u64 vmcb_gpa); =20 static inline bool kvm_cpu_has_npt(void) diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 1dcb9b86d33d3..4bcfd60e3aecb 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -554,7 +554,7 @@ union vmx_ctrl_msr { =20 struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva); bool prepare_for_vmx_operation(struct vmx_pages *vmx); -void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp); +void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip); bool load_vmcs(struct vmx_pages *vmx); =20 bool ept_1g_pages_supported(void); diff --git a/tools/testing/selftests/kvm/lib/x86/memstress.c b/tools/testin= g/selftests/kvm/lib/x86/memstress.c index fa07ef037cad1..e19e8b5a09c5a 100644 --- a/tools/testing/selftests/kvm/lib/x86/memstress.c +++ b/tools/testing/selftests/kvm/lib/x86/memstress.c @@ -30,21 +30,15 @@ __asm__( " ud2;" ); =20 -#define L2_GUEST_STACK_SIZE 64 - static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_id) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - unsigned long *rsp; - GUEST_ASSERT(vmx->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); GUEST_ASSERT(ept_1g_pages_supported()); =20 - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; *(u64 *)vmx->stack =3D vcpu_id; - prepare_vmcs(vmx, memstress_l2_guest_entry, rsp); + prepare_vmcs(vmx, memstress_l2_guest_entry); =20 GUEST_ASSERT(!vmlaunch()); GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); @@ -53,12 +47,8 @@ static void l1_vmx_code(struct vmx_pages *vmx, u64 vcpu_= id) =20 static void l1_svm_code(struct svm_test_data *svm, u64 vcpu_id) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - unsigned long *rsp; - - rsp =3D &l2_guest_stack[L2_GUEST_STACK_SIZE - 1]; *(u64 *)svm->stack =3D vcpu_id; - generic_svm_setup(svm, memstress_l2_guest_entry, rsp); + generic_svm_setup(svm, memstress_l2_guest_entry); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL); diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 4e9c37f8d1a61..1445b890986fd 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -83,7 +83,7 @@ void vm_enable_npt(struct kvm_vm *vm) tdp_mmu_init(vm, vm->mmu.pgtable_levels, &pte_masks); } =20 -void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *g= uest_rsp) +void generic_svm_setup(struct svm_test_data *svm, void *guest_rip) { struct vmcb *vmcb =3D svm->vmcb; u64 vmcb_gpa =3D svm->vmcb_gpa; diff --git a/tools/testing/selftests/kvm/lib/x86/vmx.c b/tools/testing/self= tests/kvm/lib/x86/vmx.c index 36aa108088ddd..cd09c9de4485a 100644 --- a/tools/testing/selftests/kvm/lib/x86/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86/vmx.c @@ -368,7 +368,7 @@ static inline void init_vmcs_guest_state(void *rip, voi= d *rsp) vmwrite(GUEST_SYSENTER_EIP, vmreadz(HOST_IA32_SYSENTER_EIP)); } =20 -void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp) +void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip) { init_vmcs_control_fields(vmx); init_vmcs_host_state(); diff --git a/tools/testing/selftests/kvm/x86/aperfmperf_test.c b/tools/test= ing/selftests/kvm/x86/aperfmperf_test.c index c91660103137b..845cb685f1743 100644 --- a/tools/testing/selftests/kvm/x86/aperfmperf_test.c +++ b/tools/testing/selftests/kvm/x86/aperfmperf_test.c @@ -54,8 +54,6 @@ static void guest_read_aperf_mperf(void) GUEST_SYNC2(rdmsr(MSR_IA32_APERF), rdmsr(MSR_IA32_MPERF)); } =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { guest_read_aperf_mperf(); @@ -64,21 +62,18 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZE= ]); + generic_svm_setup(svm, l2_guest_code); run_guest(vmcb, svm->vmcb_gpa); } =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); =20 /* * Enable MSR bitmaps (the bitmap itself is allocated, zeroed, and set diff --git a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c b/to= ols/testing/selftests/kvm/x86/evmcs_smm_controls_test.c index 5b3aef109cfc5..77ce87c41a868 100644 --- a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c +++ b/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c @@ -52,8 +52,6 @@ static void l2_guest_code(void) static void guest_code(struct vmx_pages *vmx_pages, struct hyperv_test_pages *hv_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; =20 /* Set up Hyper-V enlightenments and eVMCS */ wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); @@ -62,8 +60,7 @@ static void guest_code(struct vmx_pages *vmx_pages, =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_evmcs(hv_pages)); - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); =20 diff --git a/tools/testing/selftests/kvm/x86/hyperv_evmcs.c b/tools/testing= /selftests/kvm/x86/hyperv_evmcs.c index c7fa114aee20f..1bda2cd3f7396 100644 --- a/tools/testing/selftests/kvm/x86/hyperv_evmcs.c +++ b/tools/testing/selftests/kvm/x86/hyperv_evmcs.c @@ -78,9 +78,6 @@ void l2_guest_code(void) void guest_code(struct vmx_pages *vmx_pages, struct hyperv_test_pages *hv_= pages, gpa_t hv_hcall_page_gpa) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); wrmsr(HV_X64_MSR_HYPERCALL, hv_hcall_page_gpa); =20 @@ -100,8 +97,7 @@ void guest_code(struct vmx_pages *vmx_pages, struct hype= rv_test_pages *hv_pages, GUEST_SYNC(4); GUEST_ASSERT(vmptrstz() =3D=3D hv_pages->enlightened_vmcs_gpa); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_SYNC(5); GUEST_ASSERT(vmptrstz() =3D=3D hv_pages->enlightened_vmcs_gpa); diff --git a/tools/testing/selftests/kvm/x86/hyperv_svm_test.c b/tools/test= ing/selftests/kvm/x86/hyperv_svm_test.c index 7a62f6a9d606d..1f74b0fa9b835 100644 --- a/tools/testing/selftests/kvm/x86/hyperv_svm_test.c +++ b/tools/testing/selftests/kvm/x86/hyperv_svm_test.c @@ -18,8 +18,6 @@ #include "svm_util.h" #include "hyperv.h" =20 -#define L2_GUEST_STACK_SIZE 256 - /* Exit to L1 from L2 with RDMSR instruction */ static inline void rdmsr_from_l2(u32 msr) { @@ -69,7 +67,6 @@ static void __attribute__((__flatten__)) guest_code(struc= t svm_test_data *svm, struct hyperv_test_pages *hv_pages, gpa_t pgs_gpa) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; struct hv_vmcb_enlightenments *hve =3D &vmcb->control.hv_enlightenments; =20 @@ -81,8 +78,7 @@ static void __attribute__((__flatten__)) guest_code(struc= t svm_test_data *svm, =20 GUEST_ASSERT(svm->vmcb_gpa); /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* L2 TLB flush setup */ hve->partition_assist_page =3D hv_pages->partition_assist_gpa; diff --git a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c b/tools/tes= ting/selftests/kvm/x86/kvm_buslock_test.c index 52014a3210c88..25a182be00a97 100644 --- a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c +++ b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c @@ -26,8 +26,6 @@ static void guest_generate_buslocks(void) atomic_inc(val); } =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { guest_generate_buslocks(); @@ -36,21 +34,18 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZE= ]); + generic_svm_setup(svm, l2_guest_code); run_guest(vmcb, svm->vmcb_gpa); } =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); =20 GUEST_ASSERT(!vmwrite(GUEST_RIP, (u64)l2_guest_code)); GUEST_ASSERT(!vmlaunch()); diff --git a/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c b/tool= s/testing/selftests/kvm/x86/nested_close_kvm_test.c index 761fec2934080..b974cfb347d6e 100644 --- a/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c +++ b/tools/testing/selftests/kvm/x86/nested_close_kvm_test.c @@ -21,8 +21,6 @@ enum { PORT_L0_EXIT =3D 0x2000, }; =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { /* Exit to L0 */ @@ -32,14 +30,11 @@ static void l2_guest_code(void) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); GUEST_ASSERT(0); @@ -47,11 +42,8 @@ static void l1_vmx_code(struct vmx_pages *vmx_pages) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Prepare the VMCB for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT(0); diff --git a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c b/tool= s/testing/selftests/kvm/x86/nested_dirty_log_test.c index 0e67cce835701..26b474bf13535 100644 --- a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c +++ b/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c @@ -40,8 +40,6 @@ =20 #define TEST_HVA(vm, idx) addr_gpa2hva(vm, TEST_GPA(idx)) =20 -#define L2_GUEST_STACK_SIZE 64 - /* Use the page offset bits to communicate the access+fault type. */ #define TEST_SYNC_READ_FAULT BIT(0) #define TEST_SYNC_WRITE_FAULT BIT(1) @@ -92,7 +90,6 @@ static void l2_guest_code_tdp_disabled(void) =20 void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; void *l2_rip; =20 GUEST_ASSERT(vmx->vmcs_gpa); @@ -104,7 +101,7 @@ void l1_vmx_code(struct vmx_pages *vmx) else l2_rip =3D l2_guest_code_tdp_disabled; =20 - prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, l2_rip); =20 GUEST_SYNC(TEST_SYNC_NO_FAULT); GUEST_ASSERT(!vmlaunch()); @@ -115,7 +112,6 @@ void l1_vmx_code(struct vmx_pages *vmx) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; void *l2_rip; =20 if (svm->ncr3_gpa) @@ -123,7 +119,7 @@ static void l1_svm_code(struct svm_test_data *svm) else l2_rip =3D l2_guest_code_tdp_disabled; =20 - generic_svm_setup(svm, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_rip); =20 GUEST_SYNC(TEST_SYNC_NO_FAULT); run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/x86/nested_emulation_test.c b/tool= s/testing/selftests/kvm/x86/nested_emulation_test.c index fb7dcbe53ac73..e08c6b0697e50 100644 --- a/tools/testing/selftests/kvm/x86/nested_emulation_test.c +++ b/tools/testing/selftests/kvm/x86/nested_emulation_test.c @@ -57,7 +57,7 @@ static void guest_code(void *test_data) struct svm_test_data *svm =3D test_data; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, NULL, NULL); + generic_svm_setup(svm, NULL); vmcb->save.idtr.limit =3D 0; vmcb->save.rip =3D (u64)l2_guest_code; =20 @@ -69,7 +69,7 @@ static void guest_code(void *test_data) GUEST_ASSERT(prepare_for_vmx_operation(test_data)); GUEST_ASSERT(load_vmcs(test_data)); =20 - prepare_vmcs(test_data, NULL, NULL); + prepare_vmcs(test_data, NULL); GUEST_ASSERT(!vmwrite(GUEST_IDTR_LIMIT, 0)); GUEST_ASSERT(!vmwrite(GUEST_RIP, (u64)l2_guest_code)); GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, 0)); diff --git a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c b/too= ls/testing/selftests/kvm/x86/nested_exceptions_test.c index 186e980aa8eee..aeec3121c8e83 100644 --- a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c +++ b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c @@ -5,8 +5,6 @@ #include "vmx.h" #include "svm_util.h" =20 -#define L2_GUEST_STACK_SIZE 256 - /* * Arbitrary, never shoved into KVM/hardware, just need to avoid conflict = with * the "real" exceptions used, #SS/#GP/#DF (12/13/8). @@ -91,9 +89,8 @@ static void svm_run_l2(struct svm_test_data *svm, void *l= 2_code, int vector, static void l1_svm_code(struct svm_test_data *svm) { struct vmcb_control_area *ctrl =3D &svm->vmcb->control; - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; =20 - generic_svm_setup(svm, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, NULL); svm->vmcb->save.idtr.limit =3D 0; ctrl->intercept |=3D BIT_ULL(INTERCEPT_SHUTDOWN); =20 @@ -128,13 +125,11 @@ static void vmx_run_l2(void *l2_code, int vector, u32= error_code) =20 static void l1_vmx_code(struct vmx_pages *vmx) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT_EQ(prepare_for_vmx_operation(vmx), true); =20 GUEST_ASSERT_EQ(load_vmcs(vmx), true); =20 - prepare_vmcs(vmx, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, NULL); GUEST_ASSERT_EQ(vmwrite(GUEST_IDTR_LIMIT, 0), 0); =20 /* diff --git a/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c b/to= ols/testing/selftests/kvm/x86/nested_invalid_cr3_test.c index 11fd2467d8233..8c2ba9674558e 100644 --- a/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c +++ b/tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c @@ -11,8 +11,6 @@ #include "kselftest.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { vmcall(); @@ -20,11 +18,9 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; uintptr_t save_cr3; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* Try to run L2 with invalid CR3 and make sure it fails */ save_cr3 =3D svm->vmcb->save.cr3; @@ -42,14 +38,12 @@ static void l1_svm_code(struct svm_test_data *svm) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; uintptr_t save_cr3; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* Try to run L2 with invalid CR3 and make sure it fails */ save_cr3 =3D vmreadz(GUEST_CR3); diff --git a/tools/testing/selftests/kvm/x86/nested_tdp_fault_test.c b/tool= s/testing/selftests/kvm/x86/nested_tdp_fault_test.c index fa95568f55ffc..2e04563790ff2 100644 --- a/tools/testing/selftests/kvm/x86/nested_tdp_fault_test.c +++ b/tools/testing/selftests/kvm/x86/nested_tdp_fault_test.c @@ -9,8 +9,6 @@ #include "svm_util.h" #include "vmx.h" =20 -#define L2_GUEST_STACK_SIZE 64 - enum test_type { TEST_FINAL_PAGE_UNMAPPED, /* Final data page not present */ TEST_PT_PAGE_UNMAPPED, /* Page table page not present */ @@ -54,14 +52,13 @@ static void l2_guest_code_ins(void) static void l1_vmx_code(struct vmx_pages *vmx, u64 expected_fault_gpa, u64 test_type) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 exit_qual; =20 GUEST_ASSERT(vmx->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); =20 - prepare_vmcs(vmx, l2_entry, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, l2_entry); =20 GUEST_ASSERT(!vmlaunch()); =20 @@ -120,12 +117,10 @@ static void l1_vmx_code(struct vmx_pages *vmx, u64 ex= pected_fault_gpa, static void l1_svm_code(struct svm_test_data *svm, u64 expected_fault_gpa, u64 test_type) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; u64 exit_info_1; =20 - generic_svm_setup(svm, l2_entry, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_entry); =20 run_guest(vmcb, svm->vmcb_gpa); =20 diff --git a/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c b/too= ls/testing/selftests/kvm/x86/nested_tsc_adjust_test.c index f0e4adac47510..cb79d7b9619c2 100644 --- a/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c +++ b/tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c @@ -34,8 +34,6 @@ #define TSC_ADJUST_VALUE (1ll << 32) #define TSC_OFFSET_VALUE -(1ll << 48) =20 -#define L2_GUEST_STACK_SIZE 64 - enum { PORT_ABORT =3D 0x1000, PORT_REPORT, @@ -75,8 +73,6 @@ static void l2_guest_code(void) =20 static void l1_guest_code(void *data) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Set TSC from L1 and make sure TSC_ADJUST is updated correctly */ GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE); wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE); @@ -93,8 +89,7 @@ static void l1_guest_code(void *data) GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETTING; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); @@ -105,8 +100,7 @@ static void l1_guest_code(void *data) } else { struct svm_test_data *svm =3D data; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 svm->vmcb->control.tsc_offset =3D TSC_OFFSET_VALUE; run_guest(svm->vmcb, svm->vmcb_gpa); diff --git a/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c b/to= ols/testing/selftests/kvm/x86/nested_tsc_scaling_test.c index 190e93af20a14..18f765835bf4c 100644 --- a/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c +++ b/tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c @@ -22,8 +22,6 @@ #define TSC_OFFSET_L2 ((u64)-33125236320908) #define TSC_MULTIPLIER_L2 (L2_SCALE_FACTOR << 48) =20 -#define L2_GUEST_STACK_SIZE 64 - enum { USLEEP, UCHECK_L1, UCHECK_L2 }; #define GUEST_SLEEP(sec) ucall(UCALL_SYNC, 2, USLEEP, sec) #define GUEST_CHECK(level, freq) ucall(UCALL_SYNC, 2, level, freq) @@ -82,13 +80,10 @@ static void l2_guest_code(void) =20 static void l1_svm_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* check that L1's frequency looks alright before launching L2 */ check_tsc_freq(UCHECK_L1); =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* enable TSC scaling for L2 */ wrmsr(MSR_AMD64_TSC_RATIO, L2_SCALE_FACTOR << 32); @@ -105,7 +100,6 @@ static void l1_svm_code(struct svm_test_data *svm) =20 static void l1_vmx_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 /* check that L1's frequency looks alright before launching L2 */ @@ -115,7 +109,7 @@ static void l1_vmx_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* prepare the VMCS for L2 execution */ - prepare_vmcs(vmx_pages, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* enable TSC offsetting and TSC scaling for L2 */ control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); diff --git a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c b/= tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c index 85d3f4cc76f39..a130759f39a19 100644 --- a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c +++ b/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c @@ -28,8 +28,6 @@ =20 #define TEST_VMCB_L2_GPA TEST_VMCB_L1_GPA(0) =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code_vmsave(void) { asm volatile("vmsave %0" : : "a"(TEST_VMCB_L2_GPA) : "memory"); @@ -70,10 +68,8 @@ static void l2_guest_code_vmcb1(void) =20 static void l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - /* Each test case initializes the guest RIP below */ - generic_svm_setup(svm, NULL, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, NULL); =20 /* Set VMSAVE/VMLOAD intercepts and make sure they work with.. */ svm->vmcb->control.intercept |=3D (BIT_ULL(INTERCEPT_VMSAVE) | diff --git a/tools/testing/selftests/kvm/x86/smm_test.c b/tools/testing/sel= ftests/kvm/x86/smm_test.c index 740051167dbd4..e2542f4ced605 100644 --- a/tools/testing/selftests/kvm/x86/smm_test.c +++ b/tools/testing/selftests/kvm/x86/smm_test.c @@ -63,8 +63,6 @@ static void l2_guest_code(void) =20 static void guest_code(void *arg) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 apicbase =3D rdmsr(MSR_IA32_APICBASE); struct svm_test_data *svm =3D arg; struct vmx_pages *vmx_pages =3D arg; @@ -81,13 +79,11 @@ static void guest_code(void *arg) =20 if (arg) { if (this_cpu_has(X86_FEATURE_SVM)) { - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); } else { GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); } =20 sync_with_host(5); diff --git a/tools/testing/selftests/kvm/x86/state_test.c b/tools/testing/s= elftests/kvm/x86/state_test.c index 409c6cc9f9214..4a1056a6cb8dc 100644 --- a/tools/testing/selftests/kvm/x86/state_test.c +++ b/tools/testing/selftests/kvm/x86/state_test.c @@ -19,8 +19,6 @@ #include "vmx.h" #include "svm_util.h" =20 -#define L2_GUEST_STACK_SIZE 256 - void svm_l2_guest_code(void) { GUEST_SYNC(4); @@ -35,13 +33,11 @@ void svm_l2_guest_code(void) =20 static void svm_l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 GUEST_ASSERT(svm->vmcb_gpa); /* Prepare for L2 execution. */ - generic_svm_setup(svm, svm_l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, svm_l2_guest_code); =20 vmcb->control.int_ctl |=3D (V_GIF_ENABLE_MASK | V_GIF_MASK); =20 @@ -78,8 +74,6 @@ void vmx_l2_guest_code(void) =20 static void vmx_l1_guest_code(struct vmx_pages *vmx_pages) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(vmx_pages->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_SYNC(3); @@ -89,8 +83,7 @@ static void vmx_l1_guest_code(struct vmx_pages *vmx_pages) GUEST_SYNC(4); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); =20 - prepare_vmcs(vmx_pages, vmx_l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, vmx_l2_guest_code); =20 GUEST_SYNC(5); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); diff --git a/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c b/tools/tes= ting/selftests/kvm/x86/svm_int_ctl_test.c index d3cc5e4f78831..7b1f4a4818bdd 100644 --- a/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c +++ b/tools/testing/selftests/kvm/x86/svm_int_ctl_test.c @@ -54,15 +54,12 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 x2apic_enable(); =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* No virtual interrupt masking */ vmcb->control.int_ctl &=3D ~V_INTR_MASKING_MASK; diff --git a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c b/tools= /testing/selftests/kvm/x86/svm_lbr_nested_state.c index 7fbfaa054c952..77c6ce9f45078 100644 --- a/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c +++ b/tools/testing/selftests/kvm/x86/svm_lbr_nested_state.c @@ -9,8 +9,6 @@ #include "svm_util.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - #define DO_BRANCH() do { asm volatile("jmp 1f\n 1: nop"); } while (0) =20 struct lbr_branch { @@ -55,7 +53,6 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm, bool nested_lbrv) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; struct lbr_branch l1_branch; =20 @@ -65,8 +62,7 @@ static void l1_guest_code(struct svm_test_data *svm, bool= nested_lbrv) CHECK_BRANCH_MSRS(&l1_branch); =20 /* Run L2, which will also do the same */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 if (nested_lbrv) vmcb->control.misc_ctl2 =3D SVM_MISC2_ENABLE_V_LBR; diff --git a/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c b= /tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c index 6a89eaffc6578..6bc301207cbcb 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_clear_efer_svme.c @@ -8,8 +8,6 @@ #include "kselftest.h" =20 =20 -#define L2_GUEST_STACK_SIZE 64 - static void l2_guest_code(void) { unsigned long efer =3D rdmsr(MSR_EFER); @@ -24,10 +22,7 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct svm_test_data *svm) { - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); run_guest(svm->vmcb, svm->vmcb_gpa); =20 /* Unreachable, L1 should be shutdown */ diff --git a/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c b/t= ools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c index c6ea3d609a629..2a4a216954bb3 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_shutdown_test.c @@ -19,12 +19,9 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 vmcb->control.intercept &=3D ~(BIT(INTERCEPT_SHUTDOWN)); =20 diff --git a/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c = b/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c index f72f11d4c4f83..0b640d09d1943 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_soft_inject_test.c @@ -78,17 +78,13 @@ static void l2_guest_code_nmi(void) =20 static void l1_guest_code(struct svm_test_data *svm, u64 is_nmi, u64 idt_a= lt) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 if (is_nmi) x2apic_enable(); =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, - is_nmi ? l2_guest_code_nmi : l2_guest_code_int, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, is_nmi ? l2_guest_code_nmi : l2_guest_code_int); =20 vmcb->control.intercept_exceptions |=3D BIT(PF_VECTOR) | BIT(UD_VECTOR); vmcb->control.intercept |=3D BIT(INTERCEPT_NMI) | BIT(INTERCEPT_HLT); diff --git a/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c b/tool= s/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c index a4935ce2fb998..b3f45035745ff 100644 --- a/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c +++ b/tools/testing/selftests/kvm/x86/svm_nested_vmcb12_gpa.c @@ -9,14 +9,9 @@ #include "kvm_test_harness.h" #include "test_util.h" =20 - -#define L2_GUEST_STACK_SIZE 64 - #define SYNC_GP 101 #define SYNC_L2_STARTED 102 =20 -static unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - static void guest_gp_handler(struct ex_regs *regs) { GUEST_SYNC(SYNC_GP); @@ -30,28 +25,28 @@ static void l2_code(void) =20 static void l1_vmrun(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmrun %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmload(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmload %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmsave(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 asm volatile ("vmsave %[gpa]" : : [gpa] "a" (gpa) : "memory"); } =20 static void l1_vmexit(struct svm_test_data *svm, gpa_t gpa) { - generic_svm_setup(svm, l2_code, &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_code); =20 run_guest(svm->vmcb, svm->vmcb_gpa); GUEST_ASSERT(svm->vmcb->control.exit_code =3D=3D SVM_EXIT_VMMCALL); diff --git a/tools/testing/selftests/kvm/x86/svm_vmcall_test.c b/tools/test= ing/selftests/kvm/x86/svm_vmcall_test.c index b1887242f3b8e..7c57fb7e64221 100644 --- a/tools/testing/selftests/kvm/x86/svm_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86/svm_vmcall_test.c @@ -19,13 +19,10 @@ static void l2_guest_code(struct svm_test_data *svm) =20 static void l1_guest_code(struct svm_test_data *svm) { - #define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; struct vmcb *vmcb =3D svm->vmcb; =20 /* Prepare for L2 execution. */ - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 run_guest(vmcb, svm->vmcb_gpa); =20 diff --git a/tools/testing/selftests/kvm/x86/triple_fault_event_test.c b/to= ols/testing/selftests/kvm/x86/triple_fault_event_test.c index f1c488e0d4975..0d83516f4bd08 100644 --- a/tools/testing/selftests/kvm/x86/triple_fault_event_test.c +++ b/tools/testing/selftests/kvm/x86/triple_fault_event_test.c @@ -21,9 +21,6 @@ static void l2_guest_code(void) : : [port] "d" (ARBITRARY_IO_PORT) : "rax"); } =20 -#define L2_GUEST_STACK_SIZE 64 -unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - void l1_guest_code_vmx(struct vmx_pages *vmx) { =20 @@ -31,8 +28,7 @@ void l1_guest_code_vmx(struct vmx_pages *vmx) GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); =20 - prepare_vmcs(vmx, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx, l2_guest_code); =20 GUEST_ASSERT(!vmlaunch()); /* L2 should triple fault after a triple fault event injected. */ @@ -44,8 +40,7 @@ void l1_guest_code_svm(struct svm_test_data *svm) { struct vmcb *vmcb =3D svm->vmcb; =20 - generic_svm_setup(svm, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + generic_svm_setup(svm, l2_guest_code); =20 /* don't intercept shutdown to test the case of SVM allowing to do so */ vmcb->control.intercept &=3D ~(BIT(INTERCEPT_SHUTDOWN)); diff --git a/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c b/tools= /testing/selftests/kvm/x86/vmx_apic_access_test.c index 1720113eae799..463f73aa9159a 100644 --- a/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_apic_access_test.c @@ -36,16 +36,13 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages, unsigned long high_= gpa) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); diff --git a/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c b/too= ls/testing/selftests/kvm/x86/vmx_apicv_updates_test.c index 80a4fd1e5bbbe..f9b88a6f6113d 100644 --- a/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_apicv_updates_test.c @@ -31,15 +31,13 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u32 control; =20 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); + prepare_vmcs(vmx_pages, l2_guest_code); control =3D vmreadz(CPU_BASED_VM_EXEC_CONTROL); control |=3D CPU_BASED_USE_MSR_BITMAPS; vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); diff --git a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state= .c b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c index a2eaceed9ad52..6d88c54f69faa 100644 --- a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c +++ b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c @@ -25,15 +25,11 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; - GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 /* Prepare the VMCS for L2 execution. */ - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * L2 must be run without unrestricted guest, verify that the selftests diff --git a/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c b= /tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c index f13dee3173837..75073efa926da 100644 --- a/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c @@ -27,8 +27,6 @@ static void l2_guest_code(void) =20 static void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 guest_cr4; gpa_t pml5_pa, pml4_pa; u64 *pml5; @@ -42,8 +40,7 @@ static void l1_guest_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); GUEST_ASSERT(load_vmcs(vmx_pages)); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * Set up L2 with a 4-level page table by pointing its CR3 to diff --git a/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c b/= tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c index 1b7b6ba23de76..eb8021c33cd43 100644 --- a/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c +++ b/tools/testing/selftests/kvm/x86/vmx_preemption_timer_test.c @@ -66,8 +66,6 @@ void l2_guest_code(void) =20 void l1_guest_code(struct vmx_pages *vmx_pages) { -#define L2_GUEST_STACK_SIZE 64 - unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; u64 l1_vmx_pt_start; u64 l1_vmx_pt_finish; u64 l1_tsc_deadline, l2_tsc_deadline; @@ -77,8 +75,7 @@ void l1_guest_code(struct vmx_pages *vmx_pages) GUEST_ASSERT(load_vmcs(vmx_pages)); GUEST_ASSERT(vmptrstz() =3D=3D vmx_pages->vmcs_gpa); =20 - prepare_vmcs(vmx_pages, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + prepare_vmcs(vmx_pages, l2_guest_code); =20 /* * Check for Preemption timer support --=20 2.54.0.794.g4f17f83d09-goog From nobody Mon Jun 8 16:28:22 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D17D93DFC94; Wed, 27 May 2026 23:47:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925652; cv=none; b=QTXQV8hbrZYJPdGWyl25rtvMhCs9f+BY8EmA8qXOlWCZSbcXoL6VFqsJrFlhrE3PccWGS9wb8KDqTGAQIIPSXV8sdMg5awjQn0P66N/0+IkeogpCRR6i8efoVv9bOAZcbKYLoF8ibHJkQy60osGd+3+oHlIqtlJzIll/4iYCDwQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779925652; c=relaxed/simple; bh=htyzYObhK3/cOuj6AyO0FGGU7bBU3a64wSW49SLrOYY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y6MONI4qch5lABMIi0J94vgGzp7TaFVTLGNPmvZ0N9SXeMnBf7kpeSZ9CQEiHdl/oWQWc8g/umCblGqBQYIu7hRpnNjXkZpVRO6t0CUrKlUzHfvHywOp9N4PipVv/ViCA0KMp0J4DeltcHyWpMGKVmZXeCdYzWn+CnHsbCYxz9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Yd1749ux; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Yd1749ux" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 369791F000E9; Wed, 27 May 2026 23:47:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779925650; bh=1U24eWW9n3ACEjNCNLe2CqY0Gd2RUHuKZSqNGo/OPpU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Yd1749uxPX+bYLLb0F4WoiJGlXHSEoLk1/XJp/LHCOnqqCKD+5VCE9V2/xUjm8T0j nfFbDsM/BTchn/J9TwSyNM03ZoiGrY+01/MvSRrPInvzwnWnS5G3+EMt7Be7Fu22jQ E0YfBLt5ZSpyOBVoCONtt0f0UXe27z0JmdVh6Z+9ANpT+lskDdbHkJxQFvhSWidwXo Wx/sZ4WceJohdEYuTXQXXM1XHBHsrjp+w/hJAtClfqt0pZbG6B/L2Qn95sZIT8St7N 7t1bvqSrFQ8h/ijpabtDqPsiARSKM9DNlYxpk00BdMK74KzY3LqWpnDDC0wajr8oBH f3WRJWRAigiHA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , Jim Mattson , Dapeng Mi , Sandipan Das , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 17/17] KVM: selftests: Add svm_pmu_host_guest_test for Host-Only/Guest-Only bits Date: Wed, 27 May 2026 23:47:11 +0000 Message-ID: <20260527234711.4175166-18-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.794.g4f17f83d09-goog In-Reply-To: <20260527234711.4175166-1-yosry@kernel.org> References: <20260527234711.4175166-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jim Mattson Add a selftest to verify KVM correctly virtualizes the AMD PMU Host-Only (bit 41) and Guest-Only (bit 40) event selector bits across all relevant SVM state transitions. The test programs 4 PMCs simultaneously with all combinations of the Host-Only and Guest-Only bits, then verifies correct counting behavior with EFER.SVME clear and set, as well as in host mode and guest mode. The test also verifies that updating Host-Only / Guest-Only bits for a PMC works as intended, and that event filtering is still respected. Signed-off-by: Jim Mattson Co-developed-by: Yosry Ahmed Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/Makefile.kvm | 1 + tools/testing/selftests/kvm/include/x86/pmu.h | 6 + .../kvm/x86/svm_pmu_host_guest_test.c | 216 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test= .c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 2908eca1647a1..4449851bc0f23 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -119,6 +119,7 @@ TEST_GEN_PROGS_x86 +=3D x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_soft_inject_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_vmcb12_gpa TEST_GEN_PROGS_x86 +=3D x86/svm_lbr_nested_state +TEST_GEN_PROGS_x86 +=3D x86/svm_pmu_host_guest_test TEST_GEN_PROGS_x86 +=3D x86/tsc_scaling_sync TEST_GEN_PROGS_x86 +=3D x86/sync_regs_test TEST_GEN_PROGS_x86 +=3D x86/ucna_injection_test diff --git a/tools/testing/selftests/kvm/include/x86/pmu.h b/tools/testing/= selftests/kvm/include/x86/pmu.h index 98537cc8840d1..608ed83d7c6a6 100644 --- a/tools/testing/selftests/kvm/include/x86/pmu.h +++ b/tools/testing/selftests/kvm/include/x86/pmu.h @@ -38,6 +38,12 @@ #define ARCH_PERFMON_EVENTSEL_INV BIT_ULL(23) #define ARCH_PERFMON_EVENTSEL_CMASK GENMASK_ULL(31, 24) =20 +/* + * These are AMD-specific bits. + */ +#define AMD64_EVENTSEL_GUESTONLY BIT_ULL(40) +#define AMD64_EVENTSEL_HOSTONLY BIT_ULL(41) + /* RDPMC control flags, Intel only. */ #define INTEL_RDPMC_METRICS BIT_ULL(29) #define INTEL_RDPMC_FIXED BIT_ULL(30) diff --git a/tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c b/to= ols/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c new file mode 100644 index 0000000000000..ee4633ab79aa7 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_pmu_host_guest_test.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KVM nested SVM PMU Host-Only/Guest-Only test + * + * Copyright (C) 2026, Google LLC. + * + * Test that KVM correctly virtualizes the AMD PMU Host-Only (bit 41) and + * Guest-Only (bit 40) event selector bits across all SVM state + * transitions. + * + * Programs 4 PMCs simultaneously with all combinations of Host-Only and + * Guest-Only bits, then verifies correct counting behavior with different + * combinations of EFER.SVME and host/guest mode -- as well as event filte= ring. + */ +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" +#include "pmu.h" + +#define EVENTSEL_RETIRED_INSNS (ARCH_PERFMON_EVENTSEL_OS | \ + ARCH_PERFMON_EVENTSEL_USR | \ + ARCH_PERFMON_EVENTSEL_ENABLE | \ + AMD_ZEN_INSTRUCTIONS_RETIRED) + +/* PMC configurations: index corresponds to Host-Only | Guest-Only bits */ +#define PMC_NONE 0 /* Neither bit set */ +#define PMC_G 1 /* Guest-Only bit set */ +#define PMC_H 2 /* Host-Only bit set */ +#define PMC_HG 3 /* Both bits set */ +#define NR_PMCS 4 + +#define LOOP_INSNS 1000 + +static __always_inline void run_instruction_loop(void) +{ + unsigned int i; + + for (i =3D 0; i < LOOP_INSNS; i++) + __asm__ __volatile__("nop"); +} + +static __always_inline void read_counters(uint64_t *counts) +{ + int i; + + for (i =3D 0; i < NR_PMCS; i++) + counts[i] =3D rdmsr(MSR_F15H_PERF_CTR + 2 * i); +} + +static __always_inline void run_and_measure(uint64_t *deltas) +{ + uint64_t before[NR_PMCS], after[NR_PMCS]; + int i; + + read_counters(before); + run_instruction_loop(); + read_counters(after); + + for (i =3D 0; i < NR_PMCS; i++) + deltas[i] =3D after[i] - before[i]; +} + +static void assert_pmc_counts(uint64_t *deltas, unsigned int expected_coun= ting) +{ + int i; + + for (i =3D 0; i < NR_PMCS; i++) { + if (expected_counting & BIT(i)) + GUEST_ASSERT_NE(deltas[i], 0); + else + GUEST_ASSERT_EQ(deltas[i], 0); + } +} + +static uint64_t l2_deltas[NR_PMCS]; + +static void l2_guest_code(void) +{ + run_and_measure(l2_deltas); + vmmcall(); +} + +static void l1_guest_code(struct svm_test_data *svm) +{ + struct vmcb *vmcb =3D svm->vmcb; + uint64_t deltas[NR_PMCS]; + uint64_t eventsel; + int i; + + /* Program 4 PMCs with all combinations of Host-Only/Guest-Only bits */ + for (i =3D 0; i < NR_PMCS; i++) { + eventsel =3D EVENTSEL_RETIRED_INSNS; + if (i & PMC_G) + eventsel |=3D AMD64_EVENTSEL_GUESTONLY; + if (i & PMC_H) + eventsel |=3D AMD64_EVENTSEL_HOSTONLY; + wrmsr(MSR_F15H_PERF_CTL + 2 * i, eventsel); + wrmsr(MSR_F15H_PERF_CTR + 2 * i, 0); + } + + /* Step 1: SVME=3D0 - Only the counter with neither bits set counts */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) & ~EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE)); + + /* Step 2: Set SVME=3D1 - In L1 "host mode"; Guest-Only stops */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 3: VMRUN to L2 - In "guest mode"; Host-Only stops */ + generic_svm_setup(svm, l2_guest_code); + vmcb->control.intercept &=3D ~(1ULL << INTERCEPT_MSR_PROT); + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + assert_pmc_counts(l2_deltas, BIT(PMC_NONE) | BIT(PMC_G) | BIT(PMC_HG)); + + /* Step 4: After VMEXIT to L1 - Back in "host mode"; Guest-Only stops */ + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 5: Set KVM_PMU_EVENT_DENY - all counters stop */ + GUEST_SYNC(KVM_PMU_EVENT_DENY); + run_and_measure(deltas); + assert_pmc_counts(deltas, 0); + + /* Step 6: Set KVM_PMU_EVENT_ALLOW - back to all except Guest-only */ + GUEST_SYNC(KVM_PMU_EVENT_ALLOW); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 7: Clear Host-Only for PMC_HG - counter stops in "host mode" */ + eventsel =3D rdmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG); + wrmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG, eventsel & ~AMD64_EVENTSEL_HOSTONLY= ); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H)); + + /* Step 8: Restore Host-Only for PMC_HG - counter counts again */ + wrmsr(MSR_F15H_PERF_CTL + 2 * PMC_HG, eventsel); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE) | BIT(PMC_H) | BIT(PMC_HG)); + + /* Step 9: Clear SVME - Only the counter with neither bits set counts */ + wrmsr(MSR_EFER, rdmsr(MSR_EFER) & ~EFER_SVME); + run_and_measure(deltas); + assert_pmc_counts(deltas, BIT(PMC_NONE)); + + GUEST_DONE(); +} + +static struct kvm_pmu_event_filter *alloc_event_filter(u64 event) +{ + struct kvm_pmu_event_filter *filter; + + filter =3D malloc(sizeof(*filter) + sizeof(event)); + TEST_ASSERT(filter !=3D NULL, "Filter allocation failed"); + + memset(filter, 0, sizeof(*filter)); + memcpy(filter->events, &event, sizeof(event)); + filter->nevents =3D 1; + filter->action =3D KVM_PMU_EVENT_ALLOW; + + return filter; +} + +int main(int argc, char *argv[]) +{ + struct kvm_pmu_event_filter *filter; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + gva_t svm_gva; + + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + TEST_REQUIRE(kvm_is_pmu_enabled()); + TEST_REQUIRE(get_kvm_amd_param_bool("enable_mediated_pmu")); + TEST_REQUIRE(host_cpu_is_amd && kvm_cpu_family() >=3D 0x17); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_guest_code); + + vcpu_alloc_svm(vm, &svm_gva); + vcpu_args_set(vcpu, 1, svm_gva); + + filter =3D alloc_event_filter(AMD_ZEN_INSTRUCTIONS_RETIRED); + + for (;;) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + goto done; + case UCALL_DONE: + goto done; + case UCALL_SYNC: + filter->action =3D uc.args[1]; + vm_ioctl(vm, KVM_SET_PMU_EVENT_FILTER, filter); + break; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + goto done; + } + } +done: + kvm_vm_free(vm); + return 0; +} --=20 2.54.0.794.g4f17f83d09-goog