kprobes-thumb.c revision b48354d3584e93284fba2ee99f6f9f44d18e4f83
12437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst/* 22437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * arch/arm/kernel/kprobes-thumb.c 32437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * 42437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. 52437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * 62437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * This program is free software; you can redistribute it and/or modify 72437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * it under the terms of the GNU General Public License version 2 as 82437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * published by the Free Software Foundation. 92437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst */ 102437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 112437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kernel.h> 122437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kprobes.h> 132437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 142437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include "kprobes.h" 152437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 16eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst 17eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst/* 18eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * True if current instruction is in an IT block. 19eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst */ 20eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000) 21eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst 22eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst/* 23eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * Return the condition code to check for the currently executing instruction. 24eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if 25eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst * in_it_block returns true. 26eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst */ 27eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst#define current_cond(cpsr) ((cpsr >> 12) & 0xf) 28eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst 29a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst/* 30a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * Return the PC value for a probe in thumb code. 31a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * This is the address of the probed instruction plus 4. 32a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * We subtract one because the address will have bit zero set to indicate 33a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * a pointer to thumb code. 34a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst */ 35a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurststatic inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) 36a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst{ 37a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst return (unsigned long)p->addr - 1 + 4; 38a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst} 39a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 40eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurststatic enum kprobe_insn __kprobes 41eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurstt32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) 42eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst{ 43eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); 44eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 45eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* Fixup modified instruction to have halfwords in correct order...*/ 46eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst insn = asi->insn[0]; 47eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst ((u16 *)asi->insn)[0] = insn >> 16; 48eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst ((u16 *)asi->insn)[1] = insn & 0xffff; 49eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 50eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst return ret; 51eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst} 52eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 53b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurststatic void __kprobes 54b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurstt32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) 55b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst{ 56b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst kprobe_opcode_t insn = p->opcode; 57b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst unsigned long pc = thumb_probe_pc(p) & ~3; 58b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rt1 = (insn >> 12) & 0xf; 59b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rt2 = (insn >> 8) & 0xf; 60b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rn = (insn >> 16) & 0xf; 61b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 62b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rt1v asm("r0") = regs->uregs[rt1]; 63b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rt2v asm("r1") = regs->uregs[rt2]; 64b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rnv asm("r2") = (rn == 15) ? pc 65b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : regs->uregs[rn]; 66b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 67b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst __asm__ __volatile__ ( 68b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst "blx %[fn]" 69b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) 70b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn) 71b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : "lr", "memory", "cc" 72b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst ); 73b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 74b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst if (rn != 15) 75b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rn] = rnv; /* Writeback base register */ 76b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rt1] = rt1v; 77b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rt2] = rt2v; 78b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst} 79b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 80eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurststatic const union decode_item t32_table_1110_100x_x0xx[] = { 81eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* Load/store multiple instructions */ 82eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 83eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */ 84eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xfe4f0000, 0xe80f0000), 85eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 86eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */ 87eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */ 88eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xffc00000, 0xe8000000), 89eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */ 90eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */ 91eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xffc00000, 0xe9800000), 92eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 93eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */ 94eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xfe508000, 0xe8008000), 95eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */ 96eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xfe50c000, 0xe810c000), 97eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */ 98eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_REJECT (0xfe402000, 0xe8002000), 99eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 100eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */ 101eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */ 102eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */ 103eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */ 104eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm), 105eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 106eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_END 107eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst}; 108eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 109b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurststatic const union decode_item t32_table_1110_100x_x1xx[] = { 110b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* Load/store dual, load/store exclusive, table branch */ 111b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 112b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */ 113b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */ 114b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst DECODE_OR (0xff600000, 0xe8600000), 115b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ 116b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ 117b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, 118b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), 119b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 120b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ 121b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ 122b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ 123b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */ 124b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */ 125b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */ 126b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */ 127b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */ 128b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* And unallocated instructions... */ 129b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst DECODE_END 130b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst}; 131b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 132f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurststatic const union decode_item t32_table_1111_0xxx___1[] = { 133f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* Branches and miscellaneous control */ 134f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 135f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */ 136f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_OR (0xfff0d7ff, 0xf3a08001), 137f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */ 138f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none), 139f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */ 140f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */ 141f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */ 142f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop), 143f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 144f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_END 145f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst}; 146f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 147f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurstconst union decode_item kprobe_decode_thumb32_table[] = { 148f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 149f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst /* 150eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst * Load/store multiple instructions 151eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx 152eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst */ 153eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx), 154eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 155eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* 156b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst * Load/store dual, load/store exclusive, table branch 157b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx 158b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst */ 159b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx), 160b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 161b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst /* 162f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst * Branches and miscellaneous control 163f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx 164f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst */ 165f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1), 166f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 167f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst DECODE_END 168f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst}; 169f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst 170a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurststatic void __kprobes 171a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurstt16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) 172a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst{ 173a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst kprobe_opcode_t insn = p->opcode; 174a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst unsigned long pc = thumb_probe_pc(p); 175a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst int rm = (insn >> 3) & 0xf; 176a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; 177a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 178a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst if (insn & (1 << 7)) /* BLX ? */ 179a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst regs->ARM_lr = (unsigned long)p->addr + 2; 180a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 181a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst bx_write_pc(rmv, regs); 182a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst} 183a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 184f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurststatic void __kprobes 185f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurstt16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) 186f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{ 187f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst kprobe_opcode_t insn = p->opcode; 188f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3); 189f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst long index = insn & 0xff; 190f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst int rt = (insn >> 8) & 0x7; 191f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst regs->uregs[rt] = base[index]; 192f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst} 193f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 194f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurststatic void __kprobes 195f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurstt16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) 196f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{ 197f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst kprobe_opcode_t insn = p->opcode; 198f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst unsigned long* base = (unsigned long *)regs->ARM_sp; 199f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst long index = insn & 0xff; 200f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst int rt = (insn >> 8) & 0x7; 201f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst if (insn & 0x800) /* LDR */ 202f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst regs->uregs[rt] = base[index]; 203f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst else /* STR */ 204f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst base[index] = regs->uregs[rt]; 205f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst} 206f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 2072f335829040cb16d0640e87121bef208894d4934Jon Medhurststatic void __kprobes 2082f335829040cb16d0640e87121bef208894d4934Jon Medhurstt16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) 2092f335829040cb16d0640e87121bef208894d4934Jon Medhurst{ 2102f335829040cb16d0640e87121bef208894d4934Jon Medhurst kprobe_opcode_t insn = p->opcode; 2112f335829040cb16d0640e87121bef208894d4934Jon Medhurst unsigned long base = (insn & 0x800) ? regs->ARM_sp 2122f335829040cb16d0640e87121bef208894d4934Jon Medhurst : (thumb_probe_pc(p) & ~3); 2132f335829040cb16d0640e87121bef208894d4934Jon Medhurst long offset = insn & 0xff; 2142f335829040cb16d0640e87121bef208894d4934Jon Medhurst int rt = (insn >> 8) & 0x7; 2152f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->uregs[rt] = base + offset * 4; 2162f335829040cb16d0640e87121bef208894d4934Jon Medhurst} 2172f335829040cb16d0640e87121bef208894d4934Jon Medhurst 2182f335829040cb16d0640e87121bef208894d4934Jon Medhurststatic void __kprobes 2192f335829040cb16d0640e87121bef208894d4934Jon Medhurstt16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) 2202f335829040cb16d0640e87121bef208894d4934Jon Medhurst{ 2212f335829040cb16d0640e87121bef208894d4934Jon Medhurst kprobe_opcode_t insn = p->opcode; 2222f335829040cb16d0640e87121bef208894d4934Jon Medhurst long imm = insn & 0x7f; 2232f335829040cb16d0640e87121bef208894d4934Jon Medhurst if (insn & 0x80) /* SUB */ 2242f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->ARM_sp -= imm * 4; 2252f335829040cb16d0640e87121bef208894d4934Jon Medhurst else /* ADD */ 2262f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->ARM_sp += imm * 4; 2272f335829040cb16d0640e87121bef208894d4934Jon Medhurst} 2282f335829040cb16d0640e87121bef208894d4934Jon Medhurst 22932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurststatic void __kprobes 23032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurstt16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) 23132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst{ 23232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst kprobe_opcode_t insn = p->opcode; 23332818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst int rn = insn & 0x7; 23432818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; 23532818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst if (nonzero & 0x800) { 23632818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst long i = insn & 0x200; 23732818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst long imm5 = insn & 0xf8; 23832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst unsigned long pc = thumb_probe_pc(p); 23932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); 24032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst } 24132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst} 24232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst 2435b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic void __kprobes 2445b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_simulate_it(struct kprobe *p, struct pt_regs *regs) 2455b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 2465b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst /* 2475b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * The 8 IT state bits are split into two parts in CPSR: 2485b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * ITSTATE<1:0> are in CPSR<26:25> 2495b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * ITSTATE<7:2> are in CPSR<15:10> 2505b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * The new IT state is in the lower byte of insn. 2515b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst */ 2525b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst kprobe_opcode_t insn = p->opcode; 2535b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst unsigned long cpsr = regs->ARM_cpsr; 2545b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr &= ~PSR_IT_MASK; 2555b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr |= (insn & 0xfc) << 8; 2565b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr |= (insn & 0x03) << 25; 2575b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst regs->ARM_cpsr = cpsr; 2585b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 2595b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 2605b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic void __kprobes 2615b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_singlestep_it(struct kprobe *p, struct pt_regs *regs) 2625b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 2635b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst regs->ARM_pc += 2; 2645b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst t16_simulate_it(p, regs); 2655b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 2665b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 2675b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurststatic enum kprobe_insn __kprobes 2685b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurstt16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi) 2695b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 2705b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst asi->insn_singlestep = t16_singlestep_it; 2715b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst return INSN_GOOD_NO_SLOT; 2725b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 2735b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 274396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic void __kprobes 275396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) 276396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 277396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst kprobe_opcode_t insn = p->opcode; 278396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst unsigned long pc = thumb_probe_pc(p); 279396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst long offset = insn & 0x7f; 280396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst offset -= insn & 0x80; /* Apply sign bit */ 281396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst regs->ARM_pc = pc + (offset * 2); 282396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 283396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 284396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic enum kprobe_insn __kprobes 285396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) 286396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 287396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst int cc = (insn >> 8) & 0xf; 288396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst asi->insn_check_cc = kprobe_condition_checks[cc]; 289396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst asi->insn_handler = t16_simulate_cond_branch; 290396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst return INSN_GOOD_NO_SLOT; 291396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 292396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 293396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurststatic void __kprobes 294396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurstt16_simulate_branch(struct kprobe *p, struct pt_regs *regs) 295396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 296396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst kprobe_opcode_t insn = p->opcode; 297396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst unsigned long pc = thumb_probe_pc(p); 298396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst long offset = insn & 0x3ff; 299396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst offset -= insn & 0x400; /* Apply sign bit */ 300396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst regs->ARM_pc = pc + (offset * 2); 301396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 302396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 30302d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic unsigned long __kprobes 30402d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) 30502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 30602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst unsigned long oldcpsr = regs->ARM_cpsr; 30702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst unsigned long newcpsr; 30802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 30902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst __asm__ __volatile__ ( 31002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "msr cpsr_fs, %[oldcpsr] \n\t" 31102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "ldmia %[regs], {r0-r7} \n\t" 31202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "blx %[fn] \n\t" 31302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "stmia %[regs], {r0-r7} \n\t" 31402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "mrs %[newcpsr], cpsr \n\t" 31502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : [newcpsr] "=r" (newcpsr) 31602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), 31702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst [fn] "r" (p->ainsn.insn_fn) 31802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 31902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "lr", "memory", "cc" 32002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst ); 32102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 32202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK); 32302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 32402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 32502d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic void __kprobes 32602d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) 32702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 32802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst regs->ARM_cpsr = t16_emulate_loregs(p, regs); 32902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 33002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 33102d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic void __kprobes 33202d194f64772aee91e7319ca033905b0bafee04cJon Medhurstt16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) 33302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 33402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst unsigned long cpsr = t16_emulate_loregs(p, regs); 33502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst if (!in_it_block(cpsr)) 33602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst regs->ARM_cpsr = cpsr; 33702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 33802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 3393b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurststatic void __kprobes 3403b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurstt16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) 3413b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{ 3423b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst kprobe_opcode_t insn = p->opcode; 3433b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst unsigned long pc = thumb_probe_pc(p); 3443b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); 3453b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst int rm = (insn >> 3) & 0xf; 3463b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3473b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst register unsigned long rdnv asm("r1"); 3483b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst register unsigned long rmv asm("r0"); 3493b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst unsigned long cpsr = regs->ARM_cpsr; 3503b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3513b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rdnv = (rdn == 15) ? pc : regs->uregs[rdn]; 3523b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rmv = (rm == 15) ? pc : regs->uregs[rm]; 3533b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3543b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst __asm__ __volatile__ ( 3553b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "msr cpsr_fs, %[cpsr] \n\t" 3563b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "blx %[fn] \n\t" 3573b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "mrs %[cpsr], cpsr \n\t" 3583b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst : "=r" (rdnv), [cpsr] "=r" (cpsr) 3593b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) 3603b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst : "lr", "memory", "cc" 3613b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst ); 3623b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3633b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst if (rdn == 15) 3643b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rdnv &= ~1; 3653b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3663b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst regs->uregs[rdn] = rdnv; 3673b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 3683b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst} 3693b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 3703b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurststatic enum kprobe_insn __kprobes 3713b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurstt16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) 3723b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{ 3733b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst insn &= ~0x00ff; 3743b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ 3753b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst ((u16 *)asi->insn)[0] = insn; 3763b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst asi->insn_handler = t16_emulate_hiregs; 3773b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst return INSN_GOOD; 3783b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst} 3793b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 380fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes 381fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_push(struct kprobe *p, struct pt_regs *regs) 382fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 383fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 384fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 385fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r8, [%[regs], #14*4] \n\t" 386fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 387fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 388fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 389fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : 390fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 391fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", 392fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 393fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 394fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 395fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 396fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic enum kprobe_insn __kprobes 397fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) 398fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 399fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* 400fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" 401fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * and call it with R9=SP and LR in the register list represented 402fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * by R8. 403fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst */ 404fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */ 405fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ 406fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst asi->insn_handler = t16_emulate_push; 407fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst return INSN_GOOD; 408fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 409fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 410fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes 411fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) 412fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 413fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 414fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 415fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 416fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 417fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "stmia %[regs], {r0-r7} \n\t" 418fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 419fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : 420fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 421fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 422fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 423fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 424fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 425fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 426fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic void __kprobes 427fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) 428fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 429fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst register unsigned long pc asm("r8"); 430fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 431fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 432fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 433fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 434fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 435fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "stmia %[regs], {r0-r7} \n\t" 436fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 437fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "=r" (pc) 438fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) 439fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 440fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 441fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 442fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 443fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst bx_write_pc(pc, regs); 444fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 445fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 446fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurststatic enum kprobe_insn __kprobes 447fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurstt16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) 448fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 449fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* 450fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" 451fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * and call it with R9=SP and PC in the register list represented 452fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * by R8. 453fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst */ 454fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */ 455fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ 456fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc 457fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : t16_emulate_pop_nopc; 458fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst return INSN_GOOD; 459fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 460fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 4613f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurststatic const union decode_item t16_table_1011[] = { 4623f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* Miscellaneous 16-bit instructions */ 4633f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 4642f335829040cb16d0640e87121bef208894d4934Jon Medhurst /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */ 4652f335829040cb16d0640e87121bef208894d4934Jon Medhurst /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */ 4662f335829040cb16d0640e87121bef208894d4934Jon Medhurst DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm), 4672f335829040cb16d0640e87121bef208894d4934Jon Medhurst 46832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* CBZ 1011 00x1 xxxx xxxx */ 46932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* CBNZ 1011 10x1 xxxx xxxx */ 47032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz), 47132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst 47232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* SXTH 1011 0010 00xx xxxx */ 47332818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* SXTB 1011 0010 01xx xxxx */ 47432818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* UXTH 1011 0010 10xx xxxx */ 47532818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* UXTB 1011 0010 11xx xxxx */ 47632818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* REV 1011 1010 00xx xxxx */ 47732818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* REV16 1011 1010 01xx xxxx */ 47832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* ??? 1011 1010 10xx xxxx */ 47932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst /* REVSH 1011 1010 11xx xxxx */ 48032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst DECODE_REJECT (0xffc0, 0xba80), 48132818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags), 48232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst 483fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* PUSH 1011 010x xxxx xxxx */ 484fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push), 485fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* POP 1011 110x xxxx xxxx */ 486fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop), 487fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 4883f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* 4893f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst * If-Then, and hints 4903f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst * 1011 1111 xxxx xxxx 4913f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst */ 4923f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 4933f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* YIELD 1011 1111 0001 0000 */ 4943f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_OR (0xffff, 0xbf10), 4953f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* SEV 1011 1111 0100 0000 */ 4963f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none), 4973f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* NOP 1011 1111 0000 0000 */ 4983f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* WFE 1011 1111 0010 0000 */ 4993f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* WFI 1011 1111 0011 0000 */ 5003f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop), 5013f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* Unassigned hints 1011 1111 xxxx 0000 */ 5023f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_REJECT (0xff0f, 0xbf00), 5035b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst /* IT 1011 1111 xxxx xxxx */ 5045b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it), 5053f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 5060a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst /* SETEND 1011 0110 010x xxxx */ 5070a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst /* CPS 1011 0110 011x xxxx */ 5080a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst /* BKPT 1011 1110 xxxx xxxx */ 5090a188ccb5eceb58101fcc11b3ec2d860ccbf92a3Jon Medhurst /* And unallocated instructions... */ 5103f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_END 5113f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst}; 5123f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 5133f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurstconst union decode_item kprobe_decode_thumb16_table[] = { 5143f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 5153f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst /* 51602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst * Shift (immediate), add, subtract, move, and compare 51702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst * 00xx xxxx xxxx xxxx 51802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst */ 51902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 52002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* CMP (immediate) 0010 1xxx xxxx xxxx */ 52102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags), 52202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 52302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ADD (register) 0001 100x xxxx xxxx */ 52402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* SUB (register) 0001 101x xxxx xxxx */ 52502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* LSL (immediate) 0000 0xxx xxxx xxxx */ 52602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* LSR (immediate) 0000 1xxx xxxx xxxx */ 52702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ASR (immediate) 0001 0xxx xxxx xxxx */ 52802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */ 52902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */ 53002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* MOV (immediate) 0010 0xxx xxxx xxxx */ 53102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ 53202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ 53302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags), 53402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 53502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* 53602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst * 16-bit Thumb data-processing instructions 53702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst * 0100 00xx xxxx xxxx 53802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst */ 53902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 54002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* TST (register) 0100 0010 00xx xxxx */ 54102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags), 54202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* CMP (register) 0100 0010 10xx xxxx */ 54302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* CMN (register) 0100 0010 11xx xxxx */ 54402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags), 54502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* AND (register) 0100 0000 00xx xxxx */ 54602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* EOR (register) 0100 0000 01xx xxxx */ 54702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* LSL (register) 0100 0000 10xx xxxx */ 54802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* LSR (register) 0100 0000 11xx xxxx */ 54902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ASR (register) 0100 0001 00xx xxxx */ 55002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ADC (register) 0100 0001 01xx xxxx */ 55102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* SBC (register) 0100 0001 10xx xxxx */ 55202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ROR (register) 0100 0001 11xx xxxx */ 55302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* RSB (immediate) 0100 0010 01xx xxxx */ 55402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* ORR (register) 0100 0011 00xx xxxx */ 55502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* MUL 0100 0011 00xx xxxx */ 55602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* BIC (register) 0100 0011 10xx xxxx */ 55702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* MVN (register) 0100 0011 10xx xxxx */ 55802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags), 55902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 56002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst /* 561a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * Special data instructions and branch and exchange 562a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst * 0100 01xx xxxx xxxx 563a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst */ 564a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 565a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst /* BLX pc 0100 0111 1111 1xxx */ 566a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst DECODE_REJECT (0xfff8, 0x47f8), 567a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 568a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst /* BX (register) 0100 0111 0xxx xxxx */ 569a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst /* BLX (register) 0100 0111 1xxx xxxx */ 570a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx), 571a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 5723b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst /* ADD pc, pc 0100 0100 1111 1111 */ 5733b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst DECODE_REJECT (0xffff, 0x44ff), 5743b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 5753b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst /* ADD (register) 0100 0100 xxxx xxxx */ 5763b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst /* CMP (register) 0100 0101 xxxx xxxx */ 5773b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst /* MOV (register) 0100 0110 xxxx xxxx */ 5783b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs), 5793b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 580a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst /* 581f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * Load from Literal Pool 582f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * LDR (literal) 0100 1xxx xxxx xxxx 583f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst */ 584f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal), 585f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 586f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* 587f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * 16-bit Thumb Load/store instructions 588f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * 0101 xxxx xxxx xxxx 589f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * 011x xxxx xxxx xxxx 590f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst * 100x xxxx xxxx xxxx 591f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst */ 592f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 593f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STR (register) 0101 000x xxxx xxxx */ 594f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STRH (register) 0101 001x xxxx xxxx */ 595f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STRB (register) 0101 010x xxxx xxxx */ 596f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRSB (register) 0101 011x xxxx xxxx */ 597f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDR (register) 0101 100x xxxx xxxx */ 598f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRH (register) 0101 101x xxxx xxxx */ 599f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRB (register) 0101 110x xxxx xxxx */ 600f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRSH (register) 0101 111x xxxx xxxx */ 601f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */ 602f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */ 603f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */ 604f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */ 605f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags), 606f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ 607f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ 608f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags), 609f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ 610f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ 611f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative), 612f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 613f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* 6142f335829040cb16d0640e87121bef208894d4934Jon Medhurst * Generate PC-/SP-relative address 6152f335829040cb16d0640e87121bef208894d4934Jon Medhurst * ADR (literal) 1010 0xxx xxxx xxxx 6162f335829040cb16d0640e87121bef208894d4934Jon Medhurst * ADD (SP plus immediate) 1010 1xxx xxxx xxxx 6172f335829040cb16d0640e87121bef208894d4934Jon Medhurst */ 6182f335829040cb16d0640e87121bef208894d4934Jon Medhurst DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr), 6192f335829040cb16d0640e87121bef208894d4934Jon Medhurst 6202f335829040cb16d0640e87121bef208894d4934Jon Medhurst /* 6213f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst * Miscellaneous 16-bit instructions 6223f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst * 1011 xxxx xxxx xxxx 6233f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst */ 6243f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_TABLE (0xf000, 0xb000, t16_table_1011), 6253f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 626f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* STM 1100 0xxx xxxx xxxx */ 627f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst /* LDM 1100 1xxx xxxx xxxx */ 628f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags), 629f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 630444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst /* 631444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst * Conditional branch, and Supervisor Call 632444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst */ 633444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst 634444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst /* Permanently UNDEFINED 1101 1110 xxxx xxxx */ 635444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst /* SVC 1101 1111 xxxx xxxx */ 636444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst DECODE_REJECT (0xfe00, 0xde00), 637444956677eccfcdfe05de761e1286f62c423ce88Jon Medhurst 638396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst /* Conditional branch 1101 xxxx xxxx xxxx */ 639396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch), 640396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 641396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst /* 642396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst * Unconditional branch 643396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst * B 1110 0xxx xxxx xxxx 644396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst */ 645396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch), 646396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 6473f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst DECODE_END 6483f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst}; 6493f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst 650eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurststatic unsigned long __kprobes thumb_check_cc(unsigned long cpsr) 651eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst{ 652eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst if (unlikely(in_it_block(cpsr))) 653eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst return kprobe_condition_checks[current_cond(cpsr)](cpsr); 654eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst return true; 655eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst} 656eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst 657c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurststatic void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) 658c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst{ 659c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst regs->ARM_pc += 2; 660c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst p->ainsn.insn_handler(p, regs); 661c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst regs->ARM_cpsr = it_advance(regs->ARM_cpsr); 662c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst} 663c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst 664c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurststatic void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) 665c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst{ 666c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst regs->ARM_pc += 4; 667c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst p->ainsn.insn_handler(p, regs); 668c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst regs->ARM_cpsr = it_advance(regs->ARM_cpsr); 669c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst} 670c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst 6712437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstenum kprobe_insn __kprobes 6722437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstthumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) 6732437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst{ 674c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst asi->insn_singlestep = thumb16_singlestep; 675eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst asi->insn_check_cc = thumb_check_cc; 6763f92dfed6a9a5f490128c8e7cc6a64dfe412994fJon Medhurst return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true); 6772437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst} 6782437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 6792437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstenum kprobe_insn __kprobes 6802437170710c4a3dee137a65623960aa7ac82a32eJon Medhurstthumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) 6812437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst{ 682c6a7d97d57ef41477a85f4c0f48ea5243132ee1fJon Medhurst asi->insn_singlestep = thumb32_singlestep; 683eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst asi->insn_check_cc = thumb_check_cc; 684f39ca8b488a6c1e8db47746e1cdb841a6999edd7Jon Medhurst return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true); 6852437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst} 686