On Thu, 2009-08-06 at 19:03 +0200, Philippe Gerum wrote:
> On Wed, 2009-08-05 at 17:51 -0400, Andreas Glatz wrote:
> > Hi,
> > 
> > I'm running xenomai-2.4.8, Linux-2.6.26 on a MPC8360 PowerPC.
> > 
> > I enabled nucleus debugging and found out that tasks sometimes
> > switch to secondary mode due to data alignment exceptions (#1536 ==
> > 0x600):
> > 
> > <snip>
> > Xenomai: Switching bgndT30_3 to secondary mode after exception #1536
> > from user-space at 0x101013f4 (pid 3191)
> > Xenomai: Switching bgndT30_3 to secondary mode after exception #1536
> > from user-space at 0x101013f4 (pid 3191)
> > ...
> > </snip>
> > 
> > I know that we get those exceptions because we pass the -fpack-struct
> > option to gcc and some data in structures are misaligned. It would
> > be quite a lot of work to go through the code to change it so that 
> > we don't have to pass the -fpack-struct option.
> > 
> > Is there a way to execute the exception handler from primary mode 
> > to prevent the tasks to switch to secondary mode?
> 
> I have absolutely no freaking idea whether the following patch will
> work, but you are welcome to feel lucky:
> 
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 701fe3b..3efe546 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -917,7 +917,8 @@ void alignment_exception(struct pt_regs *regs)
>  {
>       int sig, code, fixed = 0;
>  
> -     if (ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT,regs))
> +     if (test_bit(IPIPE_NOSTACK_FLAG, &ipipe_this_cpudom_var(status)) &&
> +         ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT, regs))
>               return;
>  
>       /* we don't implement logging of alignment exceptions */
> @@ -930,6 +931,10 @@ void alignment_exception(struct pt_regs *regs)
>               return;
>       }
>  
> +     if (!ipipe_root_domain_p &&
> +         ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT, regs))
> +             return;
> +
>       /* Operand address was bad */
>       if (fixed == -EFAULT) {
>               sig = SIGSEGV;
> 

This one should require a bit less luck to work in some cases:

diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index e06f75d..89f9521 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -788,10 +788,11 @@ int fix_alignment(struct pt_regs *regs)
                if (flags & S) {
                        /* Single-precision FP store requires conversion... */
 #ifdef CONFIG_PPC_FPU
-                       preempt_disable();
+                       unsigned long irqflags;
+                       ipipe_preempt_disable(irqflags);
                        enable_kernel_fp();
                        cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
-                       preempt_enable();
+                       ipipe_preempt_enable(irqflags);
 #else
                        return 0;
 #endif
@@ -832,10 +833,13 @@ int fix_alignment(struct pt_regs *regs)
        /* Single-precision FP load requires conversion... */
        case LD+F+S:
 #ifdef CONFIG_PPC_FPU
-               preempt_disable();
+       {
+               unsigned long irqflags;
+               ipipe_preempt_disable(irqflags);
                enable_kernel_fp();
                cvt_fd((float *)&data.v[4], &data.dd, &current->thread);
-               preempt_enable();
+               ipipe_preempt_enable(irqflags);
+       }
 #else
                return 0;
 #endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6979da6..46b0ca1 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -62,6 +62,8 @@ struct task_struct *last_task_used_spe = NULL;
  */
 void flush_fp_to_thread(struct task_struct *tsk)
 {
+       unsigned long flags;
+
        if (tsk->thread.regs) {
                /*
                 * We need to disable preemption here because if we didn't,
@@ -71,7 +73,7 @@ void flush_fp_to_thread(struct task_struct *tsk)
                 * FPU, and then when we get scheduled again we would store
                 * bogus values for the remaining FP registers.
                 */
-               preempt_disable();
+               ipipe_preempt_disable(flags);
                if (tsk->thread.regs->msr & MSR_FP) {
 #ifdef CONFIG_SMP
                        /*
@@ -85,13 +87,13 @@ void flush_fp_to_thread(struct task_struct *tsk)
 #endif
                        giveup_fpu(tsk);
                }
-               preempt_enable();
+               ipipe_preempt_enable(flags);
        }
 }
 
 void enable_kernel_fp(void)
 {
-       WARN_ON(preemptible());
+       WARN_ON(ipipe_root_domain_p && preemptible());
 
 #ifdef CONFIG_SMP
        if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
@@ -198,15 +200,17 @@ EXPORT_SYMBOL(enable_kernel_spe);
 
 void flush_spe_to_thread(struct task_struct *tsk)
 {
+       unsigned long flags;
+
        if (tsk->thread.regs) {
-               preempt_disable();
+               ipipe_preempt_disable(flags);
                if (tsk->thread.regs->msr & MSR_SPE) {
 #ifdef CONFIG_SMP
                        BUG_ON(tsk != current);
 #endif
                        giveup_spe(tsk);
                }
-               preempt_enable();
+               ipipe_preempt_enable(flags);
        }
 }
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 701fe3b..3efe546 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -917,7 +917,8 @@ void alignment_exception(struct pt_regs *regs)
 {
        int sig, code, fixed = 0;
 
-       if (ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT,regs))
+       if (test_bit(IPIPE_NOSTACK_FLAG, &ipipe_this_cpudom_var(status)) &&
+           ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT, regs))
                return;
 
        /* we don't implement logging of alignment exceptions */
@@ -930,6 +931,10 @@ void alignment_exception(struct pt_regs *regs)
                return;
        }
 
+       if (!ipipe_root_domain_p &&
+           ipipe_trap_notify(IPIPE_TRAP_ALIGNMENT, regs))
+               return;
+
        /* Operand address was bad */
        if (fixed == -EFAULT) {
                sig = SIGSEGV;

-- 
Philippe.



_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to