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