1*433d6423SLionel Sambuc #include "kernel/kernel.h" 2*433d6423SLionel Sambuc #include "arch_proto.h" 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc #include "debugreg.h" 5*433d6423SLionel Sambuc breakpoint_set(phys_bytes linaddr,int bp,const int flags)6*433d6423SLionel Sambucint breakpoint_set(phys_bytes linaddr, int bp, const int flags) 7*433d6423SLionel Sambuc { 8*433d6423SLionel Sambuc unsigned long dr7, dr7flags; 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc if (bp >= BREAKPOINT_COUNT) 11*433d6423SLionel Sambuc return EINVAL; 12*433d6423SLionel Sambuc 13*433d6423SLionel Sambuc /* convert flags */ 14*433d6423SLionel Sambuc dr7flags = 0; 15*433d6423SLionel Sambuc switch (flags & BREAKPOINT_FLAG_RW_MASK) { 16*433d6423SLionel Sambuc case BREAKPOINT_FLAG_RW_EXEC: dr7flags |= DR7_RW_EXEC(bp); break; 17*433d6423SLionel Sambuc case BREAKPOINT_FLAG_RW_WRITE: dr7flags |= DR7_RW_WRITE(bp); break; 18*433d6423SLionel Sambuc case BREAKPOINT_FLAG_RW_RW: dr7flags |= DR7_RW_RW(bp); break; 19*433d6423SLionel Sambuc default: return EINVAL; 20*433d6423SLionel Sambuc } 21*433d6423SLionel Sambuc switch (flags & BREAKPOINT_FLAG_LEN_MASK) { 22*433d6423SLionel Sambuc case BREAKPOINT_FLAG_LEN_1: dr7flags |= DR7_LN_1(bp); break; 23*433d6423SLionel Sambuc case BREAKPOINT_FLAG_LEN_2: dr7flags |= DR7_LN_2(bp); break; 24*433d6423SLionel Sambuc case BREAKPOINT_FLAG_LEN_4: dr7flags |= DR7_LN_4(bp); break; 25*433d6423SLionel Sambuc default: return EINVAL; 26*433d6423SLionel Sambuc } 27*433d6423SLionel Sambuc switch (flags & BREAKPOINT_FLAG_MODE_MASK) { 28*433d6423SLionel Sambuc case BREAKPOINT_FLAG_MODE_OFF: break; 29*433d6423SLionel Sambuc case BREAKPOINT_FLAG_MODE_LOCAL: dr7flags |= DR7_L(bp); break; 30*433d6423SLionel Sambuc case BREAKPOINT_FLAG_MODE_GLOBAL: dr7flags |= DR7_G(bp); break; 31*433d6423SLionel Sambuc default: return EINVAL; 32*433d6423SLionel Sambuc } 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc /* disable breakpoint before setting address */ 35*433d6423SLionel Sambuc dr7 = st_dr7(); 36*433d6423SLionel Sambuc dr7 &= ~(DR7_L(bp) | DR7_G(bp) | DR7_RW_MASK(bp) | DR7_LN_MASK(bp)); 37*433d6423SLionel Sambuc ld_dr7(dr7); 38*433d6423SLionel Sambuc 39*433d6423SLionel Sambuc /* need to set new breakpoint? */ 40*433d6423SLionel Sambuc if ((flags & BREAKPOINT_FLAG_MODE_MASK) == BREAKPOINT_FLAG_MODE_OFF) 41*433d6423SLionel Sambuc return 0; 42*433d6423SLionel Sambuc 43*433d6423SLionel Sambuc /* set breakpoint address */ 44*433d6423SLionel Sambuc switch (bp) { 45*433d6423SLionel Sambuc case 0: ld_dr0(linaddr); break; 46*433d6423SLionel Sambuc case 1: ld_dr1(linaddr); break; 47*433d6423SLionel Sambuc case 2: ld_dr2(linaddr); break; 48*433d6423SLionel Sambuc case 3: ld_dr3(linaddr); break; 49*433d6423SLionel Sambuc default: panic("%s:%d: invalid breakpoint index", __FILE__, __LINE__); 50*433d6423SLionel Sambuc } 51*433d6423SLionel Sambuc 52*433d6423SLionel Sambuc /* set new flags */ 53*433d6423SLionel Sambuc dr7 |= dr7flags; 54*433d6423SLionel Sambuc ld_dr7(dr7); 55*433d6423SLionel Sambuc return 0; 56*433d6423SLionel Sambuc } 57*433d6423SLionel Sambuc 58