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