Path: blob/master/arch/arm/kernel/kprobes-decode.c
10817 views
/*1* arch/arm/kernel/kprobes-decode.c2*3* Copyright (C) 2006, 2007 Motorola Inc.4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License version 2 as7* published by the Free Software Foundation.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* General Public License for more details.13*/1415/*16* We do not have hardware single-stepping on ARM, This17* effort is further complicated by the ARM not having a18* "next PC" register. Instructions that change the PC19* can't be safely single-stepped in a MP environment, so20* we have a lot of work to do:21*22* In the prepare phase:23* *) If it is an instruction that does anything24* with the CPU mode, we reject it for a kprobe.25* (This is out of laziness rather than need. The26* instructions could be simulated.)27*28* *) Otherwise, decode the instruction rewriting its29* registers to take fixed, ordered registers and30* setting a handler for it to run the instruction.31*32* In the execution phase by an instruction's handler:33*34* *) If the PC is written to by the instruction, the35* instruction must be fully simulated in software.36*37* *) Otherwise, a modified form of the instruction is38* directly executed. Its handler calls the39* instruction in insn[0]. In insn[1] is a40* "mov pc, lr" to return.41*42* Before calling, load up the reordered registers43* from the original instruction's registers. If one44* of the original input registers is the PC, compute45* and adjust the appropriate input register.46*47* After call completes, copy the output registers to48* the original instruction's original registers.49*50* We don't use a real breakpoint instruction since that51* would have us in the kernel go from SVC mode to SVC52* mode losing the link register. Instead we use an53* undefined instruction. To simplify processing, the54* undefined instruction used for kprobes must be reserved55* exclusively for kprobes use.56*57* TODO: ifdef out some instruction decoding based on architecture.58*/5960#include <linux/kernel.h>61#include <linux/kprobes.h>6263#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))6465#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)6667#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))6869/*70* Test if load/store instructions writeback the address register.71* if P (bit 24) == 0 or W (bit 21) == 172*/73#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)7475#define PSR_fs (PSR_f|PSR_s)7677#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */7879typedef long (insn_0arg_fn_t)(void);80typedef long (insn_1arg_fn_t)(long);81typedef long (insn_2arg_fn_t)(long, long);82typedef long (insn_3arg_fn_t)(long, long, long);83typedef long (insn_4arg_fn_t)(long, long, long, long);84typedef long long (insn_llret_0arg_fn_t)(void);85typedef long long (insn_llret_3arg_fn_t)(long, long, long);86typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);8788union reg_pair {89long long dr;90#ifdef __LITTLE_ENDIAN91struct { long r0, r1; };92#else93struct { long r1, r0; };94#endif95};9697/*98* For STR and STM instructions, an ARM core may choose to use either99* a +8 or a +12 displacement from the current instruction's address.100* Whichever value is chosen for a given core, it must be the same for101* both instructions and may not change. This function measures it.102*/103104static int str_pc_offset;105106static void __init find_str_pc_offset(void)107{108int addr, scratch, ret;109110__asm__ (111"sub %[ret], pc, #4 \n\t"112"str pc, %[addr] \n\t"113"ldr %[scr], %[addr] \n\t"114"sub %[ret], %[scr], %[ret] \n\t"115: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));116117str_pc_offset = ret;118}119120/*121* The insnslot_?arg_r[w]flags() functions below are to keep the122* msr -> *fn -> mrs instruction sequences indivisible so that123* the state of the CPSR flags aren't inadvertently modified124* just before or just after the call.125*/126127static inline long __kprobes128insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)129{130register long ret asm("r0");131132__asm__ __volatile__ (133"msr cpsr_fs, %[cpsr] \n\t"134"mov lr, pc \n\t"135"mov pc, %[fn] \n\t"136: "=r" (ret)137: [cpsr] "r" (cpsr), [fn] "r" (fn)138: "lr", "cc"139);140return ret;141}142143static inline long long __kprobes144insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)145{146register long ret0 asm("r0");147register long ret1 asm("r1");148union reg_pair fnr;149150__asm__ __volatile__ (151"msr cpsr_fs, %[cpsr] \n\t"152"mov lr, pc \n\t"153"mov pc, %[fn] \n\t"154: "=r" (ret0), "=r" (ret1)155: [cpsr] "r" (cpsr), [fn] "r" (fn)156: "lr", "cc"157);158fnr.r0 = ret0;159fnr.r1 = ret1;160return fnr.dr;161}162163static inline long __kprobes164insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)165{166register long rr0 asm("r0") = r0;167register long ret asm("r0");168169__asm__ __volatile__ (170"msr cpsr_fs, %[cpsr] \n\t"171"mov lr, pc \n\t"172"mov pc, %[fn] \n\t"173: "=r" (ret)174: "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)175: "lr", "cc"176);177return ret;178}179180static inline long __kprobes181insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)182{183register long rr0 asm("r0") = r0;184register long rr1 asm("r1") = r1;185register long ret asm("r0");186187__asm__ __volatile__ (188"msr cpsr_fs, %[cpsr] \n\t"189"mov lr, pc \n\t"190"mov pc, %[fn] \n\t"191: "=r" (ret)192: "0" (rr0), "r" (rr1),193[cpsr] "r" (cpsr), [fn] "r" (fn)194: "lr", "cc"195);196return ret;197}198199static inline long __kprobes200insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)201{202register long rr0 asm("r0") = r0;203register long rr1 asm("r1") = r1;204register long rr2 asm("r2") = r2;205register long ret asm("r0");206207__asm__ __volatile__ (208"msr cpsr_fs, %[cpsr] \n\t"209"mov lr, pc \n\t"210"mov pc, %[fn] \n\t"211: "=r" (ret)212: "0" (rr0), "r" (rr1), "r" (rr2),213[cpsr] "r" (cpsr), [fn] "r" (fn)214: "lr", "cc"215);216return ret;217}218219static inline long long __kprobes220insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,221insn_llret_3arg_fn_t *fn)222{223register long rr0 asm("r0") = r0;224register long rr1 asm("r1") = r1;225register long rr2 asm("r2") = r2;226register long ret0 asm("r0");227register long ret1 asm("r1");228union reg_pair fnr;229230__asm__ __volatile__ (231"msr cpsr_fs, %[cpsr] \n\t"232"mov lr, pc \n\t"233"mov pc, %[fn] \n\t"234: "=r" (ret0), "=r" (ret1)235: "0" (rr0), "r" (rr1), "r" (rr2),236[cpsr] "r" (cpsr), [fn] "r" (fn)237: "lr", "cc"238);239fnr.r0 = ret0;240fnr.r1 = ret1;241return fnr.dr;242}243244static inline long __kprobes245insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,246insn_4arg_fn_t *fn)247{248register long rr0 asm("r0") = r0;249register long rr1 asm("r1") = r1;250register long rr2 asm("r2") = r2;251register long rr3 asm("r3") = r3;252register long ret asm("r0");253254__asm__ __volatile__ (255"msr cpsr_fs, %[cpsr] \n\t"256"mov lr, pc \n\t"257"mov pc, %[fn] \n\t"258: "=r" (ret)259: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),260[cpsr] "r" (cpsr), [fn] "r" (fn)261: "lr", "cc"262);263return ret;264}265266static inline long __kprobes267insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)268{269register long rr0 asm("r0") = r0;270register long ret asm("r0");271long oldcpsr = *cpsr;272long newcpsr;273274__asm__ __volatile__ (275"msr cpsr_fs, %[oldcpsr] \n\t"276"mov lr, pc \n\t"277"mov pc, %[fn] \n\t"278"mrs %[newcpsr], cpsr \n\t"279: "=r" (ret), [newcpsr] "=r" (newcpsr)280: "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)281: "lr", "cc"282);283*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);284return ret;285}286287static inline long __kprobes288insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)289{290register long rr0 asm("r0") = r0;291register long rr1 asm("r1") = r1;292register long ret asm("r0");293long oldcpsr = *cpsr;294long newcpsr;295296__asm__ __volatile__ (297"msr cpsr_fs, %[oldcpsr] \n\t"298"mov lr, pc \n\t"299"mov pc, %[fn] \n\t"300"mrs %[newcpsr], cpsr \n\t"301: "=r" (ret), [newcpsr] "=r" (newcpsr)302: "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)303: "lr", "cc"304);305*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);306return ret;307}308309static inline long __kprobes310insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,311insn_3arg_fn_t *fn)312{313register long rr0 asm("r0") = r0;314register long rr1 asm("r1") = r1;315register long rr2 asm("r2") = r2;316register long ret asm("r0");317long oldcpsr = *cpsr;318long newcpsr;319320__asm__ __volatile__ (321"msr cpsr_fs, %[oldcpsr] \n\t"322"mov lr, pc \n\t"323"mov pc, %[fn] \n\t"324"mrs %[newcpsr], cpsr \n\t"325: "=r" (ret), [newcpsr] "=r" (newcpsr)326: "0" (rr0), "r" (rr1), "r" (rr2),327[oldcpsr] "r" (oldcpsr), [fn] "r" (fn)328: "lr", "cc"329);330*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);331return ret;332}333334static inline long __kprobes335insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,336insn_4arg_fn_t *fn)337{338register long rr0 asm("r0") = r0;339register long rr1 asm("r1") = r1;340register long rr2 asm("r2") = r2;341register long rr3 asm("r3") = r3;342register long ret asm("r0");343long oldcpsr = *cpsr;344long newcpsr;345346__asm__ __volatile__ (347"msr cpsr_fs, %[oldcpsr] \n\t"348"mov lr, pc \n\t"349"mov pc, %[fn] \n\t"350"mrs %[newcpsr], cpsr \n\t"351: "=r" (ret), [newcpsr] "=r" (newcpsr)352: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),353[oldcpsr] "r" (oldcpsr), [fn] "r" (fn)354: "lr", "cc"355);356*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);357return ret;358}359360static inline long long __kprobes361insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,362insn_llret_4arg_fn_t *fn)363{364register long rr0 asm("r0") = r0;365register long rr1 asm("r1") = r1;366register long rr2 asm("r2") = r2;367register long rr3 asm("r3") = r3;368register long ret0 asm("r0");369register long ret1 asm("r1");370long oldcpsr = *cpsr;371long newcpsr;372union reg_pair fnr;373374__asm__ __volatile__ (375"msr cpsr_fs, %[oldcpsr] \n\t"376"mov lr, pc \n\t"377"mov pc, %[fn] \n\t"378"mrs %[newcpsr], cpsr \n\t"379: "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)380: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),381[oldcpsr] "r" (oldcpsr), [fn] "r" (fn)382: "lr", "cc"383);384*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);385fnr.r0 = ret0;386fnr.r1 = ret1;387return fnr.dr;388}389390/*391* To avoid the complications of mimicing single-stepping on a392* processor without a Next-PC or a single-step mode, and to393* avoid having to deal with the side-effects of boosting, we394* simulate or emulate (almost) all ARM instructions.395*396* "Simulation" is where the instruction's behavior is duplicated in397* C code. "Emulation" is where the original instruction is rewritten398* and executed, often by altering its registers.399*400* By having all behavior of the kprobe'd instruction completed before401* returning from the kprobe_handler(), all locks (scheduler and402* interrupt) can safely be released. There is no need for secondary403* breakpoints, no race with MP or preemptable kernels, nor having to404* clean up resources counts at a later time impacting overall system405* performance. By rewriting the instruction, only the minimum registers406* need to be loaded and saved back optimizing performance.407*408* Calling the insnslot_*_rwflags version of a function doesn't hurt409* anything even when the CPSR flags aren't updated by the410* instruction. It's just a little slower in return for saving411* a little space by not having a duplicate function that doesn't412* update the flags. (The same optimization can be said for413* instructions that do or don't perform register writeback)414* Also, instructions can either read the flags, only write the415* flags, or read and write the flags. To save combinations416* rather than for sheer performance, flag functions just assume417* read and write of flags.418*/419420static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)421{422kprobe_opcode_t insn = p->opcode;423long iaddr = (long)p->addr;424int disp = branch_displacement(insn);425426if (insn & (1 << 24))427regs->ARM_lr = iaddr + 4;428429regs->ARM_pc = iaddr + 8 + disp;430}431432static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)433{434kprobe_opcode_t insn = p->opcode;435long iaddr = (long)p->addr;436int disp = branch_displacement(insn);437438regs->ARM_lr = iaddr + 4;439regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);440regs->ARM_cpsr |= PSR_T_BIT;441}442443static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)444{445kprobe_opcode_t insn = p->opcode;446int rm = insn & 0xf;447long rmv = regs->uregs[rm];448449if (insn & (1 << 5))450regs->ARM_lr = (long)p->addr + 4;451452regs->ARM_pc = rmv & ~0x1;453regs->ARM_cpsr &= ~PSR_T_BIT;454if (rmv & 0x1)455regs->ARM_cpsr |= PSR_T_BIT;456}457458static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)459{460kprobe_opcode_t insn = p->opcode;461int rd = (insn >> 12) & 0xf;462unsigned long mask = 0xf8ff03df; /* Mask out execution state */463regs->uregs[rd] = regs->ARM_cpsr & mask;464}465466static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)467{468kprobe_opcode_t insn = p->opcode;469int rn = (insn >> 16) & 0xf;470int lbit = insn & (1 << 20);471int wbit = insn & (1 << 21);472int ubit = insn & (1 << 23);473int pbit = insn & (1 << 24);474long *addr = (long *)regs->uregs[rn];475int reg_bit_vector;476int reg_count;477478reg_count = 0;479reg_bit_vector = insn & 0xffff;480while (reg_bit_vector) {481reg_bit_vector &= (reg_bit_vector - 1);482++reg_count;483}484485if (!ubit)486addr -= reg_count;487addr += (!pbit == !ubit);488489reg_bit_vector = insn & 0xffff;490while (reg_bit_vector) {491int reg = __ffs(reg_bit_vector);492reg_bit_vector &= (reg_bit_vector - 1);493if (lbit)494regs->uregs[reg] = *addr++;495else496*addr++ = regs->uregs[reg];497}498499if (wbit) {500if (!ubit)501addr -= reg_count;502addr -= (!pbit == !ubit);503regs->uregs[rn] = (long)addr;504}505}506507static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)508{509regs->ARM_pc = (long)p->addr + str_pc_offset;510simulate_ldm1stm1(p, regs);511regs->ARM_pc = (long)p->addr + 4;512}513514static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)515{516regs->uregs[12] = regs->uregs[13];517}518519static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)520{521insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];522kprobe_opcode_t insn = p->opcode;523long ppc = (long)p->addr + 8;524int rd = (insn >> 12) & 0xf;525int rn = (insn >> 16) & 0xf;526int rm = insn & 0xf; /* rm may be invalid, don't care. */527long rmv = (rm == 15) ? ppc : regs->uregs[rm];528long rnv = (rn == 15) ? ppc : regs->uregs[rn];529530/* Not following the C calling convention here, so need asm(). */531__asm__ __volatile__ (532"ldr r0, %[rn] \n\t"533"ldr r1, %[rm] \n\t"534"msr cpsr_fs, %[cpsr]\n\t"535"mov lr, pc \n\t"536"mov pc, %[i_fn] \n\t"537"str r0, %[rn] \n\t" /* in case of writeback */538"str r2, %[rd0] \n\t"539"str r3, %[rd1] \n\t"540: [rn] "+m" (rnv),541[rd0] "=m" (regs->uregs[rd]),542[rd1] "=m" (regs->uregs[rd+1])543: [rm] "m" (rmv),544[cpsr] "r" (regs->ARM_cpsr),545[i_fn] "r" (i_fn)546: "r0", "r1", "r2", "r3", "lr", "cc"547);548if (is_writeback(insn))549regs->uregs[rn] = rnv;550}551552static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)553{554insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];555kprobe_opcode_t insn = p->opcode;556long ppc = (long)p->addr + 8;557int rd = (insn >> 12) & 0xf;558int rn = (insn >> 16) & 0xf;559int rm = insn & 0xf;560long rnv = (rn == 15) ? ppc : regs->uregs[rn];561/* rm/rmv may be invalid, don't care. */562long rmv = (rm == 15) ? ppc : regs->uregs[rm];563long rnv_wb;564565rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],566regs->uregs[rd+1],567regs->ARM_cpsr, i_fn);568if (is_writeback(insn))569regs->uregs[rn] = rnv_wb;570}571572static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)573{574insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];575kprobe_opcode_t insn = p->opcode;576long ppc = (long)p->addr + 8;577union reg_pair fnr;578int rd = (insn >> 12) & 0xf;579int rn = (insn >> 16) & 0xf;580int rm = insn & 0xf;581long rdv;582long rnv = (rn == 15) ? ppc : regs->uregs[rn];583long rmv = (rm == 15) ? ppc : regs->uregs[rm];584long cpsr = regs->ARM_cpsr;585586fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);587if (rn != 15)588regs->uregs[rn] = fnr.r0; /* Save Rn in case of writeback. */589rdv = fnr.r1;590591if (rd == 15) {592#if __LINUX_ARM_ARCH__ >= 5593cpsr &= ~PSR_T_BIT;594if (rdv & 0x1)595cpsr |= PSR_T_BIT;596regs->ARM_cpsr = cpsr;597rdv &= ~0x1;598#else599rdv &= ~0x2;600#endif601}602regs->uregs[rd] = rdv;603}604605static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)606{607insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];608kprobe_opcode_t insn = p->opcode;609long iaddr = (long)p->addr;610int rd = (insn >> 12) & 0xf;611int rn = (insn >> 16) & 0xf;612int rm = insn & 0xf;613long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];614long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];615long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */616long rnv_wb;617618rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);619if (rn != 15)620regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */621}622623static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)624{625insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];626kprobe_opcode_t insn = p->opcode;627int rd = (insn >> 12) & 0xf;628int rm = insn & 0xf;629long rmv = regs->uregs[rm];630631/* Writes Q flag */632regs->uregs[rd] = insnslot_1arg_rwflags(rmv, ®s->ARM_cpsr, i_fn);633}634635static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)636{637insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];638kprobe_opcode_t insn = p->opcode;639int rd = (insn >> 12) & 0xf;640int rn = (insn >> 16) & 0xf;641int rm = insn & 0xf;642long rnv = regs->uregs[rn];643long rmv = regs->uregs[rm];644645/* Reads GE bits */646regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);647}648649static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)650{651insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];652653insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);654}655656static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)657{658}659660static void __kprobes661emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)662{663insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];664kprobe_opcode_t insn = p->opcode;665int rd = (insn >> 12) & 0xf;666long rdv = regs->uregs[rd];667668regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);669}670671static void __kprobes672emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)673{674insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];675kprobe_opcode_t insn = p->opcode;676int rd = (insn >> 12) & 0xf;677int rn = insn & 0xf;678long rdv = regs->uregs[rd];679long rnv = regs->uregs[rn];680681regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);682}683684static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)685{686insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];687kprobe_opcode_t insn = p->opcode;688int rd = (insn >> 12) & 0xf;689int rm = insn & 0xf;690long rmv = regs->uregs[rm];691692regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);693}694695static void __kprobes696emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)697{698insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];699kprobe_opcode_t insn = p->opcode;700int rd = (insn >> 12) & 0xf;701int rn = (insn >> 16) & 0xf;702int rm = insn & 0xf;703long rnv = regs->uregs[rn];704long rmv = regs->uregs[rm];705706regs->uregs[rd] =707insnslot_2arg_rwflags(rnv, rmv, ®s->ARM_cpsr, i_fn);708}709710static void __kprobes711emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)712{713insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];714kprobe_opcode_t insn = p->opcode;715int rd = (insn >> 16) & 0xf;716int rn = (insn >> 12) & 0xf;717int rs = (insn >> 8) & 0xf;718int rm = insn & 0xf;719long rnv = regs->uregs[rn];720long rsv = regs->uregs[rs];721long rmv = regs->uregs[rm];722723regs->uregs[rd] =724insnslot_3arg_rwflags(rnv, rsv, rmv, ®s->ARM_cpsr, i_fn);725}726727static void __kprobes728emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)729{730insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];731kprobe_opcode_t insn = p->opcode;732int rd = (insn >> 16) & 0xf;733int rs = (insn >> 8) & 0xf;734int rm = insn & 0xf;735long rsv = regs->uregs[rs];736long rmv = regs->uregs[rm];737738regs->uregs[rd] =739insnslot_2arg_rwflags(rsv, rmv, ®s->ARM_cpsr, i_fn);740}741742static void __kprobes743emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)744{745insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];746kprobe_opcode_t insn = p->opcode;747union reg_pair fnr;748int rdhi = (insn >> 16) & 0xf;749int rdlo = (insn >> 12) & 0xf;750int rs = (insn >> 8) & 0xf;751int rm = insn & 0xf;752long rsv = regs->uregs[rs];753long rmv = regs->uregs[rm];754755fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],756regs->uregs[rdlo], rsv, rmv,757®s->ARM_cpsr, i_fn);758regs->uregs[rdhi] = fnr.r0;759regs->uregs[rdlo] = fnr.r1;760}761762static void __kprobes763emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)764{765insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];766kprobe_opcode_t insn = p->opcode;767int rd = (insn >> 12) & 0xf;768int rn = (insn >> 16) & 0xf;769long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];770771regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);772}773774static void __kprobes775emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)776{777insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];778kprobe_opcode_t insn = p->opcode;779int rd = (insn >> 12) & 0xf;780int rn = (insn >> 16) & 0xf;781long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];782783regs->uregs[rd] = insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn);784}785786static void __kprobes787emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)788{789insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];790kprobe_opcode_t insn = p->opcode;791int rn = (insn >> 16) & 0xf;792long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];793794insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn);795}796797static void __kprobes798emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)799{800insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];801kprobe_opcode_t insn = p->opcode;802long ppc = (long)p->addr + 8;803int rd = (insn >> 12) & 0xf;804int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */805int rs = (insn >> 8) & 0xf; /* invalid, don't care. */806int rm = insn & 0xf;807long rnv = (rn == 15) ? ppc : regs->uregs[rn];808long rmv = (rm == 15) ? ppc : regs->uregs[rm];809long rsv = regs->uregs[rs];810811regs->uregs[rd] =812insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);813}814815static void __kprobes816emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)817{818insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];819kprobe_opcode_t insn = p->opcode;820long ppc = (long)p->addr + 8;821int rd = (insn >> 12) & 0xf;822int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */823int rs = (insn >> 8) & 0xf; /* invalid, don't care. */824int rm = insn & 0xf;825long rnv = (rn == 15) ? ppc : regs->uregs[rn];826long rmv = (rm == 15) ? ppc : regs->uregs[rm];827long rsv = regs->uregs[rs];828829regs->uregs[rd] =830insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn);831}832833static void __kprobes834emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)835{836insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];837kprobe_opcode_t insn = p->opcode;838long ppc = (long)p->addr + 8;839int rn = (insn >> 16) & 0xf;840int rs = (insn >> 8) & 0xf; /* rs/rsv may be invalid, don't care. */841int rm = insn & 0xf;842long rnv = (rn == 15) ? ppc : regs->uregs[rn];843long rmv = (rm == 15) ? ppc : regs->uregs[rm];844long rsv = regs->uregs[rs];845846insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn);847}848849static enum kprobe_insn __kprobes850prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)851{852int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))853: (~insn & (1 << 22));854855if (is_writeback(insn) && is_r15(insn, 16))856return INSN_REJECTED; /* Writeback to PC */857858insn &= 0xfff00fff;859insn |= 0x00001000; /* Rn = r0, Rd = r1 */860if (not_imm) {861insn &= ~0xf;862insn |= 2; /* Rm = r2 */863}864asi->insn[0] = insn;865asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;866return INSN_GOOD;867}868869static enum kprobe_insn __kprobes870prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)871{872if (is_r15(insn, 12))873return INSN_REJECTED; /* Rd is PC */874875insn &= 0xffff0fff; /* Rd = r0 */876asi->insn[0] = insn;877asi->insn_handler = emulate_rd12_modify;878return INSN_GOOD;879}880881static enum kprobe_insn __kprobes882prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,883struct arch_specific_insn *asi)884{885if (is_r15(insn, 12))886return INSN_REJECTED; /* Rd is PC */887888insn &= 0xffff0ff0; /* Rd = r0 */889insn |= 0x00000001; /* Rn = r1 */890asi->insn[0] = insn;891asi->insn_handler = emulate_rd12rn0_modify;892return INSN_GOOD;893}894895static enum kprobe_insn __kprobes896prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)897{898if (is_r15(insn, 12))899return INSN_REJECTED; /* Rd is PC */900901insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */902asi->insn[0] = insn;903asi->insn_handler = emulate_rd12rm0;904return INSN_GOOD;905}906907static enum kprobe_insn __kprobes908prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,909struct arch_specific_insn *asi)910{911if (is_r15(insn, 12))912return INSN_REJECTED; /* Rd is PC */913914insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */915insn |= 0x00000001; /* Rm = r1 */916asi->insn[0] = insn;917asi->insn_handler = emulate_rd12rn16rm0_rwflags;918return INSN_GOOD;919}920921static enum kprobe_insn __kprobes922prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,923struct arch_specific_insn *asi)924{925if (is_r15(insn, 16))926return INSN_REJECTED; /* Rd is PC */927928insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */929insn |= 0x00000001; /* Rm = r1 */930asi->insn[0] = insn;931asi->insn_handler = emulate_rd16rs8rm0_rwflags;932return INSN_GOOD;933}934935static enum kprobe_insn __kprobes936prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,937struct arch_specific_insn *asi)938{939if (is_r15(insn, 16))940return INSN_REJECTED; /* Rd is PC */941942insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */943insn |= 0x00000102; /* Rs = r1, Rm = r2 */944asi->insn[0] = insn;945asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;946return INSN_GOOD;947}948949static enum kprobe_insn __kprobes950prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,951struct arch_specific_insn *asi)952{953if (is_r15(insn, 16) || is_r15(insn, 12))954return INSN_REJECTED; /* RdHi or RdLo is PC */955956insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */957insn |= 0x00001203; /* Rs = r2, Rm = r3 */958asi->insn[0] = insn;959asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;960return INSN_GOOD;961}962963/*964* For the instruction masking and comparisons in all the "space_*"965* functions below, Do _not_ rearrange the order of tests unless966* you're very, very sure of what you are doing. For the sake of967* efficiency, the masks for some tests sometimes assume other test968* have been done prior to them so the number of patterns to test969* for an instruction set can be as broad as possible to reduce the970* number of tests needed.971*/972973static enum kprobe_insn __kprobes974space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)975{976/* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */977/* PLDI : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */978/* PLDW : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */979/* PLD : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */980if ((insn & 0xfe300000) == 0xf4100000) {981asi->insn_handler = emulate_nop;982return INSN_GOOD_NO_SLOT;983}984985/* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */986if ((insn & 0xfe000000) == 0xfa000000) {987asi->insn_handler = simulate_blx1;988return INSN_GOOD_NO_SLOT;989}990991/* CPS : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */992/* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */993994/* SRS : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */995/* RFE : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */996997/* Coprocessor instructions... */998/* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */999/* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */1000/* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */1001/* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */1002/* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */1003/* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */1004/* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */10051006return INSN_REJECTED;1007}10081009static enum kprobe_insn __kprobes1010space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)1011{1012/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */1013if ((insn & 0x0f900010) == 0x01000000) {10141015/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */1016if ((insn & 0x0ff000f0) == 0x01000000) {1017if (is_r15(insn, 12))1018return INSN_REJECTED; /* Rd is PC */1019asi->insn_handler = simulate_mrs;1020return INSN_GOOD_NO_SLOT;1021}10221023/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */1024if ((insn & 0x0ff00090) == 0x01400080)1025return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,1026asi);10271028/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */1029/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */1030if ((insn & 0x0ff000b0) == 0x012000a0 ||1031(insn & 0x0ff00090) == 0x01600080)1032return prep_emulate_rd16rs8rm0_wflags(insn, asi);10331034/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */1035/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */1036if ((insn & 0x0ff00090) == 0x01000080 ||1037(insn & 0x0ff000b0) == 0x01200080)1038return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);10391040/* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */1041/* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */1042/* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */10431044/* Other instruction encodings aren't yet defined */1045return INSN_REJECTED;1046}10471048/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */1049else if ((insn & 0x0f900090) == 0x01000010) {10501051/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */1052/* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */1053if ((insn & 0x0ff000d0) == 0x01200010) {1054if ((insn & 0x0ff000ff) == 0x0120003f)1055return INSN_REJECTED; /* BLX pc */1056asi->insn_handler = simulate_blx2bx;1057return INSN_GOOD_NO_SLOT;1058}10591060/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */1061if ((insn & 0x0ff000f0) == 0x01600010)1062return prep_emulate_rd12rm0(insn, asi);10631064/* QADD : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */1065/* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */1066/* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */1067/* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */1068if ((insn & 0x0f9000f0) == 0x01000050)1069return prep_emulate_rd12rn16rm0_wflags(insn, asi);10701071/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */1072/* SMC : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */10731074/* Other instruction encodings aren't yet defined */1075return INSN_REJECTED;1076}10771078/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */1079else if ((insn & 0x0f0000f0) == 0x00000090) {10801081/* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */1082/* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */1083/* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */1084/* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */1085/* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */1086/* undef : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx : */1087/* MLS : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx : */1088/* undef : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx : */1089/* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */1090/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */1091/* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */1092/* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */1093/* SMULL : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx : */1094/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */1095/* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */1096/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */1097if ((insn & 0x00d00000) == 0x00500000)1098return INSN_REJECTED;1099else if ((insn & 0x00e00000) == 0x00000000)1100return prep_emulate_rd16rs8rm0_wflags(insn, asi);1101else if ((insn & 0x00a00000) == 0x00200000)1102return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);1103else1104return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,1105asi);1106}11071108/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */1109else if ((insn & 0x0e000090) == 0x00000090) {11101111/* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */1112/* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */1113/* ??? : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */1114/* ??? : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */1115/* ??? : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */1116/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */1117/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */1118/* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */1119/* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */1120/* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */1121/* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */1122/* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */1123/* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */11241125/* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */1126/* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */1127/* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */1128/* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */1129/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */1130/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */1131if ((insn & 0x0f0000f0) == 0x01000090) {1132if ((insn & 0x0fb000f0) == 0x01000090) {1133/* SWP/SWPB */1134return prep_emulate_rd12rn16rm0_wflags(insn,1135asi);1136} else {1137/* STREX/LDREX variants and unallocaed space */1138return INSN_REJECTED;1139}11401141} else if ((insn & 0x0e1000d0) == 0x00000d0) {1142/* STRD/LDRD */1143if ((insn & 0x0000e000) == 0x0000e000)1144return INSN_REJECTED; /* Rd is LR or PC */1145if (is_writeback(insn) && is_r15(insn, 16))1146return INSN_REJECTED; /* Writeback to PC */11471148insn &= 0xfff00fff;1149insn |= 0x00002000; /* Rn = r0, Rd = r2 */1150if (!(insn & (1 << 22))) {1151/* Register index */1152insn &= ~0xf;1153insn |= 1; /* Rm = r1 */1154}1155asi->insn[0] = insn;1156asi->insn_handler =1157(insn & (1 << 5)) ? emulate_strd : emulate_ldrd;1158return INSN_GOOD;1159}11601161/* LDRH/STRH/LDRSB/LDRSH */1162if (is_r15(insn, 12))1163return INSN_REJECTED; /* Rd is PC */1164return prep_emulate_ldr_str(insn, asi);1165}11661167/* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */11681169/*1170* ALU op with S bit and Rd == 15 :1171* cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx1172*/1173if ((insn & 0x0e10f000) == 0x0010f000)1174return INSN_REJECTED;11751176/*1177* "mov ip, sp" is the most common kprobe'd instruction by far.1178* Check and optimize for it explicitly.1179*/1180if (insn == 0xe1a0c00d) {1181asi->insn_handler = simulate_mov_ipsp;1182return INSN_GOOD_NO_SLOT;1183}11841185/*1186* Data processing: Immediate-shift / Register-shift1187* ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx1188* CPY : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx1189* MOV : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx1190* *S (bit 20) updates condition codes1191* ADC/SBC/RSC reads the C flag1192*/1193insn &= 0xfff00ff0; /* Rn = r0, Rd = r0 */1194insn |= 0x00000001; /* Rm = r1 */1195if (insn & 0x010) {1196insn &= 0xfffff0ff; /* register shift */1197insn |= 0x00000200; /* Rs = r2 */1198}1199asi->insn[0] = insn;12001201if ((insn & 0x0f900000) == 0x01100000) {1202/*1203* TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx1204* TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx1205* CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx1206* CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx1207*/1208asi->insn_handler = emulate_alu_tests;1209} else {1210/* ALU ops which write to Rd */1211asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */1212emulate_alu_rwflags : emulate_alu_rflags;1213}1214return INSN_GOOD;1215}12161217static enum kprobe_insn __kprobes1218space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)1219{1220/* MOVW : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */1221/* MOVT : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */1222if ((insn & 0x0fb00000) == 0x03000000)1223return prep_emulate_rd12_modify(insn, asi);12241225/* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */1226if ((insn & 0x0fff0000) == 0x03200000) {1227unsigned op2 = insn & 0x000000ff;1228if (op2 == 0x01 || op2 == 0x04) {1229/* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */1230/* SEV : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */1231asi->insn[0] = insn;1232asi->insn_handler = emulate_none;1233return INSN_GOOD;1234} else if (op2 <= 0x03) {1235/* NOP : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */1236/* WFE : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */1237/* WFI : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */1238/*1239* We make WFE and WFI true NOPs to avoid stalls due1240* to missing events whilst processing the probe.1241*/1242asi->insn_handler = emulate_nop;1243return INSN_GOOD_NO_SLOT;1244}1245/* For DBG and unallocated hints it's safest to reject them */1246return INSN_REJECTED;1247}12481249/*1250* MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx1251* ALU op with S bit and Rd == 15 :1252* cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx1253*/1254if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */1255(insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */1256return INSN_REJECTED;12571258/*1259* Data processing: 32-bit Immediate1260* ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx1261* MOV : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx1262* *S (bit 20) updates condition codes1263* ADC/SBC/RSC reads the C flag1264*/1265insn &= 0xfff00fff; /* Rn = r0 and Rd = r0 */1266asi->insn[0] = insn;12671268if ((insn & 0x0f900000) == 0x03100000) {1269/*1270* TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx1271* TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx1272* CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx1273* CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx1274*/1275asi->insn_handler = emulate_alu_tests_imm;1276} else {1277/* ALU ops which write to Rd */1278asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */1279emulate_alu_imm_rwflags : emulate_alu_imm_rflags;1280}1281return INSN_GOOD;1282}12831284static enum kprobe_insn __kprobes1285space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)1286{1287/* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */1288if ((insn & 0x0ff000f0) == 0x068000b0) {1289if (is_r15(insn, 12))1290return INSN_REJECTED; /* Rd is PC */1291insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */1292insn |= 0x00000001; /* Rm = r1 */1293asi->insn[0] = insn;1294asi->insn_handler = emulate_sel;1295return INSN_GOOD;1296}12971298/* SSAT : cccc 0110 101x xxxx xxxx xxxx xx01 xxxx :Q */1299/* USAT : cccc 0110 111x xxxx xxxx xxxx xx01 xxxx :Q */1300/* SSAT16 : cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx :Q */1301/* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */1302if ((insn & 0x0fa00030) == 0x06a00010 ||1303(insn & 0x0fb000f0) == 0x06a00030) {1304if (is_r15(insn, 12))1305return INSN_REJECTED; /* Rd is PC */1306insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */1307asi->insn[0] = insn;1308asi->insn_handler = emulate_sat;1309return INSN_GOOD;1310}13111312/* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */1313/* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */1314/* RBIT : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */1315/* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */1316if ((insn & 0x0ff00070) == 0x06b00030 ||1317(insn & 0x0ff00070) == 0x06f00030)1318return prep_emulate_rd12rm0(insn, asi);13191320/* ??? : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx : */1321/* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */1322/* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */1323/* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */1324/* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */1325/* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */1326/* ??? : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx : */1327/* ??? : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx : */1328/* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */1329/* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */1330/* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */1331/* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */1332/* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */1333/* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */1334/* ??? : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx : */1335/* ??? : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx : */1336/* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */1337/* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */1338/* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */1339/* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */1340/* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */1341/* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */1342/* ??? : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx : */1343/* ??? : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx : */1344/* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */1345/* ??? : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx : */1346/* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */1347/* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */1348/* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */1349/* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */1350/* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */1351/* ??? : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx : */1352/* ??? : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx : */1353/* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */1354/* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */1355/* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */1356/* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */1357/* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */1358/* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */1359/* ??? : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx : */1360/* ??? : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx : */1361/* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */1362/* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */1363/* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */1364/* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */1365/* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */1366/* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */1367/* ??? : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx : */1368/* ??? : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx : */1369/* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */1370if ((insn & 0x0f800010) == 0x06000010) {1371if ((insn & 0x00300000) == 0x00000000 ||1372(insn & 0x000000e0) == 0x000000a0 ||1373(insn & 0x000000e0) == 0x000000c0)1374return INSN_REJECTED; /* Unallocated space */1375return prep_emulate_rd12rn16rm0_wflags(insn, asi);1376}13771378/* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */1379/* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */1380if ((insn & 0x0ff00030) == 0x06800010)1381return prep_emulate_rd12rn16rm0_wflags(insn, asi);13821383/* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */1384/* SXTB16 : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx : */1385/* ??? : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx : */1386/* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */1387/* SXTB : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx : */1388/* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */1389/* SXTH : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx : */1390/* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */1391/* UXTB16 : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx : */1392/* ??? : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx : */1393/* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */1394/* UXTB : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx : */1395/* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */1396/* UXTH : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx : */1397if ((insn & 0x0f8000f0) == 0x06800070) {1398if ((insn & 0x00300000) == 0x00100000)1399return INSN_REJECTED; /* Unallocated space */14001401if ((insn & 0x000f0000) == 0x000f0000)1402return prep_emulate_rd12rm0(insn, asi);1403else1404return prep_emulate_rd12rn16rm0_wflags(insn, asi);1405}14061407/* Other instruction encodings aren't yet defined */1408return INSN_REJECTED;1409}14101411static enum kprobe_insn __kprobes1412space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)1413{1414/* Undef : cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */1415if ((insn & 0x0ff000f0) == 0x03f000f0)1416return INSN_REJECTED;14171418/* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */1419/* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */1420if ((insn & 0x0ff00090) == 0x07400010)1421return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);14221423/* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */1424/* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */1425/* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */1426/* SMUSD : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx : */1427/* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */1428/* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */1429/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx : */1430/* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx : */1431if ((insn & 0x0ff00090) == 0x07000010 ||1432(insn & 0x0ff000d0) == 0x07500010 ||1433(insn & 0x0ff000f0) == 0x07800010) {14341435if ((insn & 0x0000f000) == 0x0000f000)1436return prep_emulate_rd16rs8rm0_wflags(insn, asi);1437else1438return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);1439}14401441/* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */1442if ((insn & 0x0ff000d0) == 0x075000d0)1443return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);14441445/* SBFX : cccc 0111 101x xxxx xxxx xxxx x101 xxxx : */1446/* UBFX : cccc 0111 111x xxxx xxxx xxxx x101 xxxx : */1447if ((insn & 0x0fa00070) == 0x07a00050)1448return prep_emulate_rd12rm0(insn, asi);14491450/* BFI : cccc 0111 110x xxxx xxxx xxxx x001 xxxx : */1451/* BFC : cccc 0111 110x xxxx xxxx xxxx x001 1111 : */1452if ((insn & 0x0fe00070) == 0x07c00010) {14531454if ((insn & 0x0000000f) == 0x0000000f)1455return prep_emulate_rd12_modify(insn, asi);1456else1457return prep_emulate_rd12rn0_modify(insn, asi);1458}14591460return INSN_REJECTED;1461}14621463static enum kprobe_insn __kprobes1464space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)1465{1466/* LDR : cccc 01xx x0x1 xxxx xxxx xxxx xxxx xxxx */1467/* LDRB : cccc 01xx x1x1 xxxx xxxx xxxx xxxx xxxx */1468/* LDRBT : cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */1469/* LDRT : cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */1470/* STR : cccc 01xx x0x0 xxxx xxxx xxxx xxxx xxxx */1471/* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */1472/* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */1473/* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */14741475if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))1476return INSN_REJECTED; /* LDRB into PC */14771478return prep_emulate_ldr_str(insn, asi);1479}14801481static enum kprobe_insn __kprobes1482space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)1483{1484/* LDM(2) : cccc 100x x101 xxxx 0xxx xxxx xxxx xxxx */1485/* LDM(3) : cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */1486if ((insn & 0x0e708000) == 0x85000000 ||1487(insn & 0x0e508000) == 0x85010000)1488return INSN_REJECTED;14891490/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */1491/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */1492asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */1493simulate_stm1_pc : simulate_ldm1stm1;1494return INSN_GOOD_NO_SLOT;1495}14961497static enum kprobe_insn __kprobes1498space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)1499{1500/* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */1501/* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */1502asi->insn_handler = simulate_bbl;1503return INSN_GOOD_NO_SLOT;1504}15051506static enum kprobe_insn __kprobes1507space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)1508{1509/* Coprocessor instructions... */1510/* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */1511/* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */1512/* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */1513/* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */1514/* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */1515/* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */1516/* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */15171518/* SVC : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */15191520return INSN_REJECTED;1521}15221523static unsigned long __kprobes __check_eq(unsigned long cpsr)1524{1525return cpsr & PSR_Z_BIT;1526}15271528static unsigned long __kprobes __check_ne(unsigned long cpsr)1529{1530return (~cpsr) & PSR_Z_BIT;1531}15321533static unsigned long __kprobes __check_cs(unsigned long cpsr)1534{1535return cpsr & PSR_C_BIT;1536}15371538static unsigned long __kprobes __check_cc(unsigned long cpsr)1539{1540return (~cpsr) & PSR_C_BIT;1541}15421543static unsigned long __kprobes __check_mi(unsigned long cpsr)1544{1545return cpsr & PSR_N_BIT;1546}15471548static unsigned long __kprobes __check_pl(unsigned long cpsr)1549{1550return (~cpsr) & PSR_N_BIT;1551}15521553static unsigned long __kprobes __check_vs(unsigned long cpsr)1554{1555return cpsr & PSR_V_BIT;1556}15571558static unsigned long __kprobes __check_vc(unsigned long cpsr)1559{1560return (~cpsr) & PSR_V_BIT;1561}15621563static unsigned long __kprobes __check_hi(unsigned long cpsr)1564{1565cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */1566return cpsr & PSR_C_BIT;1567}15681569static unsigned long __kprobes __check_ls(unsigned long cpsr)1570{1571cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */1572return (~cpsr) & PSR_C_BIT;1573}15741575static unsigned long __kprobes __check_ge(unsigned long cpsr)1576{1577cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */1578return (~cpsr) & PSR_N_BIT;1579}15801581static unsigned long __kprobes __check_lt(unsigned long cpsr)1582{1583cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */1584return cpsr & PSR_N_BIT;1585}15861587static unsigned long __kprobes __check_gt(unsigned long cpsr)1588{1589unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */1590temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */1591return (~temp) & PSR_N_BIT;1592}15931594static unsigned long __kprobes __check_le(unsigned long cpsr)1595{1596unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */1597temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */1598return temp & PSR_N_BIT;1599}16001601static unsigned long __kprobes __check_al(unsigned long cpsr)1602{1603return true;1604}16051606static kprobe_check_cc * const condition_checks[16] = {1607&__check_eq, &__check_ne, &__check_cs, &__check_cc,1608&__check_mi, &__check_pl, &__check_vs, &__check_vc,1609&__check_hi, &__check_ls, &__check_ge, &__check_lt,1610&__check_gt, &__check_le, &__check_al, &__check_al1611};16121613/* Return:1614* INSN_REJECTED If instruction is one not allowed to kprobe,1615* INSN_GOOD If instruction is supported and uses instruction slot,1616* INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.1617*1618* For instructions we don't want to kprobe (INSN_REJECTED return result):1619* These are generally ones that modify the processor state making1620* them "hard" to simulate such as switches processor modes or1621* make accesses in alternate modes. Any of these could be simulated1622* if the work was put into it, but low return considering they1623* should also be very rare.1624*/1625enum kprobe_insn __kprobes1626arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)1627{1628asi->insn_check_cc = condition_checks[insn>>28];1629asi->insn[1] = KPROBE_RETURN_INSTRUCTION;16301631if ((insn & 0xf0000000) == 0xf0000000)16321633return space_1111(insn, asi);16341635else if ((insn & 0x0e000000) == 0x00000000)16361637return space_cccc_000x(insn, asi);16381639else if ((insn & 0x0e000000) == 0x02000000)16401641return space_cccc_001x(insn, asi);16421643else if ((insn & 0x0f000010) == 0x06000010)16441645return space_cccc_0110__1(insn, asi);16461647else if ((insn & 0x0f000010) == 0x07000010)16481649return space_cccc_0111__1(insn, asi);16501651else if ((insn & 0x0c000000) == 0x04000000)16521653return space_cccc_01xx(insn, asi);16541655else if ((insn & 0x0e000000) == 0x08000000)16561657return space_cccc_100x(insn, asi);16581659else if ((insn & 0x0e000000) == 0x0a000000)16601661return space_cccc_101x(insn, asi);16621663return space_cccc_11xx(insn, asi);1664}16651666void __init arm_kprobe_decode_init(void)1667{1668find_str_pc_offset();1669}167016711672