diff options
Diffstat (limited to 'drivers/clocksource/hyperv_timer.c')
-rw-r--r-- | drivers/clocksource/hyperv_timer.c | 45 |
1 files changed, 16 insertions, 29 deletions
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index ba2c79e6a0ee..2317d4e3daaf 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/mshyperv.h> | 22 | #include <asm/mshyperv.h> |
23 | 23 | ||
24 | static struct clock_event_device __percpu *hv_clock_event; | 24 | static struct clock_event_device __percpu *hv_clock_event; |
25 | static u64 hv_sched_clock_offset __ro_after_init; | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * If false, we're using the old mechanism for stimer0 interrupts | 28 | * If false, we're using the old mechanism for stimer0 interrupts |
@@ -212,19 +213,17 @@ EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup); | |||
212 | struct clocksource *hyperv_cs; | 213 | struct clocksource *hyperv_cs; |
213 | EXPORT_SYMBOL_GPL(hyperv_cs); | 214 | EXPORT_SYMBOL_GPL(hyperv_cs); |
214 | 215 | ||
215 | #ifdef CONFIG_HYPERV_TSCPAGE | 216 | static struct ms_hyperv_tsc_page tsc_pg __aligned(PAGE_SIZE); |
216 | |||
217 | static struct ms_hyperv_tsc_page *tsc_pg; | ||
218 | 217 | ||
219 | struct ms_hyperv_tsc_page *hv_get_tsc_page(void) | 218 | struct ms_hyperv_tsc_page *hv_get_tsc_page(void) |
220 | { | 219 | { |
221 | return tsc_pg; | 220 | return &tsc_pg; |
222 | } | 221 | } |
223 | EXPORT_SYMBOL_GPL(hv_get_tsc_page); | 222 | EXPORT_SYMBOL_GPL(hv_get_tsc_page); |
224 | 223 | ||
225 | static u64 notrace read_hv_sched_clock_tsc(void) | 224 | static u64 notrace read_hv_clock_tsc(struct clocksource *arg) |
226 | { | 225 | { |
227 | u64 current_tick = hv_read_tsc_page(tsc_pg); | 226 | u64 current_tick = hv_read_tsc_page(&tsc_pg); |
228 | 227 | ||
229 | if (current_tick == U64_MAX) | 228 | if (current_tick == U64_MAX) |
230 | hv_get_time_ref_count(current_tick); | 229 | hv_get_time_ref_count(current_tick); |
@@ -232,9 +231,9 @@ static u64 notrace read_hv_sched_clock_tsc(void) | |||
232 | return current_tick; | 231 | return current_tick; |
233 | } | 232 | } |
234 | 233 | ||
235 | static u64 read_hv_clock_tsc(struct clocksource *arg) | 234 | static u64 read_hv_sched_clock_tsc(void) |
236 | { | 235 | { |
237 | return read_hv_sched_clock_tsc(); | 236 | return read_hv_clock_tsc(NULL) - hv_sched_clock_offset; |
238 | } | 237 | } |
239 | 238 | ||
240 | static struct clocksource hyperv_cs_tsc = { | 239 | static struct clocksource hyperv_cs_tsc = { |
@@ -244,9 +243,8 @@ static struct clocksource hyperv_cs_tsc = { | |||
244 | .mask = CLOCKSOURCE_MASK(64), | 243 | .mask = CLOCKSOURCE_MASK(64), |
245 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 244 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
246 | }; | 245 | }; |
247 | #endif | ||
248 | 246 | ||
249 | static u64 notrace read_hv_sched_clock_msr(void) | 247 | static u64 notrace read_hv_clock_msr(struct clocksource *arg) |
250 | { | 248 | { |
251 | u64 current_tick; | 249 | u64 current_tick; |
252 | /* | 250 | /* |
@@ -258,9 +256,9 @@ static u64 notrace read_hv_sched_clock_msr(void) | |||
258 | return current_tick; | 256 | return current_tick; |
259 | } | 257 | } |
260 | 258 | ||
261 | static u64 read_hv_clock_msr(struct clocksource *arg) | 259 | static u64 read_hv_sched_clock_msr(void) |
262 | { | 260 | { |
263 | return read_hv_sched_clock_msr(); | 261 | return read_hv_clock_msr(NULL) - hv_sched_clock_offset; |
264 | } | 262 | } |
265 | 263 | ||
266 | static struct clocksource hyperv_cs_msr = { | 264 | static struct clocksource hyperv_cs_msr = { |
@@ -271,7 +269,6 @@ static struct clocksource hyperv_cs_msr = { | |||
271 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 269 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
272 | }; | 270 | }; |
273 | 271 | ||
274 | #ifdef CONFIG_HYPERV_TSCPAGE | ||
275 | static bool __init hv_init_tsc_clocksource(void) | 272 | static bool __init hv_init_tsc_clocksource(void) |
276 | { | 273 | { |
277 | u64 tsc_msr; | 274 | u64 tsc_msr; |
@@ -280,12 +277,8 @@ static bool __init hv_init_tsc_clocksource(void) | |||
280 | if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) | 277 | if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) |
281 | return false; | 278 | return false; |
282 | 279 | ||
283 | tsc_pg = vmalloc(PAGE_SIZE); | ||
284 | if (!tsc_pg) | ||
285 | return false; | ||
286 | |||
287 | hyperv_cs = &hyperv_cs_tsc; | 280 | hyperv_cs = &hyperv_cs_tsc; |
288 | phys_addr = page_to_phys(vmalloc_to_page(tsc_pg)); | 281 | phys_addr = virt_to_phys(&tsc_pg); |
289 | 282 | ||
290 | /* | 283 | /* |
291 | * The Hyper-V TLFS specifies to preserve the value of reserved | 284 | * The Hyper-V TLFS specifies to preserve the value of reserved |
@@ -302,17 +295,11 @@ static bool __init hv_init_tsc_clocksource(void) | |||
302 | hv_set_clocksource_vdso(hyperv_cs_tsc); | 295 | hv_set_clocksource_vdso(hyperv_cs_tsc); |
303 | clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); | 296 | clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); |
304 | 297 | ||
305 | /* sched_clock_register is needed on ARM64 but is a no-op on x86 */ | 298 | hv_sched_clock_offset = hyperv_cs->read(hyperv_cs); |
306 | sched_clock_register(read_hv_sched_clock_tsc, 64, HV_CLOCK_HZ); | 299 | hv_setup_sched_clock(read_hv_sched_clock_tsc); |
300 | |||
307 | return true; | 301 | return true; |
308 | } | 302 | } |
309 | #else | ||
310 | static bool __init hv_init_tsc_clocksource(void) | ||
311 | { | ||
312 | return false; | ||
313 | } | ||
314 | #endif | ||
315 | |||
316 | 303 | ||
317 | void __init hv_init_clocksource(void) | 304 | void __init hv_init_clocksource(void) |
318 | { | 305 | { |
@@ -333,7 +320,7 @@ void __init hv_init_clocksource(void) | |||
333 | hyperv_cs = &hyperv_cs_msr; | 320 | hyperv_cs = &hyperv_cs_msr; |
334 | clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); | 321 | clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); |
335 | 322 | ||
336 | /* sched_clock_register is needed on ARM64 but is a no-op on x86 */ | 323 | hv_sched_clock_offset = hyperv_cs->read(hyperv_cs); |
337 | sched_clock_register(read_hv_sched_clock_msr, 64, HV_CLOCK_HZ); | 324 | hv_setup_sched_clock(read_hv_sched_clock_msr); |
338 | } | 325 | } |
339 | EXPORT_SYMBOL_GPL(hv_init_clocksource); | 326 | EXPORT_SYMBOL_GPL(hv_init_clocksource); |