Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * arch/arm/probes/kprobes/actions-arm.c
0004  *
0005  * Copyright (C) 2006, 2007 Motorola Inc.
0006  */
0007 
0008 /*
0009  * We do not have hardware single-stepping on ARM, This
0010  * effort is further complicated by the ARM not having a
0011  * "next PC" register.  Instructions that change the PC
0012  * can't be safely single-stepped in a MP environment, so
0013  * we have a lot of work to do:
0014  *
0015  * In the prepare phase:
0016  *   *) If it is an instruction that does anything
0017  *      with the CPU mode, we reject it for a kprobe.
0018  *      (This is out of laziness rather than need.  The
0019  *      instructions could be simulated.)
0020  *
0021  *   *) Otherwise, decode the instruction rewriting its
0022  *      registers to take fixed, ordered registers and
0023  *      setting a handler for it to run the instruction.
0024  *
0025  * In the execution phase by an instruction's handler:
0026  *
0027  *   *) If the PC is written to by the instruction, the
0028  *      instruction must be fully simulated in software.
0029  *
0030  *   *) Otherwise, a modified form of the instruction is
0031  *      directly executed.  Its handler calls the
0032  *      instruction in insn[0].  In insn[1] is a
0033  *      "mov pc, lr" to return.
0034  *
0035  *      Before calling, load up the reordered registers
0036  *      from the original instruction's registers.  If one
0037  *      of the original input registers is the PC, compute
0038  *      and adjust the appropriate input register.
0039  *
0040  *  After call completes, copy the output registers to
0041  *      the original instruction's original registers.
0042  *
0043  * We don't use a real breakpoint instruction since that
0044  * would have us in the kernel go from SVC mode to SVC
0045  * mode losing the link register.  Instead we use an
0046  * undefined instruction.  To simplify processing, the
0047  * undefined instruction used for kprobes must be reserved
0048  * exclusively for kprobes use.
0049  *
0050  * TODO: ifdef out some instruction decoding based on architecture.
0051  */
0052 
0053 #include <linux/kernel.h>
0054 #include <linux/kprobes.h>
0055 #include <linux/ptrace.h>
0056 
0057 #include "../decode-arm.h"
0058 #include "core.h"
0059 #include "checkers.h"
0060 
0061 #if  __LINUX_ARM_ARCH__ >= 6
0062 #define BLX(reg)    "blx    "reg"       \n\t"
0063 #else
0064 #define BLX(reg)    "mov    lr, pc      \n\t"   \
0065             "mov    pc, "reg"   \n\t"
0066 #endif
0067 
0068 static void __kprobes
0069 emulate_ldrdstrd(probes_opcode_t insn,
0070     struct arch_probes_insn *asi, struct pt_regs *regs)
0071 {
0072     unsigned long pc = regs->ARM_pc + 4;
0073     int rt = (insn >> 12) & 0xf;
0074     int rn = (insn >> 16) & 0xf;
0075     int rm = insn & 0xf;
0076 
0077     register unsigned long rtv asm("r0") = regs->uregs[rt];
0078     register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
0079     register unsigned long rnv asm("r2") = (rn == 15) ? pc
0080                               : regs->uregs[rn];
0081     register unsigned long rmv asm("r3") = regs->uregs[rm];
0082 
0083     __asm__ __volatile__ (
0084         BLX("%[fn]")
0085         : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
0086         : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
0087           [fn] "r" (asi->insn_fn)
0088         : "lr", "memory", "cc"
0089     );
0090 
0091     regs->uregs[rt] = rtv;
0092     regs->uregs[rt+1] = rt2v;
0093     if (is_writeback(insn))
0094         regs->uregs[rn] = rnv;
0095 }
0096 
0097 static void __kprobes
0098 emulate_ldr(probes_opcode_t insn,
0099     struct arch_probes_insn *asi, struct pt_regs *regs)
0100 {
0101     unsigned long pc = regs->ARM_pc + 4;
0102     int rt = (insn >> 12) & 0xf;
0103     int rn = (insn >> 16) & 0xf;
0104     int rm = insn & 0xf;
0105 
0106     register unsigned long rtv asm("r0");
0107     register unsigned long rnv asm("r2") = (rn == 15) ? pc
0108                               : regs->uregs[rn];
0109     register unsigned long rmv asm("r3") = regs->uregs[rm];
0110 
0111     __asm__ __volatile__ (
0112         BLX("%[fn]")
0113         : "=r" (rtv), "=r" (rnv)
0114         : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
0115         : "lr", "memory", "cc"
0116     );
0117 
0118     if (rt == 15)
0119         load_write_pc(rtv, regs);
0120     else
0121         regs->uregs[rt] = rtv;
0122 
0123     if (is_writeback(insn))
0124         regs->uregs[rn] = rnv;
0125 }
0126 
0127 static void __kprobes
0128 emulate_str(probes_opcode_t insn,
0129     struct arch_probes_insn *asi, struct pt_regs *regs)
0130 {
0131     unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
0132     unsigned long rnpc = regs->ARM_pc + 4;
0133     int rt = (insn >> 12) & 0xf;
0134     int rn = (insn >> 16) & 0xf;
0135     int rm = insn & 0xf;
0136 
0137     register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
0138                               : regs->uregs[rt];
0139     register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
0140                               : regs->uregs[rn];
0141     register unsigned long rmv asm("r3") = regs->uregs[rm];
0142 
0143     __asm__ __volatile__ (
0144         BLX("%[fn]")
0145         : "=r" (rnv)
0146         : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
0147         : "lr", "memory", "cc"
0148     );
0149 
0150     if (is_writeback(insn))
0151         regs->uregs[rn] = rnv;
0152 }
0153 
0154 static void __kprobes
0155 emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
0156     struct arch_probes_insn *asi, struct pt_regs *regs)
0157 {
0158     unsigned long pc = regs->ARM_pc + 4;
0159     int rd = (insn >> 12) & 0xf;
0160     int rn = (insn >> 16) & 0xf;
0161     int rm = insn & 0xf;
0162     int rs = (insn >> 8) & 0xf;
0163 
0164     register unsigned long rdv asm("r0") = regs->uregs[rd];
0165     register unsigned long rnv asm("r2") = (rn == 15) ? pc
0166                               : regs->uregs[rn];
0167     register unsigned long rmv asm("r3") = (rm == 15) ? pc
0168                               : regs->uregs[rm];
0169     register unsigned long rsv asm("r1") = regs->uregs[rs];
0170     unsigned long cpsr = regs->ARM_cpsr;
0171 
0172     __asm__ __volatile__ (
0173         "msr    cpsr_fs, %[cpsr]    \n\t"
0174         BLX("%[fn]")
0175         "mrs    %[cpsr], cpsr       \n\t"
0176         : "=r" (rdv), [cpsr] "=r" (cpsr)
0177         : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
0178           "1" (cpsr), [fn] "r" (asi->insn_fn)
0179         : "lr", "memory", "cc"
0180     );
0181 
0182     if (rd == 15)
0183         alu_write_pc(rdv, regs);
0184     else
0185         regs->uregs[rd] = rdv;
0186     regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
0187 }
0188 
0189 static void __kprobes
0190 emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
0191     struct arch_probes_insn *asi, struct pt_regs *regs)
0192 {
0193     int rd = (insn >> 12) & 0xf;
0194     int rn = (insn >> 16) & 0xf;
0195     int rm = insn & 0xf;
0196 
0197     register unsigned long rdv asm("r0") = regs->uregs[rd];
0198     register unsigned long rnv asm("r2") = regs->uregs[rn];
0199     register unsigned long rmv asm("r3") = regs->uregs[rm];
0200     unsigned long cpsr = regs->ARM_cpsr;
0201 
0202     __asm__ __volatile__ (
0203         "msr    cpsr_fs, %[cpsr]    \n\t"
0204         BLX("%[fn]")
0205         "mrs    %[cpsr], cpsr       \n\t"
0206         : "=r" (rdv), [cpsr] "=r" (cpsr)
0207         : "0" (rdv), "r" (rnv), "r" (rmv),
0208           "1" (cpsr), [fn] "r" (asi->insn_fn)
0209         : "lr", "memory", "cc"
0210     );
0211 
0212     regs->uregs[rd] = rdv;
0213     regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
0214 }
0215 
0216 static void __kprobes
0217 emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
0218     struct arch_probes_insn *asi,
0219     struct pt_regs *regs)
0220 {
0221     int rd = (insn >> 16) & 0xf;
0222     int rn = (insn >> 12) & 0xf;
0223     int rm = insn & 0xf;
0224     int rs = (insn >> 8) & 0xf;
0225 
0226     register unsigned long rdv asm("r2") = regs->uregs[rd];
0227     register unsigned long rnv asm("r0") = regs->uregs[rn];
0228     register unsigned long rmv asm("r3") = regs->uregs[rm];
0229     register unsigned long rsv asm("r1") = regs->uregs[rs];
0230     unsigned long cpsr = regs->ARM_cpsr;
0231 
0232     __asm__ __volatile__ (
0233         "msr    cpsr_fs, %[cpsr]    \n\t"
0234         BLX("%[fn]")
0235         "mrs    %[cpsr], cpsr       \n\t"
0236         : "=r" (rdv), [cpsr] "=r" (cpsr)
0237         : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
0238           "1" (cpsr), [fn] "r" (asi->insn_fn)
0239         : "lr", "memory", "cc"
0240     );
0241 
0242     regs->uregs[rd] = rdv;
0243     regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
0244 }
0245 
0246 static void __kprobes
0247 emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
0248     struct arch_probes_insn *asi, struct pt_regs *regs)
0249 {
0250     int rd = (insn >> 12) & 0xf;
0251     int rm = insn & 0xf;
0252 
0253     register unsigned long rdv asm("r0") = regs->uregs[rd];
0254     register unsigned long rmv asm("r3") = regs->uregs[rm];
0255 
0256     __asm__ __volatile__ (
0257         BLX("%[fn]")
0258         : "=r" (rdv)
0259         : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
0260         : "lr", "memory", "cc"
0261     );
0262 
0263     regs->uregs[rd] = rdv;
0264 }
0265 
0266 static void __kprobes
0267 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
0268     struct arch_probes_insn *asi,
0269     struct pt_regs *regs)
0270 {
0271     int rdlo = (insn >> 12) & 0xf;
0272     int rdhi = (insn >> 16) & 0xf;
0273     int rn = insn & 0xf;
0274     int rm = (insn >> 8) & 0xf;
0275 
0276     register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
0277     register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
0278     register unsigned long rnv asm("r3") = regs->uregs[rn];
0279     register unsigned long rmv asm("r1") = regs->uregs[rm];
0280     unsigned long cpsr = regs->ARM_cpsr;
0281 
0282     __asm__ __volatile__ (
0283         "msr    cpsr_fs, %[cpsr]    \n\t"
0284         BLX("%[fn]")
0285         "mrs    %[cpsr], cpsr       \n\t"
0286         : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
0287         : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
0288           "2" (cpsr), [fn] "r" (asi->insn_fn)
0289         : "lr", "memory", "cc"
0290     );
0291 
0292     regs->uregs[rdlo] = rdlov;
0293     regs->uregs[rdhi] = rdhiv;
0294     regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
0295 }
0296 
0297 const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
0298     [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
0299     [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
0300     [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
0301     [PROBES_MRS] = {.handler = simulate_mrs},
0302     [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
0303     [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
0304     [PROBES_SATURATING_ARITHMETIC] = {
0305         .handler = emulate_rd12rn16rm0_rwflags_nopc},
0306     [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
0307     [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
0308     [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
0309     [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
0310     [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
0311     [PROBES_LOAD] = {.handler = emulate_ldr},
0312     [PROBES_STORE_EXTRA] = {.handler = emulate_str},
0313     [PROBES_STORE] = {.handler = emulate_str},
0314     [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
0315     [PROBES_DATA_PROCESSING_REG] = {
0316         .handler = emulate_rd12rn16rm0rs8_rwflags},
0317     [PROBES_DATA_PROCESSING_IMM] = {
0318         .handler = emulate_rd12rn16rm0rs8_rwflags},
0319     [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
0320     [PROBES_SEV] = {.handler = probes_emulate_none},
0321     [PROBES_WFE] = {.handler = probes_simulate_nop},
0322     [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
0323     [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
0324     [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
0325     [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
0326     [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
0327     [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
0328     [PROBES_MUL_ADD_LONG] = {
0329         .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
0330     [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
0331     [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
0332     [PROBES_BRANCH] = {.handler = simulate_bbl},
0333     [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
0334 };
0335 
0336 const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL};