lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250228085115.105648-15-Neeraj.Upadhyay@amd.com>
Date: Fri, 28 Feb 2025 14:21:10 +0530
From: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
To: <seanjc@...gle.com>, <pbonzini@...hat.com>, <kvm@...r.kernel.org>
CC: <linux-kernel@...r.kernel.org>, <bp@...en8.de>, <tglx@...utronix.de>,
	<mingo@...hat.com>, <dave.hansen@...ux.intel.com>, <Thomas.Lendacky@....com>,
	<nikunj@....com>, <Santosh.Shukla@....com>, <Vasant.Hegde@....com>,
	<Suravee.Suthikulpanit@....com>, <David.Kaplan@....com>, <x86@...nel.org>,
	<hpa@...or.com>, <peterz@...radead.org>, <huibo.wang@....com>,
	<naveen.rao@....com>, <binbin.wu@...ux.intel.com>, <isaku.yamahata@...el.com>
Subject: [RFC PATCH 14/19] KVM: SVM/SEV: Add SVM_VMGEXIT_SECURE_AVIC GHCB protocol event handling

This GHCB protocol event is used by the guest to notify KVM
of the GPA of the APIC backing page being used by a vCPU. The APIC ID
parameter is used to identify the vCPU to which the backing page
action is related is assigned. An APIC ID value of 0xffff_ffff_ffff_ffff
means that the backing page action is for the vCPU performing the call.

Secure AVIC requires the guest vCPU APIC backing page entry to be
always present in the guest’s Nested Paginge Table (NPT) while the
vCPU is running because some AVIC hardware acceleration sequences
may not be restartable when Secure AVIC is enabled. If an access to
the guest's APIC backing page by Secure AVIC hardware results in a
nested page fault, the BUSY bit in the VMSA is set and subsequent
VMRUN fails with a VMEXIT_BUSY error code. VMEXIT_BUSY is unrecoverable
in this instance and the vCPU cannot be resumed post this event.

Two actions are available to the guest to notify KVM of these pages.

• SVM_VMGEXIT_SAVIC_REGISTER_BACKING_PAGE (0)

A Secure AVIC guest should use this action to inform KVM of the
page-aligned GPA that will be used as the Secure AVIC backing
page for the specified vCPU.

To ensure that the backing page NPT entry is present while vCPU is
running, KVM does a PSMASH for the GPA if the corresponding NPT entry
is of size 2M. Without PSMASH, it is possible for other allocations
to be part of the same 2M page as the APIC backing page and any
modifications (page state change from private to shared) to any one
of those allocations would result in splitting the 2M page to 4K pages.
This would result in zapping the 2M PTE while APIC backing page is
potentially being accessed by Secure AVIC hardware.

Setting a Secure AVIC backing page GPA automatically clears any
currently set Secure AVIC backing page GPA.

• SVM_VMGEXIT_SAVIC_UNREGISTER_BACKING_PAGE (1)

A guest may use this action to inform KVM that the previously set
GPA is no longer being used as the Secure AVIC backing page for
the specified vCPU. This removes the requirement on KVM to ensure
that the specified GPA is always present in the NPT of the guest
while the specified vCPU is running. KVM returns the GPA that was
currently SET or 0 if there was no previously set GPA.

Co-developed-by: Kishon Vijay Abraham I <kvijayab@....com>
Signed-off-by: Kishon Vijay Abraham I <kvijayab@....com>
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
---

Initial GHCB draft spec for the new GHCB event for Secure AVIC is at:

https://lore.kernel.org/linux-coco/3453675d-ca29-4715-9c17-10b56b3af17e@amd.com/T/#u

The GHCB event has been updated to pass the action param
for GPA register/unregister. The new GHCB spec will be published soon.
I will share the link to the updated spec once it is available
publically.


 arch/x86/include/uapi/asm/svm.h |  3 ++
 arch/x86/kvm/svm/sev.c          | 58 +++++++++++++++++++++++++++++++++
 arch/x86/kvm/svm/svm.h          |  1 +
 3 files changed, 62 insertions(+)

diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
index ec1321248dac..0a1e8687f464 100644
--- a/arch/x86/include/uapi/asm/svm.h
+++ b/arch/x86/include/uapi/asm/svm.h
@@ -117,6 +117,9 @@
 #define SVM_VMGEXIT_AP_CREATE			1
 #define SVM_VMGEXIT_AP_DESTROY			2
 #define SVM_VMGEXIT_SNP_RUN_VMPL		0x80000018
+#define SVM_VMGEXIT_SECURE_AVIC			0x8000001a
+#define SVM_VMGEXIT_SAVIC_REGISTER_BACKING_PAGE	0
+#define SVM_VMGEXIT_SAVIC_UNREGISTER_BACKING_PAGE	1
 #define SVM_VMGEXIT_HV_FEATURES			0x8000fffd
 #define SVM_VMGEXIT_TERM_REQUEST		0x8000fffe
 #define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code)	\
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 40314c4086c2..77c1ecebf677 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3400,6 +3400,14 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
 		    !kvm_ghcb_rcx_is_valid(svm))
 			goto vmgexit_err;
 		break;
+	case SVM_VMGEXIT_SECURE_AVIC:
+		if (!sev_savic_active(vcpu->kvm) ||
+		    !kvm_ghcb_rax_is_valid(svm))
+			goto vmgexit_err;
+		if (svm->vmcb->control.exit_info_1 == SVM_VMGEXIT_SAVIC_REGISTER_BACKING_PAGE)
+			if (!kvm_ghcb_rbx_is_valid(svm))
+				goto vmgexit_err;
+		break;
 	case SVM_VMGEXIT_MMIO_READ:
 	case SVM_VMGEXIT_MMIO_WRITE:
 		if (!kvm_ghcb_sw_scratch_is_valid(svm))
@@ -4511,6 +4519,53 @@ static bool savic_handle_msr_exit(struct kvm_vcpu *vcpu)
 	return false;
 }
 
+static int sev_handle_savic_vmgexit(struct vcpu_svm *svm)
+{
+	struct kvm_vcpu *vcpu = NULL;
+	u64 apic_id;
+
+	apic_id = kvm_rax_read(&svm->vcpu);
+
+	if (apic_id == -1ULL) {
+		vcpu = &svm->vcpu;
+	} else {
+		vcpu = kvm_get_vcpu_by_id(vcpu->kvm, apic_id);
+		if (!vcpu)
+			goto savic_request_invalid;
+	}
+
+	switch (svm->vmcb->control.exit_info_1) {
+	case SVM_VMGEXIT_SAVIC_REGISTER_BACKING_PAGE:
+		gpa_t gpa;
+
+		gpa = kvm_rbx_read(&svm->vcpu);
+		if (!PAGE_ALIGNED(gpa))
+			goto savic_request_invalid;
+
+		/*
+		 * sev_handle_rmp_fault() invocation would result in PSMASH if
+		 * NPTE size is 2M.
+		 */
+		sev_handle_rmp_fault(vcpu, gpa, 0);
+		to_svm(vcpu)->sev_savic_gpa = gpa;
+		break;
+	case SVM_VMGEXIT_SAVIC_UNREGISTER_BACKING_PAGE:
+		kvm_rbx_write(&svm->vcpu, to_svm(vcpu)->sev_savic_gpa);
+		to_svm(vcpu)->sev_savic_gpa = 0;
+		break;
+	default:
+		goto savic_request_invalid;
+	}
+
+	return 1;
+
+savic_request_invalid:
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
+
+	return 1;
+}
+
 int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -4653,6 +4708,9 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
 			    control->exit_info_1, control->exit_info_2);
 		ret = -EINVAL;
 		break;
+	case SVM_VMGEXIT_SECURE_AVIC:
+		ret = sev_handle_savic_vmgexit(svm);
+		break;
 	case SVM_EXIT_MSR:
 		if (sev_savic_active(vcpu->kvm) && savic_handle_msr_exit(vcpu))
 			return 1;
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 62e3581b7d31..be87b9a0284f 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -329,6 +329,7 @@ struct vcpu_svm {
 	bool guest_gif;
 
 	bool sev_savic_has_pending_ipi;
+	gpa_t sev_savic_gpa;
 };
 
 struct svm_cpu_data {
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ