]> err.no Git - linux-2.6/commitdiff
[PATCH] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc
authorPaul Mackerras <paulus@samba.org>
Wed, 7 Jun 2006 06:15:39 +0000 (16:15 +1000)
committerPaul Mackerras <paulus@samba.org>
Fri, 9 Jun 2006 11:24:16 +0000 (21:24 +1000)
This gives the ability to control whether alignment exceptions get
fixed up or reported to the process as a SIGBUS, using the existing
PR_SET_UNALIGN and PR_GET_UNALIGN prctls.  We do not implement the
option of logging a message on alignment exceptions.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/process.c
arch/powerpc/kernel/traps.c
include/asm-powerpc/processor.h

index 2d35d83961b29d9ce4bc0496d14aa2b04249c935..e4732459c48571c6508631b81c6ed46917dae082 100644 (file)
@@ -752,6 +752,17 @@ int get_endian(struct task_struct *tsk, unsigned long adr)
        return put_user(val, (unsigned int __user *)adr);
 }
 
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+       tsk->thread.align_ctl = val;
+       return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+       return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
+}
+
 #define TRUNC_PTR(x)   ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
 
 int sys_clone(unsigned long clone_flags, unsigned long usp,
index 03def5715494222ec7c52289109a62236dd812b1..91a6e04d9741fb197f4fb91ec039a1a154b2eabd 100644 (file)
@@ -805,9 +805,11 @@ void __kprobes program_check_exception(struct pt_regs *regs)
 
 void alignment_exception(struct pt_regs *regs)
 {
-       int fixed;
+       int fixed = 0;
 
-       fixed = fix_alignment(regs);
+       /* we don't implement logging of alignment exceptions */
+       if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+               fixed = fix_alignment(regs);
 
        if (fixed == 1) {
                regs->nip += 4; /* skip over emulated instruction */
index fa6163268153be8ecbfbb96480e988a403ec9c85..d2c2c95f913b46af94874b9965841e8e7f3cb041 100644 (file)
@@ -149,6 +149,7 @@ struct thread_struct {
                unsigned int val;       /* Floating point status */
        } fpscr;
        int             fpexc_mode;     /* floating-point exception mode */
+       unsigned int    align_ctl;      /* alignment handling control */
 #ifdef CONFIG_PPC64
        unsigned long   start_tb;       /* Start purr when proc switched in */
        unsigned long   accum_tb;       /* Total accumilated purr for process */
@@ -217,6 +218,12 @@ extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
 extern int get_endian(struct task_struct *tsk, unsigned long adr);
 extern int set_endian(struct task_struct *tsk, unsigned int val);
 
+#define GET_UNALIGN_CTL(tsk, adr)      get_unalign_ctl((tsk), (adr))
+#define SET_UNALIGN_CTL(tsk, val)      set_unalign_ctl((tsk), (val))
+
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
 static inline unsigned int __unpack_fe01(unsigned long msr_bits)
 {
        return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);