extern void free_thread_xstate(struct task_struct *);
extern struct kmem_cache *task_xstate_cachep;
+/* arch/sh/mm/alignment.c */
+extern int get_unalign_ctl(struct task_struct *, unsigned long addr);
+extern int set_unalign_ctl(struct task_struct *, unsigned int val);
+
+#define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr))
+#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
+
/* arch/sh/mm/init.c */
extern unsigned int mem_init_done;
const char *get_cpu_subtype(struct sh_cpuinfo *c);
extern const struct seq_operations cpuinfo_op;
+/* thread_struct flags */
+#define SH_THREAD_UAC_NOPRINT (1 << 0)
+#define SH_THREAD_UAC_SIGBUS (1 << 1)
+#define SH_THREAD_UAC_MASK (SH_THREAD_UAC_NOPRINT | SH_THREAD_UAC_SIGBUS)
+
/* processor boot mode configuration */
#define MODE_PIN0 (1 << 0)
#define MODE_PIN1 (1 << 1)
unsigned long sp;
unsigned long pc;
+ /* Various thread flags, see SH_THREAD_xxx */
+ unsigned long flags;
+
/* Save middle states of ptrace breakpoints */
- struct perf_event *ptrace_bps[HBP_NUM];
+ struct perf_event *ptrace_bps[HBP_NUM];
#ifdef CONFIG_SH_DSP
/* Dsp status information */
#define INIT_THREAD { \
.sp = sizeof(init_stack) + (long) &init_stack, \
+ .flags = 0, \
}
/* Forward declaration, a strange C thing */
struct thread_struct {
unsigned long sp;
unsigned long pc;
+
+ /* Various thread flags, see SH_THREAD_xxx */
+ unsigned long flags;
+
/* This stores the address of the pt_regs built during a context
switch, or of the register save area built for a kernel mode
exception. It is used for backtracing the stack of a sleeping task
.trap_no = 0, \
.error_code = 0, \
.address = 0, \
+ .flags = 0, \
}
/*
#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;
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,