diff --git a/thermosphere/src/gdb/debug.c b/thermosphere/src/gdb/debug.c index 60b18dc91..8847018dc 100644 --- a/thermosphere/src/gdb/debug.c +++ b/thermosphere/src/gdb/debug.c @@ -228,9 +228,16 @@ int GDB_SendStopReply(GDBContext *ctx, const DebugEventInfo *info) case Exception_WatchpointLowerEl: { static const char *kinds[] = { "", "r", "", "a" }; - n = GDB_ParseExceptionFrame(buffer, ctx, SIGTRAP); - u32 kind = 3; // TODO: retrieve the actual wp direction (if it's a bidirectional wp or not) - sprintf(buffer + n, "%swatch:%016lx;", kinds[kind], info->frame->far_el2); + // Note: exception info doesn't provide us with the access size. Use 1. + bool wnr = (info->frame->esr_el2.iss & BIT(6)) != 0; + WatchpointLoadStoreControl dr = wnr ? WatchpointLoadStoreControl_Store : WatchpointLoadStoreControl_Load; + DebugControlRegister cr = retrieveSplitWatchpointConfig(info->frame->far_el2, 1, dr, false); + if (!cr.enabled) { + DEBUG("GDB: oops, unhandled watchpoint for core id %u, far=%016lx\n", info->coreId, info->frame->far_el2); + } else { + n = GDB_ParseExceptionFrame(buffer, ctx, SIGTRAP); + sprintf(buffer + n, "%swatch:%016lx;", kinds[cr.lsc], info->frame->far_el2); + } } // Note: we don't really support 32-bit sw breakpoints, we'll still report them diff --git a/thermosphere/src/watchpoints.c b/thermosphere/src/watchpoints.c index 6fb792376..3cd1d06c7 100644 --- a/thermosphere/src/watchpoints.c +++ b/thermosphere/src/watchpoints.c @@ -189,10 +189,14 @@ static DebugRegisterPair *doFindSplitWatchpoint(u64 addr, size_t size, Watchpoin return NULL; } -DebugRegisterPair *findSplitWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction, bool strict) +DebugControlRegister retrieveSplitWatchpointConfig(u64 addr, size_t size, WatchpointLoadStoreControl direction, bool strict) { recursiveSpinlockLock(&g_watchpointManager.lock); - DebugRegisterPair *ret = doFindSplitWatchpoint(addr, size, direction, strict); + DebugRegisterPair *wp = doFindSplitWatchpoint(addr, size, direction, strict); + DebugControlRegister ret = { 0 }; + if (wp != NULL) { + ret = wp->cr; + } recursiveSpinlockUnlock(&g_watchpointManager.lock); return ret; } diff --git a/thermosphere/src/watchpoints.h b/thermosphere/src/watchpoints.h index 1ab79fafa..b277efee4 100644 --- a/thermosphere/src/watchpoints.h +++ b/thermosphere/src/watchpoints.h @@ -35,7 +35,7 @@ typedef struct WatchpointManager { extern WatchpointManager g_watchpointManager; void initWatchpoints(void); -DebugRegisterPair *findSplitWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction, bool strict); +DebugControlRegister retrieveSplitWatchpointConfig(u64 addr, size_t size, WatchpointLoadStoreControl direction, bool strict); int addWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction); int removeWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction); int removeAllWatchpoints(void);