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