diff options
| -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, |
