1 /*
2  * ARM debug helpers.
3  *
4  * This code is licensed under the GNU GPL v2 or later.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 #include "qemu/osdep.h"
9 #include "cpu.h"
10 #include "internals.h"
11 #include "exec/exec-all.h"
12 #include "exec/helper-proto.h"
13 
14 /* Return true if the linked breakpoint entry lbn passes its checks */
linked_bp_matches(ARMCPU * cpu,int lbn)15 static bool linked_bp_matches(ARMCPU *cpu, int lbn)
16 {
17     CPUARMState *env = &cpu->env;
18     uint64_t bcr = env->cp15.dbgbcr[lbn];
19     int brps = extract32(cpu->dbgdidr, 24, 4);
20     int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
21     int bt;
22     uint32_t contextidr;
23 
24     /*
25      * Links to unimplemented or non-context aware breakpoints are
26      * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or
27      * as if linked to an UNKNOWN context-aware breakpoint (in which
28      * case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
29      * We choose the former.
30      */
31     if (lbn > brps || lbn < (brps - ctx_cmps)) {
32         return false;
33     }
34 
35     bcr = env->cp15.dbgbcr[lbn];
36 
37     if (extract64(bcr, 0, 1) == 0) {
38         /* Linked breakpoint disabled : generate no events */
39         return false;
40     }
41 
42     bt = extract64(bcr, 20, 4);
43 
44     /*
45      * We match the whole register even if this is AArch32 using the
46      * short descriptor format (in which case it holds both PROCID and ASID),
47      * since we don't implement the optional v7 context ID masking.
48      */
49     contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
50 
51     switch (bt) {
52     case 3: /* linked context ID match */
53         if (arm_current_el(env) > 1) {
54             /* Context matches never fire in EL2 or (AArch64) EL3 */
55             return false;
56         }
57         return (contextidr == extract64(env->cp15.dbgbvr[lbn], 0, 32));
58     case 5: /* linked address mismatch (reserved in AArch64) */
59     case 9: /* linked VMID match (reserved if no EL2) */
60     case 11: /* linked context ID and VMID match (reserved if no EL2) */
61     default:
62         /*
63          * Links to Unlinked context breakpoints must generate no
64          * events; we choose to do the same for reserved values too.
65          */
66         return false;
67     }
68 
69     return false;
70 }
71 
bp_wp_matches(ARMCPU * cpu,int n,bool is_wp)72 static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
73 {
74     CPUARMState *env = &cpu->env;
75     uint64_t cr;
76     int pac, hmc, ssc, wt, lbn;
77     /*
78      * Note that for watchpoints the check is against the CPU security
79      * state, not the S/NS attribute on the offending data access.
80      */
81     bool is_secure = arm_is_secure(env);
82     int access_el = arm_current_el(env);
83 
84     if (is_wp) {
85         CPUWatchpoint *wp = env->cpu_watchpoint[n];
86 
87         if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
88             return false;
89         }
90         cr = env->cp15.dbgwcr[n];
91         if (wp->hitattrs.user) {
92             /*
93              * The LDRT/STRT/LDT/STT "unprivileged access" instructions should
94              * match watchpoints as if they were accesses done at EL0, even if
95              * the CPU is at EL1 or higher.
96              */
97             access_el = 0;
98         }
99     } else {
100         uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
101 
102         if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {
103             return false;
104         }
105         cr = env->cp15.dbgbcr[n];
106     }
107     /*
108      * The WATCHPOINT_HIT flag guarantees us that the watchpoint is
109      * enabled and that the address and access type match; for breakpoints
110      * we know the address matched; check the remaining fields, including
111      * linked breakpoints. We rely on WCR and BCR having the same layout
112      * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.
113      * Note that some combinations of {PAC, HMC, SSC} are reserved and
114      * must act either like some valid combination or as if the watchpoint
115      * were disabled. We choose the former, and use this together with
116      * the fact that EL3 must always be Secure and EL2 must always be
117      * Non-Secure to simplify the code slightly compared to the full
118      * table in the ARM ARM.
119      */
120     pac = extract64(cr, 1, 2);
121     hmc = extract64(cr, 13, 1);
122     ssc = extract64(cr, 14, 2);
123 
124     switch (ssc) {
125     case 0:
126         break;
127     case 1:
128     case 3:
129         if (is_secure) {
130             return false;
131         }
132         break;
133     case 2:
134         if (!is_secure) {
135             return false;
136         }
137         break;
138     }
139 
140     switch (access_el) {
141     case 3:
142     case 2:
143         if (!hmc) {
144             return false;
145         }
146         break;
147     case 1:
148         if (extract32(pac, 0, 1) == 0) {
149             return false;
150         }
151         break;
152     case 0:
153         if (extract32(pac, 1, 1) == 0) {
154             return false;
155         }
156         break;
157     default:
158         g_assert_not_reached();
159     }
160 
161     wt = extract64(cr, 20, 1);
162     lbn = extract64(cr, 16, 4);
163 
164     if (wt && !linked_bp_matches(cpu, lbn)) {
165         return false;
166     }
167 
168     return true;
169 }
170 
check_watchpoints(ARMCPU * cpu)171 static bool check_watchpoints(ARMCPU *cpu)
172 {
173     CPUARMState *env = &cpu->env;
174     int n;
175 
176     /*
177      * If watchpoints are disabled globally or we can't take debug
178      * exceptions here then watchpoint firings are ignored.
179      */
180     if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
181         || !arm_generate_debug_exceptions(env)) {
182         return false;
183     }
184 
185     for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {
186         if (bp_wp_matches(cpu, n, true)) {
187             return true;
188         }
189     }
190     return false;
191 }
192 
check_breakpoints(ARMCPU * cpu)193 static bool check_breakpoints(ARMCPU *cpu)
194 {
195     CPUARMState *env = &cpu->env;
196     int n;
197 
198     /*
199      * If breakpoints are disabled globally or we can't take debug
200      * exceptions here then breakpoint firings are ignored.
201      */
202     if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
203         || !arm_generate_debug_exceptions(env)) {
204         return false;
205     }
206 
207     for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
208         if (bp_wp_matches(cpu, n, false)) {
209             return true;
210         }
211     }
212     return false;
213 }
214 
HELPER(check_breakpoints)215 void HELPER(check_breakpoints)(CPUARMState *env)
216 {
217     ARMCPU *cpu = env_archcpu(env);
218 
219     if (check_breakpoints(cpu)) {
220         HELPER(exception_internal(env, EXCP_DEBUG));
221     }
222 }
223 
arm_debug_check_watchpoint(CPUState * cs,CPUWatchpoint * wp)224 bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
225 {
226     /*
227      * Called by core code when a CPU watchpoint fires; need to check if this
228      * is also an architectural watchpoint match.
229      */
230     ARMCPU *cpu = ARM_CPU(cs);
231 
232     return check_watchpoints(cpu);
233 }
234 
arm_debug_excp_handler(CPUState * cs)235 void arm_debug_excp_handler(CPUState *cs)
236 {
237     /*
238      * Called by core code when a watchpoint or breakpoint fires;
239      * need to check which one and raise the appropriate exception.
240      */
241     ARMCPU *cpu = ARM_CPU(cs);
242     CPUARMState *env = &cpu->env;
243     CPUWatchpoint *wp_hit = cs->watchpoint_hit;
244 
245     if (wp_hit) {
246         if (wp_hit->flags & BP_CPU) {
247             bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
248             bool same_el = arm_debug_target_el(env) == arm_current_el(env);
249 
250             cs->watchpoint_hit = NULL;
251 
252             env->exception.fsr = arm_debug_exception_fsr(env);
253             env->exception.vaddress = wp_hit->hitaddr;
254             raise_exception(env, EXCP_DATA_ABORT,
255                     syn_watchpoint(same_el, 0, wnr),
256                     arm_debug_target_el(env));
257         }
258     } else {
259         uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
260         bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
261 
262         /*
263          * (1) GDB breakpoints should be handled first.
264          * (2) Do not raise a CPU exception if no CPU breakpoint has fired,
265          * since singlestep is also done by generating a debug internal
266          * exception.
267          */
268         if (cpu_breakpoint_test(cs, pc, BP_GDB)
269             || !cpu_breakpoint_test(cs, pc, BP_CPU)) {
270             return;
271         }
272 
273         env->exception.fsr = arm_debug_exception_fsr(env);
274         /*
275          * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
276          * values to the guest that it shouldn't be able to see at its
277          * exception/security level.
278          */
279         env->exception.vaddress = 0;
280         raise_exception(env, EXCP_PREFETCH_ABORT,
281                         syn_breakpoint(same_el),
282                         arm_debug_target_el(env));
283     }
284 }
285 
286 #if !defined(CONFIG_USER_ONLY)
287 
arm_adjust_watchpoint_address(CPUState * cs,vaddr addr,int len)288 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
289 {
290     ARMCPU *cpu = ARM_CPU(cs);
291     CPUARMState *env = &cpu->env;
292 
293     /*
294      * In BE32 system mode, target memory is stored byteswapped (on a
295      * little-endian host system), and by the time we reach here (via an
296      * opcode helper) the addresses of subword accesses have been adjusted
297      * to account for that, which means that watchpoints will not match.
298      * Undo the adjustment here.
299      */
300     if (arm_sctlr_b(env)) {
301         if (len == 1) {
302             addr ^= 3;
303         } else if (len == 2) {
304             addr ^= 2;
305         }
306     }
307 
308     return addr;
309 }
310 
311 #endif
312