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