diff options
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/timekeeping.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6a92794427c9..8af77006e937 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -496,6 +496,39 @@ u64 notrace ktime_get_boot_fast_ns(void) | |||
| 496 | } | 496 | } |
| 497 | EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns); | 497 | EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns); |
| 498 | 498 | ||
| 499 | |||
| 500 | /* | ||
| 501 | * See comment for __ktime_get_fast_ns() vs. timestamp ordering | ||
| 502 | */ | ||
| 503 | static __always_inline u64 __ktime_get_real_fast_ns(struct tk_fast *tkf) | ||
| 504 | { | ||
| 505 | struct tk_read_base *tkr; | ||
| 506 | unsigned int seq; | ||
| 507 | u64 now; | ||
| 508 | |||
| 509 | do { | ||
| 510 | seq = raw_read_seqcount_latch(&tkf->seq); | ||
| 511 | tkr = tkf->base + (seq & 0x01); | ||
| 512 | now = ktime_to_ns(tkr->base_real); | ||
| 513 | |||
| 514 | now += timekeeping_delta_to_ns(tkr, | ||
| 515 | clocksource_delta( | ||
| 516 | tk_clock_read(tkr), | ||
| 517 | tkr->cycle_last, | ||
| 518 | tkr->mask)); | ||
| 519 | } while (read_seqcount_retry(&tkf->seq, seq)); | ||
| 520 | |||
| 521 | return now; | ||
| 522 | } | ||
| 523 | |||
| 524 | /** | ||
| 525 | * ktime_get_real_fast_ns: - NMI safe and fast access to clock realtime. | ||
| 526 | */ | ||
| 527 | u64 ktime_get_real_fast_ns(void) | ||
| 528 | { | ||
| 529 | return __ktime_get_real_fast_ns(&tk_fast_mono); | ||
| 530 | } | ||
| 531 | |||
| 499 | /** | 532 | /** |
| 500 | * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. | 533 | * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. |
| 501 | * @tk: Timekeeper to snapshot. | 534 | * @tk: Timekeeper to snapshot. |
| @@ -514,6 +547,7 @@ static void halt_fast_timekeeper(struct timekeeper *tk) | |||
| 514 | memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); | 547 | memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); |
| 515 | cycles_at_suspend = tk_clock_read(tkr); | 548 | cycles_at_suspend = tk_clock_read(tkr); |
| 516 | tkr_dummy.clock = &dummy_clock; | 549 | tkr_dummy.clock = &dummy_clock; |
| 550 | tkr_dummy.base_real = tkr->base + tk->offs_real; | ||
| 517 | update_fast_timekeeper(&tkr_dummy, &tk_fast_mono); | 551 | update_fast_timekeeper(&tkr_dummy, &tk_fast_mono); |
| 518 | 552 | ||
| 519 | tkr = &tk->tkr_raw; | 553 | tkr = &tk->tkr_raw; |
| @@ -661,6 +695,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action) | |||
| 661 | update_vsyscall(tk); | 695 | update_vsyscall(tk); |
| 662 | update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); | 696 | update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); |
| 663 | 697 | ||
| 698 | tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real; | ||
| 664 | update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono); | 699 | update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono); |
| 665 | update_fast_timekeeper(&tk->tkr_raw, &tk_fast_raw); | 700 | update_fast_timekeeper(&tk->tkr_raw, &tk_fast_raw); |
| 666 | 701 | ||
