58 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "kernel/kernel.h"
 | |
| #include "arch_proto.h"
 | |
| 
 | |
| #include "debugreg.h"
 | |
| 
 | |
| PUBLIC int breakpoint_set(phys_bytes linaddr, int bp, const int flags)
 | |
| {
 | |
| 	unsigned long dr7, dr7flags;
 | |
| 	
 | |
| 	if (bp >= BREAKPOINT_COUNT)
 | |
| 		return EINVAL;
 | |
| 	
 | |
| 	/* convert flags */
 | |
| 	dr7flags = 0;
 | |
| 	switch (flags & BREAKPOINT_FLAG_RW_MASK) {
 | |
| 		case BREAKPOINT_FLAG_RW_EXEC:  dr7flags |= DR7_RW_EXEC(bp);  break;
 | |
| 		case BREAKPOINT_FLAG_RW_WRITE: dr7flags |= DR7_RW_WRITE(bp); break;
 | |
| 		case BREAKPOINT_FLAG_RW_RW:    dr7flags |= DR7_RW_RW(bp);    break;
 | |
| 		default: return EINVAL;			
 | |
| 	}
 | |
| 	switch (flags & BREAKPOINT_FLAG_LEN_MASK) {
 | |
| 		case BREAKPOINT_FLAG_LEN_1: dr7flags |= DR7_LN_1(bp); break;
 | |
| 		case BREAKPOINT_FLAG_LEN_2: dr7flags |= DR7_LN_2(bp); break;
 | |
| 		case BREAKPOINT_FLAG_LEN_4: dr7flags |= DR7_LN_4(bp); break;
 | |
| 		default: return EINVAL;	
 | |
| 	}
 | |
| 	switch (flags & BREAKPOINT_FLAG_MODE_MASK) {
 | |
| 		case BREAKPOINT_FLAG_MODE_OFF: break;
 | |
| 		case BREAKPOINT_FLAG_MODE_LOCAL: dr7flags |= DR7_L(bp); break;
 | |
| 		case BREAKPOINT_FLAG_MODE_GLOBAL: dr7flags |= DR7_G(bp); break;
 | |
| 		default: return EINVAL;	
 | |
| 	}
 | |
| 	
 | |
| 	/* disable breakpoint before setting address */
 | |
| 	dr7 = st_dr7();
 | |
| 	dr7 &= ~(DR7_L(bp) | DR7_G(bp) | DR7_RW_MASK(bp) | DR7_LN_MASK(bp));
 | |
| 	ld_dr7(dr7);
 | |
| 
 | |
| 	/* need to set new breakpoint? */	
 | |
| 	if ((flags & BREAKPOINT_FLAG_MODE_MASK) == BREAKPOINT_FLAG_MODE_OFF)
 | |
| 		return 0;
 | |
| 			
 | |
| 	/* set breakpoint address */
 | |
| 	switch (bp) {
 | |
| 		case 0: ld_dr0(linaddr); break;
 | |
| 		case 1: ld_dr1(linaddr); break;
 | |
| 		case 2: ld_dr2(linaddr); break;
 | |
| 		case 3: ld_dr3(linaddr); break;
 | |
| 		default: panic("%s:%d: invalid breakpoint index", __FILE__,  __LINE__);
 | |
| 	}
 | |
| 	
 | |
| 	/* set new flags */
 | |
| 	dr7 |= dr7flags;
 | |
| 	ld_dr7(dr7);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | 
