1/*- 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie the 24 * rights to redistribute these changes. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include "opt_compat.h" 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/kdb.h> 35#include <sys/proc.h> 36#include <sys/smp.h> 37#include <sys/stack.h> 38#include <sys/sysent.h> 39 40#include <machine/cpu.h> 41#include <machine/md_var.h> 42#include <machine/pcb.h> 43#include <machine/reg.h> 44#include <machine/stack.h> 45 46#include <vm/vm.h> 47#include <vm/vm_param.h> 48#include <vm/pmap.h> 49 50#include <ddb/ddb.h> 51#include <ddb/db_access.h> 52#include <ddb/db_sym.h> 53#include <ddb/db_variables.h> 54 55static db_varfcn_t db_dr0; 56static db_varfcn_t db_dr1; 57static db_varfcn_t db_dr2; 58static db_varfcn_t db_dr3; 59static db_varfcn_t db_dr4; 60static db_varfcn_t db_dr5; 61static db_varfcn_t db_dr6; 62static db_varfcn_t db_dr7; 63static db_varfcn_t db_frame; 64static db_varfcn_t db_rsp; 65static db_varfcn_t db_ss; 66 67CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg)); 68 69/* 70 * Machine register set. 71 */ 72#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 73struct db_variable db_regs[] = { 74 { "cs", DB_OFFSET(tf_cs), db_frame }, 75 { "ds", DB_OFFSET(tf_ds), db_frame }, 76 { "es", DB_OFFSET(tf_es), db_frame }, 77 { "fs", DB_OFFSET(tf_fs), db_frame }, 78 { "gs", DB_OFFSET(tf_gs), db_frame }, 79 { "ss", NULL, db_ss }, 80 { "rax", DB_OFFSET(tf_rax), db_frame }, 81 { "rcx", DB_OFFSET(tf_rcx), db_frame }, 82 { "rdx", DB_OFFSET(tf_rdx), db_frame }, 83 { "rbx", DB_OFFSET(tf_rbx), db_frame }, 84 { "rsp", NULL, db_rsp }, 85 { "rbp", DB_OFFSET(tf_rbp), db_frame }, 86 { "rsi", DB_OFFSET(tf_rsi), db_frame }, 87 { "rdi", DB_OFFSET(tf_rdi), db_frame }, 88 { "r8", DB_OFFSET(tf_r8), db_frame }, 89 { "r9", DB_OFFSET(tf_r9), db_frame }, 90 { "r10", DB_OFFSET(tf_r10), db_frame }, 91 { "r11", DB_OFFSET(tf_r11), db_frame }, 92 { "r12", DB_OFFSET(tf_r12), db_frame }, 93 { "r13", DB_OFFSET(tf_r13), db_frame }, 94 { "r14", DB_OFFSET(tf_r14), db_frame }, 95 { "r15", DB_OFFSET(tf_r15), db_frame }, 96 { "rip", DB_OFFSET(tf_rip), db_frame }, 97 { "rflags", DB_OFFSET(tf_rflags), db_frame }, 98#define DB_N_SHOW_REGS 24 /* Don't show registers after here. */ 99 { "dr0", NULL, db_dr0 }, 100 { "dr1", NULL, db_dr1 }, 101 { "dr2", NULL, db_dr2 }, 102 { "dr3", NULL, db_dr3 }, 103 { "dr4", NULL, db_dr4 }, 104 { "dr5", NULL, db_dr5 }, 105 { "dr6", NULL, db_dr6 }, 106 { "dr7", NULL, db_dr7 }, 107}; 108struct db_variable *db_eregs = db_regs + DB_N_SHOW_REGS; 109 110#define DB_DRX_FUNC(reg) \ 111static int \ 112db_ ## reg (vp, valuep, op) \ 113 struct db_variable *vp; \ 114 db_expr_t * valuep; \ 115 int op; \ 116{ \ 117 if (op == DB_VAR_GET) \ 118 *valuep = r ## reg (); \ 119 else \ 120 load_ ## reg (*valuep); \ 121 return (1); \ 122} 123 124DB_DRX_FUNC(dr0) 125DB_DRX_FUNC(dr1) 126DB_DRX_FUNC(dr2) 127DB_DRX_FUNC(dr3) 128DB_DRX_FUNC(dr4) 129DB_DRX_FUNC(dr5) 130DB_DRX_FUNC(dr6) 131DB_DRX_FUNC(dr7) 132 133static __inline long 134get_rsp(struct trapframe *tf) 135{ 136 return ((ISPL(tf->tf_cs)) ? tf->tf_rsp : 137 (db_expr_t)tf + offsetof(struct trapframe, tf_rsp)); 138} 139 140static int 141db_frame(struct db_variable *vp, db_expr_t *valuep, int op) 142{ 143 long *reg; 144 145 if (kdb_frame == NULL) 146 return (0); 147 148 reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep); 149 if (op == DB_VAR_GET) 150 *valuep = *reg; 151 else 152 *reg = *valuep; 153 return (1); 154} 155 156static int 157db_rsp(struct db_variable *vp, db_expr_t *valuep, int op) 158{ 159 160 if (kdb_frame == NULL) 161 return (0); 162 163 if (op == DB_VAR_GET) 164 *valuep = get_rsp(kdb_frame); 165 else if (ISPL(kdb_frame->tf_cs)) 166 kdb_frame->tf_rsp = *valuep; 167 return (1); 168} 169 170static int 171db_ss(struct db_variable *vp, db_expr_t *valuep, int op) 172{ 173 174 if (kdb_frame == NULL) 175 return (0); 176 177 if (op == DB_VAR_GET) 178 *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss(); 179 else if (ISPL(kdb_frame->tf_cs)) 180 kdb_frame->tf_ss = *valuep; 181 return (1); 182} 183 184#define NORMAL 0 185#define TRAP 1 186#define INTERRUPT 2 187#define SYSCALL 3 188#define TRAP_INTERRUPT 5 189 190static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *); 191static int db_numargs(struct amd64_frame *); 192static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t, 193 void *); 194static void decode_syscall(int, struct thread *); 195 196static const char * watchtype_str(int type); 197int amd64_set_watch(int watchnum, unsigned long watchaddr, int size, 198 int access, struct dbreg *d); 199int amd64_clr_watch(int watchnum, struct dbreg *d); 200 201/* 202 * Figure out how many arguments were passed into the frame at "fp". 203 */ 204static int 205db_numargs(fp) 206 struct amd64_frame *fp; 207{ 208#if 1 209 return (0); /* regparm, needs dwarf2 info */ 210#else 211 long *argp; 212 int inst; 213 int args; 214 215 argp = (long *)db_get_value((long)&fp->f_retaddr, 8, FALSE); 216 /* 217 * XXX etext is wrong for LKMs. We should attempt to interpret 218 * the instruction at the return address in all cases. This 219 * may require better fault handling. 220 */ 221 if (argp < (long *)btext || argp >= (long *)etext) { 222 args = 5; 223 } else { 224 inst = db_get_value((long)argp, 4, FALSE); 225 if ((inst & 0xff) == 0x59) /* popl %ecx */ 226 args = 1; 227 else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ 228 args = ((inst >> 16) & 0xff) / 4; 229 else 230 args = 5; 231 } 232 return (args); 233#endif 234} 235 236static void 237db_print_stack_entry(name, narg, argnp, argp, callpc, frame) 238 const char *name; 239 int narg; 240 char **argnp; 241 long *argp; 242 db_addr_t callpc; 243 void *frame; 244{ 245 db_printf("%s(", name); 246#if 0 247 while (narg) { 248 if (argnp) 249 db_printf("%s=", *argnp++); 250 db_printf("%lr", (long)db_get_value((long)argp, 8, FALSE)); 251 argp++; 252 if (--narg != 0) 253 db_printf(","); 254 } 255#endif 256 db_printf(") at "); 257 db_printsym(callpc, DB_STGY_PROC); 258 if (frame != NULL) 259 db_printf("/frame 0x%lx", (register_t)frame); 260 db_printf("\n"); 261} 262 263static void 264decode_syscall(int number, struct thread *td) 265{ 266 struct proc *p; 267 c_db_sym_t sym; 268 db_expr_t diff; 269 sy_call_t *f; 270 const char *symname; 271 272 db_printf(" (%d", number); 273 p = (td != NULL) ? td->td_proc : NULL; 274 if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) { 275 f = p->p_sysent->sv_table[number].sy_call; 276 sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff); 277 if (sym != DB_SYM_NULL && diff == 0) { 278 db_symbol_values(sym, &symname, NULL); 279 db_printf(", %s, %s", p->p_sysent->sv_name, symname); 280 } 281 } 282 db_printf(")"); 283} 284 285/* 286 * Figure out the next frame up in the call stack. 287 */ 288static void 289db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td) 290{ 291 struct trapframe *tf; 292 int frame_type; 293 long rip, rsp, rbp; 294 db_expr_t offset; 295 c_db_sym_t sym; 296 const char *name; 297 298 rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE); 299 rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE); 300 301 /* 302 * Figure out frame type. We look at the address just before 303 * the saved instruction pointer as the saved EIP is after the 304 * call function, and if the function being called is marked as 305 * dead (such as panic() at the end of dblfault_handler()), then 306 * the instruction at the saved EIP will be part of a different 307 * function (syscall() in this example) rather than the one that 308 * actually made the call. 309 */ 310 frame_type = NORMAL; 311 sym = db_search_symbol(rip - 1, DB_STGY_ANY, &offset); 312 db_symbol_values(sym, &name, NULL); 313 if (name != NULL) { 314 if (strcmp(name, "calltrap") == 0 || 315 strcmp(name, "fork_trampoline") == 0 || 316 strcmp(name, "nmi_calltrap") == 0 || 317 strcmp(name, "Xdblfault") == 0) 318 frame_type = TRAP; 319 else if (strncmp(name, "Xatpic_intr", 11) == 0 || 320 strncmp(name, "Xapic_isr", 9) == 0 || 321 strcmp(name, "Xtimerint") == 0 || 322 strcmp(name, "Xipi_intr_bitmap_handler") == 0 || 323 strcmp(name, "Xcpustop") == 0 || 324 strcmp(name, "Xcpususpend") == 0 || 325 strcmp(name, "Xrendezvous") == 0) 326 frame_type = INTERRUPT; 327 else if (strcmp(name, "Xfast_syscall") == 0) 328 frame_type = SYSCALL; 329#ifdef COMPAT_FREEBSD32 330 else if (strcmp(name, "Xint0x80_syscall") == 0) 331 frame_type = SYSCALL; 332#endif 333 /* XXX: These are interrupts with trap frames. */ 334 else if (strcmp(name, "Xtimerint") == 0 || 335 strcmp(name, "Xcpustop") == 0 || 336 strcmp(name, "Xcpususpend") == 0 || 337 strcmp(name, "Xrendezvous") == 0 || 338 strcmp(name, "Xipi_intr_bitmap_handler") == 0) 339 frame_type = TRAP_INTERRUPT; 340 } 341 342 /* 343 * Normal frames need no special processing. 344 */ 345 if (frame_type == NORMAL) { 346 *ip = (db_addr_t) rip; 347 *fp = (struct amd64_frame *) rbp; 348 return; 349 } 350 351 db_print_stack_entry(name, 0, 0, 0, rip, &(*fp)->f_frame); 352 353 /* 354 * Point to base of trapframe which is just above the 355 * current frame. 356 */ 357 tf = (struct trapframe *)((long)*fp + 16); 358 359 if (INKERNEL((long) tf)) { 360 rsp = get_rsp(tf); 361 rip = tf->tf_rip; 362 rbp = tf->tf_rbp; 363 switch (frame_type) { 364 case TRAP: 365 db_printf("--- trap %#r", tf->tf_trapno); 366 break; 367 case SYSCALL: 368 db_printf("--- syscall"); 369 decode_syscall(tf->tf_rax, td); 370 break; 371 case TRAP_INTERRUPT: 372 case INTERRUPT: 373 db_printf("--- interrupt"); 374 break; 375 default: 376 panic("The moon has moved again."); 377 } 378 db_printf(", rip = %#lr, rsp = %#lr, rbp = %#lr ---\n", rip, 379 rsp, rbp); 380 } 381 382 *ip = (db_addr_t) rip; 383 *fp = (struct amd64_frame *) rbp; 384} 385 386static int 387db_backtrace(struct thread *td, struct trapframe *tf, 388 struct amd64_frame *frame, db_addr_t pc, int count) 389{ 390 struct amd64_frame *actframe; 391#define MAXNARG 16 392 char *argnames[MAXNARG], **argnp = NULL; 393 const char *name; 394 long *argp; 395 db_expr_t offset; 396 c_db_sym_t sym; 397 int narg; 398 boolean_t first; 399 400 if (count == -1) 401 count = 1024; 402 403 first = TRUE; 404 while (count-- && !db_pager_quit) { 405 sym = db_search_symbol(pc, DB_STGY_ANY, &offset); 406 db_symbol_values(sym, &name, NULL); 407 408 /* 409 * Attempt to determine a (possibly fake) frame that gives 410 * the caller's pc. It may differ from `frame' if the 411 * current function never sets up a standard frame or hasn't 412 * set one up yet or has just discarded one. The last two 413 * cases can be guessed fairly reliably for code generated 414 * by gcc. The first case is too much trouble to handle in 415 * general because the amount of junk on the stack depends 416 * on the pc (the special handling of "calltrap", etc. in 417 * db_nextframe() works because the `next' pc is special). 418 */ 419 actframe = frame; 420 if (first) { 421 if (tf != NULL) { 422 int instr; 423 424 instr = db_get_value(pc, 4, FALSE); 425 if ((instr & 0xffffffff) == 0xe5894855) { 426 /* pushq %rbp; movq %rsp, %rbp */ 427 actframe = (void *)(get_rsp(tf) - 8); 428 } else if ((instr & 0xffffff) == 0xe58948) { 429 /* movq %rsp, %rbp */ 430 actframe = (void *)get_rsp(tf); 431 if (tf->tf_rbp == 0) { 432 /* Fake frame better. */ 433 frame = actframe; 434 } 435 } else if ((instr & 0xff) == 0xc3) { 436 /* ret */ 437 actframe = (void *)(get_rsp(tf) - 8); 438 } else if (offset == 0) { 439 /* Probably an assembler symbol. */ 440 actframe = (void *)(get_rsp(tf) - 8); 441 } 442 } else if (strcmp(name, "fork_trampoline") == 0) { 443 /* 444 * Don't try to walk back on a stack for a 445 * process that hasn't actually been run yet. 446 */ 447 db_print_stack_entry(name, 0, 0, 0, pc, 448 actframe); 449 break; 450 } 451 first = FALSE; 452 } 453 454 argp = &actframe->f_arg0; 455 narg = MAXNARG; 456 if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) { 457 argnp = argnames; 458 } else { 459 narg = db_numargs(frame); 460 } 461 462 db_print_stack_entry(name, narg, argnp, argp, pc, actframe); 463 464 if (actframe != frame) { 465 /* `frame' belongs to caller. */ 466 pc = (db_addr_t) 467 db_get_value((long)&actframe->f_retaddr, 8, FALSE); 468 continue; 469 } 470 471 db_nextframe(&frame, &pc, td); 472 473 if (INKERNEL((long)pc) && !INKERNEL((long)frame)) { 474 sym = db_search_symbol(pc, DB_STGY_ANY, &offset); 475 db_symbol_values(sym, &name, NULL); 476 db_print_stack_entry(name, 0, 0, 0, pc, frame); 477 break; 478 } 479 if (!INKERNEL((long) frame)) { 480 break; 481 } 482 } 483 484 return (0); 485} 486 487void 488db_trace_self(void) 489{ 490 struct amd64_frame *frame; 491 db_addr_t callpc; 492 register_t rbp; 493 494 __asm __volatile("movq %%rbp,%0" : "=r" (rbp)); 495 frame = (struct amd64_frame *)rbp; 496 callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE); 497 frame = frame->f_frame; 498 db_backtrace(curthread, NULL, frame, callpc, -1); 499} 500 501int 502db_trace_thread(struct thread *thr, int count) 503{ 504 struct pcb *ctx; 505 506 ctx = kdb_thr_ctx(thr); 507 return (db_backtrace(thr, NULL, (struct amd64_frame *)ctx->pcb_rbp, 508 ctx->pcb_rip, count)); 509} 510 511int 512amd64_set_watch(watchnum, watchaddr, size, access, d) 513 int watchnum; 514 unsigned long watchaddr; 515 int size; 516 int access; 517 struct dbreg *d; 518{ 519 int i, len; 520 521 if (watchnum == -1) { 522 for (i = 0; i < 4; i++) 523 if (!DBREG_DR7_ENABLED(d->dr[7], i)) 524 break; 525 if (i < 4) 526 watchnum = i; 527 else 528 return (-1); 529 } 530 531 switch (access) { 532 case DBREG_DR7_EXEC: 533 size = 1; /* size must be 1 for an execution breakpoint */ 534 /* fall through */ 535 case DBREG_DR7_WRONLY: 536 case DBREG_DR7_RDWR: 537 break; 538 default: 539 return (-1); 540 } 541 542 /* 543 * we can watch a 1, 2, 4, or 8 byte sized location 544 */ 545 switch (size) { 546 case 1: 547 len = DBREG_DR7_LEN_1; 548 break; 549 case 2: 550 len = DBREG_DR7_LEN_2; 551 break; 552 case 4: 553 len = DBREG_DR7_LEN_4; 554 break; 555 case 8: 556 len = DBREG_DR7_LEN_8; 557 break; 558 default: 559 return (-1); 560 } 561 562 /* clear the bits we are about to affect */ 563 d->dr[7] &= ~DBREG_DR7_MASK(watchnum); 564 565 /* set drN register to the address, N=watchnum */ 566 DBREG_DRX(d, watchnum) = watchaddr; 567 568 /* enable the watchpoint */ 569 d->dr[7] |= DBREG_DR7_SET(watchnum, len, access, 570 DBREG_DR7_GLOBAL_ENABLE); 571 572 return (watchnum); 573} 574 575 576int 577amd64_clr_watch(watchnum, d) 578 int watchnum; 579 struct dbreg *d; 580{ 581 582 if (watchnum < 0 || watchnum >= 4) 583 return (-1); 584 585 d->dr[7] &= ~DBREG_DR7_MASK(watchnum); 586 DBREG_DRX(d, watchnum) = 0; 587 588 return (0); 589} 590 591 592int 593db_md_set_watchpoint(addr, size) 594 db_expr_t addr; 595 db_expr_t size; 596{ 597 struct dbreg *d; 598 struct pcpu *pc; 599 int avail, c, cpu, i, wsize; 600 601 d = (struct dbreg *)PCPU_PTR(dbreg); 602 cpu = PCPU_GET(cpuid); 603 fill_dbregs(NULL, d); 604 605 avail = 0; 606 for (i = 0; i < 4; i++) { 607 if (!DBREG_DR7_ENABLED(d->dr[7], i)) 608 avail++; 609 } 610 611 if (avail * 8 < size) 612 return (-1); 613 614 for (i = 0; i < 4 && size > 0; i++) { 615 if (!DBREG_DR7_ENABLED(d->dr[7], i)) { 616 if (size >= 8 || (avail == 1 && size > 4)) 617 wsize = 8; 618 else if (size > 2) 619 wsize = 4; 620 else 621 wsize = size; 622 amd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, d); 623 addr += wsize; 624 size -= wsize; 625 avail--; 626 } 627 } 628 629 set_dbregs(NULL, d); 630 CPU_FOREACH(c) { 631 if (c == cpu) 632 continue; 633 pc = pcpu_find(c); 634 memcpy(pc->pc_dbreg, d, sizeof(*d)); 635 pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; 636 } 637 638 return (0); 639} 640 641int 642db_md_clr_watchpoint(addr, size) 643 db_expr_t addr; 644 db_expr_t size; 645{ 646 struct dbreg *d; 647 struct pcpu *pc; 648 int i, c, cpu; 649 650 d = (struct dbreg *)PCPU_PTR(dbreg); 651 cpu = PCPU_GET(cpuid); 652 fill_dbregs(NULL, d); 653 654 for (i = 0; i < 4; i++) { 655 if (DBREG_DR7_ENABLED(d->dr[7], i)) { 656 if (DBREG_DRX((d), i) >= addr && 657 DBREG_DRX((d), i) < addr + size) 658 amd64_clr_watch(i, d); 659 660 } 661 } 662 663 set_dbregs(NULL, d); 664 CPU_FOREACH(c) { 665 if (c == cpu) 666 continue; 667 pc = pcpu_find(c); 668 memcpy(pc->pc_dbreg, d, sizeof(*d)); 669 pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; 670 } 671 672 return (0); 673} 674 675 676static const char * 677watchtype_str(type) 678 int type; 679{ 680 switch (type) { 681 case DBREG_DR7_EXEC : return "execute"; break; 682 case DBREG_DR7_RDWR : return "read/write"; break; 683 case DBREG_DR7_WRONLY : return "write"; break; 684 default : return "invalid"; break; 685 } 686} 687 688 689void 690db_md_list_watchpoints() 691{ 692 struct dbreg d; 693 int i, len, type; 694 695 fill_dbregs(NULL, &d); 696 697 db_printf("\nhardware watchpoints:\n"); 698 db_printf(" watch status type len address\n"); 699 db_printf(" ----- -------- ---------- --- ------------------\n"); 700 for (i = 0; i < 4; i++) { 701 if (DBREG_DR7_ENABLED(d.dr[7], i)) { 702 type = DBREG_DR7_ACCESS(d.dr[7], i); 703 len = DBREG_DR7_LEN(d.dr[7], i); 704 if (len == DBREG_DR7_LEN_8) 705 len = 8; 706 else 707 len++; 708 db_printf(" %-5d %-8s %10s %3d ", 709 i, "enabled", watchtype_str(type), len); 710 db_printsym((db_addr_t)DBREG_DRX((&d), i), DB_STGY_ANY); 711 db_printf("\n"); 712 } else { 713 db_printf(" %-5d disabled\n", i); 714 } 715 } 716 717 db_printf("\ndebug register values:\n"); 718 for (i = 0; i < 8; i++) { 719 db_printf(" dr%d 0x%016lx\n", i, DBREG_DRX((&d), i)); 720 } 721 db_printf("\n"); 722} 723 724void 725amd64_db_resume_dbreg(void) 726{ 727 struct dbreg *d; 728 729 switch (PCPU_GET(dbreg_cmd)) { 730 case PC_DBREG_CMD_LOAD: 731 d = (struct dbreg *)PCPU_PTR(dbreg); 732 set_dbregs(NULL, d); 733 PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE); 734 break; 735 } 736} 737