| 705 | } |
| 706 | |
| 707 | static int |
| 708 | dbg_remove_xpoint(struct dbg_wb_conf *conf) |
| 709 | { |
| 710 | struct pcpu *pcpu; |
| 711 | struct dbreg *d; |
| 712 | uint32_t reg_ctrl, reg_addr, addr; |
| 713 | boolean_t is_bkpt; |
| 714 | u_int cpu; |
| 715 | u_int i; |
| 716 | |
| 717 | if (!dbg_capable()) |
| 718 | return (ENXIO); |
| 719 | |
| 720 | is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT); |
| 721 | addr = conf->address; |
| 722 | |
| 723 | if (is_bkpt) { |
| 724 | i = conf->slot; |
| 725 | reg_ctrl = DBG_REG_BASE_BCR; |
| 726 | reg_addr = DBG_REG_BASE_BVR; |
| 727 | } else { |
| 728 | i = dbg_find_slot(DBG_TYPE_WATCHPOINT, addr); |
| 729 | if (i == ~0U) { |
| 730 | db_printf("Can not find watchpoint for address 0%x\n", addr); |
| 731 | return (EINVAL); |
| 732 | } |
| 733 | reg_ctrl = DBG_REG_BASE_WCR; |
| 734 | reg_addr = DBG_REG_BASE_WVR; |
| 735 | } |
| 736 | |
| 737 | dbg_wb_write_reg(reg_ctrl, i, 0); |
| 738 | dbg_wb_write_reg(reg_addr, i, 0); |
| 739 | |
| 740 | /* |
| 741 | * Save watchpoint settings for all CPUs. |
| 742 | * We don't need to do the same with breakpoints since HW breakpoints |
| 743 | * are only used to perform single stepping. |
| 744 | */ |
| 745 | if (!is_bkpt) { |
| 746 | CPU_FOREACH(cpu) { |
| 747 | pcpu = pcpu_find(cpu); |
| 748 | /* Fill out the settings for watchpoint */ |
| 749 | d = (struct dbreg *)pcpu->pc_dbreg; |
| 750 | d->dbg_wvr[i] = 0; |
| 751 | d->dbg_wcr[i] = 0; |
| 752 | /* Skip update command for the current CPU */ |
| 753 | if (cpu != PCPU_GET(cpuid)) |
| 754 | pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD; |
| 755 | } |
| 756 | /* Ensure all data is written before waking other CPUs */ |
| 757 | atomic_thread_fence_rel(); |
| 758 | } |
| 759 | |
| 760 | return (0); |
| 761 | } |
| 762 | |
| 763 | static __inline uint32_t |
| 764 | dbg_get_debug_model(void) |
no test coverage detected