SELFOUR-836: Hardware debug API functions should take tcb_t and not arch_tcb_t
Touches files all throughout x86 (32 and 64) and ARM.
This commit is contained in:
parent
4e5cc369ff
commit
3f90fad605
13 changed files with 195 additions and 202 deletions
|
|
@ -186,18 +186,18 @@ seL4_Fault_t handleUserLevelDebugException(word_t fault_vaddr);
|
|||
* bitfield.
|
||||
*/
|
||||
static inline void
|
||||
setBreakpointUsedFlag(arch_tcb_t *uds, uint16_t bp_num)
|
||||
setBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
if (uds != NULL) {
|
||||
uds->tcbContext.breakpointState.used_breakpoints_bf |= BIT(bp_num);
|
||||
if (t != NULL) {
|
||||
t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf |= BIT(bp_num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
unsetBreakpointUsedFlag(arch_tcb_t *uds, uint16_t bp_num)
|
||||
unsetBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
if (uds != NULL) {
|
||||
uds->tcbContext.breakpointState.used_breakpoints_bf &= ~BIT(bp_num);
|
||||
if (t != NULL) {
|
||||
t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf &= ~BIT(bp_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ static inline void Arch_initContext(user_context_t* context)
|
|||
{
|
||||
context->registers[CPSR] = CPSR_USER;
|
||||
#if !defined(CONFIG_VERIFICATION_BUILD) && (defined(CONFIG_HARDWARE_DEBUG_API) || defined(CONFIG_ARM_HYPERVISOR_SUPPORT))
|
||||
Arch_initBreakpointContext(&context->breakpointState);
|
||||
Arch_initBreakpointContext(context);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
void restore_user_debug_context(tcb_t *target_thread);
|
||||
void Arch_debugAssociateVCPUTCB(tcb_t *t);
|
||||
void Arch_debugDissociateVCPUTCB(tcb_t *t);
|
||||
void saveAllBreakpointState(arch_tcb_t *at);
|
||||
void saveAllBreakpointState(tcb_t *t);
|
||||
void loadAllDisabledBreakpointState(void);
|
||||
#endif
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ getTypeFromBpNum(uint16_t bp_num)
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeConfigureSingleStepping(arch_tcb_t *at,
|
||||
Arch_decodeConfigureSingleStepping(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t n_instr,
|
||||
bool_t is_reply)
|
||||
|
|
@ -132,7 +132,7 @@ Arch_decodeConfigureSingleStepping(arch_tcb_t *at,
|
|||
* configured bp_num. Of course, this assumes that a register had
|
||||
* already previously been configured for single-stepping.
|
||||
*/
|
||||
if (!at->tcbContext.breakpointState.single_step_enabled) {
|
||||
if (!t->tcbArch.tcbContext.breakpointState.single_step_enabled) {
|
||||
userError("Debug: Single-step reply when single-stepping not "
|
||||
"enabled.");
|
||||
ret.type = seL4_IllegalOperation;
|
||||
|
|
@ -140,7 +140,7 @@ Arch_decodeConfigureSingleStepping(arch_tcb_t *at,
|
|||
}
|
||||
|
||||
type = seL4_InstructionBreakpoint;
|
||||
bp_num = at->tcbContext.breakpointState.single_step_hw_bp_num;
|
||||
bp_num = t->tcbArch.tcbContext.breakpointState.single_step_hw_bp_num;
|
||||
} else {
|
||||
type = getTypeFromBpNum(bp_num);
|
||||
bp_num = convertBpNumToArch(bp_num);
|
||||
|
|
@ -154,8 +154,8 @@ Arch_decodeConfigureSingleStepping(arch_tcb_t *at,
|
|||
ret.invalidArgumentNumber = 0;
|
||||
return ret;
|
||||
}
|
||||
if (at->tcbContext.breakpointState.single_step_enabled == true) {
|
||||
if (bp_num != at->tcbContext.breakpointState.single_step_hw_bp_num) {
|
||||
if (t->tcbArch.tcbContext.breakpointState.single_step_enabled == true) {
|
||||
if (bp_num != t->tcbArch.tcbContext.breakpointState.single_step_hw_bp_num) {
|
||||
/* Can't configure more than one register for stepping. */
|
||||
userError("Debug: Only one register can be configured for "
|
||||
"single-stepping at a time.");
|
||||
|
|
@ -171,7 +171,7 @@ Arch_decodeConfigureSingleStepping(arch_tcb_t *at,
|
|||
bool_t byte8WatchpointsSupported(void);
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeSetBreakpoint(arch_tcb_t *uds,
|
||||
Arch_decodeSetBreakpoint(tcb_t *t,
|
||||
uint16_t bp_num, word_t vaddr, word_t type,
|
||||
word_t size, word_t rw)
|
||||
{
|
||||
|
|
@ -216,7 +216,7 @@ Arch_decodeSetBreakpoint(arch_tcb_t *uds,
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeGetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
Arch_decodeGetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
syscall_error_t ret = {
|
||||
.type = seL4_NoError
|
||||
|
|
@ -231,7 +231,7 @@ Arch_decodeGetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeUnsetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
Arch_decodeUnsetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
syscall_error_t ret = {
|
||||
.type = seL4_NoError
|
||||
|
|
@ -249,7 +249,7 @@ Arch_decodeUnsetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
type = getTypeFromBpNum(bp_num);
|
||||
bp_num = convertBpNumToArch(bp_num);
|
||||
|
||||
bcr.words[0] = uds->tcbContext.breakpointState.breakpoint[bp_num].cr;
|
||||
bcr.words[0] = t->tcbArch.tcbContext.breakpointState.breakpoint[bp_num].cr;
|
||||
if (type == seL4_InstructionBreakpoint) {
|
||||
if (Arch_breakpointIsMismatch(bcr) == true && dbg_bcr_get_enabled(bcr)) {
|
||||
userError("Rejecting call to unsetBreakpoint on breakpoint configured "
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ writeDrReg(uint8_t reg, word_t val)
|
|||
*@param source The memory block from which to load the register values.
|
||||
*/
|
||||
static inline void
|
||||
loadBreakpointState(arch_tcb_t *source)
|
||||
loadBreakpointState(tcb_t *source)
|
||||
{
|
||||
/* Order does matter when restoring the registers: we want to restore the
|
||||
* breakpoint control register (DR7) last since it is what "activates" the
|
||||
|
|
@ -132,7 +132,7 @@ loadBreakpointState(arch_tcb_t *source)
|
|||
"movl (%%edx), %%ecx \n\t"
|
||||
"movl %%ecx, %%dr7 \n\t"
|
||||
:
|
||||
: "r" (source->tcbContext.breakpointState.dr)
|
||||
: "r" (source->tcbArch.tcbContext.breakpointState.dr)
|
||||
: "edx", "ecx");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ writeDrReg(uint8_t reg, word_t val)
|
|||
*@param source The memory block from which to load the register values.
|
||||
*/
|
||||
static inline void
|
||||
loadBreakpointState(arch_tcb_t *source)
|
||||
loadBreakpointState(tcb_t *source)
|
||||
{
|
||||
/* Order does matter when restoring the registers: we want to restore the
|
||||
* breakpoint control register (DR7) last since it is what "activates" the
|
||||
|
|
@ -132,7 +132,7 @@ loadBreakpointState(arch_tcb_t *source)
|
|||
"movq (%%rdx), %%rcx \n\t"
|
||||
"movq %%rcx, %%dr7 \n\t"
|
||||
:
|
||||
: "r" (source->tcbContext.breakpointState.dr)
|
||||
: "r" (source->tcbArch.tcbContext.breakpointState.dr)
|
||||
: "rdx", "rcx");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,18 +58,18 @@ exception_t handleUserLevelDebugException(int int_vector);
|
|||
* bitfield.
|
||||
*/
|
||||
static inline void
|
||||
setBreakpointUsedFlag(arch_tcb_t *uds, uint16_t bp_num)
|
||||
setBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
if (uds != NULL) {
|
||||
uds->tcbContext.breakpointState.used_breakpoints_bf |= BIT(bp_num);
|
||||
if (t != NULL) {
|
||||
t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf |= BIT(bp_num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
unsetBreakpointUsedFlag(arch_tcb_t *uds, uint16_t bp_num)
|
||||
unsetBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
if (uds != NULL) {
|
||||
uds->tcbContext.breakpointState.used_breakpoints_bf &= ~BIT(bp_num);
|
||||
if (t != NULL) {
|
||||
t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf &= ~BIT(bp_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,11 +82,11 @@ unsetBreakpointUsedFlag(arch_tcb_t *uds, uint16_t bp_num)
|
|||
* setting the disable bits.
|
||||
*/
|
||||
static void
|
||||
loadAllDisabledBreakpointState(arch_tcb_t *at)
|
||||
loadAllDisabledBreakpointState(tcb_t *t)
|
||||
{
|
||||
word_t disable_value;
|
||||
|
||||
disable_value = at->tcbContext.breakpointState.dr[5];
|
||||
disable_value = t->tcbArch.tcbContext.breakpointState.dr[5];
|
||||
disable_value &= ~(X86_DEBUG_BP0_ENABLE_BIT | X86_DEBUG_BP1_ENABLE_BIT
|
||||
| X86_DEBUG_BP2_ENABLE_BIT | X86_DEBUG_BP3_ENABLE_BIT);
|
||||
|
||||
|
|
@ -98,9 +98,9 @@ restore_user_debug_context(tcb_t *target_thread)
|
|||
{
|
||||
arch_tcb_t *uds = &target_thread->tcbArch;
|
||||
if (uds->tcbContext.breakpointState.used_breakpoints_bf != 0) {
|
||||
loadBreakpointState(uds);
|
||||
loadBreakpointState(target_thread);
|
||||
} else {
|
||||
loadAllDisabledBreakpointState(uds);
|
||||
loadAllDisabledBreakpointState(target_thread);
|
||||
}
|
||||
|
||||
/* If single-stepping was enabled, we need to re-set the TF flag as well. */
|
||||
|
|
@ -126,7 +126,7 @@ restore_user_debug_context(tcb_t *target_thread)
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeConfigureSingleStepping(arch_tcb_t *uc,
|
||||
Arch_decodeConfigureSingleStepping(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t n_instr,
|
||||
bool_t is_reply)
|
||||
|
|
@ -140,7 +140,7 @@ Arch_decodeConfigureSingleStepping(arch_tcb_t *uc,
|
|||
bool_t byte8BreakpointsSupported(void);
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeSetBreakpoint(arch_tcb_t *uds,
|
||||
Arch_decodeSetBreakpoint(tcb_t *t,
|
||||
uint16_t bp_num, word_t vaddr, word_t types,
|
||||
word_t size, word_t rw)
|
||||
{
|
||||
|
|
@ -165,7 +165,7 @@ Arch_decodeSetBreakpoint(arch_tcb_t *uds,
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeGetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
Arch_decodeGetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
syscall_error_t ret = {
|
||||
.type = seL4_NoError
|
||||
|
|
@ -181,7 +181,7 @@ Arch_decodeGetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
}
|
||||
|
||||
static inline syscall_error_t
|
||||
Arch_decodeUnsetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
Arch_decodeUnsetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
syscall_error_t ret = {
|
||||
.type = seL4_NoError
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ void Arch_breakpointThreadDelete(tcb_t *thread);
|
|||
* context-saving memory block, and this function will write to that
|
||||
* context-saving memory block instead.
|
||||
*/
|
||||
void setBreakpoint(arch_tcb_t *uds,
|
||||
void setBreakpoint(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t vaddr, word_t type, word_t size, word_t rw);
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ typedef struct getBreakpointRet {
|
|||
bool_t is_enabled;
|
||||
} getBreakpoint_t;
|
||||
|
||||
getBreakpoint_t getBreakpoint(arch_tcb_t *uds, uint16_t bp_num);
|
||||
getBreakpoint_t getBreakpoint(tcb_t *t, uint16_t bp_num);
|
||||
|
||||
/** Clears a breakpoint's configuration and disables it.
|
||||
* @param bp_num Hardware breakpoint ID. Usually an integer from 0..N.
|
||||
|
|
@ -71,15 +71,15 @@ getBreakpoint_t getBreakpoint(arch_tcb_t *uds, uint16_t bp_num);
|
|||
* context-saving memory block, and this function will write to that
|
||||
* context-saving memory block instead.
|
||||
*/
|
||||
void unsetBreakpoint(arch_tcb_t *uds, uint16_t bp_num);
|
||||
void unsetBreakpoint(tcb_t *t, uint16_t bp_num);
|
||||
|
||||
bool_t configureSingleStepping(arch_tcb_t *uc,
|
||||
bool_t configureSingleStepping(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t n_instr,
|
||||
bool_t is_reply);
|
||||
|
||||
static inline bool_t
|
||||
singleStepFaultCounterReady(arch_tcb_t *uc)
|
||||
singleStepFaultCounterReady(tcb_t *t)
|
||||
{
|
||||
/* For a single-step exception, the user may have specified a certain
|
||||
* number of instructions to skip over before the next stop-point, so
|
||||
|
|
@ -88,10 +88,10 @@ singleStepFaultCounterReady(arch_tcb_t *uc)
|
|||
* We will check the counter's value when deciding whether or not to
|
||||
* actually send a fault message to userspace.
|
||||
*/
|
||||
if (uc->tcbContext.breakpointState.n_instructions > 0) {
|
||||
uc->tcbContext.breakpointState.n_instructions--;
|
||||
if (t->tcbArch.tcbContext.breakpointState.n_instructions > 0) {
|
||||
t->tcbArch.tcbContext.breakpointState.n_instructions--;
|
||||
}
|
||||
return uc->tcbContext.breakpointState.n_instructions == 0;
|
||||
return t->tcbArch.tcbContext.breakpointState.n_instructions == 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HARDWARE_DEBUG_API */
|
||||
|
|
|
|||
|
|
@ -164,12 +164,12 @@ handleFaultReply(tcb_t *receiver, tcb_t *sender)
|
|||
|
||||
syscall_error_t res;
|
||||
|
||||
res = Arch_decodeConfigureSingleStepping(&receiver->tcbArch, 0, n_instrs, true);
|
||||
res = Arch_decodeConfigureSingleStepping(receiver, 0, n_instrs, true);
|
||||
if (res.type != seL4_NoError) {
|
||||
return false;
|
||||
};
|
||||
|
||||
configureSingleStepping(&receiver->tcbArch, 0, n_instrs, true);
|
||||
configureSingleStepping(receiver, 0, n_instrs, true);
|
||||
|
||||
/* Replying will always resume the thread: the only variant behaviour
|
||||
* is whether or not the thread will be resumed with stepping still
|
||||
|
|
|
|||
|
|
@ -1364,7 +1364,7 @@ handleVMFault(tcb_t *thread, vm_fault_type_t vm_faultType)
|
|||
current_fault = handleUserLevelDebugException(pc);
|
||||
|
||||
if (seL4_Fault_DebugException_get_exceptionReason(current_fault) == seL4_SingleStep
|
||||
&& !singleStepFaultCounterReady(&thread->tcbArch)) {
|
||||
&& !singleStepFaultCounterReady(thread)) {
|
||||
/* Don't send a fault message to the thread yet if we were asked
|
||||
* to step through N instructions and the counter isn't depleted
|
||||
* yet.
|
||||
|
|
|
|||
|
|
@ -306,59 +306,59 @@ DEBUG_GENERATE_WRITE_FN(writeWvrCp, DBGWVR)
|
|||
* context and not from the hardware registers.
|
||||
*/
|
||||
static word_t
|
||||
readBcrContext(arch_tcb_t *at, uint16_t index)
|
||||
readBcrContext(tcb_t *t, uint16_t index)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveBreakpoints);
|
||||
return at->tcbContext.breakpointState.breakpoint[index].cr;
|
||||
return t->tcbArch.tcbContext.breakpointState.breakpoint[index].cr;
|
||||
}
|
||||
|
||||
static word_t
|
||||
readBvrContext(arch_tcb_t *at, uint16_t index)
|
||||
readBvrContext(tcb_t *t, uint16_t index)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveBreakpoints);
|
||||
return at->tcbContext.breakpointState.breakpoint[index].vr;
|
||||
return t->tcbArch.tcbContext.breakpointState.breakpoint[index].vr;
|
||||
}
|
||||
|
||||
static word_t
|
||||
readWcrContext(arch_tcb_t *at, uint16_t index)
|
||||
readWcrContext(tcb_t *t, uint16_t index)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveWatchpoints);
|
||||
return at->tcbContext.breakpointState.watchpoint[index].cr;
|
||||
return t->tcbArch.tcbContext.breakpointState.watchpoint[index].cr;
|
||||
}
|
||||
|
||||
static word_t
|
||||
readWvrContext(arch_tcb_t *at, uint16_t index)
|
||||
readWvrContext(tcb_t *t, uint16_t index)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveWatchpoints);
|
||||
return at->tcbContext.breakpointState.watchpoint[index].vr;
|
||||
return t->tcbArch.tcbContext.breakpointState.watchpoint[index].vr;
|
||||
}
|
||||
|
||||
static void
|
||||
writeBcrContext(arch_tcb_t *at, uint16_t index, word_t val)
|
||||
writeBcrContext(tcb_t *t, uint16_t index, word_t val)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveBreakpoints);
|
||||
at->tcbContext.breakpointState.breakpoint[index].cr = val;
|
||||
t->tcbArch.tcbContext.breakpointState.breakpoint[index].cr = val;
|
||||
}
|
||||
|
||||
static void
|
||||
writeBvrContext(arch_tcb_t *at, uint16_t index, word_t val)
|
||||
writeBvrContext(tcb_t *t, uint16_t index, word_t val)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveBreakpoints);
|
||||
at->tcbContext.breakpointState.breakpoint[index].vr = val;
|
||||
t->tcbArch.tcbContext.breakpointState.breakpoint[index].vr = val;
|
||||
}
|
||||
|
||||
static void
|
||||
writeWcrContext(arch_tcb_t *at, uint16_t index, word_t val)
|
||||
writeWcrContext(tcb_t *t, uint16_t index, word_t val)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveWatchpoints);
|
||||
at->tcbContext.breakpointState.watchpoint[index].cr = val;
|
||||
t->tcbArch.tcbContext.breakpointState.watchpoint[index].cr = val;
|
||||
}
|
||||
|
||||
static void
|
||||
writeWvrContext(arch_tcb_t *at, uint16_t index, word_t val)
|
||||
writeWvrContext(tcb_t *t, uint16_t index, word_t val)
|
||||
{
|
||||
assert(index < seL4_NumExclusiveWatchpoints);
|
||||
at->tcbContext.breakpointState.watchpoint[index].vr = val;
|
||||
t->tcbArch.tcbContext.breakpointState.watchpoint[index].vr = val;
|
||||
}
|
||||
|
||||
#endif /* !defined(CONFIG_VERIFICATION_BUILD) && (CONFIG_HARDWARE_DEBUG_API || CONFIG_ARM_HYPERVISOR_SUPPORT) */
|
||||
|
|
@ -394,16 +394,16 @@ dumpBpsAndWpsCp(int nBp, int nWp)
|
|||
* @param mWp Number of WP regs to print, beginning at WP #0.
|
||||
*/
|
||||
UNUSED static void
|
||||
dumpBpsAndWpsContext(arch_tcb_t *at, int nBp, int nWp)
|
||||
dumpBpsAndWpsContext(tcb_t *t, int nBp, int nWp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nBp; i++) {
|
||||
userError("Ctxt BP %d: Bcr %lx, Bvr %lx", i, readBcrContext(at, i), readBvrContext(at, i));
|
||||
userError("Ctxt BP %d: Bcr %lx, Bvr %lx", i, readBcrContext(t, i), readBvrContext(t, i));
|
||||
}
|
||||
|
||||
for (i = 0; i < nWp; i++) {
|
||||
userError("Ctxt WP %d: Wcr %lx, Wvr %lx", i, readWcrContext(at, i), readWvrContext(at, i));
|
||||
userError("Ctxt WP %d: Wcr %lx, Wvr %lx", i, readWcrContext(t, i), readWvrContext(t, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,7 +547,7 @@ getMethodOfEntry(void)
|
|||
* All documented in the seL4 API Manuals.
|
||||
*/
|
||||
void
|
||||
setBreakpoint(arch_tcb_t *at,
|
||||
setBreakpoint(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t vaddr, word_t type, word_t size, word_t rw)
|
||||
{
|
||||
|
|
@ -576,23 +576,23 @@ setBreakpoint(arch_tcb_t *at,
|
|||
if (type == seL4_InstructionBreakpoint) {
|
||||
dbg_bcr_t bcr;
|
||||
|
||||
writeBvrContext(at, bp_num, vaddr);
|
||||
writeBvrContext(t, bp_num, vaddr);
|
||||
|
||||
/* Preserve reserved bits. */
|
||||
bcr.words[0] = readBcrContext(at, bp_num);
|
||||
bcr.words[0] = readBcrContext(t, bp_num);
|
||||
bcr = dbg_bcr_set_enabled(bcr, 1);
|
||||
bcr = dbg_bcr_set_linkedBrp(bcr, 0);
|
||||
bcr = dbg_bcr_set_supervisorAccess(bcr, DBGBCR_PRIV_USER);
|
||||
bcr = dbg_bcr_set_byteAddressSelect(bcr, convertSizeToArch(4));
|
||||
bcr = Arch_setupBcr(bcr, true);
|
||||
writeBcrContext(at, bp_num, bcr.words[0]);
|
||||
writeBcrContext(t, bp_num, bcr.words[0]);
|
||||
} else {
|
||||
dbg_wcr_t wcr;
|
||||
|
||||
writeWvrContext(at, bp_num, vaddr);
|
||||
writeWvrContext(t, bp_num, vaddr);
|
||||
|
||||
/* Preserve reserved bits */
|
||||
wcr.words[0] = readWcrContext(at, bp_num);
|
||||
wcr.words[0] = readWcrContext(t, bp_num);
|
||||
wcr = dbg_wcr_set_enabled(wcr, 1);
|
||||
wcr = dbg_wcr_set_supervisorAccess(wcr, DBGWCR_PRIV_USER);
|
||||
wcr = dbg_wcr_set_byteAddressSelect(wcr, convertSizeToArch(size));
|
||||
|
|
@ -600,7 +600,7 @@ setBreakpoint(arch_tcb_t *at,
|
|||
wcr = dbg_wcr_set_enableLinking(wcr, 0);
|
||||
wcr = dbg_wcr_set_linkedBrp(wcr, 0);
|
||||
wcr = Arch_setupWcr(wcr);
|
||||
writeWcrContext(at, bp_num, wcr.words[0]);
|
||||
writeWcrContext(t, bp_num, wcr.words[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +616,7 @@ setBreakpoint(arch_tcb_t *at,
|
|||
* breakpoint.
|
||||
*/
|
||||
getBreakpoint_t
|
||||
getBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
||||
getBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
getBreakpoint_t ret;
|
||||
|
||||
|
|
@ -626,21 +626,21 @@ getBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
|||
if (ret.type == seL4_InstructionBreakpoint) {
|
||||
dbg_bcr_t bcr;
|
||||
|
||||
bcr.words[0] = readBcrContext(at, bp_num);
|
||||
bcr.words[0] = readBcrContext(t, bp_num);
|
||||
if (Arch_breakpointIsMismatch(bcr) == true) {
|
||||
ret.type = seL4_SingleStep;
|
||||
};
|
||||
ret.size = 0;
|
||||
ret.rw = seL4_BreakOnRead;
|
||||
ret.vaddr = readBvrContext(at, bp_num);
|
||||
ret.vaddr = readBvrContext(t, bp_num);
|
||||
ret.is_enabled = dbg_bcr_get_enabled(bcr);
|
||||
} else {
|
||||
dbg_wcr_t wcr;
|
||||
|
||||
wcr.words[0] = readWcrContext(at, bp_num);
|
||||
wcr.words[0] = readWcrContext(t, bp_num);
|
||||
ret.size = convertArchToSize(dbg_wcr_get_byteAddressSelect(wcr));
|
||||
ret.rw = convertArchToAccess(dbg_wcr_get_loadStore(wcr));
|
||||
ret.vaddr = readWvrContext(at, bp_num);
|
||||
ret.vaddr = readWvrContext(t, bp_num);
|
||||
ret.is_enabled = dbg_wcr_get_enabled(wcr);
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -652,7 +652,7 @@ getBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
|||
* @param bp_num The hardware breakpoint you want to disable+clear.
|
||||
*/
|
||||
void
|
||||
unsetBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
||||
unsetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t type;
|
||||
|
||||
|
|
@ -662,17 +662,17 @@ unsetBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
|||
if (type == seL4_InstructionBreakpoint) {
|
||||
dbg_bcr_t bcr;
|
||||
|
||||
bcr.words[0] = readBcrContext(at, bp_num);
|
||||
bcr.words[0] = readBcrContext(t, bp_num);
|
||||
bcr = dbg_bcr_set_enabled(bcr, 0);
|
||||
writeBcrContext(at, bp_num, bcr.words[0]);
|
||||
writeBvrContext(at, bp_num, 0);
|
||||
writeBcrContext(t, bp_num, bcr.words[0]);
|
||||
writeBvrContext(t, bp_num, 0);
|
||||
} else {
|
||||
dbg_wcr_t wcr;
|
||||
|
||||
wcr.words[0] = readWcrContext(at, bp_num);
|
||||
wcr.words[0] = readWcrContext(t, bp_num);
|
||||
wcr = dbg_wcr_set_enabled(wcr, 0);
|
||||
writeWcrContext(at, bp_num, wcr.words[0]);
|
||||
writeWvrContext(at, bp_num, 0);
|
||||
writeWcrContext(t, bp_num, wcr.words[0]);
|
||||
writeWvrContext(t, bp_num, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -683,7 +683,7 @@ unsetBreakpoint(arch_tcb_t *at, uint16_t bp_num)
|
|||
* @param n_instr The number of instructions to step over.
|
||||
*/
|
||||
bool_t
|
||||
configureSingleStepping(arch_tcb_t *at,
|
||||
configureSingleStepping(tcb_t *t,
|
||||
uint16_t bp_num,
|
||||
word_t n_instr,
|
||||
bool_t is_reply)
|
||||
|
|
@ -697,7 +697,7 @@ configureSingleStepping(arch_tcb_t *at,
|
|||
*/
|
||||
|
||||
if (is_reply) {
|
||||
bp_num = at->tcbContext.breakpointState.single_step_hw_bp_num;
|
||||
bp_num = t->tcbArch.tcbContext.breakpointState.single_step_hw_bp_num;
|
||||
} else {
|
||||
bp_num = convertBpNumToArch(bp_num);
|
||||
}
|
||||
|
|
@ -714,17 +714,17 @@ configureSingleStepping(arch_tcb_t *at,
|
|||
*/
|
||||
dbg_bcr_t bcr;
|
||||
|
||||
bcr.words[0] = readBcrContext(at, bp_num);
|
||||
bcr.words[0] = readBcrContext(t, bp_num);
|
||||
|
||||
/* If the user calls us with n_instr == 0, allow them to configure, but
|
||||
* leave it disabled.
|
||||
*/
|
||||
if (n_instr > 0) {
|
||||
bcr = dbg_bcr_set_enabled(bcr, 1);
|
||||
at->tcbContext.breakpointState.single_step_enabled = true;
|
||||
t->tcbArch.tcbContext.breakpointState.single_step_enabled = true;
|
||||
} else {
|
||||
bcr = dbg_bcr_set_enabled(bcr, 0);
|
||||
at->tcbContext.breakpointState.single_step_enabled = false;
|
||||
t->tcbArch.tcbContext.breakpointState.single_step_enabled = false;
|
||||
}
|
||||
|
||||
bcr = dbg_bcr_set_linkedBrp(bcr, 0);
|
||||
|
|
@ -732,11 +732,11 @@ configureSingleStepping(arch_tcb_t *at,
|
|||
bcr = dbg_bcr_set_byteAddressSelect(bcr, convertSizeToArch(1));
|
||||
bcr = Arch_setupBcr(bcr, false);
|
||||
|
||||
writeBvrContext(at, bp_num, 0);
|
||||
writeBcrContext(at, bp_num, bcr.words[0]);
|
||||
writeBvrContext(t, bp_num, 0);
|
||||
writeBcrContext(t, bp_num, bcr.words[0]);
|
||||
|
||||
at->tcbContext.breakpointState.n_instructions = n_instr;
|
||||
at->tcbContext.breakpointState.single_step_hw_bp_num = bp_num;
|
||||
t->tcbArch.tcbContext.breakpointState.n_instructions = n_instr;
|
||||
t->tcbArch.tcbContext.breakpointState.single_step_hw_bp_num = bp_num;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1195,9 +1195,9 @@ handleUserLevelDebugException(word_t fault_vaddr)
|
|||
* coprocessor.
|
||||
*/
|
||||
void
|
||||
Arch_initBreakpointContext(user_breakpoint_state_t *uds)
|
||||
Arch_initBreakpointContext(user_context_t *uc)
|
||||
{
|
||||
*uds = armKSNullBreakpointState;
|
||||
uc->breakpointState = armKSNullBreakpointState;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1242,20 +1242,20 @@ loadAllDisabledBreakpointState(void)
|
|||
* associateVcpu.
|
||||
*/
|
||||
void
|
||||
saveAllBreakpointState(arch_tcb_t *at)
|
||||
saveAllBreakpointState(tcb_t *t)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(at != NULL);
|
||||
assert(t != NULL);
|
||||
|
||||
for (i = 0; i < seL4_NumExclusiveBreakpoints; i++) {
|
||||
writeBvrContext(at, i, readBvrCp(i));
|
||||
writeBcrContext(at, i, readBcrCp(i));
|
||||
writeBvrContext(t, i, readBvrCp(i));
|
||||
writeBcrContext(t, i, readBcrCp(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < seL4_NumExclusiveWatchpoints; i++) {
|
||||
writeWvrContext(at, i, readWvrCp(i));
|
||||
writeWcrContext(at, i, readWcrCp(i));
|
||||
writeWvrContext(t, i, readWvrCp(i));
|
||||
writeWcrContext(t, i, readWcrCp(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1278,16 +1278,16 @@ Arch_debugDissociateVCPUTCB(tcb_t *t)
|
|||
}
|
||||
|
||||
static void
|
||||
loadBreakpointState(arch_tcb_t *at)
|
||||
loadBreakpointState(tcb_t *t)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(at != NULL);
|
||||
assert(t != NULL);
|
||||
|
||||
for (i = 0; i < seL4_NumExclusiveBreakpoints; i++) {
|
||||
if (at->tcbContext.breakpointState.used_breakpoints_bf & BIT(i)) {
|
||||
writeBvrCp(i, readBvrContext(at, i));
|
||||
writeBcrCp(i, readBcrContext(at, i));
|
||||
if (t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf & BIT(i)) {
|
||||
writeBvrCp(i, readBvrContext(t, i));
|
||||
writeBcrCp(i, readBcrContext(t, i));
|
||||
} else {
|
||||
/* If the thread isn't using the BP, then just load
|
||||
* a default "disabled" state.
|
||||
|
|
@ -1297,10 +1297,10 @@ loadBreakpointState(arch_tcb_t *at)
|
|||
}
|
||||
|
||||
for (i = 0; i < seL4_NumExclusiveWatchpoints; i++) {
|
||||
if (at->tcbContext.breakpointState.used_breakpoints_bf &
|
||||
if (t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf &
|
||||
BIT(i + seL4_NumExclusiveBreakpoints)) {
|
||||
writeWvrCp(i, readWvrContext(at, i));
|
||||
writeWcrCp(i, readWcrContext(at, i));
|
||||
writeWvrCp(i, readWvrContext(t, i));
|
||||
writeWcrCp(i, readWcrContext(t, i));
|
||||
} else {
|
||||
writeWcrCp(i, readWcrCp(i) & ~DBGWCR_ENABLE);
|
||||
}
|
||||
|
|
@ -1319,7 +1319,7 @@ restore_user_debug_context(tcb_t *target_thread)
|
|||
if (target_thread->tcbArch.tcbContext.breakpointState.used_breakpoints_bf == 0) {
|
||||
loadAllDisabledBreakpointState();
|
||||
} else {
|
||||
loadBreakpointState(&target_thread->tcbArch);
|
||||
loadBreakpointState(target_thread);
|
||||
}
|
||||
|
||||
/* ARMv6 manual, sec D3.3.7:
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ vcpu_save(vcpu_t *vcpu, bool_t active)
|
|||
* not exporting the debug API, because in that case, native
|
||||
* threads can't modify the debug registers (i.e, without the API).
|
||||
*/
|
||||
saveAllBreakpointState(&vcpu->vcpuTCB->tcbArch);
|
||||
saveAllBreakpointState(vcpu->vcpuTCB);
|
||||
#endif
|
||||
isb();
|
||||
}
|
||||
|
|
@ -851,7 +851,7 @@ vcpu_switch(vcpu_t *new)
|
|||
} else if (unlikely(armHSVCPUActive)) {
|
||||
/* leave the current VCPU state loaded, but disable vgic and mmu */
|
||||
#ifndef CONFIG_VERIFICATION_BUILD
|
||||
saveAllBreakpointState(&armHSCurVCPU->vcpuTCB->tcbArch);
|
||||
saveAllBreakpointState(armHSCurVCPU->vcpuTCB);
|
||||
#endif
|
||||
vcpu_disable(armHSCurVCPU);
|
||||
armHSVCPUActive = false;
|
||||
|
|
|
|||
|
|
@ -72,25 +72,25 @@ bitwiseAndDr6Reg(word_t mask)
|
|||
}
|
||||
|
||||
static inline word_t
|
||||
readDr7Context(arch_tcb_t *uds)
|
||||
readDr7Context(tcb_t *t)
|
||||
{
|
||||
return uds->tcbContext.breakpointState.dr[5];
|
||||
return t->tcbArch.tcbContext.breakpointState.dr[5];
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitwiseOrDr7Context(arch_tcb_t *uds, word_t val)
|
||||
bitwiseOrDr7Context(tcb_t *t, word_t val)
|
||||
{
|
||||
uds->tcbContext.breakpointState.dr[5] |= val;
|
||||
t->tcbArch.tcbContext.breakpointState.dr[5] |= val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitwiseAndDr7Context(arch_tcb_t *uds, word_t mask)
|
||||
bitwiseAndDr7Context(tcb_t *t, word_t mask)
|
||||
{
|
||||
uds->tcbContext.breakpointState.dr[5] &= mask;
|
||||
t->tcbArch.tcbContext.breakpointState.dr[5] &= mask;
|
||||
}
|
||||
|
||||
static void
|
||||
unsetDr7BitsFor(arch_tcb_t *uds, uint16_t bp_num)
|
||||
unsetDr7BitsFor(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t mask;
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ unsetDr7BitsFor(arch_tcb_t *uds, uint16_t bp_num)
|
|||
}
|
||||
|
||||
mask = ~mask;
|
||||
bitwiseAndDr7Context(uds, mask);
|
||||
bitwiseAndDr7Context(t, mask);
|
||||
}
|
||||
|
||||
/** Converts an seL4_BreakpointType value into the underlying hardware
|
||||
|
|
@ -306,11 +306,11 @@ convertArchToSize(word_t dr7, uint16_t bp_num)
|
|||
* @param bp_num Hardware breakpoint ID. Usually an integer from 0..N.
|
||||
*/
|
||||
static void
|
||||
enableBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
enableBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t enable_bit;
|
||||
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
assert(bp_num < X86_DEBUG_BP_N_REGS);
|
||||
|
||||
switch (bp_num) {
|
||||
|
|
@ -328,18 +328,18 @@ enableBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
break;
|
||||
}
|
||||
|
||||
bitwiseOrDr7Context(uds, enable_bit);
|
||||
bitwiseOrDr7Context(t, enable_bit);
|
||||
}
|
||||
|
||||
/** Disables a breakpoint without clearing its configuration.
|
||||
* @param bp_num Hardware breakpoint ID. Usually an integer from 0..N.
|
||||
*/
|
||||
static void
|
||||
disableBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
disableBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t disable_mask;
|
||||
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
assert(bp_num < X86_DEBUG_BP_N_REGS);
|
||||
|
||||
switch (bp_num) {
|
||||
|
|
@ -357,21 +357,21 @@ disableBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
break;
|
||||
}
|
||||
|
||||
bitwiseAndDr7Context(uds, disable_mask);
|
||||
bitwiseAndDr7Context(t, disable_mask);
|
||||
}
|
||||
|
||||
/** Returns a boolean for whether or not a breakpoint is enabled.
|
||||
* @param bp_num Hardware breakpoint ID. Usually an integer from 0..N.
|
||||
*/
|
||||
static bool_t
|
||||
breakpointIsEnabled(arch_tcb_t *uds, uint16_t bp_num)
|
||||
breakpointIsEnabled(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t dr7;
|
||||
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
assert(bp_num < X86_DEBUG_BP_N_REGS);
|
||||
|
||||
dr7 = readDr7Context(uds);
|
||||
dr7 = readDr7Context(t);
|
||||
switch (bp_num) {
|
||||
case 0:
|
||||
return !!(dr7 & X86_DEBUG_BP0_ENABLE_BIT);
|
||||
|
|
@ -385,22 +385,24 @@ breakpointIsEnabled(arch_tcb_t *uds, uint16_t bp_num)
|
|||
}
|
||||
|
||||
static void
|
||||
setBpVaddrContext(user_breakpoint_state_t *uds, uint16_t bp_num, word_t vaddr)
|
||||
setBpVaddrContext(tcb_t *t, uint16_t bp_num, word_t vaddr)
|
||||
{
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
user_breakpoint_state_t *ubs = &t->tcbArch.tcbContext.breakpointState;
|
||||
|
||||
switch (bp_num) {
|
||||
case 0:
|
||||
uds->dr[0] = vaddr;
|
||||
ubs->dr[0] = vaddr;
|
||||
break;
|
||||
case 1:
|
||||
uds->dr[1] = vaddr;
|
||||
ubs->dr[1] = vaddr;
|
||||
break;
|
||||
case 2:
|
||||
uds->dr[2] = vaddr;
|
||||
ubs->dr[2] = vaddr;
|
||||
break;
|
||||
default:
|
||||
assert(bp_num == 3);
|
||||
uds->dr[3] = vaddr;
|
||||
ubs->dr[3] = vaddr;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
|
@ -418,36 +420,38 @@ setBpVaddrContext(user_breakpoint_state_t *uds, uint16_t bp_num, word_t vaddr)
|
|||
* @param rw Access type that should trigger the BP (read/write).
|
||||
*/
|
||||
void
|
||||
setBreakpoint(arch_tcb_t *uds,
|
||||
setBreakpoint(tcb_t *t,
|
||||
uint16_t bp_num, word_t vaddr, word_t types, word_t size, word_t rw)
|
||||
{
|
||||
word_t dr7val;
|
||||
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
|
||||
dr7val = convertTypeAndAccessToArch(bp_num, types, rw);
|
||||
dr7val |= convertSizeToArch(bp_num, types, size);
|
||||
|
||||
setBpVaddrContext(&uds->tcbContext.breakpointState, bp_num, vaddr);
|
||||
unsetDr7BitsFor(uds, bp_num);
|
||||
bitwiseOrDr7Context(uds, dr7val);
|
||||
enableBreakpoint(uds, bp_num);
|
||||
setBpVaddrContext(t, bp_num, vaddr);
|
||||
unsetDr7BitsFor(t, bp_num);
|
||||
bitwiseOrDr7Context(t, dr7val);
|
||||
enableBreakpoint(t, bp_num);
|
||||
}
|
||||
|
||||
static word_t
|
||||
getBpVaddrContext(user_breakpoint_state_t *uds, uint16_t bp_num)
|
||||
getBpVaddrContext(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
assert(uds != NULL);
|
||||
assert(t != NULL);
|
||||
user_breakpoint_state_t *ubs = &t->tcbArch.tcbContext.breakpointState;
|
||||
|
||||
switch (bp_num) {
|
||||
case 0:
|
||||
return uds->dr[0];
|
||||
return ubs->dr[0];
|
||||
case 1:
|
||||
return uds->dr[1];
|
||||
return ubs->dr[1];
|
||||
case 2:
|
||||
return uds->dr[2];
|
||||
return ubs->dr[2];
|
||||
default:
|
||||
assert(bp_num == 3);
|
||||
return uds->dr[3];
|
||||
return ubs->dr[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,19 +465,19 @@ getBpVaddrContext(user_breakpoint_state_t *uds, uint16_t bp_num)
|
|||
* @return Structure containing information about the status of the breakpoint.
|
||||
*/
|
||||
getBreakpoint_t
|
||||
getBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
getBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
word_t dr7val;
|
||||
getBreakpoint_t ret;
|
||||
convertedTypeAndAccess_t res;
|
||||
|
||||
dr7val = readDr7Context(uds);
|
||||
ret.vaddr = getBpVaddrContext(&uds->tcbContext.breakpointState, bp_num);
|
||||
dr7val = readDr7Context(t);
|
||||
ret.vaddr = getBpVaddrContext(t, bp_num);
|
||||
ret.size = convertArchToSize(dr7val, bp_num);
|
||||
res = convertArchToTypeAndAccess(dr7val, bp_num);
|
||||
ret.type = res.type;
|
||||
ret.rw = res.rw;
|
||||
ret.is_enabled = breakpointIsEnabled(uds, bp_num);
|
||||
ret.is_enabled = breakpointIsEnabled(t, bp_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -484,11 +488,11 @@ getBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
|||
* @param bp_num The hardware breakpoint ID you'd like to clear.
|
||||
*/
|
||||
void
|
||||
unsetBreakpoint(arch_tcb_t *uds, uint16_t bp_num)
|
||||
unsetBreakpoint(tcb_t *t, uint16_t bp_num)
|
||||
{
|
||||
disableBreakpoint(uds, bp_num);
|
||||
unsetDr7BitsFor(uds, bp_num);
|
||||
setBpVaddrContext(&uds->tcbContext.breakpointState, bp_num, 0);
|
||||
disableBreakpoint(t, bp_num);
|
||||
unsetDr7BitsFor(t, bp_num);
|
||||
setBpVaddrContext(t, bp_num, 0);
|
||||
}
|
||||
|
||||
/** Used in the exception path to determine if an exception was caused by
|
||||
|
|
@ -504,7 +508,7 @@ typedef struct {
|
|||
} testAndResetSingleStepException_t;
|
||||
|
||||
static testAndResetSingleStepException_t
|
||||
testAndResetSingleStepException(arch_tcb_t *uc)
|
||||
testAndResetSingleStepException(tcb_t *t)
|
||||
{
|
||||
testAndResetSingleStepException_t ret;
|
||||
word_t dr6;
|
||||
|
|
@ -516,7 +520,7 @@ testAndResetSingleStepException(arch_tcb_t *uc)
|
|||
}
|
||||
|
||||
ret.ret = true;
|
||||
ret.instr_vaddr = uc->tcbContext.registers[FaultIP];
|
||||
ret.instr_vaddr = t->tcbArch.tcbContext.registers[FaultIP];
|
||||
bitwiseAndDr6Reg(~X86_DEBUG_DR6_SINGLE_STEP_FLAG);
|
||||
|
||||
/* And that's not all: if the breakpoint is an instruction breakpoint, we
|
||||
|
|
@ -531,12 +535,12 @@ testAndResetSingleStepException(arch_tcb_t *uc)
|
|||
* Intel manuals, vol3, section 17.3.1.1.
|
||||
*/
|
||||
/* This will automatically be popped by restore_user_context() */
|
||||
uc->tcbContext.registers[FLAGS] |= X86_DEBUG_EFLAGS_RESUME_FLAG;
|
||||
t->tcbArch.tcbContext.registers[FLAGS] |= X86_DEBUG_EFLAGS_RESUME_FLAG;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool_t
|
||||
configureSingleStepping(arch_tcb_t *uc, uint16_t bp_num, word_t n_instr,
|
||||
configureSingleStepping(tcb_t *t, uint16_t bp_num, word_t n_instr,
|
||||
UNUSED bool_t is_reply)
|
||||
{
|
||||
/* On x86 no hardware breakpoints are needed for single stepping. */
|
||||
|
|
@ -544,13 +548,13 @@ configureSingleStepping(arch_tcb_t *uc, uint16_t bp_num, word_t n_instr,
|
|||
/* If n_instr (number of instructions to single-step) is 0, that is the
|
||||
* same as requesting that single-stepping be disabled.
|
||||
*/
|
||||
uc->tcbContext.breakpointState.single_step_enabled = false;
|
||||
uc->tcbContext.registers[FLAGS] &= ~X86_DEBUG_EFLAGS_TRAP_FLAG;
|
||||
t->tcbArch.tcbContext.breakpointState.single_step_enabled = false;
|
||||
t->tcbArch.tcbContext.registers[FLAGS] &= ~X86_DEBUG_EFLAGS_TRAP_FLAG;
|
||||
} else {
|
||||
uc->tcbContext.breakpointState.single_step_enabled = true;
|
||||
t->tcbArch.tcbContext.breakpointState.single_step_enabled = true;
|
||||
}
|
||||
|
||||
uc->tcbContext.breakpointState.n_instructions = n_instr;
|
||||
t->tcbArch.tcbContext.breakpointState.n_instructions = n_instr;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -576,7 +580,7 @@ typedef struct {
|
|||
} getAndResetActiveBreakpoint_t;
|
||||
|
||||
static getAndResetActiveBreakpoint_t
|
||||
getAndResetActiveBreakpoint(arch_tcb_t *at)
|
||||
getAndResetActiveBreakpoint(tcb_t *t)
|
||||
{
|
||||
convertedTypeAndAccess_t tmp;
|
||||
getAndResetActiveBreakpoint_t ret;
|
||||
|
|
@ -596,8 +600,8 @@ getAndResetActiveBreakpoint(arch_tcb_t *at)
|
|||
return ret;
|
||||
}
|
||||
|
||||
tmp = convertArchToTypeAndAccess(readDr7Context(at), ret.bp_num);
|
||||
ret.vaddr = getBpVaddrContext(&at->tcbContext.breakpointState, ret.bp_num);
|
||||
tmp = convertArchToTypeAndAccess(readDr7Context(t), ret.bp_num);
|
||||
ret.vaddr = getBpVaddrContext(t, ret.bp_num);
|
||||
ret.reason = tmp.type;
|
||||
|
||||
bitwiseAndDr6Reg(~BIT(ret.bp_num));
|
||||
|
|
@ -607,7 +611,7 @@ getAndResetActiveBreakpoint(arch_tcb_t *at)
|
|||
exception_t
|
||||
handleUserLevelDebugException(int int_vector)
|
||||
{
|
||||
arch_tcb_t *context;
|
||||
tcb_t *ct;
|
||||
getAndResetActiveBreakpoint_t active_bp;
|
||||
testAndResetSingleStepException_t single_step_info;
|
||||
|
||||
|
|
@ -622,7 +626,7 @@ handleUserLevelDebugException(int int_vector)
|
|||
benchmark_track_start();
|
||||
#endif
|
||||
|
||||
context = &NODE_STATE(ksCurThread)->tcbArch;
|
||||
ct = NODE_STATE(ksCurThread);
|
||||
|
||||
/* Software break request (INT3) is detected by the vector number */
|
||||
if (int_vector == int_software_break_request) {
|
||||
|
|
@ -630,20 +634,20 @@ handleUserLevelDebugException(int int_vector)
|
|||
0, seL4_SoftwareBreakRequest);
|
||||
} else {
|
||||
/* Hardware breakpoint trigger is detected using DR6 */
|
||||
active_bp = getAndResetActiveBreakpoint(context);
|
||||
active_bp = getAndResetActiveBreakpoint(ct);
|
||||
if (active_bp.bp_num >= 0) {
|
||||
current_fault = seL4_Fault_DebugException_new(active_bp.vaddr,
|
||||
active_bp.bp_num,
|
||||
active_bp.reason);
|
||||
} else {
|
||||
single_step_info = testAndResetSingleStepException(context);
|
||||
single_step_info = testAndResetSingleStepException(ct);
|
||||
if (single_step_info.ret == true) {
|
||||
/* If the caller asked us to skip over N instructions before
|
||||
* generating the next single-step breakpoint, we shouldn't
|
||||
* bother to construct a fault message until we've skipped N
|
||||
* instructions.
|
||||
*/
|
||||
if (singleStepFaultCounterReady(context) == false) {
|
||||
if (singleStepFaultCounterReady(ct) == false) {
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
current_fault = seL4_Fault_DebugException_new(single_step_info.instr_vaddr,
|
||||
|
|
|
|||
|
|
@ -389,17 +389,17 @@ decodeSetAffinity(cap_t cap, word_t length, word_t *buffer)
|
|||
|
||||
#ifdef CONFIG_HARDWARE_DEBUG_API
|
||||
static exception_t
|
||||
invokeConfigureSingleStepping(word_t *buffer, arch_tcb_t *context,
|
||||
invokeConfigureSingleStepping(word_t *buffer, tcb_t *t,
|
||||
uint16_t bp_num, word_t n_instrs)
|
||||
{
|
||||
bool_t bp_was_consumed;
|
||||
|
||||
bp_was_consumed = configureSingleStepping(context, bp_num, n_instrs, false);
|
||||
bp_was_consumed = configureSingleStepping(t, bp_num, n_instrs, false);
|
||||
if (n_instrs == 0) {
|
||||
unsetBreakpointUsedFlag(context, bp_num);
|
||||
unsetBreakpointUsedFlag(t, bp_num);
|
||||
setMR(NODE_STATE(ksCurThread), buffer, 0, false);
|
||||
} else {
|
||||
setBreakpointUsedFlag(context, bp_num);
|
||||
setBreakpointUsedFlag(t, bp_num);
|
||||
setMR(NODE_STATE(ksCurThread), buffer, 0, bp_was_consumed);
|
||||
}
|
||||
return EXCEPTION_NONE;
|
||||
|
|
@ -411,32 +411,30 @@ decodeConfigureSingleStepping(cap_t cap, word_t *buffer)
|
|||
uint16_t bp_num;
|
||||
word_t n_instrs;
|
||||
tcb_t *tcb;
|
||||
arch_tcb_t *context;
|
||||
syscall_error_t syserr;
|
||||
|
||||
tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap));
|
||||
context = &tcb->tcbArch;
|
||||
|
||||
bp_num = getSyscallArg(0, buffer);
|
||||
n_instrs = getSyscallArg(1, buffer);
|
||||
|
||||
syserr = Arch_decodeConfigureSingleStepping(context, bp_num, n_instrs, false);
|
||||
syserr = Arch_decodeConfigureSingleStepping(tcb, bp_num, n_instrs, false);
|
||||
if (syserr.type != seL4_NoError) {
|
||||
current_syscall_error = syserr;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return invokeConfigureSingleStepping(buffer, context, bp_num, n_instrs);
|
||||
return invokeConfigureSingleStepping(buffer, tcb, bp_num, n_instrs);
|
||||
}
|
||||
|
||||
static exception_t
|
||||
invokeSetBreakpoint(arch_tcb_t *context, uint16_t bp_num,
|
||||
invokeSetBreakpoint(tcb_t *tcb, uint16_t bp_num,
|
||||
word_t vaddr, word_t type, word_t size, word_t rw)
|
||||
{
|
||||
setBreakpoint(context, bp_num, vaddr, type, size, rw);
|
||||
setBreakpoint(tcb, bp_num, vaddr, type, size, rw);
|
||||
/* Signal restore_user_context() to pop the breakpoint context on return. */
|
||||
setBreakpointUsedFlag(context, bp_num);
|
||||
setBreakpointUsedFlag(tcb, bp_num);
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -446,7 +444,6 @@ decodeSetBreakpoint(cap_t cap, word_t *buffer)
|
|||
uint16_t bp_num;
|
||||
word_t vaddr, type, size, rw;
|
||||
tcb_t *tcb;
|
||||
arch_tcb_t *context;
|
||||
syscall_error_t error;
|
||||
|
||||
tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap));
|
||||
|
|
@ -548,25 +545,23 @@ decodeSetBreakpoint(cap_t cap, word_t *buffer)
|
|||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
context = &tcb->tcbArch;
|
||||
|
||||
error = Arch_decodeSetBreakpoint(context, bp_num, vaddr, type, size, rw);
|
||||
error = Arch_decodeSetBreakpoint(tcb, bp_num, vaddr, type, size, rw);
|
||||
if (error.type != seL4_NoError) {
|
||||
current_syscall_error = error;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return invokeSetBreakpoint(context, bp_num,
|
||||
return invokeSetBreakpoint(tcb, bp_num,
|
||||
vaddr, type, size, rw);
|
||||
}
|
||||
|
||||
static exception_t
|
||||
invokeGetBreakpoint(word_t *buffer, arch_tcb_t *context, uint16_t bp_num)
|
||||
invokeGetBreakpoint(word_t *buffer, tcb_t *tcb, uint16_t bp_num)
|
||||
{
|
||||
getBreakpoint_t res;
|
||||
|
||||
res = getBreakpoint(context, bp_num);
|
||||
res = getBreakpoint(tcb, bp_num);
|
||||
setMR(NODE_STATE(ksCurThread), buffer, 0, res.vaddr);
|
||||
setMR(NODE_STATE(ksCurThread), buffer, 1, res.type);
|
||||
setMR(NODE_STATE(ksCurThread), buffer, 2, res.size);
|
||||
|
|
@ -580,30 +575,27 @@ decodeGetBreakpoint(cap_t cap, word_t *buffer)
|
|||
{
|
||||
tcb_t *tcb;
|
||||
uint16_t bp_num;
|
||||
arch_tcb_t *context;
|
||||
syscall_error_t error;
|
||||
|
||||
tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap));
|
||||
bp_num = getSyscallArg(0, buffer);
|
||||
|
||||
context = &tcb->tcbArch;
|
||||
|
||||
error = Arch_decodeGetBreakpoint(context, bp_num);
|
||||
error = Arch_decodeGetBreakpoint(tcb, bp_num);
|
||||
if (error.type != seL4_NoError) {
|
||||
current_syscall_error = error;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return invokeGetBreakpoint(buffer, context, bp_num);
|
||||
return invokeGetBreakpoint(buffer, tcb, bp_num);
|
||||
}
|
||||
|
||||
static exception_t
|
||||
invokeUnsetBreakpoint(arch_tcb_t *context, uint16_t bp_num)
|
||||
invokeUnsetBreakpoint(tcb_t *tcb, uint16_t bp_num)
|
||||
{
|
||||
/* Maintain the bitfield of in-use breakpoints. */
|
||||
unsetBreakpoint(context, bp_num);
|
||||
unsetBreakpointUsedFlag(context, bp_num);
|
||||
unsetBreakpoint(tcb, bp_num);
|
||||
unsetBreakpointUsedFlag(tcb, bp_num);
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -612,22 +604,19 @@ decodeUnsetBreakpoint(cap_t cap, word_t *buffer)
|
|||
{
|
||||
tcb_t *tcb;
|
||||
uint16_t bp_num;
|
||||
arch_tcb_t *context;
|
||||
syscall_error_t error;
|
||||
|
||||
tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap));
|
||||
bp_num = getSyscallArg(0, buffer);
|
||||
|
||||
context = &tcb->tcbArch;
|
||||
|
||||
error = Arch_decodeUnsetBreakpoint(context, bp_num);
|
||||
error = Arch_decodeUnsetBreakpoint(tcb, bp_num);
|
||||
if (error.type != seL4_NoError) {
|
||||
current_syscall_error = error;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return invokeUnsetBreakpoint(context, bp_num);
|
||||
return invokeUnsetBreakpoint(tcb, bp_num);
|
||||
}
|
||||
#endif /* CONFIG_HARDWARE_DEBUG_API */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue