diff options
| author | Matthew Leach <Matthew.Leach@arm.com> | 2013-11-28 07:07:23 -0500 |
|---|---|---|
| committer | Catalin Marinas <catalin.marinas@arm.com> | 2013-11-28 13:01:29 -0500 |
| commit | 2dacab73dc9f86ad12eb41bc3355d7f492696bca (patch) | |
| tree | ff6bd65df00a7f7af816dfc92f70b82f7a07dec0 | |
| parent | 6a2e5e521c333a0b56cb60dc5587e3f90859c5e7 (diff) | |
arm64: debug: make aarch32 bkpt checking endian clean
The current breakpoint instruction checking code for A32 is not endian
clean. Fix this with appropriate byte-swapping when retrieving
instructions.
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
| -rw-r--r-- | arch/arm64/kernel/debug-monitors.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 6a0a9b132d7a..4ae68579031d 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c | |||
| @@ -248,7 +248,8 @@ static int brk_handler(unsigned long addr, unsigned int esr, | |||
| 248 | int aarch32_break_handler(struct pt_regs *regs) | 248 | int aarch32_break_handler(struct pt_regs *regs) |
| 249 | { | 249 | { |
| 250 | siginfo_t info; | 250 | siginfo_t info; |
| 251 | unsigned int instr; | 251 | u32 arm_instr; |
| 252 | u16 thumb_instr; | ||
| 252 | bool bp = false; | 253 | bool bp = false; |
| 253 | void __user *pc = (void __user *)instruction_pointer(regs); | 254 | void __user *pc = (void __user *)instruction_pointer(regs); |
| 254 | 255 | ||
| @@ -257,18 +258,21 @@ int aarch32_break_handler(struct pt_regs *regs) | |||
| 257 | 258 | ||
| 258 | if (compat_thumb_mode(regs)) { | 259 | if (compat_thumb_mode(regs)) { |
| 259 | /* get 16-bit Thumb instruction */ | 260 | /* get 16-bit Thumb instruction */ |
| 260 | get_user(instr, (u16 __user *)pc); | 261 | get_user(thumb_instr, (u16 __user *)pc); |
| 261 | if (instr == AARCH32_BREAK_THUMB2_LO) { | 262 | thumb_instr = le16_to_cpu(thumb_instr); |
| 263 | if (thumb_instr == AARCH32_BREAK_THUMB2_LO) { | ||
| 262 | /* get second half of 32-bit Thumb-2 instruction */ | 264 | /* get second half of 32-bit Thumb-2 instruction */ |
| 263 | get_user(instr, (u16 __user *)(pc + 2)); | 265 | get_user(thumb_instr, (u16 __user *)(pc + 2)); |
| 264 | bp = instr == AARCH32_BREAK_THUMB2_HI; | 266 | thumb_instr = le16_to_cpu(thumb_instr); |
| 267 | bp = thumb_instr == AARCH32_BREAK_THUMB2_HI; | ||
| 265 | } else { | 268 | } else { |
| 266 | bp = instr == AARCH32_BREAK_THUMB; | 269 | bp = thumb_instr == AARCH32_BREAK_THUMB; |
| 267 | } | 270 | } |
| 268 | } else { | 271 | } else { |
| 269 | /* 32-bit ARM instruction */ | 272 | /* 32-bit ARM instruction */ |
| 270 | get_user(instr, (u32 __user *)pc); | 273 | get_user(arm_instr, (u32 __user *)pc); |
| 271 | bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM; | 274 | arm_instr = le32_to_cpu(arm_instr); |
| 275 | bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM; | ||
| 272 | } | 276 | } |
| 273 | 277 | ||
| 274 | if (!bp) | 278 | if (!bp) |
