Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * arch/arm/probes/kprobes/actions-common.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Copyright (C) 2006, 2007 Motorola Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kprobes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <asm/opcodes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 		struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 		struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	int rn = (insn >> 16) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	int lbit = insn & (1 << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	int wbit = insn & (1 << 21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	int ubit = insn & (1 << 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	int pbit = insn & (1 << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	long *addr = (long *)regs->uregs[rn];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	int reg_bit_vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	int reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	reg_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	reg_bit_vector = insn & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	while (reg_bit_vector) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		reg_bit_vector &= (reg_bit_vector - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		++reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (!ubit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		addr -= reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	addr += (!pbit == !ubit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	reg_bit_vector = insn & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	while (reg_bit_vector) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		int reg = __ffs(reg_bit_vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		reg_bit_vector &= (reg_bit_vector - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		if (lbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			regs->uregs[reg] = *addr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			*addr++ = regs->uregs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	if (wbit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		if (!ubit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			addr -= reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		addr -= (!pbit == !ubit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		regs->uregs[rn] = (long)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static void __kprobes simulate_stm1_pc(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	unsigned long addr = regs->ARM_pc - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	regs->ARM_pc = (long)addr + str_pc_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	simulate_ldm1stm1(insn, asi, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	regs->ARM_pc = (long)addr + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	simulate_ldm1stm1(insn, asi, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	load_write_pc(regs->ARM_pc, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static void __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) emulate_generic_r0_12_noflags(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct arch_probes_insn *asi, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	register void *rregs asm("r1") = regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	register void *rfn asm("lr") = asi->insn_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		"stmdb	sp!, {%[regs], r11}	\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		"ldmia	%[regs], {r0-r12}	\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #if __LINUX_ARM_ARCH__ >= 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		"blx	%[fn]			\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		"str	%[fn], [sp, #-4]!	\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		"adr	lr, 1f			\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		"ldr	pc, [sp], #4		\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		"1:				\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		"ldr	lr, [sp], #4		\n\t" /* lr = regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		"stmia	lr, {r0-r12}		\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		"ldr	r11, [sp], #4		\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		: [regs] "=r" (rregs), [fn] "=r" (rfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		: "0" (rregs), "1" (rfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		: "r0", "r2", "r3", "r4", "r5", "r6", "r7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		  "r8", "r9", "r10", "r12", "memory", "cc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static void __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) emulate_generic_r2_14_noflags(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	struct arch_probes_insn *asi, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	emulate_generic_r0_12_noflags(insn, asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		(struct pt_regs *)(regs->uregs+2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) emulate_ldm_r3_15(probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct arch_probes_insn *asi, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	emulate_generic_r0_12_noflags(insn, asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		(struct pt_regs *)(regs->uregs+3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	load_write_pc(regs->ARM_pc, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) enum probes_insn __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		const struct decode_header *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	probes_insn_handler_t *handler = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	unsigned reglist = insn & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	int is_ldm = insn & 0x100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	int rn = (insn >> 16) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (rn <= 12 && (reglist & 0xe000) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		/* Instruction only uses registers in the range R0..R12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		handler = emulate_generic_r0_12_noflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	} else if (rn >= 2 && (reglist & 0x8003) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		/* Instruction only uses registers in the range R2..R14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		rn -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		reglist >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		handler = emulate_generic_r2_14_noflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	} else if (rn >= 3 && (reglist & 0x0007) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		/* Instruction only uses registers in the range R3..R15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		if (is_ldm && (reglist & 0x8000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			rn -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			reglist >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			handler = emulate_ldm_r3_15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (handler) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		/* We can emulate the instruction in (possibly) modified form */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 						   (rn << 16) | reglist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		asi->insn_handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return INSN_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/* Fallback to slower simulation... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (reglist & 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		handler = simulate_ldm1stm1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	asi->insn_handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	return INSN_GOOD_NO_SLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)