aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-02-22 22:56:30 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-02-22 22:56:30 -0500
commit94ea5e449ae834af058ef005d16a8ad44fcf13d6 (patch)
tree4152e5cc7cd5535452b2cd074b6ba041abc7c301 /arch/sh
parent7c1b2c6890a1a033dde4f6991c0a1fcd69cf58ce (diff)
sh: wire up SET/GET_UNALIGN_CTL.
This hooks up the SET/GET_UNALIGN_CTL knobs cribbing the bulk of it from the PPC and ia64 implementations. The thread flags happen to be the logical inverse of what the global fault mode is set to, so this works out pretty cleanly. By default the global fault mode is used, with tasks now being able to override their own settings via prctl(). Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/processor.h12
-rw-r--r--arch/sh/include/asm/processor_32.h6
-rw-r--r--arch/sh/include/asm/processor_64.h5
-rw-r--r--arch/sh/mm/alignment.c30
4 files changed, 51 insertions, 2 deletions
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 87a8d1ef64e4..9605e062840f 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -107,6 +107,13 @@ extern unsigned int xstate_size;
107extern void free_thread_xstate(struct task_struct *); 107extern void free_thread_xstate(struct task_struct *);
108extern struct kmem_cache *task_xstate_cachep; 108extern struct kmem_cache *task_xstate_cachep;
109 109
110/* arch/sh/mm/alignment.c */
111extern int get_unalign_ctl(struct task_struct *, unsigned long addr);
112extern int set_unalign_ctl(struct task_struct *, unsigned int val);
113
114#define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr))
115#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
116
110/* arch/sh/mm/init.c */ 117/* arch/sh/mm/init.c */
111extern unsigned int mem_init_done; 118extern unsigned int mem_init_done;
112 119
@@ -114,6 +121,11 @@ extern unsigned int mem_init_done;
114const char *get_cpu_subtype(struct sh_cpuinfo *c); 121const char *get_cpu_subtype(struct sh_cpuinfo *c);
115extern const struct seq_operations cpuinfo_op; 122extern const struct seq_operations cpuinfo_op;
116 123
124/* thread_struct flags */
125#define SH_THREAD_UAC_NOPRINT (1 << 0)
126#define SH_THREAD_UAC_SIGBUS (1 << 1)
127#define SH_THREAD_UAC_MASK (SH_THREAD_UAC_NOPRINT | SH_THREAD_UAC_SIGBUS)
128
117/* processor boot mode configuration */ 129/* processor boot mode configuration */
118#define MODE_PIN0 (1 << 0) 130#define MODE_PIN0 (1 << 0)
119#define MODE_PIN1 (1 << 1) 131#define MODE_PIN1 (1 << 1)
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 488f0a906a41..572b4eb09493 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -101,8 +101,11 @@ struct thread_struct {
101 unsigned long sp; 101 unsigned long sp;
102 unsigned long pc; 102 unsigned long pc;
103 103
104 /* Various thread flags, see SH_THREAD_xxx */
105 unsigned long flags;
106
104 /* Save middle states of ptrace breakpoints */ 107 /* Save middle states of ptrace breakpoints */
105 struct perf_event *ptrace_bps[HBP_NUM]; 108 struct perf_event *ptrace_bps[HBP_NUM];
106 109
107#ifdef CONFIG_SH_DSP 110#ifdef CONFIG_SH_DSP
108 /* Dsp status information */ 111 /* Dsp status information */
@@ -115,6 +118,7 @@ struct thread_struct {
115 118
116#define INIT_THREAD { \ 119#define INIT_THREAD { \
117 .sp = sizeof(init_stack) + (long) &init_stack, \ 120 .sp = sizeof(init_stack) + (long) &init_stack, \
121 .flags = 0, \
118} 122}
119 123
120/* Forward declaration, a strange C thing */ 124/* Forward declaration, a strange C thing */
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index 7b1560f03d14..621bc4618c6b 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -108,6 +108,10 @@ union thread_xstate {
108struct thread_struct { 108struct thread_struct {
109 unsigned long sp; 109 unsigned long sp;
110 unsigned long pc; 110 unsigned long pc;
111
112 /* Various thread flags, see SH_THREAD_xxx */
113 unsigned long flags;
114
111 /* This stores the address of the pt_regs built during a context 115 /* This stores the address of the pt_regs built during a context
112 switch, or of the register save area built for a kernel mode 116 switch, or of the register save area built for a kernel mode
113 exception. It is used for backtracing the stack of a sleeping task 117 exception. It is used for backtracing the stack of a sleeping task
@@ -138,6 +142,7 @@ struct thread_struct {
138 .trap_no = 0, \ 142 .trap_no = 0, \
139 .error_code = 0, \ 143 .error_code = 0, \
140 .address = 0, \ 144 .address = 0, \
145 .flags = 0, \
141} 146}
142 147
143/* 148/*
diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c
index 00fb9e3f057c..b2595b8548ee 100644
--- a/arch/sh/mm/alignment.c
+++ b/arch/sh/mm/alignment.c
@@ -14,6 +14,7 @@
14#include <linux/proc_fs.h> 14#include <linux/proc_fs.h>
15#include <linux/uaccess.h> 15#include <linux/uaccess.h>
16#include <asm/alignment.h> 16#include <asm/alignment.h>
17#include <asm/processor.h>
17 18
18static unsigned long se_user; 19static unsigned long se_user;
19static unsigned long se_sys; 20static unsigned long se_sys;
@@ -59,9 +60,36 @@ void inc_unaligned_kernel_access(void)
59 se_sys++; 60 se_sys++;
60} 61}
61 62
63/*
64 * This defaults to the global policy which can be set from the command
65 * line, while processes can overload their preferences via prctl().
66 */
62unsigned int unaligned_user_action(void) 67unsigned int unaligned_user_action(void)
63{ 68{
64 return se_usermode; 69 unsigned int action = se_usermode;
70
71 if (current->thread.flags & SH_THREAD_UAC_SIGBUS) {
72 action &= ~UM_FIXUP;
73 action |= UM_SIGNAL;
74 }
75
76 if (current->thread.flags & SH_THREAD_UAC_NOPRINT)
77 action &= ~UM_WARN;
78
79 return action;
80}
81
82int get_unalign_ctl(struct task_struct *tsk, unsigned long addr)
83{
84 return put_user(tsk->thread.flags & SH_THREAD_UAC_MASK,
85 (unsigned int __user *)addr);
86}
87
88int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
89{
90 tsk->thread.flags = (tsk->thread.flags & ~SH_THREAD_UAC_MASK) |
91 (val & SH_THREAD_UAC_MASK);
92 return 0;
65} 93}
66 94
67void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn, 95void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn,