From: Alex James <[email protected]>

Encrypted VMware guests can use a virtual Trusted Platform Module
(vTPM) implemented by a paravisor, trusted code running alongside Linux
inside the protected VM. Its register page needs a private mapping so
accesses reach the paravisor instead of host device emulation.

The default ioremap() path maps device registers as shared. Without a
VMware private-MMIO override, this also applies to the vTPM registers,
preventing the guest from communicating with the paravisor's TPM.

Install is_private_mmio() for the vTPM's single register page when guest
memory encryption is active and firmware supplies a TPM event log. This
lets ioremap() select a private mapping for the device. Hyper-V already
does the same for its paravisor vTPM in hv_is_private_mmio(), added by
commit 812b0597fb40 ("x86/hyperv: Change vTOM handling to use standard
coco mechanisms").

[ zack: Moved the include and explained the private-mapping requirement ]

Signed-off-by: Alex James <[email protected]>
Signed-off-by: Zack Rusin <[email protected]>
---
 arch/x86/kernel/cpu/vmware.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 34b73573b108..afb40036ff49 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -26,6 +26,7 @@
 #include <linux/export.h>
 #include <linux/clocksource.h>
 #include <linux/cpu.h>
+#include <linux/tpm_ptp.h>
 #include <linux/efi.h>
 #include <linux/reboot.h>
 #include <linux/static_call.h>
@@ -374,6 +375,17 @@ static void __init vmware_paravirt_ops_setup(void)
 #define vmware_paravirt_ops_setup() do {} while (0)
 #endif
 
+/*
+ * VMware hypervisors use a paravisor to provide a secure vTPM device to
+ * encrypted VMs. The vTPM MMIO region must be mapped as private to ensure
+ * that it is handled by the paravisor.
+ */
+static bool vmware_is_private_mmio(u64 addr)
+{
+       return addr >= TIS_MEM_X86_LPC_BASE &&
+              addr < TIS_MEM_X86_LPC_BASE + PAGE_SIZE;
+}
+
 /*
  * VMware hypervisor takes care of exporting a reliable TSC to the guest.
  * Still, due to timing difference when running on virtual cpus, the TSC can
@@ -442,6 +454,12 @@ static void __init vmware_platform_setup(void)
 #endif
 
        vmware_set_capabilities();
+
+       if (IS_ENABLED(CONFIG_X86_MEM_ENCRYPT) &&
+           cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) &&
+           efi.tpm_log != EFI_INVALID_TABLE_ADDR) {
+               x86_platform.hyper.is_private_mmio = vmware_is_private_mmio;
+       }
 }
 
 static u8 __init vmware_select_hypercall(void)

base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222

Reply via email to