1 /*- 2 * Copyright (c) 2014 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Semihalf under 6 * the sponsorship of the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include "opt_ddb.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 48 #ifdef DDB 49 #include <ddb/ddb.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 /* Called from the exception handlers */ 65 void dbg_monitor_enter(struct thread *); 66 void dbg_monitor_exit(struct thread *, struct trapframe *); 67 68 /* Watchpoints/breakpoints control register bitfields */ 69 #define DBG_WATCH_CTRL_LEN_1 (0x1 << 5) 70 #define DBG_WATCH_CTRL_LEN_2 (0x3 << 5) 71 #define DBG_WATCH_CTRL_LEN_4 (0xf << 5) 72 #define DBG_WATCH_CTRL_LEN_8 (0xff << 5) 73 #define DBG_WATCH_CTRL_LEN_MASK(x) ((x) & (0xff << 5)) 74 #define DBG_WATCH_CTRL_EXEC (0x0 << 3) 75 #define DBG_WATCH_CTRL_LOAD (0x1 << 3) 76 #define DBG_WATCH_CTRL_STORE (0x2 << 3) 77 #define DBG_WATCH_CTRL_ACCESS_MASK(x) ((x) & (0x3 << 3)) 78 79 /* Common for breakpoint and watchpoint */ 80 #define DBG_WB_CTRL_EL1 (0x1 << 1) 81 #define DBG_WB_CTRL_EL0 (0x2 << 1) 82 #define DBG_WB_CTRL_ELX_MASK(x) ((x) & (0x3 << 1)) 83 #define DBG_WB_CTRL_E (0x1 << 0) 84 85 #define DBG_REG_BASE_BVR 0 86 #define DBG_REG_BASE_BCR (DBG_REG_BASE_BVR + 16) 87 #define DBG_REG_BASE_WVR (DBG_REG_BASE_BCR + 16) 88 #define DBG_REG_BASE_WCR (DBG_REG_BASE_WVR + 16) 89 90 /* Watchpoint/breakpoint helpers */ 91 #define DBG_WB_WVR "wvr" 92 #define DBG_WB_WCR "wcr" 93 #define DBG_WB_BVR "bvr" 94 #define DBG_WB_BCR "bcr" 95 96 #define DBG_WB_READ(reg, num, val) do { \ 97 __asm __volatile("mrs %0, dbg" reg #num "_el1" : "=r" (val)); \ 98 } while (0) 99 100 #define DBG_WB_WRITE(reg, num, val) do { \ 101 __asm __volatile("msr dbg" reg #num "_el1, %0" :: "r" (val)); \ 102 } while (0) 103 104 #define READ_WB_REG_CASE(reg, num, offset, val) \ 105 case (num + offset): \ 106 DBG_WB_READ(reg, num, val); \ 107 break 108 109 #define WRITE_WB_REG_CASE(reg, num, offset, val) \ 110 case (num + offset): \ 111 DBG_WB_WRITE(reg, num, val); \ 112 break 113 114 #define SWITCH_CASES_READ_WB_REG(reg, offset, val) \ 115 READ_WB_REG_CASE(reg, 0, offset, val); \ 116 READ_WB_REG_CASE(reg, 1, offset, val); \ 117 READ_WB_REG_CASE(reg, 2, offset, val); \ 118 READ_WB_REG_CASE(reg, 3, offset, val); \ 119 READ_WB_REG_CASE(reg, 4, offset, val); \ 120 READ_WB_REG_CASE(reg, 5, offset, val); \ 121 READ_WB_REG_CASE(reg, 6, offset, val); \ 122 READ_WB_REG_CASE(reg, 7, offset, val); \ 123 READ_WB_REG_CASE(reg, 8, offset, val); \ 124 READ_WB_REG_CASE(reg, 9, offset, val); \ 125 READ_WB_REG_CASE(reg, 10, offset, val); \ 126 READ_WB_REG_CASE(reg, 11, offset, val); \ 127 READ_WB_REG_CASE(reg, 12, offset, val); \ 128 READ_WB_REG_CASE(reg, 13, offset, val); \ 129 READ_WB_REG_CASE(reg, 14, offset, val); \ 130 READ_WB_REG_CASE(reg, 15, offset, val) 131 132 #define SWITCH_CASES_WRITE_WB_REG(reg, offset, val) \ 133 WRITE_WB_REG_CASE(reg, 0, offset, val); \ 134 WRITE_WB_REG_CASE(reg, 1, offset, val); \ 135 WRITE_WB_REG_CASE(reg, 2, offset, val); \ 136 WRITE_WB_REG_CASE(reg, 3, offset, val); \ 137 WRITE_WB_REG_CASE(reg, 4, offset, val); \ 138 WRITE_WB_REG_CASE(reg, 5, offset, val); \ 139 WRITE_WB_REG_CASE(reg, 6, offset, val); \ 140 WRITE_WB_REG_CASE(reg, 7, offset, val); \ 141 WRITE_WB_REG_CASE(reg, 8, offset, val); \ 142 WRITE_WB_REG_CASE(reg, 9, offset, val); \ 143 WRITE_WB_REG_CASE(reg, 10, offset, val); \ 144 WRITE_WB_REG_CASE(reg, 11, offset, val); \ 145 WRITE_WB_REG_CASE(reg, 12, offset, val); \ 146 WRITE_WB_REG_CASE(reg, 13, offset, val); \ 147 WRITE_WB_REG_CASE(reg, 14, offset, val); \ 148 WRITE_WB_REG_CASE(reg, 15, offset, val) 149 150 #ifdef DDB 151 static uint64_t 152 dbg_wb_read_reg(int reg, int n) 153 { 154 uint64_t val = 0; 155 156 switch (reg + n) { 157 SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val); 158 SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val); 159 SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val); 160 SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val); 161 default: 162 printf("trying to read from wrong debug register %d\n", n); 163 } 164 165 return val; 166 } 167 #endif /* DDB */ 168 169 static void 170 dbg_wb_write_reg(int reg, int n, uint64_t val) 171 { 172 switch (reg + n) { 173 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val); 174 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val); 175 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val); 176 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val); 177 default: 178 printf("trying to write to wrong debug register %d\n", n); 179 return; 180 } 181 isb(); 182 } 183 184 #ifdef DDB 185 void 186 kdb_cpu_set_singlestep(void) 187 { 188 189 kdb_frame->tf_spsr |= DBG_SPSR_SS; 190 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) | 191 DBG_MDSCR_SS | DBG_MDSCR_KDE); 192 193 /* 194 * Disable breakpoints and watchpoints, e.g. stepping 195 * over watched instruction will trigger break exception instead of 196 * single-step exception and locks CPU on that instruction for ever. 197 */ 198 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) { 199 WRITE_SPECIALREG(mdscr_el1, 200 READ_SPECIALREG(mdscr_el1) & ~DBG_MDSCR_MDE); 201 } 202 } 203 204 void 205 kdb_cpu_clear_singlestep(void) 206 { 207 208 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) & 209 ~(DBG_MDSCR_SS | DBG_MDSCR_KDE)); 210 211 /* Restore breakpoints and watchpoints */ 212 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) { 213 WRITE_SPECIALREG(mdscr_el1, 214 READ_SPECIALREG(mdscr_el1) | DBG_MDSCR_MDE); 215 216 if ((kernel_monitor.dbg_flags & DBGMON_KERNEL) != 0) { 217 WRITE_SPECIALREG(mdscr_el1, 218 READ_SPECIALREG(mdscr_el1) | DBG_MDSCR_KDE); 219 } 220 } 221 } 222 223 static const char * 224 dbg_watchtype_str(uint32_t type) 225 { 226 switch (type) { 227 case DBG_WATCH_CTRL_EXEC: 228 return ("execute"); 229 case DBG_WATCH_CTRL_STORE: 230 return ("write"); 231 case DBG_WATCH_CTRL_LOAD: 232 return ("read"); 233 case DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE: 234 return ("read/write"); 235 default: 236 return ("invalid"); 237 } 238 } 239 240 static int 241 dbg_watchtype_len(uint32_t len) 242 { 243 switch (len) { 244 case DBG_WATCH_CTRL_LEN_1: 245 return (1); 246 case DBG_WATCH_CTRL_LEN_2: 247 return (2); 248 case DBG_WATCH_CTRL_LEN_4: 249 return (4); 250 case DBG_WATCH_CTRL_LEN_8: 251 return (8); 252 default: 253 return (0); 254 } 255 } 256 257 void 258 dbg_show_watchpoint(void) 259 { 260 uint32_t wcr, len, type; 261 uint64_t addr; 262 int i; 263 264 db_printf("\nhardware watchpoints:\n"); 265 db_printf(" watch status type len address symbol\n"); 266 db_printf(" ----- -------- ---------- --- ------------------ ------------------\n"); 267 for (i = 0; i < dbg_watchpoint_num; i++) { 268 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i); 269 if ((wcr & DBG_WB_CTRL_E) != 0) { 270 type = DBG_WATCH_CTRL_ACCESS_MASK(wcr); 271 len = DBG_WATCH_CTRL_LEN_MASK(wcr); 272 addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i); 273 db_printf(" %-5d %-8s %10s %3d 0x%16lx ", 274 i, "enabled", dbg_watchtype_str(type), 275 dbg_watchtype_len(len), addr); 276 db_printsym((db_addr_t)addr, DB_STGY_ANY); 277 db_printf("\n"); 278 } else { 279 db_printf(" %-5d disabled\n", i); 280 } 281 } 282 } 283 #endif /* DDB */ 284 285 static int 286 dbg_find_free_slot(struct debug_monitor_state *monitor, enum dbg_t type) 287 { 288 uint64_t *reg; 289 u_int max, i; 290 291 switch(type) { 292 case DBG_TYPE_BREAKPOINT: 293 max = dbg_breakpoint_num; 294 reg = monitor->dbg_bcr; 295 break; 296 case DBG_TYPE_WATCHPOINT: 297 max = dbg_watchpoint_num; 298 reg = monitor->dbg_wcr; 299 break; 300 default: 301 printf("Unsupported debug type\n"); 302 return (i); 303 } 304 305 for (i = 0; i < max; i++) { 306 if ((reg[i] & DBG_WB_CTRL_E) == 0) 307 return (i); 308 } 309 310 return (-1); 311 } 312 313 static int 314 dbg_find_slot(struct debug_monitor_state *monitor, enum dbg_t type, 315 vm_offset_t addr) 316 { 317 uint64_t *reg_addr, *reg_ctrl; 318 u_int max, i; 319 320 switch(type) { 321 case DBG_TYPE_BREAKPOINT: 322 max = dbg_breakpoint_num; 323 reg_addr = monitor->dbg_bvr; 324 reg_ctrl = monitor->dbg_bcr; 325 break; 326 case DBG_TYPE_WATCHPOINT: 327 max = dbg_watchpoint_num; 328 reg_addr = monitor->dbg_wvr; 329 reg_ctrl = monitor->dbg_wcr; 330 break; 331 default: 332 printf("Unsupported debug type\n"); 333 return (i); 334 } 335 336 for (i = 0; i < max; i++) { 337 if (reg_addr[i] == addr && 338 (reg_ctrl[i] & DBG_WB_CTRL_E) != 0) 339 return (i); 340 } 341 342 return (-1); 343 } 344 345 int 346 dbg_setup_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr, 347 vm_size_t size, enum dbg_access_t access) 348 { 349 uint64_t wcr_size, wcr_priv, wcr_access; 350 u_int i; 351 352 if (monitor == NULL) 353 monitor = &kernel_monitor; 354 355 i = dbg_find_free_slot(monitor, DBG_TYPE_WATCHPOINT); 356 if (i == -1) { 357 printf("Can not find slot for watchpoint, max %d" 358 " watchpoints supported\n", dbg_watchpoint_num); 359 return (i); 360 } 361 362 switch(size) { 363 case 1: 364 wcr_size = DBG_WATCH_CTRL_LEN_1; 365 break; 366 case 2: 367 wcr_size = DBG_WATCH_CTRL_LEN_2; 368 break; 369 case 4: 370 wcr_size = DBG_WATCH_CTRL_LEN_4; 371 break; 372 case 8: 373 wcr_size = DBG_WATCH_CTRL_LEN_8; 374 break; 375 default: 376 printf("Unsupported address size for watchpoint\n"); 377 return (-1); 378 } 379 380 if ((monitor->dbg_flags & DBGMON_KERNEL) == 0) 381 wcr_priv = DBG_WB_CTRL_EL0; 382 else 383 wcr_priv = DBG_WB_CTRL_EL1; 384 385 switch(access) { 386 case HW_BREAKPOINT_X: 387 wcr_access = DBG_WATCH_CTRL_EXEC; 388 break; 389 case HW_BREAKPOINT_R: 390 wcr_access = DBG_WATCH_CTRL_LOAD; 391 break; 392 case HW_BREAKPOINT_W: 393 wcr_access = DBG_WATCH_CTRL_STORE; 394 break; 395 case HW_BREAKPOINT_RW: 396 wcr_access = DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE; 397 break; 398 default: 399 printf("Unsupported exception level for watchpoint\n"); 400 return (-1); 401 } 402 403 monitor->dbg_wvr[i] = addr; 404 monitor->dbg_wcr[i] = wcr_size | wcr_access | wcr_priv | DBG_WB_CTRL_E; 405 monitor->dbg_enable_count++; 406 monitor->dbg_flags |= DBGMON_ENABLED; 407 408 dbg_register_sync(monitor); 409 return (0); 410 } 411 412 int 413 dbg_remove_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr, 414 vm_size_t size) 415 { 416 u_int i; 417 418 if (monitor == NULL) 419 monitor = &kernel_monitor; 420 421 i = dbg_find_slot(monitor, DBG_TYPE_WATCHPOINT, addr); 422 if (i == -1) { 423 printf("Can not find watchpoint for address 0%lx\n", addr); 424 return (i); 425 } 426 427 monitor->dbg_wvr[i] = 0; 428 monitor->dbg_wcr[i] = 0; 429 monitor->dbg_enable_count--; 430 if (monitor->dbg_enable_count == 0) 431 monitor->dbg_flags &= ~DBGMON_ENABLED; 432 433 dbg_register_sync(monitor); 434 return (0); 435 } 436 437 void 438 dbg_register_sync(struct debug_monitor_state *monitor) 439 { 440 uint64_t mdscr; 441 int i; 442 443 if (monitor == NULL) 444 monitor = &kernel_monitor; 445 446 mdscr = READ_SPECIALREG(mdscr_el1); 447 if ((monitor->dbg_flags & DBGMON_ENABLED) == 0) { 448 mdscr &= ~(DBG_MDSCR_MDE | DBG_MDSCR_KDE); 449 } else { 450 for (i = 0; i < dbg_breakpoint_num; i++) { 451 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 452 monitor->dbg_bcr[i]); 453 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 454 monitor->dbg_bvr[i]); 455 } 456 457 for (i = 0; i < dbg_watchpoint_num; i++) { 458 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 459 monitor->dbg_wcr[i]); 460 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 461 monitor->dbg_wvr[i]); 462 } 463 mdscr |= DBG_MDSCR_MDE; 464 if ((monitor->dbg_flags & DBGMON_KERNEL) == DBGMON_KERNEL) 465 mdscr |= DBG_MDSCR_KDE; 466 } 467 WRITE_SPECIALREG(mdscr_el1, mdscr); 468 isb(); 469 } 470 471 void 472 dbg_monitor_init(void) 473 { 474 u_int i; 475 476 /* Find out many breakpoints and watchpoints we can use */ 477 dbg_watchpoint_num = ((READ_SPECIALREG(id_aa64dfr0_el1) >> 20) & 0xf) + 1; 478 dbg_breakpoint_num = ((READ_SPECIALREG(id_aa64dfr0_el1) >> 12) & 0xf) + 1; 479 480 if (bootverbose && PCPU_GET(cpuid) == 0) { 481 printf("%d watchpoints and %d breakpoints supported\n", 482 dbg_watchpoint_num, dbg_breakpoint_num); 483 } 484 485 /* 486 * We have limited number of {watch,break}points, each consists of 487 * two registers: 488 * - wcr/bcr regsiter configurates corresponding {watch,break}point 489 * behaviour 490 * - wvr/bvr register keeps address we are hunting for 491 * 492 * Reset all breakpoints and watchpoints. 493 */ 494 for (i = 0; i < dbg_watchpoint_num; i++) { 495 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0); 496 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0); 497 } 498 499 for (i = 0; i < dbg_breakpoint_num; i++) { 500 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0); 501 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0); 502 } 503 504 dbg_enable(); 505 } 506 507 void 508 dbg_monitor_enter(struct thread *thread) 509 { 510 int i; 511 512 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) { 513 /* Install the kernel version of the registers */ 514 dbg_register_sync(&kernel_monitor); 515 } else if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) { 516 /* Disable the user breakpoints until we return to userspace */ 517 for (i = 0; i < dbg_watchpoint_num; i++) { 518 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0); 519 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0); 520 } 521 522 for (i = 0; i < dbg_breakpoint_num; ++i) { 523 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0); 524 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0); 525 } 526 WRITE_SPECIALREG(mdscr_el1, 527 READ_SPECIALREG(mdscr_el1) & 528 ~(DBG_MDSCR_MDE | DBG_MDSCR_KDE)); 529 isb(); 530 } 531 } 532 533 void 534 dbg_monitor_exit(struct thread *thread, struct trapframe *frame) 535 { 536 int i; 537 538 /* 539 * PSR_D is an aarch64-only flag. On aarch32, it switches 540 * the processor to big-endian, so avoid setting it for 541 * 32bits binaries. 542 */ 543 if (!(SV_PROC_FLAG(thread->td_proc, SV_ILP32))) 544 frame->tf_spsr |= PSR_D; 545 if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) { 546 /* Install the kernel version of the registers */ 547 dbg_register_sync(&thread->td_pcb->pcb_dbg_regs); 548 frame->tf_spsr &= ~PSR_D; 549 } else if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) { 550 /* Disable the user breakpoints until we return to userspace */ 551 for (i = 0; i < dbg_watchpoint_num; i++) { 552 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0); 553 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0); 554 } 555 556 for (i = 0; i < dbg_breakpoint_num; ++i) { 557 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0); 558 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0); 559 } 560 WRITE_SPECIALREG(mdscr_el1, 561 READ_SPECIALREG(mdscr_el1) & 562 ~(DBG_MDSCR_MDE | DBG_MDSCR_KDE)); 563 isb(); 564 } 565 } 566