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