]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/debug_monitor.c
contrib/tzdata: import tzdata 2022c
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / debug_monitor.c
1 /*-
2  * Copyright (c) 2014 The FreeBSD Foundation
3  *
4  * This software was developed by Semihalf under
5  * the sponsorship of the FreeBSD Foundation.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include "opt_ddb.h"
30 #include "opt_gdb.h"
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/kdb.h>
38 #include <sys/pcpu.h>
39 #include <sys/proc.h>
40 #include <sys/systm.h>
41 #include <sys/sysent.h>
42
43 #include <machine/armreg.h>
44 #include <machine/cpu.h>
45 #include <machine/debug_monitor.h>
46 #include <machine/kdb.h>
47
48 #ifdef DDB
49 #include <ddb/ddb.h>
50 #include <ddb/db_sym.h>
51 #endif
52
53 enum dbg_t {
54         DBG_TYPE_BREAKPOINT = 0,
55         DBG_TYPE_WATCHPOINT = 1,
56 };
57
58 static int dbg_watchpoint_num;
59 static int dbg_breakpoint_num;
60 static struct debug_monitor_state kernel_monitor = {
61         .dbg_flags = DBGMON_KERNEL
62 };
63
64 /* Called from the exception handlers */
65 void dbg_monitor_enter(struct thread *);
66 void dbg_monitor_exit(struct thread *, struct trapframe *);
67
68 /* Watchpoints/breakpoints control register bitfields */
69 #define DBG_WATCH_CTRL_LEN_1            (0x1 << 5)
70 #define DBG_WATCH_CTRL_LEN_2            (0x3 << 5)
71 #define DBG_WATCH_CTRL_LEN_4            (0xf << 5)
72 #define DBG_WATCH_CTRL_LEN_8            (0xff << 5)
73 #define DBG_WATCH_CTRL_LEN_MASK(x)      ((x) & (0xff << 5))
74 #define DBG_WATCH_CTRL_EXEC             (0x0 << 3)
75 #define DBG_WATCH_CTRL_LOAD             (0x1 << 3)
76 #define DBG_WATCH_CTRL_STORE            (0x2 << 3)
77 #define DBG_WATCH_CTRL_ACCESS_MASK(x)   ((x) & (0x3 << 3))
78
79 /* Common for breakpoint and watchpoint */
80 #define DBG_WB_CTRL_EL1         (0x1 << 1)
81 #define DBG_WB_CTRL_EL0         (0x2 << 1)
82 #define DBG_WB_CTRL_ELX_MASK(x) ((x) & (0x3 << 1))
83 #define DBG_WB_CTRL_E           (0x1 << 0)
84
85 #define DBG_REG_BASE_BVR        0
86 #define DBG_REG_BASE_BCR        (DBG_REG_BASE_BVR + 16)
87 #define DBG_REG_BASE_WVR        (DBG_REG_BASE_BCR + 16)
88 #define DBG_REG_BASE_WCR        (DBG_REG_BASE_WVR + 16)
89
90 /* Watchpoint/breakpoint helpers */
91 #define DBG_WB_WVR      "wvr"
92 #define DBG_WB_WCR      "wcr"
93 #define DBG_WB_BVR      "bvr"
94 #define DBG_WB_BCR      "bcr"
95
96 #define DBG_WB_READ(reg, num, val) do {                                 \
97         __asm __volatile("mrs %0, dbg" reg #num "_el1" : "=r" (val));   \
98 } while (0)
99
100 #define DBG_WB_WRITE(reg, num, val) do {                                \
101         __asm __volatile("msr dbg" reg #num "_el1, %0" :: "r" (val));   \
102 } while (0)
103
104 #define READ_WB_REG_CASE(reg, num, offset, val)         \
105         case (num + offset):                            \
106                 DBG_WB_READ(reg, num, val);             \
107                 break
108
109 #define WRITE_WB_REG_CASE(reg, num, offset, val)        \
110         case (num + offset):                            \
111                 DBG_WB_WRITE(reg, num, val);            \
112                 break
113
114 #define SWITCH_CASES_READ_WB_REG(reg, offset, val)      \
115         READ_WB_REG_CASE(reg,  0, offset, val);         \
116         READ_WB_REG_CASE(reg,  1, offset, val);         \
117         READ_WB_REG_CASE(reg,  2, offset, val);         \
118         READ_WB_REG_CASE(reg,  3, offset, val);         \
119         READ_WB_REG_CASE(reg,  4, offset, val);         \
120         READ_WB_REG_CASE(reg,  5, offset, val);         \
121         READ_WB_REG_CASE(reg,  6, offset, val);         \
122         READ_WB_REG_CASE(reg,  7, offset, val);         \
123         READ_WB_REG_CASE(reg,  8, offset, val);         \
124         READ_WB_REG_CASE(reg,  9, offset, val);         \
125         READ_WB_REG_CASE(reg, 10, offset, val);         \
126         READ_WB_REG_CASE(reg, 11, offset, val);         \
127         READ_WB_REG_CASE(reg, 12, offset, val);         \
128         READ_WB_REG_CASE(reg, 13, offset, val);         \
129         READ_WB_REG_CASE(reg, 14, offset, val);         \
130         READ_WB_REG_CASE(reg, 15, offset, val)
131
132 #define SWITCH_CASES_WRITE_WB_REG(reg, offset, val)     \
133         WRITE_WB_REG_CASE(reg,  0, offset, val);        \
134         WRITE_WB_REG_CASE(reg,  1, offset, val);        \
135         WRITE_WB_REG_CASE(reg,  2, offset, val);        \
136         WRITE_WB_REG_CASE(reg,  3, offset, val);        \
137         WRITE_WB_REG_CASE(reg,  4, offset, val);        \
138         WRITE_WB_REG_CASE(reg,  5, offset, val);        \
139         WRITE_WB_REG_CASE(reg,  6, offset, val);        \
140         WRITE_WB_REG_CASE(reg,  7, offset, val);        \
141         WRITE_WB_REG_CASE(reg,  8, offset, val);        \
142         WRITE_WB_REG_CASE(reg,  9, offset, val);        \
143         WRITE_WB_REG_CASE(reg, 10, offset, val);        \
144         WRITE_WB_REG_CASE(reg, 11, offset, val);        \
145         WRITE_WB_REG_CASE(reg, 12, offset, val);        \
146         WRITE_WB_REG_CASE(reg, 13, offset, val);        \
147         WRITE_WB_REG_CASE(reg, 14, offset, val);        \
148         WRITE_WB_REG_CASE(reg, 15, offset, val)
149
150 #ifdef DDB
151 static uint64_t
152 dbg_wb_read_reg(int reg, int n)
153 {
154         uint64_t val = 0;
155
156         switch (reg + n) {
157         SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
158         SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
159         SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
160         SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
161         default:
162                 printf("trying to read from wrong debug register %d\n", n);
163         }
164
165         return val;
166 }
167 #endif /* DDB */
168
169 static void
170 dbg_wb_write_reg(int reg, int n, uint64_t val)
171 {
172         switch (reg + n) {
173         SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
174         SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
175         SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
176         SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
177         default:
178                 printf("trying to write to wrong debug register %d\n", n);
179                 return;
180         }
181         isb();
182 }
183
184 #if defined(DDB) || defined(GDB)
185 void
186 kdb_cpu_set_singlestep(void)
187 {
188
189         KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
190             ("%s: debug exceptions are not masked", __func__));
191
192         kdb_frame->tf_spsr |= PSR_SS;
193         WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) |
194             MDSCR_SS | MDSCR_KDE);
195
196         /*
197          * Disable breakpoints and watchpoints, e.g. stepping
198          * over watched instruction will trigger break exception instead of
199          * single-step exception and locks CPU on that instruction for ever.
200          */
201         if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
202                 WRITE_SPECIALREG(mdscr_el1,
203                     READ_SPECIALREG(mdscr_el1) & ~MDSCR_MDE);
204         }
205 }
206
207 void
208 kdb_cpu_clear_singlestep(void)
209 {
210
211         KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
212             ("%s: debug exceptions are not masked", __func__));
213
214         WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) &
215             ~(MDSCR_SS | MDSCR_KDE));
216
217         /* Restore breakpoints and watchpoints */
218         if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
219                 WRITE_SPECIALREG(mdscr_el1,
220                     READ_SPECIALREG(mdscr_el1) | MDSCR_MDE);
221
222                 if ((kernel_monitor.dbg_flags & DBGMON_KERNEL) != 0) {
223                         WRITE_SPECIALREG(mdscr_el1,
224                             READ_SPECIALREG(mdscr_el1) | MDSCR_KDE);
225                 }
226         }
227 }
228
229 int
230 kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access)
231 {
232         enum dbg_access_t dbg_access;
233
234         switch (access) {
235         case KDB_DBG_ACCESS_R:
236                 dbg_access = HW_BREAKPOINT_R;
237                 break;
238         case KDB_DBG_ACCESS_W:
239                 dbg_access = HW_BREAKPOINT_W;
240                 break;
241         case KDB_DBG_ACCESS_RW:
242                 dbg_access = HW_BREAKPOINT_RW;
243                 break;
244         default:
245                 return (EINVAL);
246         }
247
248         return (dbg_setup_watchpoint(NULL, addr, size, dbg_access));
249 }
250
251 int
252 kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size)
253 {
254
255         return (dbg_remove_watchpoint(NULL, addr, size));
256 }
257 #endif /* DDB || GDB */
258
259 #ifdef DDB
260 static const char *
261 dbg_watchtype_str(uint32_t type)
262 {
263         switch (type) {
264                 case DBG_WATCH_CTRL_EXEC:
265                         return ("execute");
266                 case DBG_WATCH_CTRL_STORE:
267                         return ("write");
268                 case DBG_WATCH_CTRL_LOAD:
269                         return ("read");
270                 case DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE:
271                         return ("read/write");
272                 default:
273                         return ("invalid");
274         }
275 }
276
277 static int
278 dbg_watchtype_len(uint32_t len)
279 {
280         switch (len) {
281         case DBG_WATCH_CTRL_LEN_1:
282                 return (1);
283         case DBG_WATCH_CTRL_LEN_2:
284                 return (2);
285         case DBG_WATCH_CTRL_LEN_4:
286                 return (4);
287         case DBG_WATCH_CTRL_LEN_8:
288                 return (8);
289         default:
290                 return (0);
291         }
292 }
293
294 void
295 dbg_show_watchpoint(void)
296 {
297         uint32_t wcr, len, type;
298         uint64_t addr;
299         int i;
300
301         db_printf("\nhardware watchpoints:\n");
302         db_printf("  watch    status        type  len             address              symbol\n");
303         db_printf("  -----  --------  ----------  ---  ------------------  ------------------\n");
304         for (i = 0; i < dbg_watchpoint_num; i++) {
305                 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
306                 if ((wcr & DBG_WB_CTRL_E) != 0) {
307                         type = DBG_WATCH_CTRL_ACCESS_MASK(wcr);
308                         len = DBG_WATCH_CTRL_LEN_MASK(wcr);
309                         addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i);
310                         db_printf("  %-5d  %-8s  %10s  %3d  0x%16lx  ",
311                             i, "enabled", dbg_watchtype_str(type),
312                             dbg_watchtype_len(len), addr);
313                         db_printsym((db_addr_t)addr, DB_STGY_ANY);
314                         db_printf("\n");
315                 } else {
316                         db_printf("  %-5d  disabled\n", i);
317                 }
318         }
319 }
320 #endif /* DDB */
321
322 static int
323 dbg_find_free_slot(struct debug_monitor_state *monitor, enum dbg_t type)
324 {
325         uint64_t *reg;
326         u_int max, i;
327
328         switch(type) {
329         case DBG_TYPE_BREAKPOINT:
330                 max = dbg_breakpoint_num;
331                 reg = monitor->dbg_bcr;
332                 break;
333         case DBG_TYPE_WATCHPOINT:
334                 max = dbg_watchpoint_num;
335                 reg = monitor->dbg_wcr;
336                 break;
337         default:
338                 printf("Unsupported debug type\n");
339                 return (i);
340         }
341
342         for (i = 0; i < max; i++) {
343                 if ((reg[i] & DBG_WB_CTRL_E) == 0)
344                         return (i);
345         }
346
347         return (-1);
348 }
349
350 static int
351 dbg_find_slot(struct debug_monitor_state *monitor, enum dbg_t type,
352     vm_offset_t addr)
353 {
354         uint64_t *reg_addr, *reg_ctrl;
355         u_int max, i;
356
357         switch(type) {
358         case DBG_TYPE_BREAKPOINT:
359                 max = dbg_breakpoint_num;
360                 reg_addr = monitor->dbg_bvr;
361                 reg_ctrl = monitor->dbg_bcr;
362                 break;
363         case DBG_TYPE_WATCHPOINT:
364                 max = dbg_watchpoint_num;
365                 reg_addr = monitor->dbg_wvr;
366                 reg_ctrl = monitor->dbg_wcr;
367                 break;
368         default:
369                 printf("Unsupported debug type\n");
370                 return (i);
371         }
372
373         for (i = 0; i < max; i++) {
374                 if (reg_addr[i] == addr &&
375                     (reg_ctrl[i] & DBG_WB_CTRL_E) != 0)
376                         return (i);
377         }
378
379         return (-1);
380 }
381
382 int
383 dbg_setup_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
384     vm_size_t size, enum dbg_access_t access)
385 {
386         uint64_t wcr_size, wcr_priv, wcr_access;
387         u_int i;
388
389         if (monitor == NULL)
390                 monitor = &kernel_monitor;
391
392         i = dbg_find_free_slot(monitor, DBG_TYPE_WATCHPOINT);
393         if (i == -1) {
394                 printf("Can not find slot for watchpoint, max %d"
395                     " watchpoints supported\n", dbg_watchpoint_num);
396                 return (EBUSY);
397         }
398
399         switch(size) {
400         case 1:
401                 wcr_size = DBG_WATCH_CTRL_LEN_1;
402                 break;
403         case 2:
404                 wcr_size = DBG_WATCH_CTRL_LEN_2;
405                 break;
406         case 4:
407                 wcr_size = DBG_WATCH_CTRL_LEN_4;
408                 break;
409         case 8:
410                 wcr_size = DBG_WATCH_CTRL_LEN_8;
411                 break;
412         default:
413                 printf("Unsupported address size for watchpoint: %zu\n", size);
414                 return (EINVAL);
415         }
416
417         if ((monitor->dbg_flags & DBGMON_KERNEL) == 0)
418                 wcr_priv = DBG_WB_CTRL_EL0;
419         else
420                 wcr_priv = DBG_WB_CTRL_EL1;
421
422         switch(access) {
423         case HW_BREAKPOINT_X:
424                 wcr_access = DBG_WATCH_CTRL_EXEC;
425                 break;
426         case HW_BREAKPOINT_R:
427                 wcr_access = DBG_WATCH_CTRL_LOAD;
428                 break;
429         case HW_BREAKPOINT_W:
430                 wcr_access = DBG_WATCH_CTRL_STORE;
431                 break;
432         case HW_BREAKPOINT_RW:
433                 wcr_access = DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE;
434                 break;
435         default:
436                 printf("Unsupported access type for watchpoint: %d\n", access);
437                 return (EINVAL);
438         }
439
440         monitor->dbg_wvr[i] = addr;
441         monitor->dbg_wcr[i] = wcr_size | wcr_access | wcr_priv | DBG_WB_CTRL_E;
442         monitor->dbg_enable_count++;
443         monitor->dbg_flags |= DBGMON_ENABLED;
444
445         dbg_register_sync(monitor);
446         return (0);
447 }
448
449 int
450 dbg_remove_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
451     vm_size_t size)
452 {
453         u_int i;
454
455         if (monitor == NULL)
456                 monitor = &kernel_monitor;
457
458         i = dbg_find_slot(monitor, DBG_TYPE_WATCHPOINT, addr);
459         if (i == -1) {
460                 printf("Can not find watchpoint for address 0%lx\n", addr);
461                 return (EINVAL);
462         }
463
464         monitor->dbg_wvr[i] = 0;
465         monitor->dbg_wcr[i] = 0;
466         monitor->dbg_enable_count--;
467         if (monitor->dbg_enable_count == 0)
468                 monitor->dbg_flags &= ~DBGMON_ENABLED;
469
470         dbg_register_sync(monitor);
471         return (0);
472 }
473
474 void
475 dbg_register_sync(struct debug_monitor_state *monitor)
476 {
477         uint64_t mdscr;
478         int i;
479
480         if (monitor == NULL)
481                 monitor = &kernel_monitor;
482
483         mdscr = READ_SPECIALREG(mdscr_el1);
484         if ((monitor->dbg_flags & DBGMON_ENABLED) == 0) {
485                 mdscr &= ~(MDSCR_MDE | MDSCR_KDE);
486         } else {
487                 for (i = 0; i < dbg_breakpoint_num; i++) {
488                         dbg_wb_write_reg(DBG_REG_BASE_BCR, i,
489                             monitor->dbg_bcr[i]);
490                         dbg_wb_write_reg(DBG_REG_BASE_BVR, i,
491                             monitor->dbg_bvr[i]);
492                 }
493
494                 for (i = 0; i < dbg_watchpoint_num; i++) {
495                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
496                             monitor->dbg_wcr[i]);
497                         dbg_wb_write_reg(DBG_REG_BASE_WVR, i,
498                             monitor->dbg_wvr[i]);
499                 }
500                 mdscr |= MDSCR_MDE;
501                 if ((monitor->dbg_flags & DBGMON_KERNEL) == DBGMON_KERNEL)
502                         mdscr |= MDSCR_KDE;
503         }
504         WRITE_SPECIALREG(mdscr_el1, mdscr);
505         isb();
506 }
507
508 void
509 dbg_monitor_init(void)
510 {
511         uint64_t aa64dfr0;
512         u_int i;
513
514         /* Find out many breakpoints and watchpoints we can use */
515         aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
516         dbg_watchpoint_num = ID_AA64DFR0_WRPs_VAL(aa64dfr0);
517         dbg_breakpoint_num = ID_AA64DFR0_BRPs_VAL(aa64dfr0);
518
519         if (bootverbose && PCPU_GET(cpuid) == 0) {
520                 printf("%d watchpoints and %d breakpoints supported\n",
521                     dbg_watchpoint_num, dbg_breakpoint_num);
522         }
523
524         /*
525          * We have limited number of {watch,break}points, each consists of
526          * two registers:
527          * - wcr/bcr regsiter configurates corresponding {watch,break}point
528          *   behaviour
529          * - wvr/bvr register keeps address we are hunting for
530          *
531          * Reset all breakpoints and watchpoints.
532          */
533         for (i = 0; i < dbg_watchpoint_num; i++) {
534                 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
535                 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
536         }
537
538         for (i = 0; i < dbg_breakpoint_num; i++) {
539                 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
540                 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
541         }
542
543         dbg_enable();
544 }
545
546 void
547 dbg_monitor_enter(struct thread *thread)
548 {
549         int i;
550
551         if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
552                 /* Install the kernel version of the registers */
553                 dbg_register_sync(&kernel_monitor);
554         } else if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
555                 /* Disable the user breakpoints until we return to userspace */
556                 for (i = 0; i < dbg_watchpoint_num; i++) {
557                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
558                         dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
559                 }
560
561                 for (i = 0; i < dbg_breakpoint_num; ++i) {
562                         dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
563                         dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
564                 }
565                 WRITE_SPECIALREG(mdscr_el1,
566                     READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));
567                 isb();
568         }
569 }
570
571 void
572 dbg_monitor_exit(struct thread *thread, struct trapframe *frame)
573 {
574         int i;
575
576         /*
577          * PSR_D is an aarch64-only flag. On aarch32, it switches
578          * the processor to big-endian, so avoid setting it for
579          * 32bits binaries.
580          */
581         if (!(SV_PROC_FLAG(thread->td_proc, SV_ILP32)))
582                 frame->tf_spsr |= PSR_D;
583         if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
584                 /* Install the thread's version of the registers */
585                 dbg_register_sync(&thread->td_pcb->pcb_dbg_regs);
586                 frame->tf_spsr &= ~PSR_D;
587         } else if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
588                 /* Disable the kernel breakpoints until we re-enter */
589                 for (i = 0; i < dbg_watchpoint_num; i++) {
590                         dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
591                         dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
592                 }
593
594                 for (i = 0; i < dbg_breakpoint_num; ++i) {
595                         dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
596                         dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
597                 }
598                 WRITE_SPECIALREG(mdscr_el1,
599                     READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));
600                 isb();
601         }
602 }