* Delays, clocks, timers, hrtimers, etc
@ 2015-01-28 13:16 Mason
2015-01-29 13:57 ` Mason
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Mason @ 2015-01-28 13:16 UTC (permalink / raw)
To: Linux ARM, cpufreq, Linux PM, DT
Hello,
I am swimming in a sea of confusion, and am hoping someone would toss
me a life-jacket (of enlightenment). Please forgive me if some of my
questions are poorly asked or appear in seemingly random order.
Working on a Cortex A9 based SoC, I set out to "clean up" the platform
specific timer code, by using as much generic framework as possible.
(Right now, there's a lot of "redundant" code in the mach dir.)
Q1. the {n,u,m}delay function family
arch/arm/include/asm/delay.h mentions
"Delay routines, using a pre-computed "loops_per_second" value."
*BUT* if the frequency changes dynamically (thanks to cpufreq)
the "loops_per_second" value cannot be pre-computed, as it would
change dynamically too, right?
Looking at arch/arm/lib/delay.c it seems the default implementation
is a busy loop (in delay-loop.S) which looks up "loops_per_jiffy"
in the prolog to determine the number of times to loop, right?
http://lxr.free-electrons.com/source/arch/arm/lib/delay-loop.S
(Side issue, why is the loop unrolled in __loop_delay? What is the
point of unrolling a busy loop? This is commented code however.)
What happens if loops_per_jiffy changes while one core is in the
busy loop? It seems we might exit the loop too early, which could
break some drivers with some weird heisenbug, no?
Also, is the update of loops_per_jiffy atomic? Is it possible that
if one core reads it while another updates it, we get garbage?
I suppose this is one reason why the default functions are overridden
by register_current_timer_delay(&arch_delay_timer) right? I think the
property of a timer is that its frequency doesn't change, even if the
CPU's frequency changes? So we are still busy looping, but we are
checking the actual time spent in the loop, whatever the cpufreq?
Reference
https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
Q2. Cortex A9 global and private timers
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/CIHGECHJ.html
(What are private timers used for?)
In my platform-specific code, there is a config option to choose between
1) the ARM global timer
2) a platform-specific timer (timer0)
I noticed that there is generic code to support the global timer in
drivers/clocksource/arm_global_timer.c
config ARM_GLOBAL_TIMER
bool
select CLKSRC_OF if OF
help
This options enables support for the ARM global timer unit
config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
bool
depends on ARM_GLOBAL_TIMER
default y
help
Use ARM global timer clock source as sched_clock
I was thinking it would be better to use the "standard" option (ARM global timer)
as it is "officially" supported in the vanilla kernel. So less code to write and
to debug, and it has likely received more testing. Why would one rely on
platform-specific timers then?
Are high-resolution timers supported with the global timer?
Q3. Using the generic global timer implementation
So, how do I use that implementation?
(Is someone other than STMicro using it?)
I see:
static void __init global_timer_of_register(struct device_node *np)
CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer", global_timer_of_register);
OF stands for open firmware, yes?
So is this related to device tree?
http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/arm/global_timer.txt
This file makes no sense to me.
- interrupts : One interrupt to each core
interrupts = <1 13 0xf01>;
what are 1 13 0xf01 ??
- clocks : Should be phandle to a clock.
clocks = <&arm_periph_clk>;
For my (old) 3.14 kernel, I found this:
/*
* ARM Peripheral clock for timers
*/
arm_periph_clk: arm_periph_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <600000000>;
};
But it looks like the definitions have moved around since then?
This device tree concept is too much to swallow in a single serving.
Please tell me if I'm going down the correct rabbit hole, and I'll
do some LWN readings to try to wrap my mind around the concept.
Anyway, if anyone can help me out on some of these topics, I'd be
eternally grateful.
Regards.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Delays, clocks, timers, hrtimers, etc
2015-01-28 13:16 Delays, clocks, timers, hrtimers, etc Mason
@ 2015-01-29 13:57 ` Mason
2015-02-03 12:09 ` Russell King - ARM Linux
2015-02-06 20:25 ` Stefan Agner
2 siblings, 0 replies; 6+ messages in thread
From: Mason @ 2015-01-29 13:57 UTC (permalink / raw)
To: Linux ARM, cpufreq, Linux PM, DT
[ I am aware that my message is way too long, and that few people would have
the time to answer all these questions. So maybe, if someone feels inclined
to answer just one or two, that might kickstart some discussion, and I might
learn something along the way. Regards. ]
FTR, I've been reading about DeviceTree:
http://lwn.net/Articles/573409/
http://www.carbondesignsystems.com/virtual-prototype-blog/bid/195122/Running-the-Latest-Linux-Kernel-on-a-Minimal-ARM-Cortex-A15-System
http://devicetree.org/Device_Tree_Usage
And I am resisting the urge to pile on a few more questions ;-/
Regards.
On 28/01/2015 14:16, Mason wrote:
> Hello,
>
> I am swimming in a sea of confusion, and am hoping someone would toss
> me a life-jacket (of enlightenment). Please forgive me if some of my
> questions are poorly asked or appear in seemingly random order.
>
> Working on a Cortex A9 based SoC, I set out to "clean up" the platform
> specific timer code, by using as much generic framework as possible.
> (Right now, there's a lot of "redundant" code in the mach dir.)
>
>
> Q1. the {n,u,m}delay function family
>
> arch/arm/include/asm/delay.h mentions
> "Delay routines, using a pre-computed "loops_per_second" value."
> *BUT* if the frequency changes dynamically (thanks to cpufreq)
> the "loops_per_second" value cannot be pre-computed, as it would
> change dynamically too, right?
>
> Looking at arch/arm/lib/delay.c it seems the default implementation
> is a busy loop (in delay-loop.S) which looks up "loops_per_jiffy"
> in the prolog to determine the number of times to loop, right?
>
> http://lxr.free-electrons.com/source/arch/arm/lib/delay-loop.S
>
> (Side issue, why is the loop unrolled in __loop_delay? What is the
> point of unrolling a busy loop? This is commented code however.)
>
> What happens if loops_per_jiffy changes while one core is in the
> busy loop? It seems we might exit the loop too early, which could
> break some drivers with some weird heisenbug, no?
>
> Also, is the update of loops_per_jiffy atomic? Is it possible that
> if one core reads it while another updates it, we get garbage?
>
> I suppose this is one reason why the default functions are overridden
> by register_current_timer_delay(&arch_delay_timer) right? I think the
> property of a timer is that its frequency doesn't change, even if the
> CPU's frequency changes? So we are still busy looping, but we are
> checking the actual time spent in the loop, whatever the cpufreq?
>
> Reference
> https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
>
>
> Q2. Cortex A9 global and private timers
>
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/CIHGECHJ.html
>
> (What are private timers used for?)
>
> In my platform-specific code, there is a config option to choose between
>
> 1) the ARM global timer
> 2) a platform-specific timer (timer0)
>
> I noticed that there is generic code to support the global timer in
> drivers/clocksource/arm_global_timer.c
>
> config ARM_GLOBAL_TIMER
> bool
> select CLKSRC_OF if OF
> help
> This options enables support for the ARM global timer unit
>
> config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
> bool
> depends on ARM_GLOBAL_TIMER
> default y
> help
> Use ARM global timer clock source as sched_clock
>
> I was thinking it would be better to use the "standard" option (ARM global timer)
> as it is "officially" supported in the vanilla kernel. So less code to write and
> to debug, and it has likely received more testing. Why would one rely on
> platform-specific timers then?
>
> Are high-resolution timers supported with the global timer?
>
>
> Q3. Using the generic global timer implementation
>
> So, how do I use that implementation?
> (Is someone other than STMicro using it?)
>
> I see:
>
> static void __init global_timer_of_register(struct device_node *np)
> CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer", global_timer_of_register);
>
> OF stands for open firmware, yes?
> So is this related to device tree?
>
> http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/arm/global_timer.txt
>
> This file makes no sense to me.
>
> - interrupts : One interrupt to each core
> interrupts = <1 13 0xf01>;
> what are 1 13 0xf01 ??
>
> - clocks : Should be phandle to a clock.
> clocks = <&arm_periph_clk>;
>
> For my (old) 3.14 kernel, I found this:
>
> /*
> * ARM Peripheral clock for timers
> */
> arm_periph_clk: arm_periph_clk {
> #clock-cells = <0>;
> compatible = "fixed-clock";
> clock-frequency = <600000000>;
> };
>
> But it looks like the definitions have moved around since then?
>
> This device tree concept is too much to swallow in a single serving.
> Please tell me if I'm going down the correct rabbit hole, and I'll
> do some LWN readings to try to wrap my mind around the concept.
>
>
> Anyway, if anyone can help me out on some of these topics, I'd be
> eternally grateful.
>
> Regards.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Delays, clocks, timers, hrtimers, etc
2015-01-28 13:16 Delays, clocks, timers, hrtimers, etc Mason
2015-01-29 13:57 ` Mason
@ 2015-02-03 12:09 ` Russell King - ARM Linux
2015-02-06 20:25 ` Stefan Agner
2 siblings, 0 replies; 6+ messages in thread
From: Russell King - ARM Linux @ 2015-02-03 12:09 UTC (permalink / raw)
To: Mason; +Cc: Linux ARM, cpufreq, Linux PM, DT
On Wed, Jan 28, 2015 at 02:16:21PM +0100, Mason wrote:
> Q1. the {n,u,m}delay function family
>
> arch/arm/include/asm/delay.h mentions
> "Delay routines, using a pre-computed "loops_per_second" value."
> *BUT* if the frequency changes dynamically (thanks to cpufreq)
> the "loops_per_second" value cannot be pre-computed, as it would
> change dynamically too, right?
cpufreq changes the loops_per_second value, but an already in-progress
delay doesn't see that (new delays will see the update though.)
> Also, is the update of loops_per_jiffy atomic? Is it possible that
> if one core reads it while another updates it, we get garbage?
32-bit reads and writes are atomic. You read either the old value or
the new value. There's no inbetween.
> I suppose this is one reason why the default functions are overridden
> by register_current_timer_delay(&arch_delay_timer) right? I think the
> property of a timer is that its frequency doesn't change, even if the
> CPU's frequency changes? So we are still busy looping, but we are
> checking the actual time spent in the loop, whatever the cpufreq?
Timers are preferred because of the problems with the software delay loop.
Note that it has always been the case that the software delay loop is
"approximate" - even without cpufreq etc, the loops_per_jiffy is slightly
on the small side because of the way the calibration works. It's about
98% of the actual value, and depends on the workload of the timer
interrupt. It's obvious when you think about it - it's counting the
number of cycles between two timer interrupts, and the timer interrupt
consumes some of the cycles.
This means that even if you ask for a 10us delay, you'll probably get a
delay of 9.8us instead.
> Q2. Cortex A9 global and private timers
>
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/CIHGECHJ.html
>
> (What are private timers used for?)
The per-cpu private timers are mostly scheduling of threads.
> In my platform-specific code, there is a config option to choose between
>
> 1) the ARM global timer
> 2) a platform-specific timer (timer0)
Most platforms implement their own timer, because its really sexy for
hardware engineers to create yet another different timer implementation
which is soo much better than every other timer implementation that has
already been created. You wouldn't believe how many different ways that
there are to create a timer - and we still have people coming up with
new novel implementations!
> Q3. Using the generic global timer implementation
>
> So, how do I use that implementation?
> (Is someone other than STMicro using it?)
>
> I see:
>
> static void __init global_timer_of_register(struct device_node *np)
> CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer", global_timer_of_register);
>
> OF stands for open firmware, yes?
> So is this related to device tree?
Yes.
> http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/arm/global_timer.txt
>
> This file makes no sense to me.
>
> - interrupts : One interrupt to each core
> interrupts = <1 13 0xf01>;
> what are 1 13 0xf01 ??
For this see Documentation/devicetree/bindings/arm/gic.txt, the
#interrupt-cells property defines the number of values between the <>,
and it goes on to define what each means.
The interrupts= property depends on your interrupt controller.
> - clocks : Should be phandle to a clock.
> clocks = <&arm_periph_clk>;
>
> For my (old) 3.14 kernel, I found this:
>
> /*
> * ARM Peripheral clock for timers
> */
> arm_periph_clk: arm_periph_clk {
> #clock-cells = <0>;
> compatible = "fixed-clock";
> clock-frequency = <600000000>;
> };
>
> But it looks like the definitions have moved around since then?
No idea. You do need to tell it where the global timer gets its clock
from so that it knows how fast it ticks, and whether there's anything
that needs to be enabled for that clock to be supplied.
> This device tree concept is too much to swallow in a single serving.
> Please tell me if I'm going down the correct rabbit hole, and I'll
> do some LWN readings to try to wrap my mind around the concept.
Yes, DT has made stuff more complicated; unfortunately, that's life now.
--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Delays, clocks, timers, hrtimers, etc
2015-01-28 13:16 Delays, clocks, timers, hrtimers, etc Mason
2015-01-29 13:57 ` Mason
2015-02-03 12:09 ` Russell King - ARM Linux
@ 2015-02-06 20:25 ` Stefan Agner
2015-02-06 21:17 ` Mason
2 siblings, 1 reply; 6+ messages in thread
From: Stefan Agner @ 2015-02-06 20:25 UTC (permalink / raw)
To: Mason; +Cc: Linux ARM, cpufreq, Linux PM, DT
On 2015-01-28 14:16, Mason wrote:
> Hello,
>
> I am swimming in a sea of confusion, and am hoping someone would toss
> me a life-jacket (of enlightenment). Please forgive me if some of my
> questions are poorly asked or appear in seemingly random order.
>
> Working on a Cortex A9 based SoC, I set out to "clean up" the platform
> specific timer code, by using as much generic framework as possible.
> (Right now, there's a lot of "redundant" code in the mach dir.)
>
>
> Q1. the {n,u,m}delay function family
>
> arch/arm/include/asm/delay.h mentions
> "Delay routines, using a pre-computed "loops_per_second" value."
> *BUT* if the frequency changes dynamically (thanks to cpufreq)
> the "loops_per_second" value cannot be pre-computed, as it would
> change dynamically too, right?
>
> Looking at arch/arm/lib/delay.c it seems the default implementation
> is a busy loop (in delay-loop.S) which looks up "loops_per_jiffy"
> in the prolog to determine the number of times to loop, right?
>
> http://lxr.free-electrons.com/source/arch/arm/lib/delay-loop.S
>
> (Side issue, why is the loop unrolled in __loop_delay? What is the
> point of unrolling a busy loop? This is commented code however.)
>
> What happens if loops_per_jiffy changes while one core is in the
> busy loop? It seems we might exit the loop too early, which could
> break some drivers with some weird heisenbug, no?
>
> Also, is the update of loops_per_jiffy atomic? Is it possible that
> if one core reads it while another updates it, we get garbage?
>
> I suppose this is one reason why the default functions are overridden
> by register_current_timer_delay(&arch_delay_timer) right? I think the
> property of a timer is that its frequency doesn't change, even if the
> CPU's frequency changes? So we are still busy looping, but we are
> checking the actual time spent in the loop, whatever the cpufreq?
>
> Reference
> https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
>
>
> Q2. Cortex A9 global and private timers
>
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407f/CIHGECHJ.html
>
> (What are private timers used for?)
>
> In my platform-specific code, there is a config option to choose between
>
> 1) the ARM global timer
> 2) a platform-specific timer (timer0)
>
> I noticed that there is generic code to support the global timer in
> drivers/clocksource/arm_global_timer.c
>
> config ARM_GLOBAL_TIMER
> bool
> select CLKSRC_OF if OF
> help
> This options enables support for the ARM global timer unit
>
> config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
> bool
> depends on ARM_GLOBAL_TIMER
> default y
> help
> Use ARM global timer clock source as sched_clock
>
> I was thinking it would be better to use the "standard" option (ARM
> global timer)
> as it is "officially" supported in the vanilla kernel. So less code to write and
> to debug, and it has likely received more testing. Why would one rely on
> platform-specific timers then?
>
> Are high-resolution timers supported with the global timer?
>
>
> Q3. Using the generic global timer implementation
>
> So, how do I use that implementation?
> (Is someone other than STMicro using it?)
>
> I see:
>
> static void __init global_timer_of_register(struct device_node *np)
> CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
> global_timer_of_register);
>
> OF stands for open firmware, yes?
> So is this related to device tree?
>
> http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/arm/global_timer.txt
>
> This file makes no sense to me.
>
> - interrupts : One interrupt to each core
> interrupts = <1 13 0xf01>;
> what are 1 13 0xf01 ??
>
> - clocks : Should be phandle to a clock.
> clocks = <&arm_periph_clk>;
>
> For my (old) 3.14 kernel, I found this:
>
> /*
> * ARM Peripheral clock for timers
> */
> arm_periph_clk: arm_periph_clk {
> #clock-cells = <0>;
> compatible = "fixed-clock";
> clock-frequency = <600000000>;
> };
>
> But it looks like the definitions have moved around since then?
Hi Mason,
Just recently I added support of ARM global timer as clocksource for
Vybrid SoC. This SoC doesn't use cpufreq, hence it is safe to use the
ARM global timer. The nice thing of device tree is, the patch to add
support for that did not change a single line of code:
http://thread.gmane.org/gmane.linux.kernel/1794460
--
Stefan
>
> This device tree concept is too much to swallow in a single serving.
> Please tell me if I'm going down the correct rabbit hole, and I'll
> do some LWN readings to try to wrap my mind around the concept.
>
>
> Anyway, if anyone can help me out on some of these topics, I'd be
> eternally grateful.
>
> Regards.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Delays, clocks, timers, hrtimers, etc
2015-02-06 20:25 ` Stefan Agner
@ 2015-02-06 21:17 ` Mason
2015-02-06 21:31 ` Stefan Agner
0 siblings, 1 reply; 6+ messages in thread
From: Mason @ 2015-02-06 21:17 UTC (permalink / raw)
To: Stefan Agner; +Cc: Linux ARM, cpufreq, Linux PM, DT
Stefan Agner wrote:
> Just recently I added support of ARM global timer as clocksource for
> Vybrid SoC. This SoC doesn't use cpufreq, hence it is safe to use the
> ARM global timer. The nice thing of device tree is, the patch to add
> support for that did not change a single line of code:
>
> http://thread.gmane.org/gmane.linux.kernel/1794460
Hello Stefan,
Your changes are not yet accepted in mainline, are they?
(I don't see them in 3.18.5)
Do you also use the ARM local timers in your port?
Is there generic code to handle them?
Regards.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Delays, clocks, timers, hrtimers, etc
2015-02-06 21:17 ` Mason
@ 2015-02-06 21:31 ` Stefan Agner
0 siblings, 0 replies; 6+ messages in thread
From: Stefan Agner @ 2015-02-06 21:31 UTC (permalink / raw)
To: Mason; +Cc: Linux ARM, cpufreq, Linux PM, DT
On 2015-02-06 22:17, Mason wrote:
> Stefan Agner wrote:
>
>> Just recently I added support of ARM global timer as clocksource for
>> Vybrid SoC. This SoC doesn't use cpufreq, hence it is safe to use the
>> ARM global timer. The nice thing of device tree is, the patch to add
>> support for that did not change a single line of code:
>>
>> http://thread.gmane.org/gmane.linux.kernel/1794460
>
> Hello Stefan,
>
> Your changes are not yet accepted in mainline, are they?
> (I don't see them in 3.18.5)
The changes have been accepted and went upstream in the 3.19 merge
window, see
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=81c4831907fb00efdc97093b09e333009a57d005
> Do you also use the ARM local timers in your port?
> Is there generic code to handle them?
It seems that there has been support for local timers once, but has been
removed. But I'm not aware of the details:
https://lkml.org/lkml/2013/2/22/49
--
Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-02-06 21:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-28 13:16 Delays, clocks, timers, hrtimers, etc Mason
2015-01-29 13:57 ` Mason
2015-02-03 12:09 ` Russell King - ARM Linux
2015-02-06 20:25 ` Stefan Agner
2015-02-06 21:17 ` Mason
2015-02-06 21:31 ` Stefan Agner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).