aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/mm/alignment.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/alignment.c')
-rw-r--r--arch/sh/mm/alignment.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
index 00fb9e3f057..b2595b8548e 100644
--- a/arch/sh/mm/alignment.c
+++ b/arch/sh/mm/alignment.c
@@ -14,6 +14,7 @@
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <asm/alignment.h>
+#include <asm/processor.h>
static unsigned long se_user;
static unsigned long se_sys;
@@ -59,9 +60,36 @@ void inc_unaligned_kernel_access(void)
se_sys++;
}
+/*
+ * This defaults to the global policy which can be set from the command
+ * line, while processes can overload their preferences via prctl().
+ */
unsigned int unaligned_user_action(void)
{
- return se_usermode;
+ unsigned int action = se_usermode;
+
+ if (current->thread.flags & SH_THREAD_UAC_SIGBUS) {
+ action &= ~UM_FIXUP;
+ action |= UM_SIGNAL;
+ }
+
+ if (current->thread.flags & SH_THREAD_UAC_NOPRINT)
+ action &= ~UM_WARN;
+
+ return action;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long addr)
+{
+ return put_user(tsk->thread.flags & SH_THREAD_UAC_MASK,
+ (unsigned int __user *)addr);
+}
+
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+ tsk->thread.flags = (tsk->thread.flags & ~SH_THREAD_UAC_MASK) |
+ (val & SH_THREAD_UAC_MASK);
+ return 0;
}
void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn,