Re: [PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-21 Thread David Long

On 03/11/2016 10:56 PM, Marc Zyngier wrote:

On Wed,  9 Mar 2016 00:32:20 -0500
David Long  wrote:

David,


From: Sandeepa Prabhu 

Kprobes needs simulation of instructions that cannot be stepped
from a different memory location, e.g.: those instructions
that uses PC-relative addressing. In simulation, the behaviour
of the instruction is implemented using a copy of pt_regs.

The following instruction categories are simulated:
  - All branching instructions(conditional, register, and immediate)
  - Literal access instructions(load-literal, adr/adrp)

Conditional execution is limited to branching instructions in
ARM v8. If conditions at PSTATE do not match the condition fields
of opcode, the instruction is effectively NOP.

Thanks to Will Cohen for assorted suggested changes.

Signed-off-by: Sandeepa Prabhu 
Signed-off-by: William Cohen 
Signed-off-by: David A. Long 
---
  arch/arm64/include/asm/insn.h|   1 +
  arch/arm64/include/asm/probes.h  |   5 +-
  arch/arm64/kernel/Makefile   |   3 +-
  arch/arm64/kernel/insn.c |   1 +
  arch/arm64/kernel/kprobes-arm64.c|  29 
  arch/arm64/kernel/kprobes.c  |  32 -
  arch/arm64/kernel/probes-simulate-insn.c | 218 +++
  arch/arm64/kernel/probes-simulate-insn.h |  28 
  8 files changed, 311 insertions(+), 6 deletions(-)
  create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
  create mode 100644 arch/arm64/kernel/probes-simulate-insn.h

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index b9567a1..26cee10 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);

  typedef bool (pstate_check_t)(unsigned long);
  extern pstate_check_t * const opcode_condition_checks[16];
+
  #endif /* __ASSEMBLY__ */

  #endif/* __ASM_INSN_H */
diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
index c5fcbe6..d524f7d 100644
--- a/arch/arm64/include/asm/probes.h
+++ b/arch/arm64/include/asm/probes.h
@@ -15,11 +15,12 @@
  #ifndef _ARM_PROBES_H
  #define _ARM_PROBES_H

+#include 
+
  struct kprobe;
  struct arch_specific_insn;

  typedef u32 kprobe_opcode_t;
-typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
  typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);

  enum pc_restore_type {
@@ -35,7 +36,7 @@ struct kprobe_pc_restore {
  /* architecture specific copy of original instruction */
  struct arch_specific_insn {
kprobe_opcode_t *insn;
-   kprobes_pstate_check_t *pstate_cc;
+   pstate_check_t *pstate_cc;
kprobes_handler_t *handler;
/* restore address after step xol */
struct kprobe_pc_restore restore;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4efb791..08325e5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)+= sleep.o suspend.o
  arm64-obj-$(CONFIG_CPU_IDLE)  += cpuidle.o
  arm64-obj-$(CONFIG_JUMP_LABEL)+= jump_label.o
  arm64-obj-$(CONFIG_KGDB)  += kgdb.o
-arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
+arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
\
+  probes-simulate-insn.o
  arm64-obj-$(CONFIG_EFI)   += efi.o efi-entry.stub.o
  arm64-obj-$(CONFIG_PCI)   += pci.o
  arm64-obj-$(CONFIG_ARMV8_DEPRECATED)  += armv8_deprecated.o
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 9f15ceb..f9a3432 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -30,6 +30,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 

  #define AARCH64_INSN_SF_BIT   BIT(31)
diff --git a/arch/arm64/kernel/kprobes-arm64.c 
b/arch/arm64/kernel/kprobes-arm64.c
index e07727a..487238a 100644
--- a/arch/arm64/kernel/kprobes-arm64.c
+++ b/arch/arm64/kernel/kprobes-arm64.c
@@ -21,6 +21,7 @@
  #include 

  #include "kprobes-arm64.h"
+#include "probes-simulate-insn.h"

  static bool __kprobes aarch64_insn_is_steppable(u32 insn)
  {
@@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
arch_specific_insn *asi)
 */
if (aarch64_insn_is_steppable(insn))
return INSN_GOOD;
+
+   if (aarch64_insn_is_bcond(insn)) {
+   asi->handler = simulate_b_cond;
+   } else if (aarch64_insn_is_cbz(insn) ||
+   aarch64_insn_is_cbnz(insn)) {
+   asi->handler = simulate_cbz_cbnz;
+   } else if (aarch64_insn_is_tbz(insn) ||
+   aarch64_insn_is_tbnz(insn)) {
+   asi->handler = simulate_tbz_tbnz;
+   } else if (aarch64_insn_is_adr_adrp(insn))
+ 

Re: [PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-21 Thread David Long

On 03/11/2016 10:56 PM, Marc Zyngier wrote:

On Wed,  9 Mar 2016 00:32:20 -0500
David Long  wrote:

David,


From: Sandeepa Prabhu 

Kprobes needs simulation of instructions that cannot be stepped
from a different memory location, e.g.: those instructions
that uses PC-relative addressing. In simulation, the behaviour
of the instruction is implemented using a copy of pt_regs.

The following instruction categories are simulated:
  - All branching instructions(conditional, register, and immediate)
  - Literal access instructions(load-literal, adr/adrp)

Conditional execution is limited to branching instructions in
ARM v8. If conditions at PSTATE do not match the condition fields
of opcode, the instruction is effectively NOP.

Thanks to Will Cohen for assorted suggested changes.

Signed-off-by: Sandeepa Prabhu 
Signed-off-by: William Cohen 
Signed-off-by: David A. Long 
---
  arch/arm64/include/asm/insn.h|   1 +
  arch/arm64/include/asm/probes.h  |   5 +-
  arch/arm64/kernel/Makefile   |   3 +-
  arch/arm64/kernel/insn.c |   1 +
  arch/arm64/kernel/kprobes-arm64.c|  29 
  arch/arm64/kernel/kprobes.c  |  32 -
  arch/arm64/kernel/probes-simulate-insn.c | 218 +++
  arch/arm64/kernel/probes-simulate-insn.h |  28 
  8 files changed, 311 insertions(+), 6 deletions(-)
  create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
  create mode 100644 arch/arm64/kernel/probes-simulate-insn.h

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index b9567a1..26cee10 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);

  typedef bool (pstate_check_t)(unsigned long);
  extern pstate_check_t * const opcode_condition_checks[16];
+
  #endif /* __ASSEMBLY__ */

  #endif/* __ASM_INSN_H */
diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
index c5fcbe6..d524f7d 100644
--- a/arch/arm64/include/asm/probes.h
+++ b/arch/arm64/include/asm/probes.h
@@ -15,11 +15,12 @@
  #ifndef _ARM_PROBES_H
  #define _ARM_PROBES_H

+#include 
+
  struct kprobe;
  struct arch_specific_insn;

  typedef u32 kprobe_opcode_t;
-typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
  typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);

  enum pc_restore_type {
@@ -35,7 +36,7 @@ struct kprobe_pc_restore {
  /* architecture specific copy of original instruction */
  struct arch_specific_insn {
kprobe_opcode_t *insn;
-   kprobes_pstate_check_t *pstate_cc;
+   pstate_check_t *pstate_cc;
kprobes_handler_t *handler;
/* restore address after step xol */
struct kprobe_pc_restore restore;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4efb791..08325e5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)+= sleep.o suspend.o
  arm64-obj-$(CONFIG_CPU_IDLE)  += cpuidle.o
  arm64-obj-$(CONFIG_JUMP_LABEL)+= jump_label.o
  arm64-obj-$(CONFIG_KGDB)  += kgdb.o
-arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
+arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
\
+  probes-simulate-insn.o
  arm64-obj-$(CONFIG_EFI)   += efi.o efi-entry.stub.o
  arm64-obj-$(CONFIG_PCI)   += pci.o
  arm64-obj-$(CONFIG_ARMV8_DEPRECATED)  += armv8_deprecated.o
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 9f15ceb..f9a3432 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -30,6 +30,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 

  #define AARCH64_INSN_SF_BIT   BIT(31)
diff --git a/arch/arm64/kernel/kprobes-arm64.c 
b/arch/arm64/kernel/kprobes-arm64.c
index e07727a..487238a 100644
--- a/arch/arm64/kernel/kprobes-arm64.c
+++ b/arch/arm64/kernel/kprobes-arm64.c
@@ -21,6 +21,7 @@
  #include 

  #include "kprobes-arm64.h"
+#include "probes-simulate-insn.h"

  static bool __kprobes aarch64_insn_is_steppable(u32 insn)
  {
@@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
arch_specific_insn *asi)
 */
if (aarch64_insn_is_steppable(insn))
return INSN_GOOD;
+
+   if (aarch64_insn_is_bcond(insn)) {
+   asi->handler = simulate_b_cond;
+   } else if (aarch64_insn_is_cbz(insn) ||
+   aarch64_insn_is_cbnz(insn)) {
+   asi->handler = simulate_cbz_cbnz;
+   } else if (aarch64_insn_is_tbz(insn) ||
+   aarch64_insn_is_tbnz(insn)) {
+   asi->handler = simulate_tbz_tbnz;
+   } else if (aarch64_insn_is_adr_adrp(insn))
+   asi->handler = simulate_adr_adrp;
+   else if (aarch64_insn_is_b(insn) ||
+   

Re: [PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-11 Thread Marc Zyngier
On Wed,  9 Mar 2016 00:32:20 -0500
David Long  wrote:

David,

> From: Sandeepa Prabhu 
> 
> Kprobes needs simulation of instructions that cannot be stepped
> from a different memory location, e.g.: those instructions
> that uses PC-relative addressing. In simulation, the behaviour
> of the instruction is implemented using a copy of pt_regs.
> 
> The following instruction categories are simulated:
>  - All branching instructions(conditional, register, and immediate)
>  - Literal access instructions(load-literal, adr/adrp)
> 
> Conditional execution is limited to branching instructions in
> ARM v8. If conditions at PSTATE do not match the condition fields
> of opcode, the instruction is effectively NOP.
> 
> Thanks to Will Cohen for assorted suggested changes.
> 
> Signed-off-by: Sandeepa Prabhu 
> Signed-off-by: William Cohen 
> Signed-off-by: David A. Long 
> ---
>  arch/arm64/include/asm/insn.h|   1 +
>  arch/arm64/include/asm/probes.h  |   5 +-
>  arch/arm64/kernel/Makefile   |   3 +-
>  arch/arm64/kernel/insn.c |   1 +
>  arch/arm64/kernel/kprobes-arm64.c|  29 
>  arch/arm64/kernel/kprobes.c  |  32 -
>  arch/arm64/kernel/probes-simulate-insn.c | 218 
> +++
>  arch/arm64/kernel/probes-simulate-insn.h |  28 
>  8 files changed, 311 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.h
> 
> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
> index b9567a1..26cee10 100644
> --- a/arch/arm64/include/asm/insn.h
> +++ b/arch/arm64/include/asm/insn.h
> @@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
>  
>  typedef bool (pstate_check_t)(unsigned long);
>  extern pstate_check_t * const opcode_condition_checks[16];
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif   /* __ASM_INSN_H */
> diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
> index c5fcbe6..d524f7d 100644
> --- a/arch/arm64/include/asm/probes.h
> +++ b/arch/arm64/include/asm/probes.h
> @@ -15,11 +15,12 @@
>  #ifndef _ARM_PROBES_H
>  #define _ARM_PROBES_H
>  
> +#include 
> +
>  struct kprobe;
>  struct arch_specific_insn;
>  
>  typedef u32 kprobe_opcode_t;
> -typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
>  typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
>  
>  enum pc_restore_type {
> @@ -35,7 +36,7 @@ struct kprobe_pc_restore {
>  /* architecture specific copy of original instruction */
>  struct arch_specific_insn {
>   kprobe_opcode_t *insn;
> - kprobes_pstate_check_t *pstate_cc;
> + pstate_check_t *pstate_cc;
>   kprobes_handler_t *handler;
>   /* restore address after step xol */
>   struct kprobe_pc_restore restore;
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 4efb791..08325e5 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)  += sleep.o suspend.o
>  arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
>  arm64-obj-$(CONFIG_JUMP_LABEL)   += jump_label.o
>  arm64-obj-$(CONFIG_KGDB) += kgdb.o
> -arm64-obj-$(CONFIG_KPROBES)  += kprobes.o kprobes-arm64.o
> +arm64-obj-$(CONFIG_KPROBES)  += kprobes.o kprobes-arm64.o
> \
> +probes-simulate-insn.o
>  arm64-obj-$(CONFIG_EFI)  += efi.o efi-entry.stub.o
>  arm64-obj-$(CONFIG_PCI)  += pci.o
>  arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index 9f15ceb..f9a3432 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -30,6 +30,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #define AARCH64_INSN_SF_BIT  BIT(31)
> diff --git a/arch/arm64/kernel/kprobes-arm64.c 
> b/arch/arm64/kernel/kprobes-arm64.c
> index e07727a..487238a 100644
> --- a/arch/arm64/kernel/kprobes-arm64.c
> +++ b/arch/arm64/kernel/kprobes-arm64.c
> @@ -21,6 +21,7 @@
>  #include 
>  
>  #include "kprobes-arm64.h"
> +#include "probes-simulate-insn.h"
>  
>  static bool __kprobes aarch64_insn_is_steppable(u32 insn)
>  {
> @@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
> arch_specific_insn *asi)
>*/
>   if (aarch64_insn_is_steppable(insn))
>   return INSN_GOOD;
> +
> + if (aarch64_insn_is_bcond(insn)) {
> + asi->handler = simulate_b_cond;
> + } else if (aarch64_insn_is_cbz(insn) ||
> + aarch64_insn_is_cbnz(insn)) {
> + asi->handler = simulate_cbz_cbnz;
> + } else if (aarch64_insn_is_tbz(insn) ||
> + 

Re: [PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-11 Thread Marc Zyngier
On Wed,  9 Mar 2016 00:32:20 -0500
David Long  wrote:

David,

> From: Sandeepa Prabhu 
> 
> Kprobes needs simulation of instructions that cannot be stepped
> from a different memory location, e.g.: those instructions
> that uses PC-relative addressing. In simulation, the behaviour
> of the instruction is implemented using a copy of pt_regs.
> 
> The following instruction categories are simulated:
>  - All branching instructions(conditional, register, and immediate)
>  - Literal access instructions(load-literal, adr/adrp)
> 
> Conditional execution is limited to branching instructions in
> ARM v8. If conditions at PSTATE do not match the condition fields
> of opcode, the instruction is effectively NOP.
> 
> Thanks to Will Cohen for assorted suggested changes.
> 
> Signed-off-by: Sandeepa Prabhu 
> Signed-off-by: William Cohen 
> Signed-off-by: David A. Long 
> ---
>  arch/arm64/include/asm/insn.h|   1 +
>  arch/arm64/include/asm/probes.h  |   5 +-
>  arch/arm64/kernel/Makefile   |   3 +-
>  arch/arm64/kernel/insn.c |   1 +
>  arch/arm64/kernel/kprobes-arm64.c|  29 
>  arch/arm64/kernel/kprobes.c  |  32 -
>  arch/arm64/kernel/probes-simulate-insn.c | 218 
> +++
>  arch/arm64/kernel/probes-simulate-insn.h |  28 
>  8 files changed, 311 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.h
> 
> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
> index b9567a1..26cee10 100644
> --- a/arch/arm64/include/asm/insn.h
> +++ b/arch/arm64/include/asm/insn.h
> @@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
>  
>  typedef bool (pstate_check_t)(unsigned long);
>  extern pstate_check_t * const opcode_condition_checks[16];
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif   /* __ASM_INSN_H */
> diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
> index c5fcbe6..d524f7d 100644
> --- a/arch/arm64/include/asm/probes.h
> +++ b/arch/arm64/include/asm/probes.h
> @@ -15,11 +15,12 @@
>  #ifndef _ARM_PROBES_H
>  #define _ARM_PROBES_H
>  
> +#include 
> +
>  struct kprobe;
>  struct arch_specific_insn;
>  
>  typedef u32 kprobe_opcode_t;
> -typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
>  typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
>  
>  enum pc_restore_type {
> @@ -35,7 +36,7 @@ struct kprobe_pc_restore {
>  /* architecture specific copy of original instruction */
>  struct arch_specific_insn {
>   kprobe_opcode_t *insn;
> - kprobes_pstate_check_t *pstate_cc;
> + pstate_check_t *pstate_cc;
>   kprobes_handler_t *handler;
>   /* restore address after step xol */
>   struct kprobe_pc_restore restore;
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 4efb791..08325e5 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)  += sleep.o suspend.o
>  arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
>  arm64-obj-$(CONFIG_JUMP_LABEL)   += jump_label.o
>  arm64-obj-$(CONFIG_KGDB) += kgdb.o
> -arm64-obj-$(CONFIG_KPROBES)  += kprobes.o kprobes-arm64.o
> +arm64-obj-$(CONFIG_KPROBES)  += kprobes.o kprobes-arm64.o
> \
> +probes-simulate-insn.o
>  arm64-obj-$(CONFIG_EFI)  += efi.o efi-entry.stub.o
>  arm64-obj-$(CONFIG_PCI)  += pci.o
>  arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index 9f15ceb..f9a3432 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -30,6 +30,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #define AARCH64_INSN_SF_BIT  BIT(31)
> diff --git a/arch/arm64/kernel/kprobes-arm64.c 
> b/arch/arm64/kernel/kprobes-arm64.c
> index e07727a..487238a 100644
> --- a/arch/arm64/kernel/kprobes-arm64.c
> +++ b/arch/arm64/kernel/kprobes-arm64.c
> @@ -21,6 +21,7 @@
>  #include 
>  
>  #include "kprobes-arm64.h"
> +#include "probes-simulate-insn.h"
>  
>  static bool __kprobes aarch64_insn_is_steppable(u32 insn)
>  {
> @@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
> arch_specific_insn *asi)
>*/
>   if (aarch64_insn_is_steppable(insn))
>   return INSN_GOOD;
> +
> + if (aarch64_insn_is_bcond(insn)) {
> + asi->handler = simulate_b_cond;
> + } else if (aarch64_insn_is_cbz(insn) ||
> + aarch64_insn_is_cbnz(insn)) {
> + asi->handler = simulate_cbz_cbnz;
> + } else if (aarch64_insn_is_tbz(insn) ||
> + aarch64_insn_is_tbnz(insn)) {
> + asi->handler = simulate_tbz_tbnz;
> + } else if (aarch64_insn_is_adr_adrp(insn))
> +   

[PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-08 Thread David Long
From: Sandeepa Prabhu 

Kprobes needs simulation of instructions that cannot be stepped
from a different memory location, e.g.: those instructions
that uses PC-relative addressing. In simulation, the behaviour
of the instruction is implemented using a copy of pt_regs.

The following instruction categories are simulated:
 - All branching instructions(conditional, register, and immediate)
 - Literal access instructions(load-literal, adr/adrp)

Conditional execution is limited to branching instructions in
ARM v8. If conditions at PSTATE do not match the condition fields
of opcode, the instruction is effectively NOP.

Thanks to Will Cohen for assorted suggested changes.

Signed-off-by: Sandeepa Prabhu 
Signed-off-by: William Cohen 
Signed-off-by: David A. Long 
---
 arch/arm64/include/asm/insn.h|   1 +
 arch/arm64/include/asm/probes.h  |   5 +-
 arch/arm64/kernel/Makefile   |   3 +-
 arch/arm64/kernel/insn.c |   1 +
 arch/arm64/kernel/kprobes-arm64.c|  29 
 arch/arm64/kernel/kprobes.c  |  32 -
 arch/arm64/kernel/probes-simulate-insn.c | 218 +++
 arch/arm64/kernel/probes-simulate-insn.h |  28 
 8 files changed, 311 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
 create mode 100644 arch/arm64/kernel/probes-simulate-insn.h

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index b9567a1..26cee10 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
 
 typedef bool (pstate_check_t)(unsigned long);
 extern pstate_check_t * const opcode_condition_checks[16];
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_INSN_H */
diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
index c5fcbe6..d524f7d 100644
--- a/arch/arm64/include/asm/probes.h
+++ b/arch/arm64/include/asm/probes.h
@@ -15,11 +15,12 @@
 #ifndef _ARM_PROBES_H
 #define _ARM_PROBES_H
 
+#include 
+
 struct kprobe;
 struct arch_specific_insn;
 
 typedef u32 kprobe_opcode_t;
-typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
 typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
 
 enum pc_restore_type {
@@ -35,7 +36,7 @@ struct kprobe_pc_restore {
 /* architecture specific copy of original instruction */
 struct arch_specific_insn {
kprobe_opcode_t *insn;
-   kprobes_pstate_check_t *pstate_cc;
+   pstate_check_t *pstate_cc;
kprobes_handler_t *handler;
/* restore address after step xol */
struct kprobe_pc_restore restore;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4efb791..08325e5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)+= sleep.o suspend.o
 arm64-obj-$(CONFIG_CPU_IDLE)   += cpuidle.o
 arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 arm64-obj-$(CONFIG_KGDB)   += kgdb.o
-arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
+arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
\
+  probes-simulate-insn.o
 arm64-obj-$(CONFIG_EFI)+= efi.o efi-entry.stub.o
 arm64-obj-$(CONFIG_PCI)+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)   += armv8_deprecated.o
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 9f15ceb..f9a3432 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define AARCH64_INSN_SF_BITBIT(31)
diff --git a/arch/arm64/kernel/kprobes-arm64.c 
b/arch/arm64/kernel/kprobes-arm64.c
index e07727a..487238a 100644
--- a/arch/arm64/kernel/kprobes-arm64.c
+++ b/arch/arm64/kernel/kprobes-arm64.c
@@ -21,6 +21,7 @@
 #include 
 
 #include "kprobes-arm64.h"
+#include "probes-simulate-insn.h"
 
 static bool __kprobes aarch64_insn_is_steppable(u32 insn)
 {
@@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
arch_specific_insn *asi)
 */
if (aarch64_insn_is_steppable(insn))
return INSN_GOOD;
+
+   if (aarch64_insn_is_bcond(insn)) {
+   asi->handler = simulate_b_cond;
+   } else if (aarch64_insn_is_cbz(insn) ||
+   aarch64_insn_is_cbnz(insn)) {
+   asi->handler = simulate_cbz_cbnz;
+   } else if (aarch64_insn_is_tbz(insn) ||
+   aarch64_insn_is_tbnz(insn)) {
+   asi->handler = simulate_tbz_tbnz;
+   } else if (aarch64_insn_is_adr_adrp(insn))
+   asi->handler = simulate_adr_adrp;
+   else if (aarch64_insn_is_b(insn) ||
+   aarch64_insn_is_bl(insn))
+   asi->handler = simulate_b_bl;
+

[PATCH v11 6/9] arm64: kprobes instruction simulation support

2016-03-08 Thread David Long
From: Sandeepa Prabhu 

Kprobes needs simulation of instructions that cannot be stepped
from a different memory location, e.g.: those instructions
that uses PC-relative addressing. In simulation, the behaviour
of the instruction is implemented using a copy of pt_regs.

The following instruction categories are simulated:
 - All branching instructions(conditional, register, and immediate)
 - Literal access instructions(load-literal, adr/adrp)

Conditional execution is limited to branching instructions in
ARM v8. If conditions at PSTATE do not match the condition fields
of opcode, the instruction is effectively NOP.

Thanks to Will Cohen for assorted suggested changes.

Signed-off-by: Sandeepa Prabhu 
Signed-off-by: William Cohen 
Signed-off-by: David A. Long 
---
 arch/arm64/include/asm/insn.h|   1 +
 arch/arm64/include/asm/probes.h  |   5 +-
 arch/arm64/kernel/Makefile   |   3 +-
 arch/arm64/kernel/insn.c |   1 +
 arch/arm64/kernel/kprobes-arm64.c|  29 
 arch/arm64/kernel/kprobes.c  |  32 -
 arch/arm64/kernel/probes-simulate-insn.c | 218 +++
 arch/arm64/kernel/probes-simulate-insn.h |  28 
 8 files changed, 311 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
 create mode 100644 arch/arm64/kernel/probes-simulate-insn.h

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index b9567a1..26cee10 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
 
 typedef bool (pstate_check_t)(unsigned long);
 extern pstate_check_t * const opcode_condition_checks[16];
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_INSN_H */
diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
index c5fcbe6..d524f7d 100644
--- a/arch/arm64/include/asm/probes.h
+++ b/arch/arm64/include/asm/probes.h
@@ -15,11 +15,12 @@
 #ifndef _ARM_PROBES_H
 #define _ARM_PROBES_H
 
+#include 
+
 struct kprobe;
 struct arch_specific_insn;
 
 typedef u32 kprobe_opcode_t;
-typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
 typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
 
 enum pc_restore_type {
@@ -35,7 +36,7 @@ struct kprobe_pc_restore {
 /* architecture specific copy of original instruction */
 struct arch_specific_insn {
kprobe_opcode_t *insn;
-   kprobes_pstate_check_t *pstate_cc;
+   pstate_check_t *pstate_cc;
kprobes_handler_t *handler;
/* restore address after step xol */
struct kprobe_pc_restore restore;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4efb791..08325e5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -36,7 +36,8 @@ arm64-obj-$(CONFIG_CPU_PM)+= sleep.o suspend.o
 arm64-obj-$(CONFIG_CPU_IDLE)   += cpuidle.o
 arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 arm64-obj-$(CONFIG_KGDB)   += kgdb.o
-arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
+arm64-obj-$(CONFIG_KPROBES)+= kprobes.o kprobes-arm64.o
\
+  probes-simulate-insn.o
 arm64-obj-$(CONFIG_EFI)+= efi.o efi-entry.stub.o
 arm64-obj-$(CONFIG_PCI)+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)   += armv8_deprecated.o
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 9f15ceb..f9a3432 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define AARCH64_INSN_SF_BITBIT(31)
diff --git a/arch/arm64/kernel/kprobes-arm64.c 
b/arch/arm64/kernel/kprobes-arm64.c
index e07727a..487238a 100644
--- a/arch/arm64/kernel/kprobes-arm64.c
+++ b/arch/arm64/kernel/kprobes-arm64.c
@@ -21,6 +21,7 @@
 #include 
 
 #include "kprobes-arm64.h"
+#include "probes-simulate-insn.h"
 
 static bool __kprobes aarch64_insn_is_steppable(u32 insn)
 {
@@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct 
arch_specific_insn *asi)
 */
if (aarch64_insn_is_steppable(insn))
return INSN_GOOD;
+
+   if (aarch64_insn_is_bcond(insn)) {
+   asi->handler = simulate_b_cond;
+   } else if (aarch64_insn_is_cbz(insn) ||
+   aarch64_insn_is_cbnz(insn)) {
+   asi->handler = simulate_cbz_cbnz;
+   } else if (aarch64_insn_is_tbz(insn) ||
+   aarch64_insn_is_tbnz(insn)) {
+   asi->handler = simulate_tbz_tbnz;
+   } else if (aarch64_insn_is_adr_adrp(insn))
+   asi->handler = simulate_adr_adrp;
+   else if (aarch64_insn_is_b(insn) ||
+   aarch64_insn_is_bl(insn))
+   asi->handler = simulate_b_bl;
+   else if (aarch64_insn_is_br(insn) ||
+   aarch64_insn_is_blr(insn) ||
+