diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5c114da0ed71..f8adea258cf0 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -83,6 +83,7 @@ static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; | |||
83 | static bool arch_timer_c3stop; | 83 | static bool arch_timer_c3stop; |
84 | static bool arch_timer_mem_use_virtual; | 84 | static bool arch_timer_mem_use_virtual; |
85 | static bool arch_counter_suspend_stop; | 85 | static bool arch_counter_suspend_stop; |
86 | static bool vdso_default = true; | ||
86 | 87 | ||
87 | static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); | 88 | static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); |
88 | 89 | ||
@@ -383,6 +384,17 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa | |||
383 | } | 384 | } |
384 | 385 | ||
385 | static_branch_enable(&arch_timer_read_ool_enabled); | 386 | static_branch_enable(&arch_timer_read_ool_enabled); |
387 | |||
388 | /* | ||
389 | * Don't use the vdso fastpath if errata require using the | ||
390 | * out-of-line counter accessor. We may change our mind pretty | ||
391 | * late in the game (with a per-CPU erratum, for example), so | ||
392 | * change both the default value and the vdso itself. | ||
393 | */ | ||
394 | if (wa->read_cntvct_el0) { | ||
395 | clocksource_counter.archdata.vdso_direct = false; | ||
396 | vdso_default = false; | ||
397 | } | ||
386 | } | 398 | } |
387 | 399 | ||
388 | static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, | 400 | static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, |
@@ -443,11 +455,19 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t | |||
443 | __val; \ | 455 | __val; \ |
444 | }) | 456 | }) |
445 | 457 | ||
458 | static bool arch_timer_this_cpu_has_cntvct_wa(void) | ||
459 | { | ||
460 | const struct arch_timer_erratum_workaround *wa; | ||
461 | |||
462 | wa = __this_cpu_read(timer_unstable_counter_workaround); | ||
463 | return wa && wa->read_cntvct_el0; | ||
464 | } | ||
446 | #else | 465 | #else |
447 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) | 466 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) |
448 | #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) | 467 | #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) |
449 | #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) | 468 | #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) |
450 | #define erratum_handler(fn, r, ...) ({false;}) | 469 | #define erratum_handler(fn, r, ...) ({false;}) |
470 | #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) | ||
451 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ | 471 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ |
452 | 472 | ||
453 | static __always_inline irqreturn_t timer_handler(const int access, | 473 | static __always_inline irqreturn_t timer_handler(const int access, |
@@ -660,15 +680,23 @@ static void arch_counter_set_user_access(void) | |||
660 | { | 680 | { |
661 | u32 cntkctl = arch_timer_get_cntkctl(); | 681 | u32 cntkctl = arch_timer_get_cntkctl(); |
662 | 682 | ||
663 | /* Disable user access to the timers and the physical counter */ | 683 | /* Disable user access to the timers and both counters */ |
664 | /* Also disable virtual event stream */ | 684 | /* Also disable virtual event stream */ |
665 | cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN | 685 | cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN |
666 | | ARCH_TIMER_USR_VT_ACCESS_EN | 686 | | ARCH_TIMER_USR_VT_ACCESS_EN |
687 | | ARCH_TIMER_USR_VCT_ACCESS_EN | ||
667 | | ARCH_TIMER_VIRT_EVT_EN | 688 | | ARCH_TIMER_VIRT_EVT_EN |
668 | | ARCH_TIMER_USR_PCT_ACCESS_EN); | 689 | | ARCH_TIMER_USR_PCT_ACCESS_EN); |
669 | 690 | ||
670 | /* Enable user access to the virtual counter */ | 691 | /* |
671 | cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; | 692 | * Enable user access to the virtual counter if it doesn't |
693 | * need to be workaround. The vdso may have been already | ||
694 | * disabled though. | ||
695 | */ | ||
696 | if (arch_timer_this_cpu_has_cntvct_wa()) | ||
697 | pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); | ||
698 | else | ||
699 | cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; | ||
672 | 700 | ||
673 | arch_timer_set_cntkctl(cntkctl); | 701 | arch_timer_set_cntkctl(cntkctl); |
674 | } | 702 | } |
@@ -791,16 +819,7 @@ static void __init arch_counter_register(unsigned type) | |||
791 | else | 819 | else |
792 | arch_timer_read_counter = arch_counter_get_cntpct; | 820 | arch_timer_read_counter = arch_counter_get_cntpct; |
793 | 821 | ||
794 | clocksource_counter.archdata.vdso_direct = true; | 822 | clocksource_counter.archdata.vdso_direct = vdso_default; |
795 | |||
796 | #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND | ||
797 | /* | ||
798 | * Don't use the vdso fastpath if errata require using | ||
799 | * the out-of-line counter accessor. | ||
800 | */ | ||
801 | if (static_branch_unlikely(&arch_timer_read_ool_enabled)) | ||
802 | clocksource_counter.archdata.vdso_direct = false; | ||
803 | #endif | ||
804 | } else { | 823 | } else { |
805 | arch_timer_read_counter = arch_counter_get_cntvct_mem; | 824 | arch_timer_read_counter = arch_counter_get_cntvct_mem; |
806 | } | 825 | } |