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