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