18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/probes/decode.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Some contents moved here from arch/arm/include/asm/kprobes.h which is 88c2ecf20Sopenharmony_ci * Copyright (C) 2006, 2007 Motorola Inc. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifndef _ARM_KERNEL_PROBES_H 128c2ecf20Sopenharmony_ci#define _ARM_KERNEL_PROBES_H 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/stddef.h> 168c2ecf20Sopenharmony_ci#include <asm/probes.h> 178c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 188c2ecf20Sopenharmony_ci#include <asm/kprobes.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_civoid __init arm_probes_decode_init(void); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciextern probes_check_cc * const probes_condition_checks[16]; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* str_pc_offset is architecturally defined from ARMv7 onwards */ 278c2ecf20Sopenharmony_ci#define str_pc_offset 8 288c2ecf20Sopenharmony_ci#define find_str_pc_offset() 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#else /* __LINUX_ARM_ARCH__ < 7 */ 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* We need a run-time check to determine str_pc_offset */ 338c2ecf20Sopenharmony_ciextern int str_pc_offset; 348c2ecf20Sopenharmony_civoid __init find_str_pc_offset(void); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#endif 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci long cpsr = regs->ARM_cpsr; 428c2ecf20Sopenharmony_ci if (pcv & 0x1) { 438c2ecf20Sopenharmony_ci cpsr |= PSR_T_BIT; 448c2ecf20Sopenharmony_ci pcv &= ~0x1; 458c2ecf20Sopenharmony_ci } else { 468c2ecf20Sopenharmony_ci cpsr &= ~PSR_T_BIT; 478c2ecf20Sopenharmony_ci pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci regs->ARM_cpsr = cpsr; 508c2ecf20Sopenharmony_ci regs->ARM_pc = pcv; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ 578c2ecf20Sopenharmony_ci#define load_write_pc_interworks true 588c2ecf20Sopenharmony_ci#define test_load_write_pc_interworking() 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#else /* __LINUX_ARM_ARCH__ < 6 */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* We need run-time testing to determine if load_write_pc() should interwork. */ 638c2ecf20Sopenharmony_ciextern bool load_write_pc_interworks; 648c2ecf20Sopenharmony_civoid __init test_load_write_pc_interworking(void); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#endif 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci if (load_write_pc_interworks) 718c2ecf20Sopenharmony_ci bx_write_pc(pcv, regs); 728c2ecf20Sopenharmony_ci else 738c2ecf20Sopenharmony_ci regs->ARM_pc = pcv; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define alu_write_pc_interworks true 808c2ecf20Sopenharmony_ci#define test_alu_write_pc_interworking() 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#elif __LINUX_ARM_ARCH__ <= 5 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ 858c2ecf20Sopenharmony_ci#define alu_write_pc_interworks false 868c2ecf20Sopenharmony_ci#define test_alu_write_pc_interworking() 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#else /* __LINUX_ARM_ARCH__ == 6 */ 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ 918c2ecf20Sopenharmony_ciextern bool alu_write_pc_interworks; 928c2ecf20Sopenharmony_civoid __init test_alu_write_pc_interworking(void); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#endif /* __LINUX_ARM_ARCH__ == 6 */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci if (alu_write_pc_interworks) 998c2ecf20Sopenharmony_ci bx_write_pc(pcv, regs); 1008c2ecf20Sopenharmony_ci else 1018c2ecf20Sopenharmony_ci regs->ARM_pc = pcv; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * Test if load/store instructions writeback the address register. 1078c2ecf20Sopenharmony_ci * if P (bit 24) == 0 or W (bit 21) == 1 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * The following definitions and macros are used to build instruction 1138c2ecf20Sopenharmony_ci * decoding tables for use by probes_decode_insn. 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * These tables are a concatenation of entries each of which consist of one of 1168c2ecf20Sopenharmony_ci * the decode_* structs. All of the fields in every type of decode structure 1178c2ecf20Sopenharmony_ci * are of the union type decode_item, therefore the entire decode table can be 1188c2ecf20Sopenharmony_ci * viewed as an array of these and declared like: 1198c2ecf20Sopenharmony_ci * 1208c2ecf20Sopenharmony_ci * static const union decode_item table_name[] = {}; 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * In order to construct each entry in the table, macros are used to 1238c2ecf20Sopenharmony_ci * initialise a number of sequential decode_item values in a layout which 1248c2ecf20Sopenharmony_ci * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct 1258c2ecf20Sopenharmony_ci * decode_simulate by initialising four decode_item objects like this... 1268c2ecf20Sopenharmony_ci * 1278c2ecf20Sopenharmony_ci * {.bits = _type}, 1288c2ecf20Sopenharmony_ci * {.bits = _mask}, 1298c2ecf20Sopenharmony_ci * {.bits = _value}, 1308c2ecf20Sopenharmony_ci * {.action = _handler}, 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * Initialising a specified member of the union means that the compiler 1338c2ecf20Sopenharmony_ci * will produce a warning if the argument is of an incorrect type. 1348c2ecf20Sopenharmony_ci * 1358c2ecf20Sopenharmony_ci * Below is a list of each of the macros used to initialise entries and a 1368c2ecf20Sopenharmony_ci * description of the action performed when that entry is matched to an 1378c2ecf20Sopenharmony_ci * instruction. A match is found when (instruction & mask) == value. 1388c2ecf20Sopenharmony_ci * 1398c2ecf20Sopenharmony_ci * DECODE_TABLE(mask, value, table) 1408c2ecf20Sopenharmony_ci * Instruction decoding jumps to parsing the new sub-table 'table'. 1418c2ecf20Sopenharmony_ci * 1428c2ecf20Sopenharmony_ci * DECODE_CUSTOM(mask, value, decoder) 1438c2ecf20Sopenharmony_ci * The value of 'decoder' is used as an index into the array of 1448c2ecf20Sopenharmony_ci * action functions, and the retrieved decoder function is invoked 1458c2ecf20Sopenharmony_ci * to complete decoding of the instruction. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * DECODE_SIMULATE(mask, value, handler) 1488c2ecf20Sopenharmony_ci * The probes instruction handler is set to the value found by 1498c2ecf20Sopenharmony_ci * indexing into the action array using the value of 'handler'. This 1508c2ecf20Sopenharmony_ci * will be used to simulate the instruction when the probe is hit. 1518c2ecf20Sopenharmony_ci * Decoding returns with INSN_GOOD_NO_SLOT. 1528c2ecf20Sopenharmony_ci * 1538c2ecf20Sopenharmony_ci * DECODE_EMULATE(mask, value, handler) 1548c2ecf20Sopenharmony_ci * The probes instruction handler is set to the value found by 1558c2ecf20Sopenharmony_ci * indexing into the action array using the value of 'handler'. This 1568c2ecf20Sopenharmony_ci * will be used to emulate the instruction when the probe is hit. The 1578c2ecf20Sopenharmony_ci * modified instruction (see below) is placed in the probes instruction 1588c2ecf20Sopenharmony_ci * slot so it may be called by the emulation code. Decoding returns 1598c2ecf20Sopenharmony_ci * with INSN_GOOD. 1608c2ecf20Sopenharmony_ci * 1618c2ecf20Sopenharmony_ci * DECODE_REJECT(mask, value) 1628c2ecf20Sopenharmony_ci * Instruction decoding fails with INSN_REJECTED 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * DECODE_OR(mask, value) 1658c2ecf20Sopenharmony_ci * This allows the mask/value test of multiple table entries to be 1668c2ecf20Sopenharmony_ci * logically ORed. Once an 'or' entry is matched the decoding action to 1678c2ecf20Sopenharmony_ci * be performed is that of the next entry which isn't an 'or'. E.g. 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * DECODE_OR (mask1, value1) 1708c2ecf20Sopenharmony_ci * DECODE_OR (mask2, value2) 1718c2ecf20Sopenharmony_ci * DECODE_SIMULATE (mask3, value3, simulation_handler) 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * This means that if any of the three mask/value pairs match the 1748c2ecf20Sopenharmony_ci * instruction being decoded, then 'simulation_handler' will be used 1758c2ecf20Sopenharmony_ci * for it. 1768c2ecf20Sopenharmony_ci * 1778c2ecf20Sopenharmony_ci * Both the SIMULATE and EMULATE macros have a second form which take an 1788c2ecf20Sopenharmony_ci * additional 'regs' argument. 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * DECODE_SIMULATEX(mask, value, handler, regs) 1818c2ecf20Sopenharmony_ci * DECODE_EMULATEX (mask, value, handler, regs) 1828c2ecf20Sopenharmony_ci * 1838c2ecf20Sopenharmony_ci * These are used to specify what kind of CPU register is encoded in each of the 1848c2ecf20Sopenharmony_ci * least significant 5 nibbles of the instruction being decoded. The regs value 1858c2ecf20Sopenharmony_ci * is specified using the REGS macro, this takes any of the REG_TYPE_* values 1868c2ecf20Sopenharmony_ci * from enum decode_reg_type as arguments; only the '*' part of the name is 1878c2ecf20Sopenharmony_ci * given. E.g. 1888c2ecf20Sopenharmony_ci * 1898c2ecf20Sopenharmony_ci * REGS(0, ANY, NOPC, 0, ANY) 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * This indicates an instruction is encoded like: 1928c2ecf20Sopenharmony_ci * 1938c2ecf20Sopenharmony_ci * bits 19..16 ignore 1948c2ecf20Sopenharmony_ci * bits 15..12 any register allowed here 1958c2ecf20Sopenharmony_ci * bits 11.. 8 any register except PC allowed here 1968c2ecf20Sopenharmony_ci * bits 7.. 4 ignore 1978c2ecf20Sopenharmony_ci * bits 3.. 0 any register allowed here 1988c2ecf20Sopenharmony_ci * 1998c2ecf20Sopenharmony_ci * This register specification is checked after a decode table entry is found to 2008c2ecf20Sopenharmony_ci * match an instruction (through the mask/value test). Any invalid register then 2018c2ecf20Sopenharmony_ci * found in the instruction will cause decoding to fail with INSN_REJECTED. In 2028c2ecf20Sopenharmony_ci * the above example this would happen if bits 11..8 of the instruction were 2038c2ecf20Sopenharmony_ci * 1111, indicating R15 or PC. 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * As well as checking for legal combinations of registers, this data is also 2068c2ecf20Sopenharmony_ci * used to modify the registers encoded in the instructions so that an 2078c2ecf20Sopenharmony_ci * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) 2088c2ecf20Sopenharmony_ci * 2098c2ecf20Sopenharmony_ci * Here is a real example which matches ARM instructions of the form 2108c2ecf20Sopenharmony_ci * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, 2138c2ecf20Sopenharmony_ci * REGS(ANY, ANY, NOPC, 0, ANY)), 2148c2ecf20Sopenharmony_ci * ^ ^ ^ ^ 2158c2ecf20Sopenharmony_ci * Rn Rd Rs Rm 2168c2ecf20Sopenharmony_ci * 2178c2ecf20Sopenharmony_ci * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because 2188c2ecf20Sopenharmony_ci * Rs == R15 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the 2218c2ecf20Sopenharmony_ci * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into 2228c2ecf20Sopenharmony_ci * the kprobes instruction slot. This can then be called later by the handler 2238c2ecf20Sopenharmony_ci * function emulate_rd12rn16rm0rs8_rwflags (a pointer to which is retrieved from 2248c2ecf20Sopenharmony_ci * the indicated slot in the action array), in order to simulate the instruction. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cienum decode_type { 2288c2ecf20Sopenharmony_ci DECODE_TYPE_END, 2298c2ecf20Sopenharmony_ci DECODE_TYPE_TABLE, 2308c2ecf20Sopenharmony_ci DECODE_TYPE_CUSTOM, 2318c2ecf20Sopenharmony_ci DECODE_TYPE_SIMULATE, 2328c2ecf20Sopenharmony_ci DECODE_TYPE_EMULATE, 2338c2ecf20Sopenharmony_ci DECODE_TYPE_OR, 2348c2ecf20Sopenharmony_ci DECODE_TYPE_REJECT, 2358c2ecf20Sopenharmony_ci NUM_DECODE_TYPES /* Must be last enum */ 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci#define DECODE_TYPE_BITS 4 2398c2ecf20Sopenharmony_ci#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cienum decode_reg_type { 2428c2ecf20Sopenharmony_ci REG_TYPE_NONE = 0, /* Not a register, ignore */ 2438c2ecf20Sopenharmony_ci REG_TYPE_ANY, /* Any register allowed */ 2448c2ecf20Sopenharmony_ci REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ 2458c2ecf20Sopenharmony_ci REG_TYPE_SP, /* Register must be SP */ 2468c2ecf20Sopenharmony_ci REG_TYPE_PC, /* Register must be PC */ 2478c2ecf20Sopenharmony_ci REG_TYPE_NOSP, /* Register must not be SP */ 2488c2ecf20Sopenharmony_ci REG_TYPE_NOSPPC, /* Register must not be SP or PC */ 2498c2ecf20Sopenharmony_ci REG_TYPE_NOPC, /* Register must not be PC */ 2508c2ecf20Sopenharmony_ci REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* The following types are used when the encoding for PC indicates 2538c2ecf20Sopenharmony_ci * another instruction form. This distiction only matters for test 2548c2ecf20Sopenharmony_ci * case coverage checks. 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_ci REG_TYPE_NOPCX, /* Register must not be PC */ 2578c2ecf20Sopenharmony_ci REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* Alias to allow '0' arg to be used in REGS macro. */ 2608c2ecf20Sopenharmony_ci REG_TYPE_0 = REG_TYPE_NONE 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci#define REGS(r16, r12, r8, r4, r0) \ 2648c2ecf20Sopenharmony_ci (((REG_TYPE_##r16) << 16) + \ 2658c2ecf20Sopenharmony_ci ((REG_TYPE_##r12) << 12) + \ 2668c2ecf20Sopenharmony_ci ((REG_TYPE_##r8) << 8) + \ 2678c2ecf20Sopenharmony_ci ((REG_TYPE_##r4) << 4) + \ 2688c2ecf20Sopenharmony_ci (REG_TYPE_##r0)) 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ciunion decode_item { 2718c2ecf20Sopenharmony_ci u32 bits; 2728c2ecf20Sopenharmony_ci const union decode_item *table; 2738c2ecf20Sopenharmony_ci int action; 2748c2ecf20Sopenharmony_ci}; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistruct decode_header; 2778c2ecf20Sopenharmony_citypedef enum probes_insn (probes_custom_decode_t)(probes_opcode_t, 2788c2ecf20Sopenharmony_ci struct arch_probes_insn *, 2798c2ecf20Sopenharmony_ci const struct decode_header *); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ciunion decode_action { 2828c2ecf20Sopenharmony_ci probes_insn_handler_t *handler; 2838c2ecf20Sopenharmony_ci probes_custom_decode_t *decoder; 2848c2ecf20Sopenharmony_ci}; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_citypedef enum probes_insn (probes_check_t)(probes_opcode_t, 2878c2ecf20Sopenharmony_ci struct arch_probes_insn *, 2888c2ecf20Sopenharmony_ci const struct decode_header *); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistruct decode_checker { 2918c2ecf20Sopenharmony_ci probes_check_t *checker; 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci#define DECODE_END \ 2958c2ecf20Sopenharmony_ci {.bits = DECODE_TYPE_END} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistruct decode_header { 2998c2ecf20Sopenharmony_ci union decode_item type_regs; 3008c2ecf20Sopenharmony_ci union decode_item mask; 3018c2ecf20Sopenharmony_ci union decode_item value; 3028c2ecf20Sopenharmony_ci}; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci#define DECODE_HEADER(_type, _mask, _value, _regs) \ 3058c2ecf20Sopenharmony_ci {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ 3068c2ecf20Sopenharmony_ci {.bits = (_mask)}, \ 3078c2ecf20Sopenharmony_ci {.bits = (_value)} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistruct decode_table { 3118c2ecf20Sopenharmony_ci struct decode_header header; 3128c2ecf20Sopenharmony_ci union decode_item table; 3138c2ecf20Sopenharmony_ci}; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#define DECODE_TABLE(_mask, _value, _table) \ 3168c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ 3178c2ecf20Sopenharmony_ci {.table = (_table)} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistruct decode_custom { 3218c2ecf20Sopenharmony_ci struct decode_header header; 3228c2ecf20Sopenharmony_ci union decode_item decoder; 3238c2ecf20Sopenharmony_ci}; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci#define DECODE_CUSTOM(_mask, _value, _decoder) \ 3268c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ 3278c2ecf20Sopenharmony_ci {.action = (_decoder)} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistruct decode_simulate { 3318c2ecf20Sopenharmony_ci struct decode_header header; 3328c2ecf20Sopenharmony_ci union decode_item handler; 3338c2ecf20Sopenharmony_ci}; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ 3368c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ 3378c2ecf20Sopenharmony_ci {.action = (_handler)} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci#define DECODE_SIMULATE(_mask, _value, _handler) \ 3408c2ecf20Sopenharmony_ci DECODE_SIMULATEX(_mask, _value, _handler, 0) 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistruct decode_emulate { 3448c2ecf20Sopenharmony_ci struct decode_header header; 3458c2ecf20Sopenharmony_ci union decode_item handler; 3468c2ecf20Sopenharmony_ci}; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ 3498c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ 3508c2ecf20Sopenharmony_ci {.action = (_handler)} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci#define DECODE_EMULATE(_mask, _value, _handler) \ 3538c2ecf20Sopenharmony_ci DECODE_EMULATEX(_mask, _value, _handler, 0) 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistruct decode_or { 3578c2ecf20Sopenharmony_ci struct decode_header header; 3588c2ecf20Sopenharmony_ci}; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci#define DECODE_OR(_mask, _value) \ 3618c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cienum probes_insn { 3648c2ecf20Sopenharmony_ci INSN_REJECTED, 3658c2ecf20Sopenharmony_ci INSN_GOOD, 3668c2ecf20Sopenharmony_ci INSN_GOOD_NO_SLOT 3678c2ecf20Sopenharmony_ci}; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistruct decode_reject { 3708c2ecf20Sopenharmony_ci struct decode_header header; 3718c2ecf20Sopenharmony_ci}; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci#define DECODE_REJECT(_mask, _value) \ 3748c2ecf20Sopenharmony_ci DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ciprobes_insn_handler_t probes_simulate_nop; 3778c2ecf20Sopenharmony_ciprobes_insn_handler_t probes_emulate_none; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ciint __kprobes 3808c2ecf20Sopenharmony_ciprobes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 3818c2ecf20Sopenharmony_ci const union decode_item *table, bool thumb, bool emulate, 3828c2ecf20Sopenharmony_ci const union decode_action *actions, 3838c2ecf20Sopenharmony_ci const struct decode_checker **checkers); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci#endif 386