[PATCH 1/5] UBUNTU: SAUCE: clocksource: hyper-v: Use InvariantTSC and enable TSC page for TDX VM (WIP)

Tim Gardner tim.gardner at canonical.com
Mon Jul 24 17:00:13 UTC 2023


From: Dexuan Cui <decui at microsoft.com>

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

Need to better address the __bss_decrypted attribute of 'tsc_pg'.

(cherry picked from commit 662d8f2222aef359039363eeba856d7a6a8ad87b https://github.com/dcui/linux/commit/662d8f2222aef359039363eeba856d7a6a8ad87b)
Signed-off-by: Dexuan Cui <decui at microsoft.com>
(cherry picked from commit 2da82f8783279af94eca2f707a87d41ea648f417 https://github.com/dcui/linux)
Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
---
 arch/x86/entry/vdso/vma.c          | 11 ++++++++---
 arch/x86/kernel/cpu/mshyperv.c     |  4 ----
 drivers/clocksource/hyperv_timer.c | 15 +++++++++++++--
 include/asm-generic/mshyperv.h     |  8 +++++++-
 4 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index b8f3f9b9e53c..809eb6644aff 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -17,6 +17,7 @@
 #include <linux/time_namespace.h>
 
 #include <asm/pvclock.h>
+#include <asm/mshyperv.h>
 #include <asm/vgtod.h>
 #include <asm/proto.h>
 #include <asm/vdso.h>
@@ -188,9 +189,13 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
 		}
 	} else if (sym_offset == image->sym_hvclock_page) {
 		pfn = hv_get_tsc_pfn();
-
-		if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
-			return vmf_insert_pfn(vma, vmf->address, pfn);
+		if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK)) {
+			if (ms_hyperv.paravisor_present)
+				return vmf_insert_pfn(vma, vmf->address, pfn);
+			else
+				return vmf_insert_pfn_prot(vma, vmf->address,
+					pfn, pgprot_decrypted(vma->vm_page_prot));
+		}
 	} else if (sym_offset == image->sym_timens_page) {
 		struct page *timens_page = find_timens_vvar_page(vma);
 
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 76701edbc0c5..9aad261d2843 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -440,10 +440,6 @@ static void __init ms_hyperv_init_platform(void)
 			 */
 			ms_hyperv.shared_gpa_boundary = cc_mkdec(0);
 
-			/* Don't use the unsafe Hyper-V TSC page */
-			ms_hyperv.features &=
-				~HV_MSR_REFERENCE_TSC_AVAILABLE;
-
 			/* HV_REGISTER_CRASH_CTL is unsupported */
 			ms_hyperv.misc_features &=
 				 ~HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE;
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index 7901a88ad918..55f029c39fdf 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/acpi.h>
 #include <linux/hyperv.h>
+#include <linux/set_memory.h>
 #include <clocksource/hyperv_timer.h>
 #include <asm/hyperv-tlfs.h>
 #include <asm/mshyperv.h>
@@ -364,8 +365,8 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup);
 
 static union {
 	struct ms_hyperv_tsc_page page;
-	u8 reserved[PAGE_SIZE];
-} tsc_pg __aligned(PAGE_SIZE);
+	u8 reserved[SZ_2M];
+} tsc_pg __bss_decrypted __aligned(SZ_2M);
 
 static struct ms_hyperv_tsc_page *tsc_page = &tsc_pg.page;
 static unsigned long tsc_pfn;
@@ -505,6 +506,7 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
 static bool __init hv_init_tsc_clocksource(void)
 {
 	union hv_reference_tsc_msr tsc_msr;
+	int ret;
 
 	/*
 	 * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly
@@ -527,6 +529,11 @@ static bool __init hv_init_tsc_clocksource(void)
 
 	hv_read_reference_counter = read_hv_clock_tsc;
 
+	if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present) {
+		ret = set_memory_decrypted((unsigned long)tsc_page, SZ_2M/PAGE_SIZE);
+		BUG_ON(ret);
+		memset(tsc_page, 0, PAGE_SIZE);
+	}
 	/*
 	 * TSC page mapping works differently in root compared to guest.
 	 * - In guest partition the guest PFN has to be passed to the
@@ -550,6 +557,10 @@ static bool __init hv_init_tsc_clocksource(void)
 		tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page));
 	tsc_msr.enable = 1;
 	tsc_msr.pfn = tsc_pfn;
+
+	if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present)
+		tsc_msr.pfn = PHYS_PFN(cc_mkdec(PFN_PHYS(tsc_msr.pfn)));
+
 	hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
 
 	clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index ddc1599d17e9..3e48cdc02b74 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -36,7 +36,13 @@ struct ms_hyperv_info {
 	u32 nested_features;
 	u32 max_vp_index;
 	u32 max_lp_index;
-	u32 isolation_config_a;
+	union {
+		u32 isolation_config_a;
+		struct {
+			u32 paravisor_present	: 1;
+			u32 reserved0		: 31;
+		};
+	};
 	union {
 		u32 isolation_config_b;
 		struct {
-- 
2.34.1




More information about the kernel-team mailing list