diff options
| -rw-r--r-- | arch/arm/kernel/traps.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 948c648fea00..0fcd82f01388 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
| @@ -154,30 +154,26 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, | |||
| 154 | set_fs(fs); | 154 | set_fs(fs); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static void dump_instr(const char *lvl, struct pt_regs *regs) | 157 | static void __dump_instr(const char *lvl, struct pt_regs *regs) |
| 158 | { | 158 | { |
| 159 | unsigned long addr = instruction_pointer(regs); | 159 | unsigned long addr = instruction_pointer(regs); |
| 160 | const int thumb = thumb_mode(regs); | 160 | const int thumb = thumb_mode(regs); |
| 161 | const int width = thumb ? 4 : 8; | 161 | const int width = thumb ? 4 : 8; |
| 162 | mm_segment_t fs; | ||
| 163 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; | 162 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; |
| 164 | int i; | 163 | int i; |
| 165 | 164 | ||
| 166 | /* | 165 | /* |
| 167 | * We need to switch to kernel mode so that we can use __get_user | 166 | * Note that we now dump the code first, just in case the backtrace |
| 168 | * to safely read from kernel space. Note that we now dump the | 167 | * kills us. |
| 169 | * code first, just in case the backtrace kills us. | ||
| 170 | */ | 168 | */ |
| 171 | fs = get_fs(); | ||
| 172 | set_fs(KERNEL_DS); | ||
| 173 | 169 | ||
| 174 | for (i = -4; i < 1 + !!thumb; i++) { | 170 | for (i = -4; i < 1 + !!thumb; i++) { |
| 175 | unsigned int val, bad; | 171 | unsigned int val, bad; |
| 176 | 172 | ||
| 177 | if (thumb) | 173 | if (thumb) |
| 178 | bad = __get_user(val, &((u16 *)addr)[i]); | 174 | bad = get_user(val, &((u16 *)addr)[i]); |
| 179 | else | 175 | else |
| 180 | bad = __get_user(val, &((u32 *)addr)[i]); | 176 | bad = get_user(val, &((u32 *)addr)[i]); |
| 181 | 177 | ||
| 182 | if (!bad) | 178 | if (!bad) |
| 183 | p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", | 179 | p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", |
| @@ -188,8 +184,20 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) | |||
| 188 | } | 184 | } |
| 189 | } | 185 | } |
| 190 | printk("%sCode: %s\n", lvl, str); | 186 | printk("%sCode: %s\n", lvl, str); |
| 187 | } | ||
| 191 | 188 | ||
| 192 | set_fs(fs); | 189 | static void dump_instr(const char *lvl, struct pt_regs *regs) |
| 190 | { | ||
| 191 | mm_segment_t fs; | ||
| 192 | |||
| 193 | if (!user_mode(regs)) { | ||
| 194 | fs = get_fs(); | ||
| 195 | set_fs(KERNEL_DS); | ||
| 196 | __dump_instr(lvl, regs); | ||
| 197 | set_fs(fs); | ||
| 198 | } else { | ||
| 199 | __dump_instr(lvl, regs); | ||
| 200 | } | ||
| 193 | } | 201 | } |
| 194 | 202 | ||
| 195 | #ifdef CONFIG_ARM_UNWIND | 203 | #ifdef CONFIG_ARM_UNWIND |
