On Wed, Oct 22, 2014 at 2:28 PM, Gilles Chanteperdrix <[email protected]> wrote: > On Mon, Oct 20, 2014 at 03:29:26PM +0800, GP Orcullo wrote: >> On Oct 9, 2014 11:14 PM, "Gilles Chanteperdrix" < >> [email protected]> wrote: >> > >> > On 10/09/2014 01:06 PM, GP Orcullo wrote: >> > > On Oct 9, 2014 6:16 PM, "Gilles Chanteperdrix" < >> > > [email protected]> wrote: >> > >> >> > >> On 10/09/2014 12:12 PM, GP Orcullo wrote: >> > >>> On Thu, Oct 9, 2014 at 6:06 PM, Gilles Chanteperdrix >> > >>> <[email protected]> wrote: >> > >>>> On 10/09/2014 12:02 PM, GP Orcullo wrote: >> > >>>>> On Mon, Oct 6, 2014 at 6:30 AM, Gilles Chanteperdrix >> > >>>>> <[email protected]> wrote: >> > >>>>>> >> > >>>>>> It means that Linux was interrupted by Xenomai during its timer >> > >>>>>> interrupt, and that Xenomai interrupted it for 280us. This may >> > >>>>>> happens with switchtest if it has a really long chain of context >> > >>>>>> switches. If you want to check what happened, enable the I-pipe >> > >>>>>> tracer, and trigger a trace freeze right before this message. >> > >>>>>> >> > >>>>> >> > >>>>> One more piece to the puzzle: disabling CONFIG_IPIPE_DEBUG_INTERNAL >> > >>>>> causes the system to lockup. >> > >>>>> >> > >>>> How do you know this is related? >> > >>>> >> > >>>> >> Gilles. >> > >>> >> > >>> Sorry, I quoted the wrong message. >> > >>> >> > >>> If CONFIG_PREEMPT is disabled and CONFIG_IPIPE_DEBUG_INTERNAL is not >> > >>> disabled, the system works fine. >> > >>> >> > >> So, there is a problem, likely in your port with CONFIG_PREEMPT, but >> > >> maybe in Xenomai (I need to check, because I am not so sure I tested >> > >> xeno-regression-test without CONFIG_PREEMPT). >> > >> >> > >> And there is a problem in your port without >> CONFIG_IPIPE_DEBUG_INTERNAL. >> > >> This I do not need to check, I have tested Xenomai wihout this option >> > >> enabled. >> > >> >> > >> So, my question is: how do you know the two issues are related? >> > >> >> > > >> > > I don't know the answer. >> > > >> > > I'm only looking at the effects and not the cause of the issue. >> > > >> > > So, where shall I start digging? What's in >> CONFIG_IPIPE_DEBUG_INTERNAL >> > > that would somehow suppress the problem? >> > > >> > >> > Quite frankly, I would go the other way: check that every piece of code >> > which may be executed over real-time context does not use any Linux >> > code. That does not include a lot of code, actually all that is covered >> > by the porting guide: >> > - the interrupt controller callbacks (note that the GIC handles some SOC >> > specific callabcks, so if you have some, you need to check them) >> > - the chained interrupt demux handlers >> > - the timer and tsc management functions. >> > - some workaround specific code that hooks in the iowrite/writel >> > functions, such as the L2 cache synchronization on omap4. >> > >> > And it seems that is all, so, there should not be a lot of code to check. >> > >> > >> >> Hello Gilles, >> >> Thanks for all the help. >> >> The problem was traced to the tsc emulation, the counter somehow gets >> messed up when the global timer is shared with Linux. > > Hi, > > could you try the following patch and tell me if it avoids the > issue? > > Thanks. > Regards. > > diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi > index fb28b2e..150beb5 100644 > --- a/arch/arm/boot/dts/imx6qdl.dtsi > +++ b/arch/arm/boot/dts/imx6qdl.dtsi > @@ -106,6 +106,12 @@ > clocks = <&clks 15>; > }; > > + timer@00a00200 { > + compatible = "arm,cortex-a9-global-timer"; > + reg = <0x00a00200 0x20>; > + clocks = <&clks 15>; > + }; > + > L2: l2-cache@00a02000 { > compatible = "arm,pl310-cache"; > reg = <0x00a02000 0x1000>; > diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi > index a914496..2cb8144 100644 > --- a/arch/arm/boot/dts/omap4.dtsi > +++ b/arch/arm/boot/dts/omap4.dtsi > @@ -67,6 +67,12 @@ > interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | > IRQ_TYPE_LEVEL_HIGH)>; > }; > > + global_timer: timer@48240200 { > + compatible = "arm,cortex-a9-global-timer"; > + reg = <0x48240200 0x20>; > + clocks = <&mpu_periphclk>; > + }; > + > /* > * The soc node represents the soc top level view. It is uses for IPs > * that are not memory mapped in the MPU view or for the MPU itself. > diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c > index f0b7c52..864651c 100644 > --- a/arch/arm/kernel/smp_twd.c > +++ b/arch/arm/kernel/smp_twd.c > @@ -28,7 +28,6 @@ > #include <asm/smp_plat.h> > #include <asm/smp_twd.h> > #include <asm/cputype.h> > -#include <asm/ipipe.h> > > /* set up by the platform code */ > static void __iomem *twd_base; > @@ -51,42 +50,9 @@ static void twd_ack(void) > writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT); > } > > -static struct __ipipe_tscinfo tsc_info; > - > static void twd_get_clock(struct device_node *np); > static void __cpuinit twd_calibrate_rate(void); > > -static void __init gt_setup(unsigned long base_paddr, unsigned bits) > -{ > - if ((read_cpuid_id() & 0xf00000) == 0) > - return; > - > - gt_base = ioremap(base_paddr, SZ_256); > - BUG_ON(!gt_base); > - > - /* Start global timer */ > - __raw_writel(1, gt_base + 0x8); > - > - tsc_info.type = IPIPE_TSC_TYPE_FREERUNNING; > - tsc_info.freq = twd_timer_rate; > - tsc_info.counter_vaddr = (unsigned long)gt_base; > - tsc_info.u.counter_paddr = base_paddr; > - > - switch(bits) { > - case 64: > - tsc_info.u.mask = 0xffffffffffffffffULL; > - break; > - case 32: > - tsc_info.u.mask = 0xffffffff; > - break; > - default: > - /* Only supported as a 32 bits or 64 bits */ > - BUG(); > - } > - > - __ipipe_tsc_register(&tsc_info); > -} > - > #ifdef CONFIG_IPIPE_DEBUG_INTERNAL > > static DEFINE_PER_CPU(int, irqs); > @@ -460,8 +426,6 @@ out_free: > > int __init twd_local_timer_register(struct twd_local_timer *tlt) > { > - int rc; > - > if (twd_base || twd_evt) > return -EBUSY; > > @@ -472,13 +436,7 @@ int __init twd_local_timer_register(struct > twd_local_timer *tlt) > return -ENOMEM; > > > - rc = twd_local_timer_common_register(NULL); > - if (rc == 0) > -#ifdef CONFIG_IPIPE > - gt_setup(tlt->res[0].start - 0x400, 32); > -#endif > - > - return rc; > + return twd_local_timer_common_register(NULL); > } > > #ifdef CONFIG_OF > @@ -503,16 +461,6 @@ static void __init twd_local_timer_of_register(struct > device_node *np) > > > err = twd_local_timer_common_register(np); > -#ifdef CONFIG_IPIPE > - if (err == 0) { > - struct resource res; > - > - if (of_address_to_resource(np, 0, &res)) > - res.start = 0; > - > - gt_setup(res.start - 0x400, 32); > - } > -#endif /* CONFIG_IPIPE */ > > out: > WARN(err, "twd_local_timer_of_register failed (%d)\n", err); > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig > index 33567aa..b825a09 100644 > --- a/arch/arm/mach-imx/Kconfig > +++ b/arch/arm/mach-imx/Kconfig > @@ -808,6 +808,7 @@ config SOC_IMX6Q > select PL310_ERRATA_727915 if CACHE_PL310 > select PL310_ERRATA_769419 if CACHE_PL310 > select PM_OPP if PM > + select ARM_GLOBAL_TIMER if SMP && IPIPE > > help > This enables support for Freescale i.MX6 Quad processor. > diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig > index 0af7ca0..63a5b42 100644 > --- a/arch/arm/mach-omap2/Kconfig > +++ b/arch/arm/mach-omap2/Kconfig > @@ -45,6 +45,7 @@ config ARCH_OMAP4 > select USB_ARCH_HAS_EHCI if USB_SUPPORT > select ARM_ERRATA_754322 > select ARM_ERRATA_775420 > + select ARM_GLOBAL_TIMER if IPIPE && SMP > > config SOC_OMAP5 > bool "TI OMAP5" > diff --git a/drivers/clocksource/arm_global_timer.c > b/drivers/clocksource/arm_global_timer.c > index 0fc31d0..62e208b 100644 > --- a/drivers/clocksource/arm_global_timer.c > +++ b/drivers/clocksource/arm_global_timer.c > @@ -24,6 +24,7 @@ > #include <linux/sched_clock.h> > > #include <asm/cputype.h> > +#include <asm/ipipe.h> > > #define GT_COUNTER0 0x00 > #define GT_COUNTER1 0x04 > @@ -48,6 +49,7 @@ > * the units for all operations. > */ > static void __iomem *gt_base; > +static unsigned long gt_pbase; > static unsigned long gt_clk_rate; > static int gt_ppi; > static struct clock_event_device __percpu *gt_evt; > @@ -210,6 +212,16 @@ static u64 notrace gt_sched_clock_read(void) > > static void __init gt_clocksource_init(void) > { > +#ifdef CONFIG_IPIPE > + struct __ipipe_tscinfo tsc_info = { > + .type = IPIPE_TSC_TYPE_FREERUNNING, > + .freq = gt_clk_rate, > + .counter_vaddr = (unsigned long)gt_base, > + .u.counter_paddr = gt_pbase, > + .u.mask = 0xffffffff, > + }; > +#endif > + > writel(0, gt_base + GT_CONTROL); > writel(0, gt_base + GT_COUNTER0); > writel(0, gt_base + GT_COUNTER1); > @@ -219,6 +231,9 @@ static void __init gt_clocksource_init(void) > #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK > sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); > #endif > +#ifdef CONFIG_IPIPE > + __ipipe_tsc_register(&tsc_info); > +#endif > clocksource_register_hz(>_clocksource, gt_clk_rate); > } > > @@ -242,8 +257,9 @@ static struct notifier_block gt_cpu_nb = { > > static void __init global_timer_of_register(struct device_node *np) > { > + int err = 0, install_clockevent = 1; > + struct resource res; > struct clk *gt_clk; > - int err = 0; > > /* > * In r2p0 the comparators for each processor with the global timer > @@ -252,13 +268,15 @@ static void __init global_timer_of_register(struct > device_node *np) > */ > if ((read_cpuid_id() & 0xf0000f) < 0x200000) { > pr_warn("global-timer: non support for this cpu version.\n"); > - return; > + install_clockevent = 0; > } > > - gt_ppi = irq_of_parse_and_map(np, 0); > - if (!gt_ppi) { > - pr_warn("global-timer: unable to parse irq\n"); > - return; > + if (install_clockevent) { > + gt_ppi = irq_of_parse_and_map(np, 0); > + if (!gt_ppi) { > + pr_warn("global-timer: unable to parse irq\n"); > + install_clockevent = 0; > + } > } > > gt_base = of_iomap(np, 0); > @@ -267,6 +285,11 @@ static void __init global_timer_of_register(struct > device_node *np) > return; > } > > + if (of_address_to_resource(np, 0, &res)) > + res.start = 0; > + > + gt_pbase = res.start; > + > gt_clk = of_clk_get(np, 0); > if (!IS_ERR(gt_clk)) { > err = clk_prepare_enable(gt_clk); > @@ -279,37 +302,39 @@ static void __init global_timer_of_register(struct > device_node *np) > } > > gt_clk_rate = clk_get_rate(gt_clk); > - gt_evt = alloc_percpu(struct clock_event_device); > - if (!gt_evt) { > - pr_warn("global-timer: can't allocate memory\n"); > - err = -ENOMEM; > - goto out_clk; > - } > - > - err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt, > + if (install_clockevent) { > + gt_evt = alloc_percpu(struct clock_event_device); > + if (!gt_evt) { > + pr_warn("global-timer: can't allocate memory\n"); > + err = -ENOMEM; > + goto out_clk; > + } > + > + err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt, > "gt", gt_evt); > - if (err) { > - pr_warn("global-timer: can't register interrupt %d (%d)\n", > - gt_ppi, err); > - goto out_free; > - } > - > - err = register_cpu_notifier(>_cpu_nb); > - if (err) { > - pr_warn("global-timer: unable to register cpu notifier.\n"); > - goto out_irq; > + if (err) { > + pr_warn("global-timer: can't register interrupt %d > (%d)\n", > + gt_ppi, err); > + goto out_free; > + } > + > + err = register_cpu_notifier(>_cpu_nb); > + if (err) { > + pr_warn("global-timer: unable to register cpu > notifier.\n"); > + free_percpu_irq(gt_ppi, gt_evt); > + out_free: > + free_percpu(gt_evt); > + install_clockevent = 0; > + } > } > > /* Immediately configure the timer on the boot CPU */ > gt_clocksource_init(); > - gt_clockevents_init(this_cpu_ptr(gt_evt)); > + if (install_clockevent) > + gt_clockevents_init(this_cpu_ptr(gt_evt)); > > return; > > -out_irq: > - free_percpu_irq(gt_ppi, gt_evt); > -out_free: > - free_percpu(gt_evt); > out_clk: > clk_disable_unprepare(gt_clk); > out_unmap: > > -- > Gilles.
Exynos is not using the arm global timers. I'm still experiencing some intermittent "rcu_preempt detected stalls". Maybe I'm dealing with more than one issue here. -- GP Orcullo _______________________________________________ Xenomai mailing list [email protected] http://www.xenomai.org/mailman/listinfo/xenomai
