From: David Woodhouse Implement the read_raw() callback for the Hyper-V TSC page clocksource. This returns the derived 10MHz reference time (for timekeeping) while also providing the raw TSC value that was used to compute it. When the TSC page is valid, hv_read_tsc_page_tsc() atomically captures both values from a single RDTSC inside the sequence-counter protected read. When the TSC page is invalid (sequence == 0), raw is set to zero indicating no value is available. This enables ktime_get_snapshot_id() to provide the raw TSC to consumers like KVM's master clock when running nested on Hyper-V. Signed-off-by: David Woodhouse Assisted-by: Kiro:claude-opus-4.6-1m --- drivers/clocksource/hyperv_timer.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index e9f5034a1bc8..c5ae01fdbd8e 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -444,6 +444,18 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg) return read_hv_clock_tsc(); } +static u64 notrace read_hv_clock_tsc_cs_raw(struct clocksource *arg, u64 *raw) +{ + u64 time; + + if (!hv_read_tsc_page_tsc(tsc_page, raw, &time)) { + time = read_hv_clock_msr(); + *raw = 0; + } + + return time; +} + static u64 noinstr read_hv_sched_clock_tsc(void) { return (read_hv_clock_tsc() - hv_sched_clock_offset) * @@ -495,6 +507,8 @@ static struct clocksource hyperv_cs_tsc = { .name = "hyperv_clocksource_tsc_page", .rating = 500, .read = read_hv_clock_tsc_cs, + .read_raw = read_hv_clock_tsc_cs_raw, + .raw_csid = CSID_X86_TSC, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, .suspend= suspend_hv_clock_tsc, -- 2.54.0