kprobes-thumb.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * arch/arm/kernel/kprobes-thumb.c
  3. *
  4. * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/kprobes.h>
  12. #include "kprobes.h"
  13. /*
  14. * True if current instruction is in an IT block.
  15. */
  16. #define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
  17. /*
  18. * Return the condition code to check for the currently executing instruction.
  19. * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
  20. * in_it_block returns true.
  21. */
  22. #define current_cond(cpsr) ((cpsr >> 12) & 0xf)
  23. static const union decode_item t16_table_1011[] = {
  24. /* Miscellaneous 16-bit instructions */
  25. /*
  26. * If-Then, and hints
  27. * 1011 1111 xxxx xxxx
  28. */
  29. /* YIELD 1011 1111 0001 0000 */
  30. DECODE_OR (0xffff, 0xbf10),
  31. /* SEV 1011 1111 0100 0000 */
  32. DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none),
  33. /* NOP 1011 1111 0000 0000 */
  34. /* WFE 1011 1111 0010 0000 */
  35. /* WFI 1011 1111 0011 0000 */
  36. DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop),
  37. /* Unassigned hints 1011 1111 xxxx 0000 */
  38. DECODE_REJECT (0xff0f, 0xbf00),
  39. DECODE_END
  40. };
  41. const union decode_item kprobe_decode_thumb16_table[] = {
  42. /*
  43. * Miscellaneous 16-bit instructions
  44. * 1011 xxxx xxxx xxxx
  45. */
  46. DECODE_TABLE (0xf000, 0xb000, t16_table_1011),
  47. DECODE_END
  48. };
  49. static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
  50. {
  51. if (unlikely(in_it_block(cpsr)))
  52. return kprobe_condition_checks[current_cond(cpsr)](cpsr);
  53. return true;
  54. }
  55. static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
  56. {
  57. regs->ARM_pc += 2;
  58. p->ainsn.insn_handler(p, regs);
  59. regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
  60. }
  61. static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
  62. {
  63. regs->ARM_pc += 4;
  64. p->ainsn.insn_handler(p, regs);
  65. regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
  66. }
  67. enum kprobe_insn __kprobes
  68. thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
  69. {
  70. asi->insn_singlestep = thumb16_singlestep;
  71. asi->insn_check_cc = thumb_check_cc;
  72. return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
  73. }
  74. enum kprobe_insn __kprobes
  75. thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
  76. {
  77. asi->insn_singlestep = thumb32_singlestep;
  78. asi->insn_check_cc = thumb_check_cc;
  79. return INSN_REJECTED;
  80. }