decode-insn.c (cc9b94029e9ef51787af908e9856b1eed314bc00) decode-insn.c (c2249707ee53b5dd696f0fae8543a754684ea04a)
1/*
2 * arch/arm64/kernel/probes/decode-insn.c
3 *
4 * Copyright (C) 2013 Linaro Limited.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.

--- 64 unchanged lines hidden (view full) ---

73 return true;
74}
75
76/* Return:
77 * INSN_REJECTED If instruction is one not allowed to kprobe,
78 * INSN_GOOD If instruction is supported and uses instruction slot,
79 * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
80 */
1/*
2 * arch/arm64/kernel/probes/decode-insn.c
3 *
4 * Copyright (C) 2013 Linaro Limited.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.

--- 64 unchanged lines hidden (view full) ---

73 return true;
74}
75
76/* Return:
77 * INSN_REJECTED If instruction is one not allowed to kprobe,
78 * INSN_GOOD If instruction is supported and uses instruction slot,
79 * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
80 */
81static enum kprobe_insn __kprobes
82arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
81enum probe_insn __kprobes
82arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api)
83{
84 /*
85 * Instructions reading or modifying the PC won't work from the XOL
86 * slot.
87 */
88 if (aarch64_insn_is_steppable(insn))
89 return INSN_GOOD;
90
91 if (aarch64_insn_is_bcond(insn)) {
83{
84 /*
85 * Instructions reading or modifying the PC won't work from the XOL
86 * slot.
87 */
88 if (aarch64_insn_is_steppable(insn))
89 return INSN_GOOD;
90
91 if (aarch64_insn_is_bcond(insn)) {
92 asi->handler = simulate_b_cond;
92 api->handler = simulate_b_cond;
93 } else if (aarch64_insn_is_cbz(insn) ||
94 aarch64_insn_is_cbnz(insn)) {
93 } else if (aarch64_insn_is_cbz(insn) ||
94 aarch64_insn_is_cbnz(insn)) {
95 asi->handler = simulate_cbz_cbnz;
95 api->handler = simulate_cbz_cbnz;
96 } else if (aarch64_insn_is_tbz(insn) ||
97 aarch64_insn_is_tbnz(insn)) {
96 } else if (aarch64_insn_is_tbz(insn) ||
97 aarch64_insn_is_tbnz(insn)) {
98 asi->handler = simulate_tbz_tbnz;
98 api->handler = simulate_tbz_tbnz;
99 } else if (aarch64_insn_is_adr_adrp(insn)) {
99 } else if (aarch64_insn_is_adr_adrp(insn)) {
100 asi->handler = simulate_adr_adrp;
100 api->handler = simulate_adr_adrp;
101 } else if (aarch64_insn_is_b(insn) ||
102 aarch64_insn_is_bl(insn)) {
101 } else if (aarch64_insn_is_b(insn) ||
102 aarch64_insn_is_bl(insn)) {
103 asi->handler = simulate_b_bl;
103 api->handler = simulate_b_bl;
104 } else if (aarch64_insn_is_br(insn) ||
105 aarch64_insn_is_blr(insn) ||
106 aarch64_insn_is_ret(insn)) {
104 } else if (aarch64_insn_is_br(insn) ||
105 aarch64_insn_is_blr(insn) ||
106 aarch64_insn_is_ret(insn)) {
107 asi->handler = simulate_br_blr_ret;
107 api->handler = simulate_br_blr_ret;
108 } else if (aarch64_insn_is_ldr_lit(insn)) {
108 } else if (aarch64_insn_is_ldr_lit(insn)) {
109 asi->handler = simulate_ldr_literal;
109 api->handler = simulate_ldr_literal;
110 } else if (aarch64_insn_is_ldrsw_lit(insn)) {
110 } else if (aarch64_insn_is_ldrsw_lit(insn)) {
111 asi->handler = simulate_ldrsw_literal;
111 api->handler = simulate_ldrsw_literal;
112 } else {
113 /*
114 * Instruction cannot be stepped out-of-line and we don't
115 * (yet) simulate it.
116 */
117 return INSN_REJECTED;
118 }
119
120 return INSN_GOOD_NO_SLOT;
121}
122
112 } else {
113 /*
114 * Instruction cannot be stepped out-of-line and we don't
115 * (yet) simulate it.
116 */
117 return INSN_REJECTED;
118 }
119
120 return INSN_GOOD_NO_SLOT;
121}
122
123#ifdef CONFIG_KPROBES
123static bool __kprobes
124is_probed_address_atomic(kprobe_opcode_t *scan_start, kprobe_opcode_t *scan_end)
125{
126 while (scan_start >= scan_end) {
127 /*
128 * atomic region starts from exclusive load and ends with
129 * exclusive store.
130 */
131 if (aarch64_insn_is_store_ex(le32_to_cpu(*scan_start)))
132 return false;
133 else if (aarch64_insn_is_load_ex(le32_to_cpu(*scan_start)))
134 return true;
135 scan_start--;
136 }
137
138 return false;
139}
140
124static bool __kprobes
125is_probed_address_atomic(kprobe_opcode_t *scan_start, kprobe_opcode_t *scan_end)
126{
127 while (scan_start >= scan_end) {
128 /*
129 * atomic region starts from exclusive load and ends with
130 * exclusive store.
131 */
132 if (aarch64_insn_is_store_ex(le32_to_cpu(*scan_start)))
133 return false;
134 else if (aarch64_insn_is_load_ex(le32_to_cpu(*scan_start)))
135 return true;
136 scan_start--;
137 }
138
139 return false;
140}
141
141enum kprobe_insn __kprobes
142enum probe_insn __kprobes
142arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
143{
143arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
144{
144 enum kprobe_insn decoded;
145 kprobe_opcode_t insn = le32_to_cpu(*addr);
146 kprobe_opcode_t *scan_end = NULL;
145 enum probe_insn decoded;
146 probe_opcode_t insn = le32_to_cpu(*addr);
147 probe_opcode_t *scan_end = NULL;
147 unsigned long size = 0, offset = 0;
148
149 /*
150 * If there's a symbol defined in front of and near enough to
151 * the probe address assume it is the entry point to this
152 * code and use it to further limit how far back we search
153 * when determining if we're in an atomic sequence. If we could
154 * not find any symbol skip the atomic test altogether as we
155 * could otherwise end up searching irrelevant text/literals.
156 * KPROBES depends on KALLSYMS so this last case should never
157 * happen.
158 */
159 if (kallsyms_lookup_size_offset((unsigned long) addr, &size, &offset)) {
160 if (offset < (MAX_ATOMIC_CONTEXT_SIZE*sizeof(kprobe_opcode_t)))
161 scan_end = addr - (offset / sizeof(kprobe_opcode_t));
162 else
163 scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE;
164 }
148 unsigned long size = 0, offset = 0;
149
150 /*
151 * If there's a symbol defined in front of and near enough to
152 * the probe address assume it is the entry point to this
153 * code and use it to further limit how far back we search
154 * when determining if we're in an atomic sequence. If we could
155 * not find any symbol skip the atomic test altogether as we
156 * could otherwise end up searching irrelevant text/literals.
157 * KPROBES depends on KALLSYMS so this last case should never
158 * happen.
159 */
160 if (kallsyms_lookup_size_offset((unsigned long) addr, &size, &offset)) {
161 if (offset < (MAX_ATOMIC_CONTEXT_SIZE*sizeof(kprobe_opcode_t)))
162 scan_end = addr - (offset / sizeof(kprobe_opcode_t));
163 else
164 scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE;
165 }
165 decoded = arm_probe_decode_insn(insn, asi);
166 decoded = arm_probe_decode_insn(insn, &asi->api);
166
167 if (decoded != INSN_REJECTED && scan_end)
168 if (is_probed_address_atomic(addr - 1, scan_end))
169 return INSN_REJECTED;
170
171 return decoded;
172}
167
168 if (decoded != INSN_REJECTED && scan_end)
169 if (is_probed_address_atomic(addr - 1, scan_end))
170 return INSN_REJECTED;
171
172 return decoded;
173}
174#endif