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(&gt_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(&gt_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(&gt_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

Reply via email to