Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource/drivers/hyper-v: Suspend/resume Hyper-V clocksource for hibernation

This is needed for hibernation, e.g. when we resume the old kernel, we need
to disable the "current" kernel's TSC page and then resume the old kernel's.

Signed-off-by: Dexuan Cui <decui@microsoft.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/1574233946-48377-1-git-send-email-decui@microsoft.com

authored by

Dexuan Cui and committed by
Daniel Lezcano
1349401f 5167c506

+25
+25
drivers/clocksource/hyperv_timer.c
··· 330 330 return read_hv_clock_tsc(NULL) - hv_sched_clock_offset; 331 331 } 332 332 333 + static void suspend_hv_clock_tsc(struct clocksource *arg) 334 + { 335 + u64 tsc_msr; 336 + 337 + /* Disable the TSC page */ 338 + hv_get_reference_tsc(tsc_msr); 339 + tsc_msr &= ~BIT_ULL(0); 340 + hv_set_reference_tsc(tsc_msr); 341 + } 342 + 343 + 344 + static void resume_hv_clock_tsc(struct clocksource *arg) 345 + { 346 + phys_addr_t phys_addr = virt_to_phys(&tsc_pg); 347 + u64 tsc_msr; 348 + 349 + /* Re-enable the TSC page */ 350 + hv_get_reference_tsc(tsc_msr); 351 + tsc_msr &= GENMASK_ULL(11, 0); 352 + tsc_msr |= BIT_ULL(0) | (u64)phys_addr; 353 + hv_set_reference_tsc(tsc_msr); 354 + } 355 + 333 356 static struct clocksource hyperv_cs_tsc = { 334 357 .name = "hyperv_clocksource_tsc_page", 335 358 .rating = 400, 336 359 .read = read_hv_clock_tsc, 337 360 .mask = CLOCKSOURCE_MASK(64), 338 361 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 362 + .suspend= suspend_hv_clock_tsc, 363 + .resume = resume_hv_clock_tsc, 339 364 }; 340 365 341 366 static u64 notrace read_hv_clock_msr(struct clocksource *arg)