From: Sasha Levin sashal@kernel.org Sent: Friday, November 18, 2022 6:11 PM
From: Anirudh Rayabharam anrayabh@linux.microsoft.com
[ Upstream commit 4ad1aa571214e8d6468a1806794d987b374b5a08 ]
Add a data structure to represent the reference TSC MSR similar to other MSRs. This simplifies the code for updating the MSR.
Signed-off-by: Anirudh Rayabharam anrayabh@linux.microsoft.com Reviewed-by: Michael Kelley mikelley@microsoft.com Link: https://lore.kernel.org/all/20221027095729.1676394-2-anrayabh@linux.microsof... Signed-off-by: Wei Liu wei.liu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org
Sasha -- I don't think this patch needs to be backported to any stable versions. Anirudh or Wei Liu, can you confirm? The patch is more about enabling a new scenario than fixing a bug.
Michael
drivers/clocksource/hyperv_timer.c | 29 +++++++++++++++-------------- include/asm-generic/hyperv-tlfs.h | 9 +++++++++ 2 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index bb47610bbd1c..18de1f439ffd 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -21,6 +21,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/acpi.h> +#include <linux/hyperv.h> #include <clocksource/hyperv_timer.h> #include <asm/hyperv-tlfs.h> #include <asm/mshyperv.h> @@ -395,25 +396,25 @@ static u64 notrace read_hv_sched_clock_tsc(void)
static void suspend_hv_clock_tsc(struct clocksource *arg) {
- u64 tsc_msr;
union hv_reference_tsc_msr tsc_msr;
/* Disable the TSC page */
- tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC);
- tsc_msr &= ~BIT_ULL(0);
- hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr);
- tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
- tsc_msr.enable = 0;
- hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
}
static void resume_hv_clock_tsc(struct clocksource *arg) { phys_addr_t phys_addr = virt_to_phys(&tsc_pg);
- u64 tsc_msr;
union hv_reference_tsc_msr tsc_msr;
/* Re-enable the TSC page */
- tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC);
- tsc_msr &= GENMASK_ULL(11, 0);
- tsc_msr |= BIT_ULL(0) | (u64)phys_addr;
- hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr);
- tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
- tsc_msr.enable = 1;
- tsc_msr.pfn = HVPFN_DOWN(phys_addr);
- hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
}
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK @@ -495,7 +496,7 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
static bool __init hv_init_tsc_clocksource(void) {
- u64 tsc_msr;
union hv_reference_tsc_msr tsc_msr; phys_addr_t phys_addr;
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
@@ -530,10 +531,10 @@ static bool __init hv_init_tsc_clocksource(void) * (which already has at least the low 12 bits set to zero since * it is page aligned). Also set the "enable" bit, which is bit 0. */
- tsc_msr = hv_get_register(HV_REGISTER_REFERENCE_TSC);
- tsc_msr &= GENMASK_ULL(11, 0);
- tsc_msr = tsc_msr | 0x1 | (u64)phys_addr;
- hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr);
tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
tsc_msr.enable = 1;
tsc_msr.pfn = HVPFN_DOWN(phys_addr);
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/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index fdce7a4cfc6f..b17c6eeb9afa 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -102,6 +102,15 @@ struct ms_hyperv_tsc_page { volatile s64 tsc_offset; } __packed;
+union hv_reference_tsc_msr {
- u64 as_uint64;
- struct {
u64 enable:1;
u64 reserved:11;
u64 pfn:52;
- } __packed;
+};
/*
- The guest OS needs to register the guest ID with the hypervisor.
- The guest ID is a 64 bit entity and the structure of this ID is
-- 2.35.1