Commit 98f07013 authored by Russell King's avatar Russell King

Merge branch 'devel-stable' into for-next

parents 53f1d9af 98775936
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <asm/opcodes.h>
#include "kprobes.h" #include "kprobes.h"
...@@ -153,7 +154,8 @@ kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -153,7 +154,8 @@ kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
if (handler) { if (handler) {
/* We can emulate the instruction in (possibly) modified form */ /* We can emulate the instruction in (possibly) modified form */
asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist; asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) |
(rn << 16) | reglist);
asi->insn_handler = handler; asi->insn_handler = handler;
return INSN_GOOD; return INSN_GOOD;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
* @ start of inline data... * @ start of inline data...
* .ascii "mov r0, r7" @ text title for test case * .ascii "mov r0, r7" @ text title for test case
* .byte 0 * .byte 0
* .align 2 * .align 2, 0
* *
* @ TEST_ARG_REG * @ TEST_ARG_REG
* .byte ARG_TYPE_REG * .byte ARG_TYPE_REG
...@@ -1333,7 +1333,8 @@ static void test_case_failed(const char *message) ...@@ -1333,7 +1333,8 @@ static void test_case_failed(const char *message)
static unsigned long next_instruction(unsigned long pc) static unsigned long next_instruction(unsigned long pc)
{ {
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1))) if ((pc & 1) &&
!is_wide_instruction(__mem_to_opcode_thumb16(*(u16 *)(pc - 1))))
return pc + 2; return pc + 2;
else else
#endif #endif
...@@ -1378,13 +1379,13 @@ static uintptr_t __used kprobes_test_case_start(const char *title, void *stack) ...@@ -1378,13 +1379,13 @@ static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
if (test_case_is_thumb) { if (test_case_is_thumb) {
u16 *p = (u16 *)(test_code & ~1); u16 *p = (u16 *)(test_code & ~1);
current_instruction = p[0]; current_instruction = __mem_to_opcode_thumb16(p[0]);
if (is_wide_instruction(current_instruction)) { if (is_wide_instruction(current_instruction)) {
current_instruction <<= 16; u16 instr2 = __mem_to_opcode_thumb16(p[1]);
current_instruction |= p[1]; current_instruction = __opcode_thumb32_compose(current_instruction, instr2);
} }
} else { } else {
current_instruction = *(u32 *)test_code; current_instruction = __mem_to_opcode_arm(*(u32 *)test_code);
} }
if (current_title[0] == '.') if (current_title[0] == '.')
......
...@@ -115,7 +115,7 @@ struct test_arg_end { ...@@ -115,7 +115,7 @@ struct test_arg_end {
/* multiple strings to be concatenated. */ \ /* multiple strings to be concatenated. */ \
".ascii "#title" \n\t" \ ".ascii "#title" \n\t" \
".byte 0 \n\t" \ ".byte 0 \n\t" \
".align 2 \n\t" ".align 2, 0 \n\t"
#define TEST_ARG_REG(reg, val) \ #define TEST_ARG_REG(reg, val) \
".byte "__stringify(ARG_TYPE_REG)" \n\t" \ ".byte "__stringify(ARG_TYPE_REG)" \n\t" \
......
...@@ -149,9 +149,9 @@ t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -149,9 +149,9 @@ t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d); enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
/* Fixup modified instruction to have halfwords in correct order...*/ /* Fixup modified instruction to have halfwords in correct order...*/
insn = asi->insn[0]; insn = __mem_to_opcode_arm(asi->insn[0]);
((u16 *)asi->insn)[0] = insn >> 16; ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16);
((u16 *)asi->insn)[1] = insn & 0xffff; ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff);
return ret; return ret;
} }
...@@ -516,7 +516,7 @@ t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -516,7 +516,7 @@ t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi,
{ {
insn &= ~0x00ff; insn &= ~0x00ff;
insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
((u16 *)asi->insn)[0] = insn; ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn);
asi->insn_handler = t16_emulate_hiregs; asi->insn_handler = t16_emulate_hiregs;
return INSN_GOOD; return INSN_GOOD;
} }
...@@ -547,8 +547,10 @@ t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -547,8 +547,10 @@ t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi,
* and call it with R9=SP and LR in the register list represented * and call it with R9=SP and LR in the register list represented
* by R8. * by R8.
*/ */
((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */ /* 1st half STMDB R9!,{} */
((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929);
/* 2nd half (register list) */
((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
asi->insn_handler = t16_emulate_push; asi->insn_handler = t16_emulate_push;
return INSN_GOOD; return INSN_GOOD;
} }
...@@ -600,8 +602,10 @@ t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -600,8 +602,10 @@ t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi,
* and call it with R9=SP and PC in the register list represented * and call it with R9=SP and PC in the register list represented
* by R8. * by R8.
*/ */
((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */ /* 1st half LDMIA R9!,{} */
((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9);
/* 2nd half (register list) */
((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
: t16_emulate_pop_nopc; : t16_emulate_pop_nopc;
return INSN_GOOD; return INSN_GOOD;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/stop_machine.h> #include <linux/stop_machine.h>
#include <linux/stringify.h> #include <linux/stringify.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/opcodes.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/bug.h> #include <linux/bug.h>
...@@ -67,10 +68,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) ...@@ -67,10 +68,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
thumb = true; thumb = true;
addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
insn = ((u16 *)addr)[0]; insn = __mem_to_opcode_thumb16(((u16 *)addr)[0]);
if (is_wide_instruction(insn)) { if (is_wide_instruction(insn)) {
insn <<= 16; u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]);
insn |= ((u16 *)addr)[1]; insn = __opcode_thumb32_compose(insn, inst2);
decode_insn = thumb32_probes_decode_insn; decode_insn = thumb32_probes_decode_insn;
actions = kprobes_t32_actions; actions = kprobes_t32_actions;
} else { } else {
...@@ -81,7 +82,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) ...@@ -81,7 +82,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
thumb = false; thumb = false;
if (addr & 0x3) if (addr & 0x3)
return -EINVAL; return -EINVAL;
insn = *p->addr; insn = __mem_to_opcode_arm(*p->addr);
decode_insn = arm_probes_decode_insn; decode_insn = arm_probes_decode_insn;
actions = kprobes_arm_actions; actions = kprobes_arm_actions;
#endif #endif
......
...@@ -202,13 +202,14 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -202,13 +202,14 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
if (thumb) { if (thumb) {
u16 *thumb_insn = (u16 *)asi->insn; u16 *thumb_insn = (u16 *)asi->insn;
thumb_insn[1] = 0x4770; /* Thumb bx lr */ /* Thumb bx lr */
thumb_insn[2] = 0x4770; /* Thumb bx lr */ thumb_insn[1] = __opcode_to_mem_thumb16(0x4770);
thumb_insn[2] = __opcode_to_mem_thumb16(0x4770);
return insn; return insn;
} }
asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */
#else #else
asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */
#endif #endif
/* Make an ARM instruction unconditional */ /* Make an ARM instruction unconditional */
if (insn < 0xe0000000) if (insn < 0xe0000000)
...@@ -228,12 +229,12 @@ set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, ...@@ -228,12 +229,12 @@ set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
if (thumb) { if (thumb) {
u16 *ip = (u16 *)asi->insn; u16 *ip = (u16 *)asi->insn;
if (is_wide_instruction(insn)) if (is_wide_instruction(insn))
*ip++ = insn >> 16; *ip++ = __opcode_to_mem_thumb16(insn >> 16);
*ip++ = insn; *ip++ = __opcode_to_mem_thumb16(insn);
return; return;
} }
#endif #endif
asi->insn[0] = insn; asi->insn[0] = __opcode_to_mem_arm(insn);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment