void db_dr ( int num, vm_offset_t linear_addr, int type, int len, int persistence) { int s = splhigh(); unsigned long dr7; if (!kernel_dr) { if (!linear_addr) { splx(s); return; } kernel_dr = TRUE; /* Clear user debugging registers */ set_dr7(0); set_dr0(0); set_dr1(0); set_dr2(0); set_dr3(0); } ids.dr[num] = linear_addr; switch (num) { case 0: set_dr0(linear_addr); break; case 1: set_dr1(linear_addr); break; case 2: set_dr2(linear_addr); break; case 3: set_dr3(linear_addr); break; } /* Replace type/len/persistence for DRnum in dr7 */ dr7 = get_dr7 (); dr7 &= ~(0xfUL << (4*num+16)) & ~(0x3UL << (2*num)); dr7 |= (((len << 2) | type) << (4*num+16)) | (persistence << (2*num)); set_dr7 (dr7); if (kernel_dr) { if (!ids.dr[0] && !ids.dr[1] && !ids.dr[2] && !ids.dr[3]) { /* Not used any more, switch back to user debugging registers */ set_dr7 (0); kernel_dr = FALSE; zero_dr = TRUE; db_load_context(current_thread()->pcb); } } splx(s); }
void db_load_context(pcb_t pcb) { #if MACH_KDB int s = splhigh(); if (kernel_dr) { splx(s); return; } #endif /* Else set user debug registers, if any */ unsigned int *dr = pcb->ims.ids.dr; boolean_t will_zero_dr = !dr[0] && !dr[1] && !dr[2] && !dr[3] && !dr[7]; if (!(zero_dr && will_zero_dr)) { set_dr0(dr[0]); set_dr1(dr[1]); set_dr2(dr[2]); set_dr3(dr[3]); set_dr7(dr[7]); zero_dr = will_zero_dr; } #if MACH_KDB splx(s); #endif }
static void dbg_hard_release_dr() { debug(DBG_HARD_BRK, "hard release dr\n"); /* XXX: release DBG_CTL_MSR */ /* XXX: vmm area check ? */ set_dr0(info->vm.dr_shadow[0].raw); set_dr1(info->vm.dr_shadow[1].raw); set_dr2(info->vm.dr_shadow[2].raw); set_dr3(info->vm.dr_shadow[3].raw); __dr6.low = info->vm.dr_shadow[4].low; __dr7.low = info->vm.dr_shadow[5].low; dbg_hard_set_dr6_dirty(0); __post_access(__dr6); __post_access(__dr7); __allow_dr_access(); }