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 } 606