drivers/clocksource/hyperv_timer.c
Source file repositories/reference/linux-study-clean/drivers/clocksource/hyperv_timer.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clocksource/hyperv_timer.c- Extension
.c- Size
- 18451 bytes
- Lines
- 669
- Domain
- Driver Families
- Bucket
- drivers/clocksource
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/percpu.hlinux/cpumask.hlinux/clockchips.hlinux/clocksource.hlinux/sched_clock.hlinux/mm.hlinux/cpuhotplug.hlinux/interrupt.hlinux/irq.hlinux/acpi.hlinux/hyperv.hlinux/export.hclocksource/hyperv_timer.hhyperv/hvhdk.hasm/mshyperv.hasm/timer.h
Detected Declarations
function hv_stimer0_isrfunction hv_stimer0_percpu_isrfunction hv_ce_set_next_eventfunction hv_ce_shutdownfunction hv_ce_set_oneshotfunction hv_stimer_initfunction hv_stimer_cleanupfunction hv_setup_stimer0_handlerfunction hv_remove_stimer0_handlerfunction hv_setup_stimer0_irqfunction hv_remove_stimer0_irqfunction hv_setup_stimer0_irqfunction hv_remove_stimer0_irqfunction hv_stimer_legacy_initfunction hv_stimer_legacy_cleanupfunction hv_stimer_global_cleanupfunction hv_stime_legacy_cleanupfunction read_hv_clock_msrfunction hv_get_tsc_pfnfunction read_hv_clock_tscfunction read_hv_clock_tsc_csfunction read_hv_clock_tsc_cs_snapshotfunction read_hv_sched_clock_tscfunction suspend_hv_clock_tscfunction resume_hv_clock_tscfunction hv_adj_sched_clock_offsetfunction hv_cs_enablefunction read_hv_clock_msr_csfunction hv_setup_sched_clockfunction hv_setup_sched_clockfunction hv_setup_sched_clockfunction hv_root_partitionfunction hv_init_clocksourcefunction hv_remap_tsc_clocksourceexport hv_stimer0_isrexport hv_stimer_cleanupexport hv_stimer_allocexport hv_stimer_legacy_initexport hv_stimer_legacy_cleanupexport hv_stimer_global_cleanupexport hv_get_tsc_pfnexport hv_get_tsc_page
Annotated Snippet
static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
#endif /* CONFIG_GENERIC_SCHED_CLOCK */
static void __init hv_init_tsc_clocksource(void)
{
union hv_reference_tsc_msr tsc_msr;
/*
* When running as a guest partition:
*
* If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly
* handles frequency and offset changes due to live migration,
* pause/resume, and other VM management operations. So lower the
* Hyper-V Reference TSC rating, causing the generic TSC to be used.
* TSC_INVARIANT is not offered on ARM64, so the Hyper-V Reference
* TSC will be preferred over the virtualized ARM64 arch counter.
*
* When running as the root partition:
*
* There is no HV_ACCESS_TSC_INVARIANT feature. Always lower the rating
* of the Hyper-V Reference TSC.
*/
if ((ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) ||
hv_root_partition()) {
hyperv_cs_tsc.rating = 250;
hyperv_cs_msr.rating = 245;
}
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
return;
hv_read_reference_counter = read_hv_clock_tsc;
/*
* TSC page mapping works differently in root compared to guest.
* - In guest partition the guest PFN has to be passed to the
* hypervisor.
* - In root partition it's other way around: it has to map the PFN
* provided by the hypervisor.
* But it can't be mapped right here as it's too early and MMU isn't
* ready yet. So, we only set the enable bit here and will remap the
* page later in hv_remap_tsc_clocksource().
*
* It worth mentioning, that TSC clocksource read function
* (read_hv_clock_tsc) has a MSR-based fallback mechanism, used when
* TSC page is zeroed (which is the case until the PFN is remapped) and
* thus TSC clocksource will work even without the real TSC page
* mapped.
*/
tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC);
if (hv_root_partition())
tsc_pfn = tsc_msr.pfn;
else
tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page));
tsc_msr.enable = 1;
tsc_msr.pfn = tsc_pfn;
hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
/*
* If TSC is invariant, then let it stay as the sched clock since it
* will be faster than reading the TSC page. But if not invariant, use
* the TSC page so that live migrations across hosts with different
* frequencies is handled correctly.
*/
if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) {
hv_sched_clock_offset = hv_read_reference_counter();
hv_setup_sched_clock(read_hv_sched_clock_tsc);
}
}
void __init hv_init_clocksource(void)
{
/*
* Try to set up the TSC page clocksource, then the MSR clocksource.
* At least one of these will always be available except on very old
* versions of Hyper-V on x86. In that case we won't have a Hyper-V
* clocksource, but Linux will still run with a clocksource based
* on the emulated PIT or LAPIC timer.
*
* Never use the MSR clocksource as sched clock. It's too slow.
* Better to use the native sched clock as the fallback.
*/
hv_init_tsc_clocksource();
if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
}
Annotation
- Immediate include surface: `linux/percpu.h`, `linux/cpumask.h`, `linux/clockchips.h`, `linux/clocksource.h`, `linux/sched_clock.h`, `linux/mm.h`, `linux/cpuhotplug.h`, `linux/interrupt.h`.
- Detected declarations: `function hv_stimer0_isr`, `function hv_stimer0_percpu_isr`, `function hv_ce_set_next_event`, `function hv_ce_shutdown`, `function hv_ce_set_oneshot`, `function hv_stimer_init`, `function hv_stimer_cleanup`, `function hv_setup_stimer0_handler`, `function hv_remove_stimer0_handler`, `function hv_setup_stimer0_irq`.
- Atlas domain: Driver Families / drivers/clocksource.
- Implementation status: integration implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.