From patchwork Wed Jul 13 09:06:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tixy X-Patchwork-Id: 971242 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6D9FDqe031024 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 13 Jul 2011 09:15:36 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QgvVs-0005T8-Bj; Wed, 13 Jul 2011 09:13:49 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QgvVp-0004tk-Cx; Wed, 13 Jul 2011 09:13:45 +0000 Received: from smarthost02.mail.zen.net.uk ([212.23.3.141]) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QgvOg-0002yT-Ca for linux-arm-kernel@lists.infradead.org; Wed, 13 Jul 2011 09:06:40 +0000 Received: from [82.69.122.217] (helo=plug1) by smarthost02.mail.zen.net.uk with esmtpsa (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1QgvOf-0000Ou-57 for linux-arm-kernel@lists.infradead.org; Wed, 13 Jul 2011 09:06:21 +0000 Received: from [192.168.2.20] (helo=computer2) by plug1 with esmtp (Exim 4.72) (envelope-from ) id 1QgvOc-0000Rj-EQ for linux-arm-kernel@lists.infradead.org; Wed, 13 Jul 2011 10:06:18 +0100 Received: from tixy by computer2 with local (Exim 4.72) (envelope-from ) id 1QgvOc-0008IN-Qd for linux-arm-kernel@lists.infradead.org; Wed, 13 Jul 2011 10:06:18 +0100 From: Tixy To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 24/24] ARM: kprobes: Remove now unused code Date: Wed, 13 Jul 2011 10:06:13 +0100 Message-Id: <1310547973-31784-25-git-send-email-tixy@yxit.co.uk> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1310547973-31784-1-git-send-email-tixy@yxit.co.uk> References: <1310547973-31784-1-git-send-email-tixy@yxit.co.uk> X-Originating-Smarthost02-IP: [82.69.122.217] X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110713_050623_030288_7B65364D X-CRM114-Status: GOOD ( 15.34 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.23.3.141 listed in list.dnswl.org] X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 13 Jul 2011 09:15:36 +0000 (UTC) From: Jon Medhurst Signed-off-by: Jon Medhurst Acked-by: Nicolas Pitre --- arch/arm/kernel/kprobes-arm.c | 738 ----------------------------------------- 1 files changed, 0 insertions(+), 738 deletions(-) diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 8a58c99..79203ee 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c @@ -74,300 +74,6 @@ "mov pc, "reg" \n\t" #endif -#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos)) - -#define PSR_fs (PSR_f|PSR_s) - -#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */ - -typedef long (insn_0arg_fn_t)(void); -typedef long (insn_1arg_fn_t)(long); -typedef long (insn_2arg_fn_t)(long, long); -typedef long (insn_3arg_fn_t)(long, long, long); -typedef long (insn_4arg_fn_t)(long, long, long, long); -typedef long long (insn_llret_0arg_fn_t)(void); -typedef long long (insn_llret_3arg_fn_t)(long, long, long); -typedef long long (insn_llret_4arg_fn_t)(long, long, long, long); - -union reg_pair { - long long dr; -#ifdef __LITTLE_ENDIAN - struct { long r0, r1; }; -#else - struct { long r1, r0; }; -#endif -}; - -/* - * The insnslot_?arg_r[w]flags() functions below are to keep the - * msr -> *fn -> mrs instruction sequences indivisible so that - * the state of the CPSR flags aren't inadvertently modified - * just before or just after the call. - */ - -static inline long __kprobes -insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn) -{ - register long ret asm("r0"); - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret) - : [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - return ret; -} - -static inline long long __kprobes -insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn) -{ - register long ret0 asm("r0"); - register long ret1 asm("r1"); - union reg_pair fnr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret0), "=r" (ret1) - : [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - fnr.r0 = ret0; - fnr.r1 = ret1; - return fnr.dr; -} - -static inline long __kprobes -insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long ret asm("r0"); - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret) - : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - return ret; -} - -static inline long __kprobes -insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long ret asm("r0"); - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret) - : "0" (rr0), "r" (rr1), - [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - return ret; -} - -static inline long __kprobes -insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long ret asm("r0"); - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret) - : "0" (rr0), "r" (rr1), "r" (rr2), - [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - return ret; -} - -static inline long long __kprobes -insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr, - insn_llret_3arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long ret0 asm("r0"); - register long ret1 asm("r1"); - union reg_pair fnr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret0), "=r" (ret1) - : "0" (rr0), "r" (rr1), "r" (rr2), - [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - fnr.r0 = ret0; - fnr.r1 = ret1; - return fnr.dr; -} - -static inline long __kprobes -insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr, - insn_4arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long rr3 asm("r3") = r3; - register long ret asm("r0"); - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - : "=r" (ret) - : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3), - [cpsr] "r" (cpsr), [fn] "r" (fn) - : "lr", "cc" - ); - return ret; -} - -static inline long __kprobes -insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long ret asm("r0"); - long oldcpsr = *cpsr; - long newcpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - "mrs %[newcpsr], cpsr \n\t" - : "=r" (ret), [newcpsr] "=r" (newcpsr) - : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn) - : "lr", "cc" - ); - *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs); - return ret; -} - -static inline long __kprobes -insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long ret asm("r0"); - long oldcpsr = *cpsr; - long newcpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - "mrs %[newcpsr], cpsr \n\t" - : "=r" (ret), [newcpsr] "=r" (newcpsr) - : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn) - : "lr", "cc" - ); - *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs); - return ret; -} - -static inline long __kprobes -insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr, - insn_3arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long ret asm("r0"); - long oldcpsr = *cpsr; - long newcpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - "mrs %[newcpsr], cpsr \n\t" - : "=r" (ret), [newcpsr] "=r" (newcpsr) - : "0" (rr0), "r" (rr1), "r" (rr2), - [oldcpsr] "r" (oldcpsr), [fn] "r" (fn) - : "lr", "cc" - ); - *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs); - return ret; -} - -static inline long __kprobes -insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr, - insn_4arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long rr3 asm("r3") = r3; - register long ret asm("r0"); - long oldcpsr = *cpsr; - long newcpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - "mrs %[newcpsr], cpsr \n\t" - : "=r" (ret), [newcpsr] "=r" (newcpsr) - : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3), - [oldcpsr] "r" (oldcpsr), [fn] "r" (fn) - : "lr", "cc" - ); - *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs); - return ret; -} - -static inline long long __kprobes -insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr, - insn_llret_4arg_fn_t *fn) -{ - register long rr0 asm("r0") = r0; - register long rr1 asm("r1") = r1; - register long rr2 asm("r2") = r2; - register long rr3 asm("r3") = r3; - register long ret0 asm("r0"); - register long ret1 asm("r1"); - long oldcpsr = *cpsr; - long newcpsr; - union reg_pair fnr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "mov lr, pc \n\t" - "mov pc, %[fn] \n\t" - "mrs %[newcpsr], cpsr \n\t" - : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr) - : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3), - [oldcpsr] "r" (oldcpsr), [fn] "r" (fn) - : "lr", "cc" - ); - *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs); - fnr.r0 = ret0; - fnr.r1 = ret1; - return fnr.dr; -} - /* * To avoid the complications of mimicing single-stepping on a * processor without a Next-PC or a single-step mode, and to @@ -449,450 +155,6 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) regs->uregs[12] = regs->uregs[13]; } -static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; /* rm may be invalid, don't care. */ - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - - /* Not following the C calling convention here, so need asm(). */ - __asm__ __volatile__ ( - "ldr r0, %[rn] \n\t" - "ldr r1, %[rm] \n\t" - "msr cpsr_fs, %[cpsr]\n\t" - "mov lr, pc \n\t" - "mov pc, %[i_fn] \n\t" - "str r0, %[rn] \n\t" /* in case of writeback */ - "str r2, %[rd0] \n\t" - "str r3, %[rd1] \n\t" - : [rn] "+m" (rnv), - [rd0] "=m" (regs->uregs[rd]), - [rd1] "=m" (regs->uregs[rd+1]) - : [rm] "m" (rmv), - [cpsr] "r" (regs->ARM_cpsr), - [i_fn] "r" (i_fn) - : "r0", "r1", "r2", "r3", "lr", "cc" - ); - if (is_writeback(insn)) - regs->uregs[rn] = rnv; -} - -static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs) -{ - insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - /* rm/rmv may be invalid, don't care. */ - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long rnv_wb; - - rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd], - regs->uregs[rd+1], - regs->ARM_cpsr, i_fn); - if (is_writeback(insn)) - regs->uregs[rn] = rnv_wb; -} - -static void __kprobes emulate_ldr_old(struct kprobe *p, struct pt_regs *regs) -{ - insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - union reg_pair fnr; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - long rdv; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long cpsr = regs->ARM_cpsr; - - fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn); - if (rn != 15) - regs->uregs[rn] = fnr.r0; /* Save Rn in case of writeback. */ - rdv = fnr.r1; - - if (rd == 15) { -#if __LINUX_ARM_ARCH__ >= 5 - cpsr &= ~PSR_T_BIT; - if (rdv & 0x1) - cpsr |= PSR_T_BIT; - regs->ARM_cpsr = cpsr; - rdv &= ~0x1; -#else - rdv &= ~0x2; -#endif - } - regs->uregs[rd] = rdv; -} - -static void __kprobes emulate_str_old(struct kprobe *p, struct pt_regs *regs) -{ - insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long iaddr = (long)p->addr; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd]; - long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn]; - long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */ - long rnv_wb; - - rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn); - if (rn != 15) - regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */ -} - -static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rm = insn & 0xf; - long rmv = regs->uregs[rm]; - - /* Writes Q flag */ - regs->uregs[rd] = insnslot_1arg_rwflags(rmv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - long rnv = regs->uregs[rn]; - long rmv = regs->uregs[rm]; - - /* Reads GE bits */ - regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs) -{ - insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0]; - - insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); -} - -static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs) -{ -} - -static void __kprobes -emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - long rdv = regs->uregs[rd]; - - regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = insn & 0xf; - long rdv = regs->uregs[rd]; - long rnv = regs->uregs[rn]; - - regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rm = insn & 0xf; - long rmv = regs->uregs[rm]; - - regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - long rnv = regs->uregs[rn]; - long rmv = regs->uregs[rm]; - - regs->uregs[rd] = - insnslot_2arg_rwflags(rnv, rmv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 16) & 0xf; - int rn = (insn >> 12) & 0xf; - int rs = (insn >> 8) & 0xf; - int rm = insn & 0xf; - long rnv = regs->uregs[rn]; - long rsv = regs->uregs[rs]; - long rmv = regs->uregs[rm]; - - regs->uregs[rd] = - insnslot_3arg_rwflags(rnv, rsv, rmv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 16) & 0xf; - int rs = (insn >> 8) & 0xf; - int rm = insn & 0xf; - long rsv = regs->uregs[rs]; - long rmv = regs->uregs[rm]; - - regs->uregs[rd] = - insnslot_2arg_rwflags(rsv, rmv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - union reg_pair fnr; - int rdhi = (insn >> 16) & 0xf; - int rdlo = (insn >> 12) & 0xf; - int rs = (insn >> 8) & 0xf; - int rm = insn & 0xf; - long rsv = regs->uregs[rs]; - long rmv = regs->uregs[rm]; - - fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi], - regs->uregs[rdlo], rsv, rmv, - ®s->ARM_cpsr, i_fn); - regs->uregs[rdhi] = fnr.r0; - regs->uregs[rdlo] = fnr.r1; -} - -static void __kprobes -emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn]; - - regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn]; - - regs->uregs[rd] = insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rn = (insn >> 16) & 0xf; - long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn]; - - insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */ - int rs = (insn >> 8) & 0xf; /* invalid, don't care. */ - int rm = insn & 0xf; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long rsv = regs->uregs[rs]; - - regs->uregs[rd] = - insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; /* rn/rnv/rs/rsv may be */ - int rs = (insn >> 8) & 0xf; /* invalid, don't care. */ - int rm = insn & 0xf; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long rsv = regs->uregs[rs]; - - regs->uregs[rd] = - insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn); -} - -static void __kprobes -emulate_alu_tests(struct kprobe *p, struct pt_regs *regs) -{ - insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - long ppc = (long)p->addr + 8; - int rn = (insn >> 16) & 0xf; - int rs = (insn >> 8) & 0xf; /* rs/rsv may be invalid, don't care. */ - int rm = insn & 0xf; - long rnv = (rn == 15) ? ppc : regs->uregs[rn]; - long rmv = (rm == 15) ? ppc : regs->uregs[rm]; - long rsv = regs->uregs[rs]; - - insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn); -} - -static enum kprobe_insn __kprobes -prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25)) - : (~insn & (1 << 22)); - - if (is_writeback(insn) && is_r15(insn, 16)) - return INSN_REJECTED; /* Writeback to PC */ - - insn &= 0xfff00fff; - insn |= 0x00001000; /* Rn = r0, Rd = r1 */ - if (not_imm) { - insn &= ~0xf; - insn |= 2; /* Rm = r2 */ - } - asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr_old : emulate_str_old; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - if (is_r15(insn, 12)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xffff0fff; /* Rd = r0 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd12_modify; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd12rn0_modify(kprobe_opcode_t insn, - struct arch_specific_insn *asi) -{ - if (is_r15(insn, 12)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xffff0ff0; /* Rd = r0 */ - insn |= 0x00000001; /* Rn = r1 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd12rn0_modify; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - if (is_r15(insn, 12)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd12rm0; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn, - struct arch_specific_insn *asi) -{ - if (is_r15(insn, 12)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */ - insn |= 0x00000001; /* Rm = r1 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd12rn16rm0_rwflags; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn, - struct arch_specific_insn *asi) -{ - if (is_r15(insn, 16)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */ - insn |= 0x00000001; /* Rm = r1 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd16rs8rm0_rwflags; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn, - struct arch_specific_insn *asi) -{ - if (is_r15(insn, 16)) - return INSN_REJECTED; /* Rd is PC */ - - insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */ - insn |= 0x00000102; /* Rs = r1, Rm = r2 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags; - return INSN_GOOD; -} - -static enum kprobe_insn __kprobes -prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn, - struct arch_specific_insn *asi) -{ - if (is_r15(insn, 16) || is_r15(insn, 12)) - return INSN_REJECTED; /* RdHi or RdLo is PC */ - - insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */ - insn |= 0x00001203; /* Rs = r2, Rm = r3 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags; - return INSN_GOOD; -} - static void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) {