📄 hal_breakpoint.c
字号:
unsigned retval;
asm volatile ( "movsg XXXX,%0\n" : "=r" (retval) : /* no inputs */ );
return retval;}
static inline void set_XXXX(unsigned val){
asm volatile ( "movgs %0,XXXX\n" : /* no outputs */ : "r" (val) );}
// ------------------------------------------------------------------------
// This is called in the same manner as exception_handler() in hal_misc.c
// Comments compare and contrast what we do here.
static unsigned int saved_brr = 0;
void
break_handler(HAL_SavedRegisters *regs)
{
unsigned int i, old_bpsr;
// See if it an actual "break" instruction.
i = get_brr();
saved_brr |= i; // do not lose previous state
// Acknowledge the trap, clear the "factor" (== cause)
set_brr( 0 );
// Now leave debug mode so that it's safe to run the stub code.
// Unfortunately, leaving debug mode isn't a self-contained
// operation. The only means of doing it is with a "rett #1"
// instruction, which will also restore the previous values of
// the ET and S status flags. We can massage the BPSR
// register so that the flags keep their current values, but
// we need to save the old one first.
i = old_bpsr = get_bpsr ();
i |= _BPSR_BS; // Stay in supervisor mode
i &= ~_BPSR_BET; // Keep traps disabled
set_bpsr (i);
HAL_FRV_EXIT_DEBUG_MODE();
// Only perturb this variable if stopping, not
// just for a break instruction.
_hal_registers = regs;
// Continue with the standard mechanism:
__handle_exception();
// Go back into debug mode.
HAL_FRV_ENTER_DEBUG_MODE();
// Restore the original BPSR register.
set_bpsr (old_bpsr);
return;
}
// ------------------------------------------------------------------------
// Now the routines to manipulate said hardware break and watchpoints.
int cyg_hal_plf_hw_breakpoint(int setflag, void *vaddr, int len)
{
unsigned int addr = (unsigned)vaddr;
unsigned int dcr;
unsigned int retcode = 0;
HAL_FRV_ENTER_DEBUG_MODE();
dcr = get_dcr();
// GDB manual suggests that idempotency is required, so first remove
// any identical BP in residence. Implements remove arm anyway.
if ( 0 != (dcr & (_DCR_IBE0 | _DCR_IBCE0)) &&
get_ibar0() == addr )
dcr &=~(_DCR_IBE0 | _DCR_IBCE0);
else if ( 0 != (dcr & (_DCR_IBE1 | _DCR_IBCE1)) &&
get_ibar1() == addr )
dcr &=~(_DCR_IBE1 | _DCR_IBCE1);
else if ( 0 != (dcr & (_DCR_IBE2 | _DCR_IBCE2)) &&
get_ibar2() == addr )
dcr &=~(_DCR_IBE2 | _DCR_IBCE2);
else if ( 0 != (dcr & (_DCR_IBE3 | _DCR_IBCE3)) &&
get_ibar3() == addr )
dcr &=~(_DCR_IBE3 | _DCR_IBCE3);
else
retcode = -1;
if (setflag) {
retcode = 0; // it is OK really
if ( 0 == (dcr & (_DCR_IBE0 | _DCR_IBCE0)) ) {
set_ibar0(addr);
dcr |= _DCR_IBE0;
}
else if ( 0 == (dcr & (_DCR_IBE1 | _DCR_IBCE1)) ) {
set_ibar1(addr);
dcr |= _DCR_IBE1;
}
else if ( 0 == (dcr & (_DCR_IBE2 | _DCR_IBCE2)) ) {
set_ibar2(addr);
dcr |= _DCR_IBE2;
}
else if ( 0 == (dcr & (_DCR_IBE3 | _DCR_IBCE3)) ) {
set_ibar3(addr);
dcr |= _DCR_IBE3;
}
else
retcode = -1;
}
if ( 0 == retcode )
set_dcr(dcr);
HAL_FRV_EXIT_DEBUG_MODE();
return retcode;
}
int cyg_hal_plf_hw_watchpoint(int setflag, void *vaddr, int len, int type)
{
unsigned int addr = (unsigned)vaddr;
unsigned int mode;
unsigned int dcr;
unsigned int retcode = 0;
unsigned long long mask;
unsigned int mask0, mask1;
int i;
// Check the length fits within one block.
if ( ((~7) & (addr + len - 1)) != ((~7) & addr) )
return -1;
// Assuming big-endian like the platform seems to be...
// Get masks for the 8-byte span. 00 means enabled, ff means ignore a
// byte, which is why this looks funny at first glance.
mask = 0x00ffffffffffffffULL >> ((len - 1) << 3);
for (i = 0; i < (addr & 7); i++) {
mask >>= 8;
mask |= 0xff00000000000000ULL;
}
mask0 = mask >> 32;
mask1 = mask & 0xffffffffULL;
addr &=~7; // round to 8-byte block
HAL_FRV_ENTER_DEBUG_MODE();
dcr = get_dcr();
// GDB manual suggests that idempotency is required, so first remove
// any identical WP in residence. Implements remove arm anyway.
if ( 0 != (dcr & (7 * _DCR_DBASE0)) &&
get_dbar0() == addr &&
get_dbmr00() == mask0 && get_dbmr01() == mask1 )
dcr &=~(7 * _DCR_DBASE0);
else if ( 0 != (dcr & (7 * _DCR_DBASE1)) &&
get_dbar1() == addr&&
get_dbmr10() == mask0 && get_dbmr11() == mask1 )
dcr &=~(7 * _DCR_DBASE1);
else
retcode = -1;
if (setflag) {
retcode = 0; // it is OK really
if (type == 2) mode = 2; // break on write
else if (type == 3) mode = 4; // break on read
else if (type == 4) mode = 6; // break on any access
else {
mode = 0; // actually add no enable at all.
retcode = -1;
}
if ( 0 == (dcr & (7 * _DCR_DBASE0)) ) {
set_dbar0(addr);
// Data and Mask 0,1 to zero (mask no bits/bytes)
set_dbdr00(0); set_dbdr01(0); set_dbmr00(mask0); set_dbmr01(mask1);
mode *= _DCR_DBASE0;
dcr |= mode;
}
else if ( 0 == (dcr & (7 * _DCR_DBASE1)) ) {
set_dbar1(addr);
set_dbdr10(0); set_dbdr11(0); set_dbmr10(mask0); set_dbmr11(mask1);
mode *= _DCR_DBASE1;
dcr |= mode;
}
else
retcode = -1;
}
if ( 0 == retcode )
set_dcr(dcr);
HAL_FRV_EXIT_DEBUG_MODE();
return retcode;
}
// Return indication of whether or not we stopped because of a
// watchpoint or hardware breakpoint. If stopped by a watchpoint,
// also set '*data_addr_p' to the data address which triggered the
// watchpoint.
int cyg_hal_plf_is_stopped_by_hardware(void **data_addr_p)
{
unsigned int brr;
int retcode = HAL_STUB_HW_STOP_NONE;
unsigned long long mask;
// There was a debug event. Check the BRR for details
brr = saved_brr;
saved_brr = 0;
if ( brr & (_BRR_IB0 | _BRR_IB1 | _BRR_IB2 | _BRR_IB3) ) {
// then it was an instruction break
retcode = HAL_STUB_HW_STOP_BREAK;
}
else if ( brr & (_BRR_DB0 | _BRR_DB1) ) {
unsigned int addr, kind;
kind = get_dcr();
if ( brr & (_BRR_DB0) ) {
addr = get_dbar0();
kind &= 7 * _DCR_DBASE0;
kind /= _DCR_DBASE0;
mask = (((unsigned long long)get_dbmr00())<<32) | (unsigned long long)get_dbmr01();
} else {
addr = get_dbar1();
kind &= 7 * _DCR_DBASE1;
kind /= _DCR_DBASE1;
mask = (((unsigned long long)get_dbmr10())<<32) | (unsigned long long)get_dbmr11();
}
if ( data_addr_p ) {
// Scan for a zero byte in the mask - this gives the true address.
// 0123456789abcdef
while ( 0 != (0xff00000000000000LLU & mask) ) {
mask <<= 8;
addr++;
}
*data_addr_p = (void *)addr;
}
// Inverse of the mapping above in the "set" code.
if (kind == 2) retcode = HAL_STUB_HW_STOP_WATCH;
else if (kind == 6) retcode = HAL_STUB_HW_STOP_AWATCH;
else if (kind == 4) retcode = HAL_STUB_HW_STOP_RWATCH;
}
return retcode;
}
// ------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -