aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-06-07 02:15:39 -0400
committerPaul Mackerras <paulus@samba.org>2006-06-09 07:24:16 -0400
commite9370ae15dc2f8ba1e1889ce26f13cda565b6ecb (patch)
tree338ed732f7a6607bc168795008e244f180876cda
parentfab5db97e44f76461f76b24adfa8ccb14d4df498 (diff)
[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 <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/process.c11
-rw-r--r--arch/powerpc/kernel/traps.c6
-rw-r--r--include/asm-powerpc/processor.h7
3 files changed, 22 insertions, 2 deletions
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)
752 return put_user(val, (unsigned int __user *)adr); 752 return put_user(val, (unsigned int __user *)adr);
753} 753}
754 754
755int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
756{
757 tsk->thread.align_ctl = val;
758 return 0;
759}
760
761int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
762{
763 return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
764}
765
755#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) 766#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
756 767
757int sys_clone(unsigned long clone_flags, unsigned long usp, 768int 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)
805 805
806void alignment_exception(struct pt_regs *regs) 806void alignment_exception(struct pt_regs *regs)
807{ 807{
808 int fixed; 808 int fixed = 0;
809 809
810 fixed = fix_alignment(regs); 810 /* we don't implement logging of alignment exceptions */
811 if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
812 fixed = fix_alignment(regs);
811 813
812 if (fixed == 1) { 814 if (fixed == 1) {
813 regs->nip += 4; /* skip over emulated instruction */ 815 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 {
149 unsigned int val; /* Floating point status */ 149 unsigned int val; /* Floating point status */
150 } fpscr; 150 } fpscr;
151 int fpexc_mode; /* floating-point exception mode */ 151 int fpexc_mode; /* floating-point exception mode */
152 unsigned int align_ctl; /* alignment handling control */
152#ifdef CONFIG_PPC64 153#ifdef CONFIG_PPC64
153 unsigned long start_tb; /* Start purr when proc switched in */ 154 unsigned long start_tb; /* Start purr when proc switched in */
154 unsigned long accum_tb; /* Total accumilated purr for process */ 155 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);
217extern int get_endian(struct task_struct *tsk, unsigned long adr); 218extern int get_endian(struct task_struct *tsk, unsigned long adr);
218extern int set_endian(struct task_struct *tsk, unsigned int val); 219extern int set_endian(struct task_struct *tsk, unsigned int val);
219 220
221#define GET_UNALIGN_CTL(tsk, adr) get_unalign_ctl((tsk), (adr))
222#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
223
224extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
225extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
226
220static inline unsigned int __unpack_fe01(unsigned long msr_bits) 227static inline unsigned int __unpack_fe01(unsigned long msr_bits)
221{ 228{
222 return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); 229 return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);