[SRU][F][PATCH 2/6] x86/kvm: Add AMD SEV specific Hypercall3

Khalid Elmously khalid.elmously at canonical.com
Tue Aug 9 07:17:59 UTC 2022

From: Brijesh Singh <brijesh.singh at amd.com>

BugLink: https://launchpad.net/bugs/1984034

KVM hypercall framework relies on alternative framework to patch the
VMCALL -> VMMCALL on AMD platform. If a hypercall is made before
apply_alternative() is called then it defaults to VMCALL. The approach
works fine on non SEV guest. A VMCALL would causes #UD, and hypervisor
will be able to decode the instruction and do the right things. But
when SEV is active, guest memory is encrypted with guest key and
hypervisor will not be able to decode the instruction bytes.

To highlight the need to provide this interface, capturing the
flow of apply_alternatives() :
setup_arch() call init_hypervisor_platform() which detects
the hypervisor platform the kernel is running under and then the
hypervisor specific initialization code can make early hypercalls.
For example, KVM specific initialization in case of SEV will try
to mark the "__bss_decrypted" section's encryption state via early
page encryption status hypercalls.

Now, apply_alternatives() is called much later when setup_arch()
calls check_bugs(), so we do need some kind of an early,
pre-alternatives hypercall interface. Other cases of pre-alternatives
hypercalls include marking per-cpu GHCB pages as decrypted on SEV-ES
and per-cpu apf_reason, steal_time and kvm_apic_eoi as decrypted for
SEV generally.

Add SEV specific hypercall3, it unconditionally uses VMMCALL. The hypercall
will be used by the SEV guest to notify encrypted pages to the hypervisor.

This kvm_sev_hypercall3() function is abstracted and used as follows :
All these early hypercalls are made through early_set_memory_XX() interfaces,
which in turn invoke pv_ops (paravirt_ops).

This early_set_memory_XX() -> pv_ops.mmu.notify_page_enc_status_changed()
is a generic interface and can easily have SEV, TDX and any other
future platform specific abstractions added to it.

Currently, pv_ops.mmu.notify_page_enc_status_changed() callback is setup to
invoke kvm_sev_hypercall3() in case of SEV.

Similarly, in case of TDX, pv_ops.mmu.notify_page_enc_status_changed()
can be setup to a TDX specific callback.

Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: "H. Peter Anvin" <hpa at zytor.com>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Cc: Joerg Roedel <joro at 8bytes.org>
Cc: Borislav Petkov <bp at suse.de>
Cc: Tom Lendacky <thomas.lendacky at amd.com>
Cc: x86 at kernel.org
Cc: kvm at vger.kernel.org
Cc: linux-kernel at vger.kernel.org
Reviewed-by: Steve Rutherford <srutherford at google.com>
Reviewed-by: Venu Busireddy <venu.busireddy at oracle.com>
Signed-off-by: Brijesh Singh <brijesh.singh at amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra at amd.com>
Message-Id: <6fd25c749205dd0b1eb492c60d41b124760cc6ae.1629726117.git.ashish.kalra at amd.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
(cherry picked from commit 08c2336df78d01fd4d634b14262ea739c399ddbd)
Signed-off-by: Khalid Elmously <khalid.elmously at canonical.com>
 arch/x86/include/asm/kvm_para.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 7ff8ad490a782..821eb160f50ab 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -82,6 +82,18 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
 	return ret;
+static inline long kvm_sev_hypercall3(unsigned int nr, unsigned long p1,
+				      unsigned long p2, unsigned long p3)
+	long ret;
+	asm volatile("vmmcall"
+		     : "=a"(ret)
+		     : "a"(nr), "b"(p1), "c"(p2), "d"(p3)
+		     : "memory");
+	return ret;
 void kvmclock_init(void);
 void kvmclock_disable(void);

More information about the kernel-team mailing list