x86/vmware: Add VMware-specific handling for VMMCALL under SEV-ES
authorDoug Covelli <dcovelli@vmware.com>
Mon, 7 Sep 2020 13:16:05 +0000 (15:16 +0200)
committerBorislav Petkov <bp@suse.de>
Wed, 9 Sep 2020 09:33:20 +0000 (11:33 +0200)
Add VMware-specific handling for #VC faults caused by VMMCALL
instructions.

Signed-off-by: Doug Covelli <dcovelli@vmware.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
[ jroedel@suse.de: - Adapt to different paravirt interface ]
Co-developed-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200907131613.12703-65-joro@8bytes.org
arch/x86/kernel/cpu/vmware.c

index 9b6fafa69be9248e5da2d1165690987432ff0a5f..924571fe5864b46182894ffa92cc8014f15a5790 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/timer.h>
 #include <asm/apic.h>
 #include <asm/vmware.h>
+#include <asm/svm.h>
 
 #undef pr_fmt
 #define pr_fmt(fmt)    "vmware: " fmt
@@ -476,10 +477,49 @@ static bool __init vmware_legacy_x2apic_available(void)
               (eax & (1 << VMWARE_CMD_LEGACY_X2APIC)) != 0;
 }
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+static void vmware_sev_es_hcall_prepare(struct ghcb *ghcb,
+                                       struct pt_regs *regs)
+{
+       /* Copy VMWARE specific Hypercall parameters to the GHCB */
+       ghcb_set_rip(ghcb, regs->ip);
+       ghcb_set_rbx(ghcb, regs->bx);
+       ghcb_set_rcx(ghcb, regs->cx);
+       ghcb_set_rdx(ghcb, regs->dx);
+       ghcb_set_rsi(ghcb, regs->si);
+       ghcb_set_rdi(ghcb, regs->di);
+       ghcb_set_rbp(ghcb, regs->bp);
+}
+
+static bool vmware_sev_es_hcall_finish(struct ghcb *ghcb, struct pt_regs *regs)
+{
+       if (!(ghcb_rbx_is_valid(ghcb) &&
+             ghcb_rcx_is_valid(ghcb) &&
+             ghcb_rdx_is_valid(ghcb) &&
+             ghcb_rsi_is_valid(ghcb) &&
+             ghcb_rdi_is_valid(ghcb) &&
+             ghcb_rbp_is_valid(ghcb)))
+               return false;
+
+       regs->bx = ghcb->save.rbx;
+       regs->cx = ghcb->save.rcx;
+       regs->dx = ghcb->save.rdx;
+       regs->si = ghcb->save.rsi;
+       regs->di = ghcb->save.rdi;
+       regs->bp = ghcb->save.rbp;
+
+       return true;
+}
+#endif
+
 const __initconst struct hypervisor_x86 x86_hyper_vmware = {
-       .name                   = "VMware",
-       .detect                 = vmware_platform,
-       .type                   = X86_HYPER_VMWARE,
-       .init.init_platform     = vmware_platform_setup,
-       .init.x2apic_available  = vmware_legacy_x2apic_available,
+       .name                           = "VMware",
+       .detect                         = vmware_platform,
+       .type                           = X86_HYPER_VMWARE,
+       .init.init_platform             = vmware_platform_setup,
+       .init.x2apic_available          = vmware_legacy_x2apic_available,
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+       .runtime.sev_es_hcall_prepare   = vmware_sev_es_hcall_prepare,
+       .runtime.sev_es_hcall_finish    = vmware_sev_es_hcall_finish,
+#endif
 };