1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Clocksource driver for the synthetic counter and timers 5 * provided by the Hyper-V hypervisor to guest VMs, as described 6 * in the Hyper-V Top Level Functional Spec (TLFS). This driver 7 * is instruction set architecture independent. 8 * 9 * Copyright (C) 2019, Microsoft, Inc. 10 * 11 * Author: Michael Kelley <mikelley@microsoft.com> 12 */ 13 14 #include <linux/percpu.h> 15 #include <linux/cpumask.h> 16 #include <linux/clockchips.h> 17 #include <linux/clocksource.h> 18 #include <linux/sched_clock.h> 19 #include <linux/mm.h> 20 #include <linux/cpuhotplug.h> 21 #include <linux/interrupt.h> 22 #include <linux/irq.h> 23 #include <linux/acpi.h> 24 #include <linux/hyperv.h> 25 #include <linux/export.h> 26 #include <clocksource/hyperv_timer.h> 27 #include <hyperv/hvhdk.h> 28 #include <asm/mshyperv.h> 29 30 static struct clock_event_device __percpu *hv_clock_event; 31 /* Note: offset can hold negative values after hibernation. */ 32 static u64 hv_sched_clock_offset __read_mostly; 33 34 static int stimer0_irq = -1; 35 static __maybe_unused DEFINE_PER_CPU(long, stimer0_evt); 36 37 static void hv_stimer0_isr(void) 38 { 39 struct clock_event_device *ce; 40 41 ce = this_cpu_ptr(hv_clock_event); 42 ce->event_handler(ce); 43 } 44 45 /* 46 * stimer0 interrupt handler for architectures that support 47 * per-cpu interrupts 48 */ 49 static irqreturn_t __maybe_unused hv_stimer0_percpu_isr(int irq, void *dev_id) 50 { 51 hv_stimer0_isr(); 52 return IRQ_HANDLED; 53 } 54 55 static int hv_ce_set_next_event(unsigned long delta, 56 struct clock_event_device *evt) 57 { 58 u64 current_tick; 59 60 current_tick = hv_read_reference_counter(); 61 current_tick += delta; 62 hv_set_msr(HV_MSR_STIMER0_COUNT, current_tick); 63 return 0; 64 } 65 66 static int hv_ce_shutdown(struct clock_event_device *evt) 67 { 68 hv_set_msr(HV_MSR_STIMER0_COUNT, 0); 69 hv_set_msr(HV_MSR_STIMER0_CONFIG, 0); 70 if (stimer0_irq >= 0) 71 disable_percpu_irq(stimer0_irq); 72 73 return 0; 74 } 75 76 static int hv_ce_set_oneshot(struct clock_event_device *evt) 77 { 78 union hv_stimer_config timer_cfg; 79 80 timer_cfg.as_uint64 = 0; 81 timer_cfg.enable = 1; 82 timer_cfg.auto_enable = 1; 83 84 /* 85 * When it expires, the timer will directly interrupt 86 * on the specified hardware vector/IRQ. 87 */ 88 timer_cfg.direct_mode = 1; 89 timer_cfg.apic_vector = HYPERV_STIMER0_VECTOR; 90 if (stimer0_irq >= 0) 91 enable_percpu_irq(stimer0_irq, IRQ_TYPE_NONE); 92 93 hv_set_msr(HV_MSR_STIMER0_CONFIG, timer_cfg.as_uint64); 94 return 0; 95 } 96 97 /* 98 * hv_stimer_init - Per-cpu initialization of the clockevent 99 */ 100 static int hv_stimer_init(unsigned int cpu) 101 { 102 struct clock_event_device *ce; 103 104 if (!hv_clock_event) 105 return 0; 106 107 ce = per_cpu_ptr(hv_clock_event, cpu); 108 ce->name = "Hyper-V clockevent"; 109 ce->features = CLOCK_EVT_FEAT_ONESHOT; 110 ce->cpumask = cpumask_of(cpu); 111 112 /* 113 * Lower the rating of the Hyper-V timer in a TDX VM without paravisor, 114 * so the local APIC timer (lapic_clockevent) is the default timer in 115 * such a VM. The Hyper-V timer is not preferred in such a VM because 116 * it depends on the slow VM Reference Counter MSR (the Hyper-V TSC 117 * page is not enbled in such a VM because the VM uses Invariant TSC 118 * as a better clocksource and it's challenging to mark the Hyper-V 119 * TSC page shared in very early boot). 120 */ 121 if (!ms_hyperv.paravisor_present && hv_isolation_type_tdx()) 122 ce->rating = 90; 123 else 124 ce->rating = 1000; 125 126 ce->set_state_shutdown = hv_ce_shutdown; 127 ce->set_state_oneshot = hv_ce_set_oneshot; 128 ce->set_next_event = hv_ce_set_next_event; 129 130 clockevents_config_and_register(ce, 131 HV_CLOCK_HZ, 132 HV_MIN_DELTA_TICKS, 133 HV_MAX_MAX_DELTA_TICKS); 134 return 0; 135 } 136 137 /* 138 * hv_stimer_cleanup - Per-cpu cleanup of the clockevent 139 */ 140 int hv_stimer_cleanup(unsigned int cpu) 141 { 142 struct clock_event_device *ce; 143 144 if (!hv_clock_event) 145 return 0; 146 147 ce = per_cpu_ptr(hv_clock_event, cpu); 148 hv_ce_shutdown(ce); 149 150 return 0; 151 } 152 EXPORT_SYMBOL_GPL(hv_stimer_cleanup); 153 154 /* 155 * These placeholders are overridden by arch specific code on 156 * architectures that need special setup of the stimer0 IRQ because 157 * they don't support per-cpu IRQs (such as x86/x64). 158 */ 159 void __weak hv_setup_stimer0_handler(void (*handler)(void)) 160 { 161 }; 162 163 void __weak hv_remove_stimer0_handler(void) 164 { 165 }; 166 167 #ifdef CONFIG_ACPI 168 /* Called only on architectures with per-cpu IRQs (i.e., not x86/x64) */ 169 static int hv_setup_stimer0_irq(void) 170 { 171 int ret; 172 173 ret = acpi_register_gsi(NULL, HYPERV_STIMER0_VECTOR, 174 ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); 175 if (ret < 0) { 176 pr_err("Can't register Hyper-V stimer0 GSI. Error %d", ret); 177 return ret; 178 } 179 stimer0_irq = ret; 180 181 ret = request_percpu_irq(stimer0_irq, hv_stimer0_percpu_isr, 182 "Hyper-V stimer0", &stimer0_evt); 183 if (ret) { 184 pr_err("Can't request Hyper-V stimer0 IRQ %d. Error %d", 185 stimer0_irq, ret); 186 acpi_unregister_gsi(stimer0_irq); 187 stimer0_irq = -1; 188 } 189 return ret; 190 } 191 192 static void hv_remove_stimer0_irq(void) 193 { 194 if (stimer0_irq == -1) { 195 hv_remove_stimer0_handler(); 196 } else { 197 free_percpu_irq(stimer0_irq, &stimer0_evt); 198 acpi_unregister_gsi(stimer0_irq); 199 stimer0_irq = -1; 200 } 201 } 202 #else 203 static int hv_setup_stimer0_irq(void) 204 { 205 return 0; 206 } 207 208 static void hv_remove_stimer0_irq(void) 209 { 210 } 211 #endif 212 213 /* hv_stimer_alloc - Global initialization of the clockevent and stimer0 */ 214 int hv_stimer_alloc(bool have_percpu_irqs) 215 { 216 int ret; 217 218 /* 219 * Synthetic timers are always available except on old versions of 220 * Hyper-V on x86. In that case, return as error as Linux will use a 221 * clockevent based on emulated LAPIC timer hardware. 222 */ 223 if (!(ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) || 224 !(ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)) 225 return -EINVAL; 226 227 hv_clock_event = alloc_percpu(struct clock_event_device); 228 if (!hv_clock_event) 229 return -ENOMEM; 230 231 if (have_percpu_irqs) { 232 ret = hv_setup_stimer0_irq(); 233 if (ret) 234 goto free_clock_event; 235 } else { 236 hv_setup_stimer0_handler(hv_stimer0_isr); 237 } 238 239 ret = cpuhp_setup_state(CPUHP_AP_HYPERV_TIMER_STARTING, 240 "clockevents/hyperv/stimer:starting", 241 hv_stimer_init, hv_stimer_cleanup); 242 if (ret < 0) { 243 hv_remove_stimer0_irq(); 244 goto free_clock_event; 245 } 246 return ret; 247 248 free_clock_event: 249 free_percpu(hv_clock_event); 250 hv_clock_event = NULL; 251 return ret; 252 } 253 EXPORT_SYMBOL_GPL(hv_stimer_alloc); 254 255 /* 256 * Do a global cleanup of clockevents for the cases of kexec and 257 * vmbus exit 258 */ 259 void hv_stimer_global_cleanup(void) 260 { 261 if (!hv_clock_event) 262 return; 263 264 cpuhp_remove_state(CPUHP_AP_HYPERV_TIMER_STARTING); 265 hv_remove_stimer0_irq(); 266 stimer0_irq = -1; 267 268 free_percpu(hv_clock_event); 269 hv_clock_event = NULL; 270 271 } 272 EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup); 273 274 static __always_inline u64 read_hv_clock_msr(void) 275 { 276 /* 277 * Read the partition counter to get the current tick count. This count 278 * is set to 0 when the partition is created and is incremented in 100 279 * nanosecond units. 280 * 281 * Use hv_raw_get_msr() because this function is used from 282 * noinstr. Notable; while HV_MSR_TIME_REF_COUNT is a synthetic 283 * register it doesn't need the GHCB path. 284 */ 285 return hv_raw_get_msr(HV_MSR_TIME_REF_COUNT); 286 } 287 288 /* 289 * Code and definitions for the Hyper-V clocksources. Two 290 * clocksources are defined: one that reads the Hyper-V defined MSR, and 291 * the other that uses the TSC reference page feature as defined in the 292 * TLFS. The MSR version is for compatibility with old versions of 293 * Hyper-V and 32-bit x86. The TSC reference page version is preferred. 294 */ 295 296 static union { 297 struct ms_hyperv_tsc_page page; 298 u8 reserved[PAGE_SIZE]; 299 } tsc_pg __bss_decrypted __aligned(PAGE_SIZE); 300 301 static struct ms_hyperv_tsc_page *tsc_page = &tsc_pg.page; 302 static unsigned long tsc_pfn; 303 304 unsigned long hv_get_tsc_pfn(void) 305 { 306 return tsc_pfn; 307 } 308 EXPORT_SYMBOL_GPL(hv_get_tsc_pfn); 309 310 struct ms_hyperv_tsc_page *hv_get_tsc_page(void) 311 { 312 return tsc_page; 313 } 314 EXPORT_SYMBOL_GPL(hv_get_tsc_page); 315 316 static __always_inline u64 read_hv_clock_tsc(void) 317 { 318 u64 cur_tsc, time; 319 320 /* 321 * The Hyper-V Top-Level Function Spec (TLFS), section Timers, 322 * subsection Refererence Counter, guarantees that the TSC and MSR 323 * times are in sync and monotonic. Therefore we can fall back 324 * to the MSR in case the TSC page indicates unavailability. 325 */ 326 if (!hv_read_tsc_page_tsc(tsc_page, &cur_tsc, &time)) 327 time = read_hv_clock_msr(); 328 329 return time; 330 } 331 332 static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg) 333 { 334 return read_hv_clock_tsc(); 335 } 336 337 static u64 notrace read_hv_clock_tsc_cs_snapshot(struct clocksource *arg, 338 struct clocksource_hw_snapshot *chs) 339 { 340 u64 time; 341 342 if (hv_read_tsc_page_tsc(tsc_page, &chs->hw_cycles, &time)) { 343 chs->hw_csid = CSID_X86_TSC; 344 } else { 345 chs->hw_cycles = 0; 346 chs->hw_csid = CSID_GENERIC; 347 time = read_hv_clock_msr(); 348 } 349 350 return time; 351 } 352 353 static u64 noinstr read_hv_sched_clock_tsc(void) 354 { 355 return (read_hv_clock_tsc() - hv_sched_clock_offset) * 356 (NSEC_PER_SEC / HV_CLOCK_HZ); 357 } 358 359 static void suspend_hv_clock_tsc(struct clocksource *arg) 360 { 361 union hv_reference_tsc_msr tsc_msr; 362 363 /* Disable the TSC page */ 364 tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC); 365 tsc_msr.enable = 0; 366 hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64); 367 } 368 369 370 static void resume_hv_clock_tsc(struct clocksource *arg) 371 { 372 union hv_reference_tsc_msr tsc_msr; 373 374 /* Re-enable the TSC page */ 375 tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC); 376 tsc_msr.enable = 1; 377 tsc_msr.pfn = tsc_pfn; 378 hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64); 379 } 380 381 /* 382 * Called during resume from hibernation, from overridden 383 * x86_platform.restore_sched_clock_state routine. This is to adjust offsets 384 * used to calculate time for hv tsc page based sched_clock, to account for 385 * time spent before hibernation. 386 */ 387 void hv_adj_sched_clock_offset(u64 offset) 388 { 389 hv_sched_clock_offset -= offset; 390 } 391 392 #ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK 393 static int hv_cs_enable(struct clocksource *cs) 394 { 395 vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK); 396 return 0; 397 } 398 #endif 399 400 static struct clocksource hyperv_cs_tsc = { 401 .name = "hyperv_clocksource_tsc_page", 402 .rating = 500, 403 .read = read_hv_clock_tsc_cs, 404 .read_snapshot = read_hv_clock_tsc_cs_snapshot, 405 .mask = CLOCKSOURCE_MASK(64), 406 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 407 .suspend = suspend_hv_clock_tsc, 408 .resume = resume_hv_clock_tsc, 409 #ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK 410 .enable = hv_cs_enable, 411 .vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK, 412 #else 413 .vdso_clock_mode = VDSO_CLOCKMODE_NONE, 414 #endif 415 }; 416 417 static u64 notrace read_hv_clock_msr_cs(struct clocksource *arg) 418 { 419 return read_hv_clock_msr(); 420 } 421 422 static struct clocksource hyperv_cs_msr = { 423 .name = "hyperv_clocksource_msr", 424 .rating = 495, 425 .read = read_hv_clock_msr_cs, 426 .mask = CLOCKSOURCE_MASK(64), 427 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 428 }; 429 430 /* 431 * Reference to pv_ops must be inline so objtool 432 * detection of noinstr violations can work correctly. 433 */ 434 #ifdef CONFIG_GENERIC_SCHED_CLOCK 435 static __always_inline void hv_setup_sched_clock(void *sched_clock) 436 { 437 /* 438 * We're on an architecture with generic sched clock (not x86/x64). 439 * The Hyper-V sched clock read function returns nanoseconds, not 440 * the normal 100ns units of the Hyper-V synthetic clock. 441 */ 442 sched_clock_register(sched_clock, 64, NSEC_PER_SEC); 443 } 444 #elif defined CONFIG_PARAVIRT 445 #include <asm/timer.h> 446 447 static __always_inline void hv_setup_sched_clock(void *sched_clock) 448 { 449 /* We're on x86/x64 *and* using PV ops */ 450 paravirt_set_sched_clock(sched_clock); 451 } 452 #else /* !CONFIG_GENERIC_SCHED_CLOCK && !CONFIG_PARAVIRT */ 453 static __always_inline void hv_setup_sched_clock(void *sched_clock) {} 454 #endif /* CONFIG_GENERIC_SCHED_CLOCK */ 455 456 static void __init hv_init_tsc_clocksource(void) 457 { 458 union hv_reference_tsc_msr tsc_msr; 459 460 /* 461 * When running as a guest partition: 462 * 463 * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly 464 * handles frequency and offset changes due to live migration, 465 * pause/resume, and other VM management operations. So lower the 466 * Hyper-V Reference TSC rating, causing the generic TSC to be used. 467 * TSC_INVARIANT is not offered on ARM64, so the Hyper-V Reference 468 * TSC will be preferred over the virtualized ARM64 arch counter. 469 * 470 * When running as the root partition: 471 * 472 * There is no HV_ACCESS_TSC_INVARIANT feature. Always lower the rating 473 * of the Hyper-V Reference TSC. 474 */ 475 if ((ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) || 476 hv_root_partition()) { 477 hyperv_cs_tsc.rating = 250; 478 hyperv_cs_msr.rating = 245; 479 } 480 481 if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) 482 return; 483 484 hv_read_reference_counter = read_hv_clock_tsc; 485 486 /* 487 * TSC page mapping works differently in root compared to guest. 488 * - In guest partition the guest PFN has to be passed to the 489 * hypervisor. 490 * - In root partition it's other way around: it has to map the PFN 491 * provided by the hypervisor. 492 * But it can't be mapped right here as it's too early and MMU isn't 493 * ready yet. So, we only set the enable bit here and will remap the 494 * page later in hv_remap_tsc_clocksource(). 495 * 496 * It worth mentioning, that TSC clocksource read function 497 * (read_hv_clock_tsc) has a MSR-based fallback mechanism, used when 498 * TSC page is zeroed (which is the case until the PFN is remapped) and 499 * thus TSC clocksource will work even without the real TSC page 500 * mapped. 501 */ 502 tsc_msr.as_uint64 = hv_get_msr(HV_MSR_REFERENCE_TSC); 503 if (hv_root_partition()) 504 tsc_pfn = tsc_msr.pfn; 505 else 506 tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page)); 507 tsc_msr.enable = 1; 508 tsc_msr.pfn = tsc_pfn; 509 hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64); 510 511 clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); 512 513 /* 514 * If TSC is invariant, then let it stay as the sched clock since it 515 * will be faster than reading the TSC page. But if not invariant, use 516 * the TSC page so that live migrations across hosts with different 517 * frequencies is handled correctly. 518 */ 519 if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) { 520 hv_sched_clock_offset = hv_read_reference_counter(); 521 hv_setup_sched_clock(read_hv_sched_clock_tsc); 522 } 523 } 524 525 void __init hv_init_clocksource(void) 526 { 527 /* 528 * Try to set up the TSC page clocksource, then the MSR clocksource. 529 * At least one of these will always be available except on very old 530 * versions of Hyper-V on x86. In that case we won't have a Hyper-V 531 * clocksource, but Linux will still run with a clocksource based 532 * on the emulated PIT or LAPIC timer. 533 * 534 * Never use the MSR clocksource as sched clock. It's too slow. 535 * Better to use the native sched clock as the fallback. 536 */ 537 hv_init_tsc_clocksource(); 538 539 if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE) 540 clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); 541 } 542 543 void __init hv_remap_tsc_clocksource(void) 544 { 545 if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) 546 return; 547 548 if (!hv_root_partition()) { 549 WARN(1, "%s: attempt to remap TSC page in guest partition\n", 550 __func__); 551 return; 552 } 553 554 tsc_page = memremap(tsc_pfn << HV_HYP_PAGE_SHIFT, sizeof(tsc_pg), 555 MEMREMAP_WB); 556 if (!tsc_page) 557 pr_err("Failed to remap Hyper-V TSC page.\n"); 558 } 559