Unify arm_generic and arch_timer drivers
Subsystems (7)
Mark Rutland
maintainerv3 cover Unify arm_generic and arch_timer drivers
This is the rebase to an -rc I promised back in December [1].
Changes since v2:
* Rebase to v3.8-rc2
Changes since v1:
* Rename arch_counter_{enable=>set}_user_access.
* * Explicitly disable access to counters from userspace on arm.
* * Add device_node refcounting fix.
* * Fix conflict with Will Deacon's AArch64 vdso changes.
* * Simplify the cpu notifier.
* * Fix a couple of style issues.
Currently we have two drivers for the ARM generic / architected timer, arch_timer in arch/arm, and arm_generic in drivers/clocksource. This is an unnecessary duplication of code, and will only lead to maintenance headaches later.
This patch series splits the generic portion of the arch_timer out to drivers/clocksource, and ports the arm64 code to use it. The now unused arm_generic driver is removed in the process.
Separating the arch_timer driver from the arm-specific local_timer api currently loses us broadcast timer support. I've posted another series
[2] which remedies this by decoupling the timer broadcast mechanism from drivers.
The series applies to v3.8-rc2, and has been tested on a TC2 test chip. It also applies to Catalin's soc-armv8-model branch [3], the result of which has been tested on an AArch64 model.
Christoffer, this will conflict with one of your KVM/ARM architected timers support patches ([PATCH v5 1/4] ARM: arch_timers: switch to physical timers if HYP mode is available). I'm happy to fold that into this series if you're ok with that?
Thanks,
Mark
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/138130.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/140528.html
[3] git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git soc-armv8-model
Mark Rutland (11):
arm: arch_timer: balance device_node refcounting
arm: arch_timer: remove redundant available check
arm: arch_timer: use u64/u32 for register data
arm: arch_timer: standardise counter reading
arm: arch_timer: split cntfrq accessor
arm: arch_timer: factor out register accessors
arm: arch_timer: divorce from local_timer api
arm: arch_timer: add arch_counter_set_user_access
arm: arch_timer: move core to drivers/clocksource
arm64: move from arm_generic to arm_arch_timer
Documentation: Add ARMv8 to arch_timer devicetree
.../devicetree/bindings/arm/arch_timer.txt | 7 +- arch/arm/Kconfig | 3 +- arch/arm/include/asm/arch_timer.h | 111 ++++- arch/arm/kernel/arch_timer.c | 504 +------------------- arch/arm/mach-omap2/Kconfig | 2 +- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/arch_timer.h | 133 +++++ arch/arm64/include/asm/arm_generic.h | 100 ---- arch/arm64/kernel/time.c | 29 +- drivers/clocksource/Kconfig | 6 +- drivers/clocksource/Makefile | 2 +- drivers/clocksource/arm_arch_timer.c | 375 +++++++++++++++ drivers/clocksource/arm_generic.c | 232 --------- include/clocksource/arm_arch_timer.h | 63 +++ include/clocksource/arm_generic.h | 21 - 15 files changed, 734 insertions(+), 855 deletions(-) create mode 100644 arch/arm64/include/asm/arch_timer.h delete mode 100644 arch/arm64/include/asm/arm_generic.h create mode 100644 drivers/clocksource/arm_arch_timer.c delete mode 100644 drivers/clocksource/arm_generic.c create mode 100644 include/clocksource/arm_arch_timer.h delete mode 100644 include/clocksource/arm_generic.h
Mark Rutland
maintainerPATCH v2 1/11 arm: arch_timer: balance device_node refcounting
When we get the device_node for the arch timer, it's refcount is automatically incremented in of_find_matching_node, but it is never decremented.
This patch decrements the refcount on the node after we're finished using it.
--- arch/arm/kernel/arch_timer.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/kernel/arch_timer.c +2 -0
@@ -488,6 +488,8 @@ int __init arch_timer_of_register(void)for (i =PHYS_SECURE_PPI ; i <MAX_TIMER_PPI ; i++) arch_timer_ppi[i] =irq_of_parse_and_map (np, i); +of_node_put (np); +/* * If no interrupt provided for virtual timer, we'll have to * stick to the physical timer. It'd better be accessible...
Signature · 1 line
1.7.0.4
PATCH v2 1/11 arm: arch_timer: balance device_node refcounting
Quoted 10 lines · Mark Rutland
When we get the
device_nodefor the arch timer, it's refcount is automatically incremented inof_find_matching_node, but it is never decremented.This patch decrements the refcount on the node after we're finished using it.
Reported-by Will Deacon <[email protected]>Signed-off-by Mark Rutland <[email protected]>---
Looks right.
Mark Rutland
maintainerPATCH v2 2/11 arm: arch_timer: remove redundant available check
In reply to Mark RutlandThis check is a holdover from the pre-devicetree days. As the timer is not probed except by platforms which register it via devicetree, it's not strictly necessary.
--- arch/arm/kernel/arch_timer.c | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-)
arch/arm/kernel/arch_timer.c +0 -12
@@ -20,11 +20,9 @@#include <linux/of_irq.h> #include <linux/io.h> -#include <asm/cputype.h> #include <asm/delay.h> #include <asm/localtimer.h> #include <asm/arch_timer.h> -#include <asm/system_info.h> #include <asm/sched_clock.h> static unsigned long arch_timer_rate;
@@ -259,20 +257,10 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk)return 0 ; } -/* Is the optional system timer available? */ -static int local_timer_is_architected (void ) -{ -return (cpu_architecture () >= CPU_ARCH_ARMv7) && - ((read_cpuid_ext (CPUID_EXT_PFR1 ) >>16 ) &0xf ) ==1 ; -} -static int arch_timer_available (void ) {unsigned long freq; -if (!local_timer_is_architected ()) -return -ENXIO ; -if (arch_timer_rate ==0 ) { freq =arch_timer_reg_read (ARCH_TIMER_PHYS_ACCESS ,ARCH_TIMER_REG_FREQ );
Signature · 1 line
1.7.0.4
PATCH v2 2/11 arm: arch_timer: remove redundant available check
Quoted 8 lines · Mark Rutland
This check is a holdover from the pre-devicetree days. As the timer is not probed except by platforms which register it via devicetree, it's not strictly necessary.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
Multi-platform build without DT could still benefit from the check but I guess the most of the A15 based platform are DT only, so its should be good to get rid of the check.
Regards,
Santosh
Mark Rutland
maintainerPATCH v2 2/11 arm: arch_timer: remove redundant available check
Quoted 5 lines · Santosh Shilimkar
Quoted 4 lines · Mark Rutland
This check is a holdover from the pre-devicetree days. As the timer is not probed except by platforms which register it via devicetree, it's not strictly necessary.
Quoted 7 lines
Quoted 4 lines
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
Multi-platform build without DT could still benefit from the check but I guess the most of the A15 based platform are DT only, so its should be good to get rid of the check.
Indeed. I'm under the impression that all platforms which might have an architected timer are devicetree only.
Quoted 4 lines
Regards,
Santosh
Thanks,
Mark.
Mark Rutland
maintainerPATCH v2 3/11 arm: arch_timer: use u64/u32 for register data
In reply to Mark RutlandTo ensure the correct size of types, use u64 for the return value of arch_timer_get_cnt{p,v}ct, and u32 for arch_timer_rate, matching the size of the registers these values are taken from. While we're changing them anyway, simplify the implementation of arch_timer_get_cnt{p,v}ct.
--- arch/arm/kernel/arch_timer.c | 30 +++++++++++------------------- 1 files changed, 11 insertions(+), 19 deletions(-)
arch/arm/kernel/arch_timer.c +11 -19
@@ -25,7 +25,7 @@#include <asm/arch_timer.h> #include <asm/sched_clock.h> -static unsigned long arch_timer_rate; +static u32 arch_timer_rate;enum ppi_nr {PHYS_SECURE_PPI ,
@@ -121,27 +121,18 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)return val; } -static inline cycle_t arch_timer_counter_read (const int access) +static inline u64 arch_counter_get_cntpct (void ) { -cycle_t cval =0 ; - -if (access ==ARCH_TIMER_PHYS_ACCESS ) - asmvolatile ("mrrc p15, 0, %Q0, %R0, c14" :"=r" (cval)); - -if (access ==ARCH_TIMER_VIRT_ACCESS ) - asmvolatile ("mrrc p15, 1, %Q0, %R0, c14" :"=r" (cval)); - +u64 cval; + asmvolatile ("mrrc p15, 0, %Q0, %R0, c14" :"=r" (cval));return cval; } -static inline cycle_t arch_counter_get_cntpct (void ) -{ -return arch_timer_counter_read (ARCH_TIMER_PHYS_ACCESS ); -} - -static inline cycle_t arch_counter_get_cntvct (void ) +static inline u64 arch_counter_get_cntvct (void ) { -return arch_timer_counter_read (ARCH_TIMER_VIRT_ACCESS ); +u64 cval; + asmvolatile ("mrrc p15, 1, %Q0, %R0, c14" :"=r" (cval)); +return cval; } static irqreturn_t inline timer_handler(const int access,
@@ -259,7 +250,7 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk)static int arch_timer_available (void ) { -unsigned long freq; +u32 freq;if (arch_timer_rate ==0 ) { freq = arch_timer_reg_read(ARCH_TIMER_PHYS_ACCESS,
@@ -275,7 +266,8 @@ static int arch_timer_available(void) }pr_info_once ("Architected local timer running at %lu.%02luMHz (%s).\n" , - arch_timer_rate /1000000 , (arch_timer_rate /10000 ) %100 , + (unsigned long )arch_timer_rate /1000000 , + (unsigned long )(arch_timer_rate /10000 ) %100 , arch_timer_use_virtual ?"virt" :"phys" );return 0 ; }
Signature · 1 line
1.7.0.4
PATCH v2 3/11 arm: arch_timer: use u64/u32 for register data
Quoted 9 lines · Mark Rutland
To ensure the correct size of types, use u64 for the return value of arch_timer_get_cnt{p,v}ct, and u32 for
arch_timer_rate, matching the size of the registers these values are taken from. While we're changing them anyway, simplify the implementation of arch_timer_get_cnt{p,v}ct.Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
Mark Rutland
maintainerPATCH v2 4/11 arm: arch_timer: standardise counter reading
In reply to Mark RutlandWe're currently inconsistent with respect to our accesses to the physical and virtual counters, mixing and matching the two.
This patch introduces and uses a function for accessing the correct counter based on whether we're using physical or virtual interrupts. All current accesses to the counter accessors are redirected through it.
--- arch/arm/kernel/arch_timer.c | 48 ++++++++++------------------------------- 1 files changed, 12 insertions(+), 36 deletions(-)
arch/arm/kernel/arch_timer.c +12 -36
@@ -272,51 +272,32 @@ static int arch_timer_available(void)return 0 ; } -static u32 notrace arch_counter_get_cntpct32(void) +u64 arch_timer_read_counter (void ) { -cycle_t cnt =arch_counter_get_cntpct (); - -/* -* The sched_clock infrastructure only knows about counters -* with at most 32bits. Forget about the upper 24 bits for the -* time being... -*/ -return (u32 )cnt; +if (arch_timer_use_virtual) +return arch_counter_get_cntvct (); +else +return arch_counter_get_cntpct (); } -static u32 notrace arch_counter_get_cntvct32(void) +static u32 arch_timer_read_counter32 (void ) { -cycle_t cnt =arch_counter_get_cntvct (); - -/* -* The sched_clock infrastructure only knows about counters -* with at most 32bits. Forget about the upper 24 bits for the -* time being... -*/ -return (u32 )cnt; +return arch_timer_read_counter (); }static cycle_t arch_counter_read (struct clocksource *cs) { -/* -* Always use the physical counter for the clocksource. -* CNTHCTL.PL1PCTEN must be set to 1. -*/ -return arch_counter_get_cntpct (); +return arch_timer_read_counter (); }static unsigned long arch_timer_read_current_timer (void ) { -return arch_counter_get_cntpct (); +return arch_timer_read_counter (); }static cycle_t arch_counter_read_cc (const struct cyclecounter *cc) { -/* -* Always use the physical counter for the clocksource. -* CNTHCTL.PL1PCTEN must be set to 1. -*/ -return arch_counter_get_cntpct (); +return arch_timer_read_counter (); }static struct clocksource clocksource_counter = {
@@ -489,18 +470,13 @@ int __init arch_timer_of_register(void)int __init arch_timer_sched_clock_init (void ) { -u32 (*cnt32)(void);int err; err =arch_timer_available ();if (err)return err; -if (arch_timer_use_virtual) - cnt32 = arch_counter_get_cntvct32; -else - cnt32 = arch_counter_get_cntpct32; - -setup_sched_clock (cnt32,32 , arch_timer_rate); +setup_sched_clock (arch_timer_read_counter32, +32 , arch_timer_rate);return 0 ; }
Signature · 1 line
1.7.0.4
PATCH v2 4/11 arm: arch_timer: standardise counter reading
Quoted 40 lines · Mark Rutland
We're currently inconsistent with respect to our accesses to the physical and virtual counters, mixing and matching the two.
This patch introduces and uses a function for accessing the correct counter based on whether we're using physical or virtual interrupts. All current accesses to the counter accessors are redirected through it.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/kernel/arch_timer.c | 48 ++++++++++------------------------------- 1 files changed, 12 insertions(+), 36 deletions(-)arch/arm/kernel/arch_timer.c +5
-9@@ -272,51 +272,32 @@ static int arch_timer_available(void)return 0 ; } -static u32 notrace arch_counter_get_cntpct32(void) +u64 arch_timer_read_counter (void ) { -cycle_t cnt =arch_counter_get_cntpct (); - -/* -* The sched_clock infrastructure only knows about counters -* with at most 32bits. Forget about the upper 24 bits for the -* time being... -*/ -return (u32 )cnt; +if (arch_timer_use_virtual) +return arch_counter_get_cntvct (); +else +return arch_counter_get_cntpct (); }
[...]
Quoted 12 lines
arch/arm/kernel/arch_timer.c +0
-1@@ -489,18 +470,13 @@ int __init arch_timer_of_register(void)int __init arch_timer_sched_clock_init (void ) { -u32 (*cnt32)(void);int err; err =arch_timer_available ();if (err)return err;
arch/arm/kernel/arch_timer.c int __init arch_timer_of_register(void) · line 482
Quoted 10 lines
arch/arm/kernel/arch_timer.c +2
-6-if (arch_timer_use_virtual) - cnt32 = arch_counter_get_cntvct32; -else - cnt32 = arch_counter_get_cntpct32; - -setup_sched_clock (cnt32,32 , arch_timer_rate); +setup_sched_clock (arch_timer_read_counter32, +32 , arch_timer_rate);return 0 ; }
I think the original idea had merit since the check was needed in init code instead of proposed one which has if check for every counter read function. No ?
Mark Rutland
maintainerPATCH v2 4/11 arm: arch_timer: standardise counter reading
Quoted 55 lines · Santosh Shilimkar
Quoted 40 lines · Mark Rutland
We're currently inconsistent with respect to our accesses to the physical and virtual counters, mixing and matching the two.
This patch introduces and uses a function for accessing the correct counter based on whether we're using physical or virtual interrupts. All current accesses to the counter accessors are redirected through it.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/kernel/arch_timer.c | 48 ++++++++++------------------------------- 1 files changed, 12 insertions(+), 36 deletions(-)arch/arm/kernel/arch_timer.c +5
-9@@ -272,51 +272,32 @@ static int arch_timer_available(void)return 0 ; } -static u32 notrace arch_counter_get_cntpct32(void) +u64 arch_timer_read_counter (void ) { -cycle_t cnt =arch_counter_get_cntpct (); - -/* -* The sched_clock infrastructure only knows about counters -* with at most 32bits. Forget about the upper 24 bits for the -* time being... -*/ -return (u32 )cnt; +if (arch_timer_use_virtual) +return arch_counter_get_cntvct (); +else +return arch_counter_get_cntpct (); }[...]
Quoted 11 lines
arch/arm/kernel/arch_timer.c +0
-1@@ -489,18 +470,13 @@ int __init arch_timer_of_register(void)int __init arch_timer_sched_clock_init (void ) { -u32 (*cnt32)(void);int err; err =arch_timer_available ();if (err)return err;
Quoted 15 lines
arch/arm/kernel/arch_timer.c int __init arch_timer_of_register(void) · line 482
Quoted 11 lines
arch/arm/kernel/arch_timer.c +2
-6-if (arch_timer_use_virtual) - cnt32 = arch_counter_get_cntvct32; -else - cnt32 = arch_counter_get_cntpct32; - -setup_sched_clock (cnt32,32 , arch_timer_rate); +setup_sched_clock (arch_timer_read_counter32, +32 , arch_timer_rate);return 0 ; }I think the original idea had merit since the check was needed in init code instead of proposed one which has if check for every counter read function. No ?
The original idea was good in that it avoided the check on each read path, but in several places the logic got duplicated (e.g. for choosing which width-altering wrapper in the above block). I'd like ensure this logic is consolidated.
I'll change arch_timer_read_counter to a function pointer, and set this in arch_timer_of_register before registering anything. Everything would still be indirected through it, but it won't have to do a check on every read.
Thanks,
Mark.
PATCH v2 4/11 arm: arch_timer: standardise counter reading
Quoted 72 lines · Mark Rutland
Quoted 55 lines · Santosh Shilimkar
Quoted 40 lines · Mark Rutland
We're currently inconsistent with respect to our accesses to the physical and virtual counters, mixing and matching the two.
This patch introduces and uses a function for accessing the correct counter based on whether we're using physical or virtual interrupts. All current accesses to the counter accessors are redirected through it.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/kernel/arch_timer.c | 48 ++++++++++------------------------------- 1 files changed, 12 insertions(+), 36 deletions(-)arch/arm/kernel/arch_timer.c +5
-9@@ -272,51 +272,32 @@ static int arch_timer_available(void)return 0 ; } -static u32 notrace arch_counter_get_cntpct32(void) +u64 arch_timer_read_counter (void ) { -cycle_t cnt =arch_counter_get_cntpct (); - -/* -* The sched_clock infrastructure only knows about counters -* with at most 32bits. Forget about the upper 24 bits for the -* time being... -*/ -return (u32 )cnt; +if (arch_timer_use_virtual) +return arch_counter_get_cntvct (); +else +return arch_counter_get_cntpct (); }[...]
Quoted 11 lines
arch/arm/kernel/arch_timer.c +0
-1@@ -489,18 +470,13 @@ int __init arch_timer_of_register(void)int __init arch_timer_sched_clock_init (void ) { -u32 (*cnt32)(void);int err; err =arch_timer_available ();if (err)return err;Quoted 15 lines
arch/arm/kernel/arch_timer.c int __init arch_timer_of_register(void) · line 482
Quoted 11 lines
arch/arm/kernel/arch_timer.c +2
-6-if (arch_timer_use_virtual) - cnt32 = arch_counter_get_cntvct32; -else - cnt32 = arch_counter_get_cntpct32; - -setup_sched_clock (cnt32,32 , arch_timer_rate); +setup_sched_clock (arch_timer_read_counter32, +32 , arch_timer_rate);return 0 ; }I think the original idea had merit since the check was needed in init code instead of proposed one which has if check for every counter read function. No ?
Quoted 9 lines
The original idea was good in that it avoided the check on each read path, but in several places the logic got duplicated (e.g. for choosing which width-altering wrapper in the above block). I'd like ensure this logic is consolidated.
I'll change
arch_timer_read_counterto a function pointer, and set this inarch_timer_of_registerbefore registering anything. Everything would still be indirected through it, but it won't have to do a check on every read.
Sounds good
Mark Rutland
maintainerPATCH v2 5/11 arm: arch_timer: split cntfrq accessor
In reply to Mark RutlandThe CNTFRQ register is not duplicated for physical and virtual timers, and accessing it as if it were is confusing.
Instead, use a separate accessor which doesn't take the access type as a parameter.
--- arch/arm/kernel/arch_timer.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-)
arch/arm/kernel/arch_timer.c +9 -8
@@ -51,8 +51,7 @@ static bool arch_timer_use_virtual = true;#define ARCH_TIMER_CTRL_IT_STAT (1 << 2)#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_FREQ 1 -#define ARCH_TIMER_REG_TVAL 2 +#define ARCH_TIMER_REG_TVAL 1#define ARCH_TIMER_PHYS_ACCESS 0#define ARCH_TIMER_VIRT_ACCESS 1
@@ -101,9 +100,6 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)case ARCH_TIMER_REG_TVAL : asmvolatile ("mrc p15, 0, %0, c14, c2, 0" :"=r" (val));break ; -case ARCH_TIMER_REG_FREQ : - asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); -break ; } }
@@ -121,6 +117,13 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)return val; } +static inline u32 arch_timer_get_cntfrq (void ) +{ +u32 val; + asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); +return val; +} +static inline u64 arch_counter_get_cntpct (void ) {u64 cval;
@@ -253,9 +256,7 @@ static int arch_timer_available(void)u32 freq;if (arch_timer_rate ==0 ) { - freq =arch_timer_reg_read (ARCH_TIMER_PHYS_ACCESS , -ARCH_TIMER_REG_FREQ ); - + freq =arch_timer_get_cntfrq ();/* Check the timer frequency. */ if (freq ==0 ) {pr_warn ("Architected timer frequency not available\n" );
Signature · 1 line
1.7.0.4
PATCH v2 5/11 arm: arch_timer: split cntfrq accessor
Quoted 52 lines · Mark Rutland
The CNTFRQ register is not duplicated for physical and virtual timers, and accessing it as if it were is confusing.
Instead, use a separate accessor which doesn't take the access type as a parameter.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/kernel/arch_timer.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-)arch/arm/kernel/arch_timer.c +8
-5@@ -51,8 +51,7 @@ static bool arch_timer_use_virtual = true;#define ARCH_TIMER_CTRL_IT_STAT (1 << 2)#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_FREQ 1 -#define ARCH_TIMER_REG_TVAL 2 +#define ARCH_TIMER_REG_TVAL 1#define ARCH_TIMER_PHYS_ACCESS 0#define ARCH_TIMER_VIRT_ACCESS 1@@ -101,9 +100,6 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)case ARCH_TIMER_REG_TVAL : asmvolatile ("mrc p15, 0, %0, c14, c2, 0" :"=r" (val));break ; -case ARCH_TIMER_REG_FREQ : - asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); -break ; } }@@ -121,6 +117,13 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)return val; } +static inline u32 arch_timer_get_cntfrq (void ) +{ +u32 val; + asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); +return val; +} +static inline u64 arch_counter_get_cntpct (void ) {u64 cval;
arch/arm/kernel/arch_timer.c static int arch_timer_available(void) · line 259
Quoted 7 lines
arch/arm/kernel/arch_timer.c +1
-3@@ -253,9 +256,7 @@ static int arch_timer_available(void)u32 freq;if (arch_timer_rate ==0 ) { - freq =arch_timer_reg_read (ARCH_TIMER_PHYS_ACCESS , -ARCH_TIMER_REG_FREQ ); - + freq =arch_timer_get_cntfrq ();
Not related to this patch a new line here will be good.
arch/arm/kernel/arch_timer.c static int arch_timer_available(void) · line 262
Quoted 4 lines
arch/arm/kernel/arch_timer.c +0
-0/* Check the timer frequency. */ if (freq ==0 ) {pr_warn ("Architected timer frequency not available\n" );
Otherwise patch looks fine to me.
Mark Rutland
maintainerPATCH v2 5/11 arm: arch_timer: split cntfrq accessor
Quoted 55 lines · Santosh Shilimkar
Quoted 54 lines · Mark Rutland
The CNTFRQ register is not duplicated for physical and virtual timers, and accessing it as if it were is confusing.
Instead, use a separate accessor which doesn't take the access type as a parameter.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/kernel/arch_timer.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-)arch/arm/kernel/arch_timer.c +8
-5@@ -51,8 +51,7 @@ static bool arch_timer_use_virtual = true;#define ARCH_TIMER_CTRL_IT_STAT (1 << 2)#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_FREQ 1 -#define ARCH_TIMER_REG_TVAL 2 +#define ARCH_TIMER_REG_TVAL 1#define ARCH_TIMER_PHYS_ACCESS 0#define ARCH_TIMER_VIRT_ACCESS 1@@ -101,9 +100,6 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)case ARCH_TIMER_REG_TVAL : asmvolatile ("mrc p15, 0, %0, c14, c2, 0" :"=r" (val));break ; -case ARCH_TIMER_REG_FREQ : - asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); -break ; } }@@ -121,6 +117,13 @@ static inline u32 arch_timer_reg_read(const int access, const int reg)return val; } +static inline u32 arch_timer_get_cntfrq (void ) +{ +u32 val; + asmvolatile ("mrc p15, 0, %0, c14, c0, 0" :"=r" (val)); +return val; +} +static inline u64 arch_counter_get_cntpct (void ) {u64 cval;@@ -253,9 +256,7 @@ static int arch_timer_available(void)u32 freq;
Quoted 6 lines
arch/arm/kernel/arch_timer.c static int arch_timer_available(void) · line 259
Quoted 5 lines
arch/arm/kernel/arch_timer.c +1
-3if (arch_timer_rate ==0 ) { - freq =arch_timer_reg_read (ARCH_TIMER_PHYS_ACCESS , -ARCH_TIMER_REG_FREQ ); - + freq =arch_timer_get_cntfrq ();Not related to this patch a new line here will be good.
Whoops. I hadn't intended to alter the line spacing here. I'll fix that up.
Quoted 7 lines
arch/arm/kernel/arch_timer.c static int arch_timer_available(void) · line 262
Quoted 4 lines
arch/arm/kernel/arch_timer.c +0
-0/* Check the timer frequency. */ if (freq ==0 ) {pr_warn ("Architected timer frequency not available\n" );Otherwise patch looks fine to me.
Acked-by Santosh Shilimkar<[email protected]>
Thanks,
Mark.
Mark Rutland
maintainerPATCH v2 6/11 arm: arch_timer: factor out register accessors
In reply to Mark RutlandCurrently the arch_timer register accessors are thrown together with the main driver, preventing us from porting the driver to other architectures.
This patch moves the register accessors into a header file, as with the arm64 version. Constants required by the accessors are also moved.
Additionally isbs are added in arch_timer_get_cnt{v,p}ct to prevent the cpu from speculating the reads and returning stale values.
--- arch/arm/include/asm/arch_timer.h | 101 +++++++++++++++++++++++++++++++++++++ arch/arm/kernel/arch_timer.c | 92 --------------------------------- 2 files changed, 101 insertions(+), 92 deletions(-)
arch/arm/include/asm/arch_timer.h +101 -0
@@ -1,13 +1,114 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H +#include <asm/barrier.h> #include <asm/errno.h> + #include <linux/clocksource.h> +#include <linux/types.h> #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); struct timecounter *arch_timer_get_timecounter(void); + +#define ARCH_TIMER_CTRL_ENABLE (1 << 0) +#define ARCH_TIMER_CTRL_IT_MASK (1 << 1) +#define ARCH_TIMER_CTRL_IT_STAT (1 << 2) + +#define ARCH_TIMER_REG_CTRL 0 +#define ARCH_TIMER_REG_TVAL 1 + +#define ARCH_TIMER_PHYS_ACCESS 0 +#define ARCH_TIMER_VIRT_ACCESS 1 + +/* + * These register accessors are marked inline so the compiler can + * nicely work out which register we want, and chuck away the rest of + * the code. At least it does so with a recent GCC (4.6.3). + */ +static inline void arch_timer_reg_write(const int access, const int reg, u32 val) +{ + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); + break; + } + } + + isb(); +} + +static inline u32 arch_timer_reg_read(const int access, const int reg) +{ + u32 val = 0; + + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); + break; + } + } + + return val; +} + +static inline u32 arch_timer_get_cntfrq(void) +{ + u32 val; + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); + return val; +} + +static inline u64 arch_counter_get_cntpct(void) +{ + u64 cval; + + isb(); + asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); + return cval; +} + +static inline u64 arch_counter_get_cntvct(void) +{ + u64 cval; + + isb(); + asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); + return cval; +} + + #else static inline int arch_timer_of_register(void) {
arch/arm/kernel/arch_timer.c +0 -92
98 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH v2 6/11 arm: arch_timer: factor out register accessors
Quoted 68 lines · Mark Rutland
Currently the
arch_timerregister accessors are thrown together with the main driver, preventing us from porting the driver to other architectures.This patch moves the register accessors into a header file, as with the arm64 version. Constants required by the accessors are also moved.
Additionally isbs are added in arch_timer_get_cnt{v,p}ct to prevent the cpu from speculating the reads and returning stale values.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/include/asm/arch_timer.h | 101 +++++++++++++++++++++++++++++++++++++ arch/arm/kernel/arch_timer.c | 92 --------------------------------- 2 files changed, 101 insertions(+), 92 deletions(-)arch/arm/include/asm/arch_timer.h +35
-0@@ -1,13 +1,114 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H +#include <asm/barrier.h> #include <asm/errno.h> + #include <linux/clocksource.h> +#include <linux/types.h> #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); struct timecounter *arch_timer_get_timecounter(void); + +#define ARCH_TIMER_CTRL_ENABLE (1 << 0) +#define ARCH_TIMER_CTRL_IT_MASK (1 << 1) +#define ARCH_TIMER_CTRL_IT_STAT (1 << 2) + +#define ARCH_TIMER_REG_CTRL 0 +#define ARCH_TIMER_REG_TVAL 1 + +#define ARCH_TIMER_PHYS_ACCESS 0 +#define ARCH_TIMER_VIRT_ACCESS 1 + +/* + * These register accessors are marked inline so the compiler can + * nicely work out which register we want, and chuck away the rest of + * the code. At least it does so with a recent GCC (4.6.3). + */ +static inline void arch_timer_reg_write(const int access, const int reg, u32 val) +{ + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL:
arch/arm/include/asm/arch_timer.h line 55
Quoted 10 lines
arch/arm/include/asm/arch_timer.h +10
-0+ asmvolatile ("mcr p15, 0, %0, c14, c3, 1" : :"r" (val)); +break ; +case ARCH_TIMER_REG_TVAL : + asmvolatile ("mcr p15, 0, %0, c14, c3, 0" : :"r" (val)); +break ; + } + } + +isb (); +}
The isb() additions is actually a sepoerate fix. I suggest you to split the subject patch into 1) Movement of header data 2) isb() additions.
Feel free to add my ack on updated patches if you agree.
Regards,
Santosh
Mark Rutland
maintainerPATCH v2 6/11 arm: arch_timer: factor out register accessors
Quoted 82 lines · Santosh Shilimkar
Quoted 68 lines · Mark Rutland
Currently the
arch_timerregister accessors are thrown together with the main driver, preventing us from porting the driver to other architectures.This patch moves the register accessors into a header file, as with the arm64 version. Constants required by the accessors are also moved.
Additionally isbs are added in arch_timer_get_cnt{v,p}ct to prevent the cpu from speculating the reads and returning stale values.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/include/asm/arch_timer.h | 101 +++++++++++++++++++++++++++++++++++++ arch/arm/kernel/arch_timer.c | 92 --------------------------------- 2 files changed, 101 insertions(+), 92 deletions(-)arch/arm/include/asm/arch_timer.h +35
-0@@ -1,13 +1,114 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H +#include <asm/barrier.h> #include <asm/errno.h> + #include <linux/clocksource.h> +#include <linux/types.h> #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); struct timecounter *arch_timer_get_timecounter(void); + +#define ARCH_TIMER_CTRL_ENABLE (1 << 0) +#define ARCH_TIMER_CTRL_IT_MASK (1 << 1) +#define ARCH_TIMER_CTRL_IT_STAT (1 << 2) + +#define ARCH_TIMER_REG_CTRL 0 +#define ARCH_TIMER_REG_TVAL 1 + +#define ARCH_TIMER_PHYS_ACCESS 0 +#define ARCH_TIMER_VIRT_ACCESS 1 + +/* + * These register accessors are marked inline so the compiler can + * nicely work out which register we want, and chuck away the rest of + * the code. At least it does so with a recent GCC (4.6.3). + */ +static inline void arch_timer_reg_write(const int access, const int reg, u32 val) +{ + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL:arch/arm/include/asm/arch_timer.h line 55
Quoted 10 lines
arch/arm/include/asm/arch_timer.h +10
-0+ asmvolatile ("mcr p15, 0, %0, c14, c3, 1" : :"r" (val)); +break ; +case ARCH_TIMER_REG_TVAL : + asmvolatile ("mcr p15, 0, %0, c14, c3, 0" : :"r" (val)); +break ; + } + } + +isb (); +}The
isb()additions is actually a sepoerate fix. I suggest you to split the subject patch into 1) Movement of header data 2)isb()additions.
Quoted 1 line
Feel free to add my ack on updated patches if you agree.
Thanks, will do.
Quoted 4 lines
Regards,
Santosh
Mark.
Mark Rutland
maintainerPATCH v2 7/11 arm: arch_timer: divorce from local_timer api
In reply to Mark RutlandCurrently, the arch_timer driver is tied to the arm port, as it relies on code in arch/arm/smp.c to setup and teardown timers as cores are hotplugged on and off. The timer is registered through an arm-specific registration mechanism, preventing sharing the driver with the arm64 port.
This patch moves the driver to using a cpu notifier instead, making it easier to port.
--- arch/arm/kernel/arch_timer.c | 52 +++++++++++++++++++++++------------------ 1 files changed, 29 insertions(+), 23 deletions(-)
arch/arm/kernel/arch_timer.c +29 -23
@@ -21,7 +21,6 @@#include <linux/io.h> #include <asm/delay.h> -#include <asm/localtimer.h> #include <asm/arch_timer.h> #include <asm/sched_clock.h>
@@ -37,7 +36,7 @@ enum ppi_nr {static int arch_timer_ppi[MAX_TIMER_PPI ]; -static struct clock_event_device __percpu **arch_timer_evt; +static struct clock_event_device __percpu *arch_timer_evt;static struct delay_timer arch_delay_timer;static bool arch_timer_use_virtual = true;
@@ -63,14 +62,14 @@ static irqreturn_t inline timer_handler(const int access,static irqreturn_t arch_timer_handler_virt (int irq,void *dev_id) { -struct clock_event_device *evt = *(struct clock_event_device **)dev_id; +struct clock_event_device *evt = dev_id;return timer_handler (ARCH_TIMER_VIRT_ACCESS , evt); }static irqreturn_t arch_timer_handler_phys (int irq,void *dev_id) { -struct clock_event_device *evt = *(struct clock_event_device **)dev_id; +struct clock_event_device *evt = dev_id;return timer_handler (ARCH_TIMER_PHYS_ACCESS , evt); }
@@ -141,13 +140,13 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk) clk->set_next_event = arch_timer_set_next_event_phys; } + clk->cpumask =cpumask_of (smp_processor_id ()); + clk->set_mode (CLOCK_EVT_MODE_SHUTDOWN ,NULL );clockevents_config_and_register (clk, arch_timer_rate,0xf ,0x7fffffff ); - *__this_cpu_ptr (arch_timer_evt) = clk; -if (arch_timer_use_virtual)enable_percpu_irq (arch_timer_ppi[VIRT_PPI ],0 );else {
@@ -245,12 +244,26 @@ static void __cpuinit arch_timer_stop(struct clock_event_device *clk) clk->set_mode (CLOCK_EVT_MODE_UNUSED , clk); } -static struct local_timer_ops arch_timer_ops__cpuinitdata = { - .setup = arch_timer_setup, - .stop = arch_timer_stop, -}; +static int __cpuinit arch_timer_cpu_notify (struct notifier_block *self, +unsigned long action,void *hcpu) +{ +struct clock_event_device *evt =this_cpu_ptr (arch_timer_evt); + +switch (action & ~CPU_TASKS_FROZEN ) { +case CPU_STARTING : +arch_timer_setup (evt); +break ; +case CPU_DYING : +arch_timer_stop (evt); +break ; + } + +return NOTIFY_OK ; +} -static struct clock_event_device arch_timer_global_evt; +static struct notifier_block arch_timer_cpu_nb__cpuinitdata = { + .notifier_call = arch_timer_cpu_notify, +};static int __init arch_timer_register (void ) {
@@ -261,7 +274,7 @@ static int __init arch_timer_register(void)if (err) goto out; - arch_timer_evt = alloc_percpu(struct clock_event_device *); + arch_timer_evt = alloc_percpu(struct clock_event_device);if (!arch_timer_evt) { err = -ENOMEM ; goto out;
@@ -297,20 +310,13 @@ static int __init arch_timer_register(void) goto out_free; } - err =local_timer_register (&arch_timer_ops); -if (err) { -/* -* We couldn't register as a local timer (could be -* because we're on a UP platform, or because some -* other local timer is already present...). Try as a -* global timer instead. -*/ - arch_timer_global_evt.cpumask =cpumask_of (0 ); - err =arch_timer_setup (&arch_timer_global_evt); - } + err =register_cpu_notifier (&arch_timer_cpu_nb);if (err) goto out_free_irq; +/* Immediately configure the timer on the boot CPU */ +arch_timer_setup (this_cpu_ptr (arch_timer_evt)); +/* Use the architected timer for the delay loop. */ arch_delay_timer.read_current_timer = &arch_timer_read_current_timer; arch_delay_timer.freq = arch_timer_rate;
Signature · 1 line
1.7.0.4
PATCH v2 7/11 arm: arch_timer: divorce from local_timer api
Quoted 6 lines · Mark Rutland
Currently, the
arch_timerdriver is tied to the arm port, as it relies on code inarch/arm/smp.cto setup and teardown timers as cores are hotplugged on and off. The timer is registered through an arm-specific registration mechanism, preventing sharing the driver with the arm64 port.
Quoted 7 lines
This patch moves the driver to using a cpu notifier instead, making it easier to port.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
This is really a nit idea. I think we should do the same for ARM gic code.
For the patch,
Catalin Marinas
maintainerPATCH v2 7/11 arm: arch_timer: divorce from local_timer api
Quoted 10 lines · Santosh Shilimkar
Quoted 9 lines · Mark Rutland
Currently, the
arch_timerdriver is tied to the arm port, as it relies on code inarch/arm/smp.cto setup and teardown timers as cores are hotplugged on and off. The timer is registered through an arm-specific registration mechanism, preventing sharing the driver with the arm64 port.This patch moves the driver to using a cpu notifier instead, making it easier to port.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
This is really a nit idea. I think we should do the same for ARM gic code.
I plan to do the same once Rob's GIC patches get merged. In my soc-armv8-model branch I have a copy of gic.c into drivers/irqchip and the CPU interface is done automatically via a notifier. The only trick is to set the priority of the GIC notifier higher than the timer one.
Signature · 1 line
Catalin
PATCH v2 7/11 arm: arch_timer: divorce from local_timer api
Quoted 15 lines · Catalin Marinas
Quoted 14 lines · Santosh Shilimkar
Quoted 13 lines · Mark Rutland
Currently, the
arch_timerdriver is tied to the arm port, as it relies on code inarch/arm/smp.cto setup and teardown timers as cores are hotplugged on and off. The timer is registered through an arm-specific registration mechanism, preventing sharing the driver with the arm64 port.This patch moves the driver to using a cpu notifier instead, making it easier to port.
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
Quoted 8 lines
Quoted 2 lines
This is really a nit idea. I think we should do the same for ARM gic code.
I plan to do the same once Rob's GIC patches get merged. In my soc-armv8-model branch I have a copy of
gic.cintodrivers/irqchipand the CPU interface is done automatically via a notifier. The only trick is to set the priority of the GIC notifier higher than the timer one.
Great. Thanks for the information.
Regards,
Santosh
Mark Rutland
maintainerPATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
In reply to Mark RutlandSeveral bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
This patch adds arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currently means disabling all userspace access.
--- arch/arm/include/asm/arch_timer.h | 11 +++++++++++ arch/arm/kernel/arch_timer.c | 2 ++ 2 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/include/asm/arch_timer.h +11 -0
@@ -108,6 +108,17 @@ static inline u64 arch_counter_get_cntvct(void) return cval; } +static inline void __cpuinit arch_counter_set_user_access (void ) +{ +u32 cntkctl; + + asmvolatile ("mrc p15, 0, %0, c14, c1, 0" :"=r" (cntkctl)); + +/* disable user access to everything */ + cntkctl &= ~((3 <<8 ) | (7 <<0 )); + + asmvolatile ("mcr p15, 0, %0, c14, c1, 0" : :"r" (cntkctl)); +}#else static inline int arch_timer_of_register (void )
arch/arm/kernel/arch_timer.c +2 -0
@@ -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 ; }
Signature · 1 line
1.7.0.4
PATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
Quoted 8 lines · Mark Rutland
Several bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
This patch adds
arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currently
minor nit.
s/arm/ARM
Quoted 35 lines
means disabling all userspace access.
Signed-off-by Mark Rutland <[email protected]>--- arch/arm/include/asm/arch_timer.h | 11 +++++++++++ arch/arm/kernel/arch_timer.c | 2 ++ 2 files changed, 13 insertions(+), 0 deletions(-)arch/arm/include/asm/arch_timer.h +11
-0@@ -108,6 +108,17 @@ static inline u64 arch_counter_get_cntvct(void) return cval; } +static inline void __cpuinit arch_counter_set_user_access (void ) +{ +u32 cntkctl; + + asmvolatile ("mrc p15, 0, %0, c14, c1, 0" :"=r" (cntkctl)); + +/* disable user access to everything */ + cntkctl &= ~((3 <<8 ) | (7 <<0 )); + + asmvolatile ("mcr p15, 0, %0, c14, c1, 0" : :"r" (cntkctl)); +}#else static inline int arch_timer_of_register (void )arch/arm/kernel/arch_timer.c +0
-0
arch/arm/kernel/arch_timer.c static int __cpuinit arch_timer_setup(struct clock_event_device *clk) · line 158
Quoted 4 lines
arch/arm/kernel/arch_timer.c +1
-0@@ -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 ();
So how do you expect platform to enabled the user-space access in case they want to access it for some cases.
Regards
Santosh
Mark Rutland
maintainerPATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
Quoted 50 lines · Santosh Shilimkar
Quoted 8 lines · Mark Rutland
Several bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
This patch adds
arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currentlyminor nit.
s/arm/ARMQuoted 38 lines
means disabling all userspace access.
Signed-off-by Mark Rutland <[email protected]>--- arch/arm/include/asm/arch_timer.h | 11 +++++++++++ arch/arm/kernel/arch_timer.c | 2 ++ 2 files changed, 13 insertions(+), 0 deletions(-)arch/arm/include/asm/arch_timer.h +11
-0@@ -108,6 +108,17 @@ static inline u64 arch_counter_get_cntvct(void) return cval; } +static inline void __cpuinit arch_counter_set_user_access (void ) +{ +u32 cntkctl; + + asmvolatile ("mrc p15, 0, %0, c14, c1, 0" :"=r" (cntkctl)); + +/* disable user access to everything */ + cntkctl &= ~((3 <<8 ) | (7 <<0 )); + + asmvolatile ("mcr p15, 0, %0, c14, c1, 0" : :"r" (cntkctl)); +}#else static inline int arch_timer_of_register (void )arch/arm/kernel/arch_timer.c +0
-0@@ -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 ); }
Quoted 3 lines
arch/arm/kernel/arch_timer.c static int __cpuinit arch_timer_setup(struct clock_event_device *clk) · line 158
Quoted 1 line
arch/arm/kernel/arch_timer.c +1
-0+arch_counter_set_user_access ();So how do you expect platform to enabled the user-space access in case they want to access it for some cases.
Unlike AArch64, at the moment we don't have the infrastructure to map this for userspace accesses, so it isn't much of a problem.
If in future we wish to map it on 32bit platforms, the arm implementation of arch_counter_set_user_access can be modified to allow userspace access to specific registers, and additional code would be required to actually map it into the user address space, etc.
Quoted 4 lines
Regards
Santosh
Thanks,
Mark.
PATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
Quoted 11 lines · Mark Rutland
Quoted 2 lines · Santosh Shilimkar
So how do you expect platform to enabled the user-space access in case they want to access it for some cases.
Unlike AArch64, at the moment we don't have the infrastructure to map this for userspace accesses, so it isn't much of a problem.
If in future we wish to map it on 32bit platforms, the arm implementation of
arch_counter_set_user_accesscan be modified to allow userspace access to specific registers, and additional code would be required to actually map it into the user address space, etc.
I'd also add that it's not up to a platform to decide whether to expose this to userspace: it needs to be an architecture-wide decision. Otherwise, userspace becomes SoC-specific, which is a complete disaster.
So, if userspace people want these available, they need to convince us to flip the switch. In the meantime, it should default to off so that if/when we do enable it we can do it in a sane manner for ARM (perhaps via the vectors page).
Will
PATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
Quoted 13 lines · Will Deacon
Quoted 11 lines · Mark Rutland
Quoted 2 lines · Santosh Shilimkar
So how do you expect platform to enabled the user-space access in case they want to access it for some cases.
Unlike AArch64, at the moment we don't have the infrastructure to map this for userspace accesses, so it isn't much of a problem.
If in future we wish to map it on 32bit platforms, the arm implementation of
arch_counter_set_user_accesscan be modified to allow userspace access to specific registers, and additional code would be required to actually map it into the user address space, etc.
Quoted 9 lines
I'd also add that it's not up to a platform to decide whether to expose this to userspace: it needs to be an architecture-wide decision. Otherwise, userspace becomes SoC-specific, which is a complete disaster.
So, if userspace people want these available, they need to convince us to flip the switch. In the meantime, it should default to off so that if/when we do enable it we can do it in a sane manner for ARM (perhaps via the vectors page).
Thanks Will for rationale behind the change. Good to capture the reasoning in changelog for future reference.
Regards,
Santosh
Catalin Marinas
maintainerPATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
In reply to Santosh ShilimkarQuoted 11 lines · Santosh Shilimkar
Quoted 8 lines · Mark Rutland
Several bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
This patch adds
arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currentlyminor nit.
s/arm/ARM
I think Mark meant arch/arm. Or we could call it AArch32 where we don't use this feature.
Signature · 1 line
Catalin
PATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
Quoted 8 lines · Catalin Marinas
Quoted 7 lines · Santosh Shilimkar
Quoted 6 lines · Mark Rutland
Several bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This patch adds
arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currentlyminor nit.
s/arm/ARMI think Mark meant
arch/arm. Or we could call it AArch32 where we don't use this feature.
OK. AArch32 or even arch/arm is just fine then.
Regards,
Santosh
Mark Rutland
maintainerPATCH v2 8/11 arm: arch_timer: add arch_counter_set_user_access
In reply to Catalin MarinasQuoted 8 lines · Catalin Marinas
Quoted 7 lines · Santosh Shilimkar
Quoted 6 lines · Mark Rutland
Several bits in CNTKCTL reset to 0, including PL0VTEN. For platforms using the generic timer which wish to have a fast gettimeofday vDSO implementation, these bits must be set to 1 by the kernel. On other platforms, the bootloader might enable userspace access when we don't want it.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
This patch adds
arch_counter_set_user_access, which sets the PL0 access permissions to that required by the platform. For arm, this currentlyminor nit.
s/arm/ARMI think Mark meant
arch/arm. Or we could call it AArch32 where we don't use this feature.
Indeed, I meant arch/arm. I'll try to be more consistent with that in future.
Mark.
Mark Rutland
maintainerPATCH v2 9/11 arm: arch_timer: move core to drivers/clocksource
In reply to Mark RutlandThe core functionality of the arch_timer driver is not directly tied to anything under arch/arm, and can be split out.
This patch factors out the core of the arch_timer driver, so it can be shared with other architectures. A couple of functions are added so that architecture-specific code can interact with the driver without needing to touch its internals.
The ARM_ARCH_TIMER config variable is moved out to drivers/clocksource/Kconfig, existing uses in arch/arm are replaced with USE_ARM_ARCH_TIMER, which selects it.
--- arch/arm/Kconfig | 3 +- arch/arm/include/asm/arch_timer.h | 19 +-- arch/arm/kernel/arch_timer.c | 375 ++-------------------------------- arch/arm/mach-omap2/Kconfig | 2 +- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 374 +++++++++++++++++++++++++++++++++ include/clocksource/arm_arch_timer.h | 63 ++++++ 8 files changed, 465 insertions(+), 375 deletions(-) create mode 100644 drivers/clocksource/arm_arch_timer.c create mode 100644 include/clocksource/arm_arch_timer.h
arch/arm/Kconfig +2 -1
@@ -1567,9 +1567,10 @@ config HAVE_ARM_SCU help This option enables support for the ARM system coherency unit -config ARM_ARCH_TIMER +config USE_ARM_ARCH_TIMER bool "Architected timer support" depends on CPU_V7 + select ARM_ARCH_TIMER help This option enables support for the ARM architected timer
arch/arm/include/asm/arch_timer.h +3 -16
@@ -5,22 +5,14 @@#include <asm/errno.h> #include <linux/clocksource.h> +#include <linux/init.h> #include <linux/types.h> +#include <clocksource/arm_arch_timer.h> +#ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_of_register (void );int arch_timer_sched_clock_init (void ); -struct timecounter *arch_timer_get_timecounter (void ); - -#define ARCH_TIMER_CTRL_ENABLE (1 << 0) -#define ARCH_TIMER_CTRL_IT_MASK (1 << 1) -#define ARCH_TIMER_CTRL_IT_STAT (1 << 2) - -#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_TVAL 1 - -#define ARCH_TIMER_PHYS_ACCESS 0 -#define ARCH_TIMER_VIRT_ACCESS 1/* * These register accessors are marked inline so the compiler can
@@ -130,11 +122,6 @@ static inline int arch_timer_sched_clock_init(void) {return -ENXIO ; } - -static inline struct timecounter *arch_timer_get_timecounter (void ) -{ -return NULL ; -}#endif #endif
arch/arm/kernel/arch_timer.c +18 -357
409 lines not on this page · raw message
arch/arm/mach-omap2/Kconfig +1 -1
@@ -76,12 +76,12 @@ config ARCH_OMAP4 config SOC_OMAP5 bool "TI OMAP5" - select ARM_ARCH_TIMER select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 select HAVE_SMP select COMMON_CLK + select USE_ARM_ARCH_TIMER comment "OMAP Core Type" depends on ARCH_OMAP2
drivers/clocksource/Kconfig +3 -0
@@ -58,3 +58,6 @@ config CLKSRC_ARM_GENERIC def_bool y if ARM64 help This option enables support for the ARM generic timer. + +config ARM_ARCH_TIMER + bool
drivers/clocksource/Makefile +1 -0
@@ -18,3 +18,4 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o +obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
drivers/clocksource/arm_arch_timer.c new file +374 -0
374 lines not on this page · raw message
include/clocksource/arm_arch_timer.h new file +63 -0
63 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH v2 9/11 arm: arch_timer: move core to drivers/clocksource
Quoted 25 lines · Mark Rutland
The core functionality of the
arch_timerdriver is not directly tied to anything underarch/arm, and can be split out.This patch factors out the core of the
arch_timerdriver, so it can be shared with other architectures. A couple of functions are added so that architecture-specific code can interact with the driver without needing to touch its internals.The
ARM_ARCH_TIMERconfig variable is moved out todrivers/clocksource/Kconfig, existing uses inarch/armare replaced withUSE_ARM_ARCH_TIMER, which selects it.Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/Kconfig | 3 +- arch/arm/include/asm/arch_timer.h | 19 +-- arch/arm/kernel/arch_timer.c | 375 ++-------------------------------- arch/arm/mach-omap2/Kconfig | 2 +- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 374 +++++++++++++++++++++++++++++++++ include/clocksource/arm_arch_timer.h | 63 ++++++ 8 files changed, 465 insertions(+), 375 deletions(-)
Quoted 3 lines
create mode 100644
drivers/clocksource/arm_arch_timer.ccreate mode 100644include/clocksource/arm_arch_timer.h
It would have been easy if you have formated the patch with -C option. That will just leave the delta changes only and hiding the file movement related diff.
Quoted 6 lines
arch/arm/Kconfig +0
-0@@ -1567,9 +1567,10 @@ config HAVE_ARM_SCU help
arch/arm/Kconfig config HAVE_ARM_SCU · line 1576
Quoted 10 lines
arch/arm/Kconfig +2
-1This option enables support for the ARM system coherency unit -config ARM_ARCH_TIMER +config USE_ARM_ARCH_TIMER bool "Architected timer support" depends on CPU_V7 + select ARM_ARCH_TIMER help This option enables support for the ARM architected timer
How about HAVE_ARM_ARCH_TIMER in-line with HAVE_ARM_TWD. No strong opinion though.
Regards
Santosh
Mark Rutland
maintainerPATCH v2 9/11 arm: arch_timer: move core to drivers/clocksource
Quoted 29 lines · Santosh Shilimkar
Quoted 25 lines · Mark Rutland
The core functionality of the
arch_timerdriver is not directly tied to anything underarch/arm, and can be split out.This patch factors out the core of the
arch_timerdriver, so it can be shared with other architectures. A couple of functions are added so that architecture-specific code can interact with the driver without needing to touch its internals.The
ARM_ARCH_TIMERconfig variable is moved out todrivers/clocksource/Kconfig, existing uses inarch/armare replaced withUSE_ARM_ARCH_TIMER, which selects it.Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm/Kconfig | 3 +- arch/arm/include/asm/arch_timer.h | 19 +-- arch/arm/kernel/arch_timer.c | 375 ++-------------------------------- arch/arm/mach-omap2/Kconfig | 2 +- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_arch_timer.c | 374 +++++++++++++++++++++++++++++++++ include/clocksource/arm_arch_timer.h | 63 ++++++ 8 files changed, 465 insertions(+), 375 deletions(-)Quoted 3 lines
create mode 100644
drivers/clocksource/arm_arch_timer.ccreate mode 100644include/clocksource/arm_arch_timer.h
Quoted 3 lines
It would have been easy if you have formated the patch with -C option. That will just leave the delta changes only and hiding the file movement related diff.
Sorry, I'll make sure I do that next time.
Quoted 8 lines
Quoted 8 lines
arch/arm/Kconfig +0
-0@@ -1567,9 +1567,10 @@ config HAVE_ARM_SCU help This option enables support for the ARM system coherency unit
Quoted 10 lines
arch/arm/Kconfig config HAVE_ARM_SCU · line 1576
Quoted 8 lines
arch/arm/Kconfig +2
-1-config ARM_ARCH_TIMER +config USE_ARM_ARCH_TIMER bool "Architected timer support" depends on CPU_V7 + select ARM_ARCH_TIMER help This option enables support for the ARM architected timerHow about
HAVE_ARM_ARCH_TIMERin-line withHAVE_ARM_TWD. No strong opinion though.
Sure. It'll also make it more consistent with HAVE_ARM_SCU.
Quoted 4 lines
Regards
Santosh
Thanks,
Mark.
Mark Rutland
maintainerPATCH v2 10/11 arm64: move from arm_generic to arm_arch_timer
In reply to Mark RutlandThe arch_timer driver supports a superset of the functionality of the arm_generic driver, and is not tied to a particular arch.
This patch moves arm64 to use the arch_timer driver, gaining additional functionality in doing so, and removes the (now unused) arm_generic driver. Timer-related hooks specific to arm64 are moved into arch/arm64/kernel/time.c.
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/arch_timer.h | 133 +++++++++++++++++++ arch/arm64/include/asm/arm_generic.h | 100 --------------- arch/arm64/kernel/time.c | 29 ++++- drivers/clocksource/Kconfig | 5 - drivers/clocksource/Makefile | 1 - drivers/clocksource/arm_arch_timer.c | 1 + drivers/clocksource/arm_generic.c | 232 ---------------------------------- include/clocksource/arm_generic.h | 21 --- 9 files changed, 162 insertions(+), 361 deletions(-) create mode 100644 arch/arm64/include/asm/arch_timer.h delete mode 100644 arch/arm64/include/asm/arm_generic.h delete mode 100644 drivers/clocksource/arm_generic.c delete mode 100644 include/clocksource/arm_generic.h
arch/arm64/Kconfig +1 -0
@@ -2,6 +2,7 @@ config ARM64 def_bool y select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_WANT_COMPAT_IPC_PARSE_VERSION + select ARM_ARCH_TIMER select COMMON_CLK select GENERIC_CLOCKEVENTS select GENERIC_HARDIRQS_NO_DEPRECATED
arch/arm64/include/asm/arch_timer.h new file +133 -0
133 lines not on this page · raw message
arch/arm64/include/asm/arm_generic.h deleted +0 -100
100 lines not on this page · raw message
arch/arm64/kernel/time.c +27 -2
@@ -31,8 +31,9 @@#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h> +#include <linux/delay.h> -#include <clocksource/arm_generic.h> +#include <clocksource/arm_arch_timer.h> #include <asm/thread_info.h> #include <asm/stacktrace.h>
@@ -59,7 +60,31 @@ unsigned long profile_pc(struct pt_regs *regs)EXPORT_SYMBOL (profile_pc);#endif +static u64 sched_clock_mult__read_mostly ; + +unsigned long long notrace sched_clock (void ) +{ +return arch_timer_read_counter () * sched_clock_mult; +} + +int read_current_timer (unsigned long *timer_value) +{ + *timer_value =arch_timer_read_counter (); +return 0 ; +} +void __init time_init (void ) { -arm_generic_timer_init (); +u32 arch_timer_rate; + +if (arch_timer_init ()) +panic ("Unable to initialise architected timer.\n" ); + + arch_timer_rate =arch_timer_get_rate (); + +/* Cache the sched_clock multiplier to save a divide in the hot path. */ + sched_clock_mult =NSEC_PER_SEC / arch_timer_rate; + +/* Calibrate the delay loop directly */ + lpj_fine = arch_timer_rate /HZ ; }
drivers/clocksource/Kconfig +0 -5
@@ -54,10 +54,5 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK help Use the always on PRCMU Timer as sched_clock -config CLKSRC_ARM_GENERIC - def_bool y if ARM64 - help - This option enables support for the ARM generic timer. - config ARM_ARCH_TIMER bool
drivers/clocksource/Makefile +0 -1
@@ -17,5 +17,4 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o -obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
drivers/clocksource/arm_arch_timer.c +1 -0
@@ -332,6 +332,7 @@ out:static const struct of_device_id arch_timer_of_match[]__initconst = { { .compatible ="arm,armv7-timer" , }, + { .compatible ="arm,armv8-timer" , }, {}, };
drivers/clocksource/arm_generic.c deleted +0 -232
232 lines not on this page · raw message
include/clocksource/arm_generic.h deleted +0 -21
@@ -1,21 +0,0 @@ -/* -* Copyright (C) 2012 ARM Ltd. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#ifndef __CLKSOURCE_ARM_GENERIC_H -#define __CLKSOURCE_ARM_GENERIC_H - -extern int arm_generic_timer_init (void ); - -#endif
Signature · 1 line
1.7.0.4
PATCH v2 10/11 arm64: move from arm_generic to arm_arch_timer
Quoted 8 lines · Mark Rutland
The
arch_timerdriver supports a superset of the functionality of thearm_genericdriver, and is not tied to a particular arch.This patch moves arm64 to use the
arch_timerdriver, gaining additional functionality in doing so, and removes the (now unused)arm_genericdriver. Timer-related hooks specific to arm64 are moved intoarch/arm64/kernel/time.c.
Quoted 4 lines
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---
Nice.
Mark Rutland
maintainerPATCH v2 11/11 Documentation: Add ARMv8 to arch_timer devicetree
In reply to Mark Rutland--- .../devicetree/bindings/arm/arch_timer.txt | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
Documentation/devicetree/bindings/arm/arch_timer.txt +4 -3
@@ -1,13 +1,14 @@ * ARM architected timer -ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which -provides per-cpu timers. +ARM cores may have a per-core architected timer, which provides per-cpu timers. The timer is attached to a GIC to deliver its per-processor interrupts. ** Timer node properties: -- compatible : Should at least contain "arm,armv7-timer". +- compatible : Should at least contain one of + "arm,armv7-timer" + "arm,armv8-timer" - interrupts : Interrupt list for secure, non-secure, virtual and hypervisor timers, in that order.
Signature · 1 line
1.7.0.4
PATCH v2 11/11 Documentation: Add ARMv8 to arch_timer devicetree
On Wednesday 09 January 2013 09:37 PM, Mark Rutland wrote:
At least a line of change log will do :-)
Quoted 4 lines
Signed-off-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Acked-by Marc Zyngier <[email protected]>---