Index: sys/amd64/amd64/db_trace.c =================================================================== --- sys/amd64/amd64/db_trace.c +++ sys/amd64/amd64/db_trace.c @@ -398,6 +398,25 @@ ctx->pcb_rip, ctx->pcb_rsp, count)); } +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} + int amd64_set_watch(watchnum, watchaddr, size, access, d) int watchnum; Index: sys/arm/arm/db_trace.c =================================================================== --- sys/arm/arm/db_trace.c +++ sys/arm/arm/db_trace.c @@ -129,6 +129,25 @@ } } +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} + void db_md_list_watchpoints(void) { Index: sys/arm64/arm64/db_trace.c =================================================================== --- sys/arm64/arm64/db_trace.c +++ sys/arm64/arm64/db_trace.c @@ -43,6 +43,27 @@ #include #include +void +db_md_list_breakpoints(void) +{ + + dbg_show_breakpoint(); +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (dbg_remove_breakpoint(addr, size)); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (dbg_setup_breakpoint(addr, count)); +} + void db_md_list_watchpoints() { Index: sys/arm64/arm64/debug_monitor.c =================================================================== --- sys/arm64/arm64/debug_monitor.c +++ sys/arm64/arm64/debug_monitor.c @@ -214,6 +214,32 @@ } } +void +dbg_show_breakpoint(void) +{ + uint32_t bcr, len, type; + uint64_t addr; + int i; + + db_printf("\nhardware breakpoints:\n"); + db_printf(" break status address symbol\n"); + db_printf(" ----- -------- ------------------ ------------------\n"); + for (i = 0; i < dbg_breakpoint_num; i++) { + bcr = dbg_wb_read_reg(DBG_REG_BASE_BCR, i); + if ((bcr & DBG_WB_CTRL_E) != 0) { + type = DBG_WATCH_CTRL_ACCESS_MASK(bcr); + len = DBG_WATCH_CTRL_LEN_MASK(bcr); + addr = dbg_wb_read_reg(DBG_REG_BASE_BVR, i); + db_printf(" %-5d %-8s 0x%16lx ", + i, "enabled", addr); + db_printsym((db_addr_t)addr, DB_STGY_ANY); + db_printf("\n"); + } else { + db_printf(" %-5d disabled\n", i); + } + } +} + static const char * dbg_watchtype_str(uint32_t type) { @@ -336,6 +362,63 @@ return (-1); } +int +dbg_setup_breakpoint(vm_offset_t addr, vm_size_t size) +{ + struct debug_monitor_state *monitor; + uint64_t bcr_priv; + u_int i; + + if (size != 1) { + printf("Can only set one hardware breakpoint at a time\n"); + return (-1); + } + + monitor = &kernel_monitor; + i = dbg_find_free_slot(monitor, DBG_TYPE_BREAKPOINT); + if (i == -1) { + printf("Can not find slot for breakpoint, max %d" + " breakpoints supported\n", dbg_breakpoint_num); + return (i); + } + + if ((monitor->dbg_flags & DBGMON_KERNEL) == 0) + bcr_priv = DBG_WB_CTRL_EL0; + else + bcr_priv = DBG_WB_CTRL_EL1; + + monitor->dbg_bvr[i] = addr; + monitor->dbg_bcr[i] = (0xf << 5) | bcr_priv | DBG_WB_CTRL_E; + monitor->dbg_enable_count++; + monitor->dbg_flags |= DBGMON_ENABLED; + dbg_register_sync(monitor); + + return (0); +} + +int +dbg_remove_breakpoint(vm_offset_t addr, vm_size_t size) +{ + struct debug_monitor_state *monitor; + u_int i; + + monitor = &kernel_monitor; + i = dbg_find_slot(monitor, DBG_TYPE_BREAKPOINT, addr); + if (i == -1) { + printf("Can not find breakpoint for address 0%lx\n", addr); + return (i); + } + + monitor->dbg_bvr[i] = 0; + monitor->dbg_bcr[i] = 0; + monitor->dbg_enable_count--; + if (monitor->dbg_enable_count == 0) + monitor->dbg_flags &= ~DBGMON_ENABLED; + dbg_register_sync(monitor); + + return (0); +} + int dbg_setup_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr, vm_size_t size, enum dbg_access_t access) Index: sys/arm64/arm64/trap.c =================================================================== --- sys/arm64/arm64/trap.c +++ sys/arm64/arm64/trap.c @@ -317,6 +317,7 @@ switch (exception) { case EXCP_BRK: + case EXCP_BRKPT_EL1: case EXCP_WATCHPT_EL1: case EXCP_SOFTSTP_EL1: break; @@ -367,6 +368,7 @@ #endif frame->tf_elr += 4; break; + case EXCP_BRKPT_EL1: case EXCP_WATCHPT_EL1: case EXCP_SOFTSTP_EL1: #ifdef KDB Index: sys/arm64/include/armreg.h =================================================================== --- sys/arm64/include/armreg.h +++ sys/arm64/include/armreg.h @@ -142,6 +142,7 @@ #define EXCP_SP_ALIGN 0x26 /* SP slignment fault */ #define EXCP_TRAP_FP 0x2c /* Trapped FP exception */ #define EXCP_SERROR 0x2f /* SError interrupt */ +#define EXCP_BRKPT_EL1 0x31 /* Hardware breakpoint, from same EL */ #define EXCP_SOFTSTP_EL0 0x32 /* Software Step, from lower EL */ #define EXCP_SOFTSTP_EL1 0x33 /* Software Step, from same EL */ #define EXCP_WATCHPT_EL1 0x35 /* Watchpoint, from same EL */ Index: sys/arm64/include/db_machdep.h =================================================================== --- sys/arm64/include/db_machdep.h +++ sys/arm64/include/db_machdep.h @@ -38,6 +38,7 @@ #include #define T_BREAKPOINT (EXCP_BRK) +#define T_HW_BREAKPOINT (EXCP_BRKPT_EL1) #define T_WATCHPOINT (EXCP_WATCHPT_EL1) typedef vm_offset_t db_addr_t; @@ -56,7 +57,8 @@ #define db_clear_single_step kdb_cpu_clear_singlestep #define db_set_single_step kdb_cpu_set_singlestep -#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT) +#define IS_BREAKPOINT_TRAP(type, code) \ + (type == T_BREAKPOINT || type == T_HW_BREAKPOINT) #define IS_WATCHPOINT_TRAP(type, code) (type == T_WATCHPOINT) #define inst_trap_return(ins) (0) Index: sys/arm64/include/debug_monitor.h =================================================================== --- sys/arm64/include/debug_monitor.h +++ sys/arm64/include/debug_monitor.h @@ -57,12 +57,15 @@ void dbg_monitor_init(void); void dbg_register_sync(struct debug_monitor_state *); +int dbg_setup_breakpoint(vm_offset_t, vm_size_t); +int dbg_remove_breakpoint(vm_offset_t, vm_size_t); int dbg_setup_watchpoint(struct debug_monitor_state *, vm_offset_t, vm_size_t, enum dbg_access_t); int dbg_remove_watchpoint(struct debug_monitor_state *, vm_offset_t, vm_size_t); #ifdef DDB void dbg_show_watchpoint(void); +void dbg_show_breakpoint(void); #endif #endif /* _KERNEL */ Index: sys/ddb/db_break.c =================================================================== --- sys/ddb/db_break.c +++ sys/ddb/db_break.c @@ -285,11 +285,41 @@ db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count); } +/* Delete hardware breakpoint */ +void +db_deletehbreak_cmd(db_expr_t addr, bool have_addr, db_expr_t count, + char *modif) +{ + int rc; + + if (count == -1) + count = 1; + + rc = db_md_clr_breakpoint(addr, count); + if (rc < 0) + db_printf("hardware breakpoint could not be delete\n"); +} + +/* Set hardware breakpoint */ +void +db_hbreakpoint_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif) +{ + int rc; + + if (count == -1) + count = 1; + + rc = db_md_set_breakpoint(addr, count); + if (rc < 0) + db_printf("hardware breakpoint could not be set\n"); +} + /* list breakpoints */ void db_listbreak_cmd(db_expr_t dummy1, bool dummy2, db_expr_t dummy3, char *dummy4) { db_list_breakpoints(); + db_md_list_breakpoints(); } /* Index: sys/ddb/db_command.c =================================================================== --- sys/ddb/db_command.c +++ sys/ddb/db_command.c @@ -116,6 +116,8 @@ { "delete", db_delete_cmd, 0, NULL }, { "d", db_delete_cmd, 0, NULL }, { "dump", db_dump, 0, NULL }, + { "dhbreak", db_deletehbreak_cmd, 0, NULL }, + { "hbreak", db_hbreakpoint_cmd, 0, NULL }, { "break", db_breakpoint_cmd, 0, NULL }, { "b", db_breakpoint_cmd, 0, NULL }, { "dwatch", db_deletewatch_cmd, 0, NULL }, Index: sys/ddb/ddb.h =================================================================== --- sys/ddb/ddb.h +++ sys/ddb/ddb.h @@ -208,6 +208,9 @@ struct vm_map *db_map_addr(vm_offset_t); bool db_map_current(struct vm_map *); bool db_map_equal(struct vm_map *, struct vm_map *); +int db_md_set_breakpoint(db_expr_t addr, db_expr_t size); +int db_md_clr_breakpoint(db_expr_t addr, db_expr_t size); +void db_md_list_breakpoints(void); int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); void db_md_list_watchpoints(void); @@ -238,10 +241,12 @@ db_cmdfcn_t db_capture_cmd; db_cmdfcn_t db_continue_cmd; db_cmdfcn_t db_delete_cmd; +db_cmdfcn_t db_deletehbreak_cmd; db_cmdfcn_t db_deletehwatch_cmd; db_cmdfcn_t db_deletewatch_cmd; db_cmdfcn_t db_examine_cmd; db_cmdfcn_t db_findstack_cmd; +db_cmdfcn_t db_hbreakpoint_cmd; db_cmdfcn_t db_hwatchpoint_cmd; db_cmdfcn_t db_listbreak_cmd; db_cmdfcn_t db_scripts_cmd; Index: sys/i386/i386/db_trace.c =================================================================== --- sys/i386/i386/db_trace.c +++ sys/i386/i386/db_trace.c @@ -605,6 +605,25 @@ ctx->pcb_eip, ctx->pcb_esp, count)); } +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} + int i386_set_watch(watchnum, watchaddr, size, access, d) int watchnum; Index: sys/mips/mips/db_trace.c =================================================================== --- sys/mips/mips/db_trace.c +++ sys/mips/mips/db_trace.c @@ -386,6 +386,25 @@ } +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} + int db_md_set_watchpoint(db_expr_t addr, db_expr_t size) { Index: sys/powerpc/powerpc/db_trace.c =================================================================== --- sys/powerpc/powerpc/db_trace.c +++ sys/powerpc/powerpc/db_trace.c @@ -318,3 +318,22 @@ ctx = kdb_thr_ctx(td); return (db_backtrace(td, (db_addr_t)ctx->pcb_sp, count)); } + +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} Index: sys/riscv/riscv/db_trace.c =================================================================== --- sys/riscv/riscv/db_trace.c +++ sys/riscv/riscv/db_trace.c @@ -48,6 +48,25 @@ #include #include +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +} + void db_md_list_watchpoints() { Index: sys/sparc64/sparc64/db_trace.c =================================================================== --- sys/sparc64/sparc64/db_trace.c +++ sys/sparc64/sparc64/db_trace.c @@ -291,3 +291,22 @@ return (db_backtrace(td, (struct frame *)(ctx->pcb_sp + SPOFF), count)); } + +void +db_md_list_breakpoints(void) +{ +} + +int +db_md_clr_breakpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_set_breakpoint(db_expr_t addr, db_expr_t count) +{ + + return (0); +}