Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9370ae1 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

[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: default avatarPaul Mackerras <paulus@samba.org>
parent fab5db97
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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,
+4 −2
Original line number Diff line number Diff line
@@ -805,8 +805,10 @@ void __kprobes program_check_exception(struct pt_regs *regs)

void alignment_exception(struct pt_regs *regs)
{
	int fixed;
	int fixed = 0;

	/* we don't implement logging of alignment exceptions */
	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
		fixed = fix_alignment(regs);

	if (fixed == 1) {
+7 −0
Original line number Diff line number Diff line
@@ -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);