^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/decode.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/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/system_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "decode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #ifndef find_str_pc_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * For STR and STM instructions, an ARM core may choose to use either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * a +8 or a +12 displacement from the current instruction's address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Whichever value is chosen for a given core, it must be the same for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * both instructions and may not change. This function measures it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int str_pc_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void __init find_str_pc_offset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int addr, scratch, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) __asm__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "sub %[ret], pc, #4 \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) "str pc, %[addr] \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) "ldr %[scr], %[addr] \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "sub %[ret], %[scr], %[ret] \n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) str_pc_offset = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #endif /* !find_str_pc_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #ifndef test_load_write_pc_interworking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) bool load_write_pc_interworks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void __init test_load_write_pc_interworking(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int arch = cpu_architecture();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) BUG_ON(arch == CPU_ARCH_UNKNOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
^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) #endif /* !test_load_write_pc_interworking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #ifndef test_alu_write_pc_interworking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) bool alu_write_pc_interworks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) void __init test_alu_write_pc_interworking(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int arch = cpu_architecture();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) BUG_ON(arch == CPU_ARCH_UNKNOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #endif /* !test_alu_write_pc_interworking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void __init arm_probes_decode_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) find_str_pc_offset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) test_load_write_pc_interworking();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) test_alu_write_pc_interworking();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static unsigned long __kprobes __check_eq(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return cpsr & PSR_Z_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static unsigned long __kprobes __check_ne(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return (~cpsr) & PSR_Z_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static unsigned long __kprobes __check_cs(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return cpsr & PSR_C_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static unsigned long __kprobes __check_cc(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return (~cpsr) & PSR_C_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static unsigned long __kprobes __check_mi(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return cpsr & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static unsigned long __kprobes __check_pl(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return (~cpsr) & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static unsigned long __kprobes __check_vs(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return cpsr & PSR_V_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static unsigned long __kprobes __check_vc(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return (~cpsr) & PSR_V_BIT;
^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) static unsigned long __kprobes __check_hi(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return cpsr & PSR_C_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static unsigned long __kprobes __check_ls(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return (~cpsr) & PSR_C_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static unsigned long __kprobes __check_ge(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return (~cpsr) & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static unsigned long __kprobes __check_lt(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return cpsr & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static unsigned long __kprobes __check_gt(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return (~temp) & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static unsigned long __kprobes __check_le(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return temp & PSR_N_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static unsigned long __kprobes __check_al(unsigned long cpsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) probes_check_cc * const probes_condition_checks[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) &__check_eq, &__check_ne, &__check_cs, &__check_cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) &__check_mi, &__check_pl, &__check_vs, &__check_vc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) &__check_hi, &__check_ls, &__check_ge, &__check_lt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) &__check_gt, &__check_le, &__check_al, &__check_al
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) void __kprobes probes_simulate_nop(probes_opcode_t opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void __kprobes probes_emulate_none(probes_opcode_t opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) asi->insn_fn();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * Prepare an instruction slot to receive an instruction for emulating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * This is done by placing a subroutine return after the location where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * instruction will be placed. We also modify ARM instructions to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * unconditional as the condition code will already be checked before any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * emulation handler is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static probes_opcode_t __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) bool thumb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #ifdef CONFIG_THUMB2_KERNEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (thumb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u16 *thumb_insn = (u16 *)asi->insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Thumb bx lr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) thumb_insn[1] = __opcode_to_mem_thumb16(0x4770);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) thumb_insn[2] = __opcode_to_mem_thumb16(0x4770);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Make an ARM instruction unconditional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (insn < 0xe0000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) insn = (insn | 0xe0000000) & ~0x10000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Write a (probably modified) instruction into the slot previously prepared by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * prepare_emulated_insn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) bool thumb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #ifdef CONFIG_THUMB2_KERNEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (thumb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u16 *ip = (u16 *)asi->insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (is_wide_instruction(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *ip++ = __opcode_to_mem_thumb16(insn >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) *ip++ = __opcode_to_mem_thumb16(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) asi->insn[0] = __opcode_to_mem_arm(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * When we modify the register numbers encoded in an instruction to be emulated,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * the new values come from this define. For ARM and 32-bit Thumb instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * this gives...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * bit position 16 12 8 4 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * ---------------+---+---+---+---+---+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * register r2 r0 r1 -- r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #define INSN_NEW_BITS 0x00020103
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define INSN_SAMEAS16_BITS 0x22222222
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Validate and modify each of the registers encoded in an instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Each nibble in regs contains a value from enum decode_reg_type. For each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * non-zero value, the corresponding nibble in pinsn is validated and modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * according to the type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) probes_opcode_t insn = *pinsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) probes_opcode_t mask = 0xf; /* Start at least significant nibble */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) for (; regs != 0; regs >>= 4, mask <<= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) probes_opcode_t new_bits = INSN_NEW_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) switch (regs & 0xf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case REG_TYPE_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* Nibble not a register, skip to next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case REG_TYPE_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Any register is allowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case REG_TYPE_SAMEAS16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Replace register with same as at bit position 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) new_bits = INSN_SAMEAS16_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) case REG_TYPE_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Only allow SP (R13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if ((insn ^ 0xdddddddd) & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case REG_TYPE_PC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* Only allow PC (R15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if ((insn ^ 0xffffffff) & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case REG_TYPE_NOSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* Reject SP (R13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (((insn ^ 0xdddddddd) & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case REG_TYPE_NOSPPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case REG_TYPE_NOSPPCX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* Reject SP and PC (R13 and R15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case REG_TYPE_NOPCWB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!is_writeback(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break; /* No writeback, so any register is OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case REG_TYPE_NOPC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case REG_TYPE_NOPCX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Reject PC (R15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (((insn ^ 0xffffffff) & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* Replace value of nibble with new register number... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) insn &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) insn |= new_bits & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (modify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *pinsn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) reject:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) [DECODE_TYPE_OR] = sizeof(struct decode_or),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int run_checkers(const struct decode_checker *checkers[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int action, probes_opcode_t insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) const struct decode_header *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) const struct decode_checker **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!checkers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return INSN_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) p = checkers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) while (*p != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) probes_check_t *checker_func = (*p)[action].checker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) retval = INSN_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (checker_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) retval = checker_func(insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (retval == INSN_REJECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return INSN_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * probes_decode_insn operates on data tables in order to decode an ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * architecture instruction onto which a kprobe has been placed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * These instruction decoding tables are a concatenation of entries each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * of which consist of one of the following structs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * decode_table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * decode_custom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * decode_simulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * decode_emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * decode_or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * decode_reject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Each of these starts with a struct decode_header which has the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * fields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * type_regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * The least significant DECODE_TYPE_BITS of type_regs contains a value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * from enum decode_type, this indicates which of the decode_* structs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * the entry contains. The value DECODE_TYPE_END indicates the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * When the table is parsed, each entry is checked in turn to see if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * matches the instruction to be decoded using the test:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * (insn & mask) == value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * If no match is found before the end of the table is reached then decoding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * fails with INSN_REJECTED.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * When a match is found, decode_regs() is called to validate and modify each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * of the registers encoded in the instruction; the data it uses to do this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * to fail with INSN_REJECTED.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * Once the instruction has passed the above tests, further processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * depends on the type of the table entry's decode struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int __kprobes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) const union decode_item *table, bool thumb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) bool emulate, const union decode_action *actions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) const struct decode_checker *checkers[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) const struct decode_header *h = (struct decode_header *)table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) const struct decode_header *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) bool matched = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * @insn can be modified by decode_regs. Save its original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * value for checkers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) probes_opcode_t origin_insn = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * stack_space is initialized to 0 here. Checker functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * should update is value if they find this is a stack store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * instruction: positive value means bytes of stack usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * negitive value means unable to determine stack usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * statically. For instruction doesn't store to stack, checker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * do nothing with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) asi->stack_space = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Similarly to stack_space, register_usage_flags is filled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * checkers. Its default value is set to ~0, which is 'all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * registers are used', to prevent any potential optimization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) asi->register_usage_flags = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (emulate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) insn = prepare_emulated_insn(insn, asi, thumb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) for (;; h = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (type == DECODE_TYPE_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) next = (struct decode_header *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ((uintptr_t)h + decode_struct_sizes[type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!matched && (insn & h->mask.bits) != h->value.bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!decode_regs(&insn, regs, emulate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case DECODE_TYPE_TABLE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct decode_table *d = (struct decode_table *)h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) next = (struct decode_header *)d->table.table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case DECODE_TYPE_CUSTOM: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct decode_custom *d = (struct decode_custom *)h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int action = d->decoder.action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err = run_checkers(checkers, action, origin_insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (err == INSN_REJECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return actions[action].decoder(insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case DECODE_TYPE_SIMULATE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct decode_simulate *d = (struct decode_simulate *)h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int action = d->handler.action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) err = run_checkers(checkers, action, origin_insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (err == INSN_REJECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) asi->insn_handler = actions[action].handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return INSN_GOOD_NO_SLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case DECODE_TYPE_EMULATE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct decode_emulate *d = (struct decode_emulate *)h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int action = d->handler.action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) err = run_checkers(checkers, action, origin_insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (err == INSN_REJECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!emulate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return actions[action].decoder(insn, asi, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) asi->insn_handler = actions[action].handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) set_emulated_insn(insn, asi, thumb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return INSN_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case DECODE_TYPE_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) matched = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case DECODE_TYPE_REJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return INSN_REJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }