From: Paul Mackerras Date: Wed, 7 Jun 2006 06:15:39 +0000 (+1000) Subject: [PATCH] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=e9370ae15dc2f8ba1e1889ce26f13cda565b6ecb;p=linux-beck.git [PATCH] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc 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 --- diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2d35d83961b2..e4732459c485 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -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, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 03def5715494..91a6e04d9741 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -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 */ diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index fa6163268153..d2c2c95f913b 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -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);