diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/processor.h | 12 | ||||
-rw-r--r-- | arch/sh/include/asm/processor_32.h | 6 | ||||
-rw-r--r-- | arch/sh/include/asm/processor_64.h | 5 | ||||
-rw-r--r-- | arch/sh/mm/alignment.c | 30 |
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; | |||
107 | extern void free_thread_xstate(struct task_struct *); | 107 | extern void free_thread_xstate(struct task_struct *); |
108 | extern struct kmem_cache *task_xstate_cachep; | 108 | extern struct kmem_cache *task_xstate_cachep; |
109 | 109 | ||
110 | /* arch/sh/mm/alignment.c */ | ||
111 | extern int get_unalign_ctl(struct task_struct *, unsigned long addr); | ||
112 | extern 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 */ |
111 | extern unsigned int mem_init_done; | 118 | extern unsigned int mem_init_done; |
112 | 119 | ||
@@ -114,6 +121,11 @@ extern unsigned int mem_init_done; | |||
114 | const char *get_cpu_subtype(struct sh_cpuinfo *c); | 121 | const char *get_cpu_subtype(struct sh_cpuinfo *c); |
115 | extern const struct seq_operations cpuinfo_op; | 122 | extern 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 { | |||
108 | struct thread_struct { | 108 | struct 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 | ||
18 | static unsigned long se_user; | 19 | static unsigned long se_user; |
19 | static unsigned long se_sys; | 20 | static 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 | */ | ||
62 | unsigned int unaligned_user_action(void) | 67 | unsigned 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 | |||
82 | int 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 | |||
88 | int 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 | ||
67 | void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn, | 95 | void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn, |