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