arm: arch_timer: add arch_counter_set_user_access
authorMark Rutland <mark.rutland@arm.com>
Wed, 14 Nov 2012 10:32:24 +0000 (10:32 +0000)
committerMark Rutland <mark.rutland@arm.com>
Thu, 31 Jan 2013 15:51:39 +0000 (15:51 +0000)
Several bits in CNTKCTL reset to 0, including PL0VTEN. For architectures
using the generic timer which wish to have a fast gettimeofday vDSO
implementation, these bits must be set to 1 by the kernel. For
architectures without a vDSO, it's best to leave the bits set to 0 for
now to ensure that if and when support is added, it's implemented sanely
architecture wide.

As the bootloader might set PL0VTEN to a value that doesn't correspond
to that which the kernel prefers, we must explicitly set it to the
architecture port's preferred value.

This patch adds arch_counter_set_user_access, which sets the PL0 access
permissions to that required by the architecture. For arch/arm, this
currently means disabling all userspace access.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm/include/asm/arch_timer.h
arch/arm/kernel/arch_timer.c

index 75975d9efd3f20567caac78b3a11929a3f23213a..729f6d98df86a6259fafaeb62792646097c3c028 100644 (file)
@@ -106,6 +106,18 @@ static inline u64 arch_counter_get_cntvct(void)
        asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
        return cval;
 }
+
+static inline void __cpuinit arch_counter_set_user_access(void)
+{
+       u32 cntkctl;
+
+       asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
+
+       /* disable user access to everything */
+       cntkctl &= ~((3 << 8) | (7 << 0));
+
+       asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
+}
 #else
 static inline int arch_timer_of_register(void)
 {
index c8dfec052f2d7c42c69a8fad12a2a28548272386..94f503394c5c8eac551234858ced13fd1a2e30c1 100644 (file)
@@ -155,6 +155,8 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
                        enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
        }
 
+       arch_counter_set_user_access();
+
        return 0;
 }