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