[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>
This commit is contained in:
Родитель
fab5db97e4
Коммит
e9370ae15d
|
@ -752,6 +752,17 @@ int get_endian(struct task_struct *tsk, unsigned long adr)
|
||||||
return put_user(val, (unsigned int __user *)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))
|
#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
|
||||||
|
|
||||||
int sys_clone(unsigned long clone_flags, unsigned long usp,
|
int sys_clone(unsigned long clone_flags, unsigned long usp,
|
||||||
|
|
|
@ -805,9 +805,11 @@ void __kprobes program_check_exception(struct pt_regs *regs)
|
||||||
|
|
||||||
void alignment_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) {
|
if (fixed == 1) {
|
||||||
regs->nip += 4; /* skip over emulated instruction */
|
regs->nip += 4; /* skip over emulated instruction */
|
||||||
|
|
|
@ -149,6 +149,7 @@ struct thread_struct {
|
||||||
unsigned int val; /* Floating point status */
|
unsigned int val; /* Floating point status */
|
||||||
} fpscr;
|
} fpscr;
|
||||||
int fpexc_mode; /* floating-point exception mode */
|
int fpexc_mode; /* floating-point exception mode */
|
||||||
|
unsigned int align_ctl; /* alignment handling control */
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
unsigned long start_tb; /* Start purr when proc switched in */
|
unsigned long start_tb; /* Start purr when proc switched in */
|
||||||
unsigned long accum_tb; /* Total accumilated purr for process */
|
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 get_endian(struct task_struct *tsk, unsigned long adr);
|
||||||
extern int set_endian(struct task_struct *tsk, unsigned int val);
|
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)
|
static inline unsigned int __unpack_fe01(unsigned long msr_bits)
|
||||||
{
|
{
|
||||||
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
|
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче