From 1775d5997751fad40de7bd229c8743e70012be58 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Tue, 13 Aug 2019 00:14:56 +0200 Subject: [PATCH] thermosphere: implement stop point broadcast --- thermosphere/src/breakpoints.c | 23 ++++++++++--- thermosphere/src/software_breakpoints.c | 46 ++++++++++++++++++------- thermosphere/src/watchpoints.c | 24 ++++++++++--- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/thermosphere/src/breakpoints.c b/thermosphere/src/breakpoints.c index 5465f9905..b9c068fcd 100644 --- a/thermosphere/src/breakpoints.c +++ b/thermosphere/src/breakpoints.c @@ -39,6 +39,19 @@ void initBreakpoints(void) recursiveSpinlockUnlock(&g_breakpointManager.lock); } +static void commitAndBroadcastBreakpointHandler(void *p) +{ + (void)p; + u64 flags = maskIrq(); + loadBreakpointRegs(g_breakpointManager.breakpoints, g_breakpointManager.maxBreakpoints); + restoreInterruptFlags(flags); +} + +static inline void commitAndBroadcastBreakpoints(void) +{ + executeFunctionOnAllCores(commitAndBroadcastBreakpointHandler, NULL, true); +} + static DebugRegisterPair *allocateBreakpoint(void) { u32 pos = __builtin_ffs(g_breakpointManager.allocationBitmap); @@ -107,9 +120,9 @@ int addBreakpoint(u64 addr) regs->vr = addr; - recursiveSpinlockUnlock(&g_breakpointManager.lock); + commitAndBroadcastBreakpoints(); - // TODO commit & broadcast + recursiveSpinlockUnlock(&g_breakpointManager.lock); return 0; } @@ -126,9 +139,9 @@ int removeBreakpoint(u64 addr) } freeBreakpoint(regs - &g_breakpointManager.breakpoints[0]); - recursiveSpinlockUnlock(&g_breakpointManager.lock); - // TODO commit & broadcast + commitAndBroadcastBreakpoints(); + recursiveSpinlockUnlock(&g_breakpointManager.lock); return 0; } @@ -139,7 +152,7 @@ int removeAllBreakpoints(void) g_breakpointManager.allocationBitmap = BIT(g_breakpointManager.maxBreakpoints) - 1; memset(g_breakpointManager.breakpoints, 0, sizeof(g_breakpointManager.breakpoints)); - // TODO: commit & broadcast + commitAndBroadcastBreakpoints(); recursiveSpinlockUnlock(&g_breakpointManager.lock); diff --git a/thermosphere/src/software_breakpoints.c b/thermosphere/src/software_breakpoints.c index 4921ab400..bf9d9f014 100644 --- a/thermosphere/src/software_breakpoints.c +++ b/thermosphere/src/software_breakpoints.c @@ -54,7 +54,7 @@ static size_t findClosestSoftwareBreakpointSlot(u64 address) return b; } -static bool doApplySoftwareBreakpoint(size_t id) +static inline bool doApplySoftwareBreakpoint(size_t id) { SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; if (bp->applied) { @@ -71,7 +71,19 @@ static bool doApplySoftwareBreakpoint(size_t id) return false; } -static bool doRevertSoftwareBreakpoint(size_t id) +static void applySoftwareBreakpointHandler(void *p) +{ + u64 flags = maskIrq(); + doApplySoftwareBreakpoint(*(size_t *)p); + restoreInterruptFlags(flags); +} + +static void applySoftwareBreakpoint(size_t id) +{ + executeFunctionOnAllCores(applySoftwareBreakpointHandler, &id, true); +} + +static inline bool doRevertSoftwareBreakpoint(size_t id) { SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; if (!bp->applied) { @@ -86,30 +98,40 @@ static bool doRevertSoftwareBreakpoint(size_t id) return false; } -// TODO write SGI handlers for those ^ +static void revertSoftwareBreakpointHandler(void *p) +{ + u64 flags = maskIrq(); + doRevertSoftwareBreakpoint(*(size_t *)p); + restoreInterruptFlags(flags); +} + +static void revertSoftwareBreakpoint(size_t id) +{ + executeFunctionOnAllCores(revertSoftwareBreakpointHandler, &id, true); +} bool applyAllSoftwareBreakpoints(void) { - recursiveSpinlockLock(&g_softwareBreakpointManager.lock); + u64 flags = recursiveSpinlockLockMaskIrq(&g_softwareBreakpointManager.lock); bool ret = true; for (size_t i = 0; i < g_softwareBreakpointManager.numBreakpoints; i++) { - ret = ret && doApplySoftwareBreakpoint(i); + ret = ret && doApplySoftwareBreakpoint(i); // note: no broadcast intentional } - recursiveSpinlockUnlock(&g_softwareBreakpointManager.lock); + recursiveSpinlockUnlockRestoreIrq(&g_softwareBreakpointManager.lock, flags); return ret; } bool revertAllSoftwareBreakpoints(void) { - recursiveSpinlockLock(&g_softwareBreakpointManager.lock); + u64 flags = recursiveSpinlockLockMaskIrq(&g_softwareBreakpointManager.lock); bool ret = true; for (size_t i = 0; i < g_softwareBreakpointManager.numBreakpoints; i++) { - ret = ret && doRevertSoftwareBreakpoint(i); + ret = ret && doRevertSoftwareBreakpoint(i); // note: no broadcast intentional } - recursiveSpinlockUnlock(&g_softwareBreakpointManager.lock); + recursiveSpinlockUnlockRestoreIrq(&g_softwareBreakpointManager.lock, flags); return ret; } @@ -142,7 +164,7 @@ int addSoftwareBreakpoint(u64 addr, bool persistent) bp->applied = false; bp->uid = 0x2000 + g_softwareBreakpointManager.bpUniqueCounter++; - // TODO: write broadcast for apply + applySoftwareBreakpoint(id); // Note: no way to handle breakpoint failing to apply on 1+ core but not all, we need to assume operation succeeds recursiveSpinlockUnlock(&g_softwareBreakpointManager.lock); @@ -166,7 +188,7 @@ int removeSoftwareBreakpoint(u64 addr, bool keepPersistent) SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; if (!keepPersistent || !bp->persistent) { - // TODO: write broadcast for 'revert' + revertSoftwareBreakpoint(id); // Note: no way to handle breakpoint failing to revert on 1+ core but not all, we need to assume operation succeeds } @@ -189,7 +211,7 @@ int removeAllSoftwareBreakpoints(bool keepPersistent) for (size_t id = 0; id < g_softwareBreakpointManager.numBreakpoints; id++) { SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; if (!keepPersistent || !bp->persistent) { - // TODO: write broadcast for 'revert' + revertSoftwareBreakpoint(id); // Note: no way to handle breakpoint failing to revert on 1+ core but not all, we need to assume operation succeeds } } diff --git a/thermosphere/src/watchpoints.c b/thermosphere/src/watchpoints.c index 060b31f83..c8dd0abb9 100644 --- a/thermosphere/src/watchpoints.c +++ b/thermosphere/src/watchpoints.c @@ -46,6 +46,19 @@ void initWatchpoints(void) recursiveSpinlockUnlock(&g_watchpointManager.lock); } +static void commitAndBroadcastWatchpointHandler(void *p) +{ + (void)p; + u64 flags = maskIrq(); + loadWatchpointRegs(g_combinedWatchpoints, g_watchpointManager.maxWatchpoints); + restoreInterruptFlags(flags); +} + +static inline void commitAndBroadcastWatchpoints(void) +{ + executeFunctionOnAllCores(commitAndBroadcastWatchpointHandler, NULL, true); +} + static DebugRegisterPair *findCombinedWatchpoint(u64 addr) { addr &= ~7ull; @@ -256,9 +269,9 @@ int addWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction) return -EINVAL; } - recursiveSpinlockUnlock(&g_watchpointManager.lock); + commitAndBroadcastWatchpoints(); - // TODO: commit and broadcast + recursiveSpinlockUnlock(&g_watchpointManager.lock); return 0; } @@ -294,9 +307,10 @@ int removeWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction recursiveSpinlockUnlock(&g_watchpointManager.lock); return -ENOENT; } - recursiveSpinlockUnlock(&g_watchpointManager.lock); - // TODO: commit and broadcast + commitAndBroadcastWatchpoints(); + + recursiveSpinlockUnlock(&g_watchpointManager.lock); return 0; } @@ -312,7 +326,7 @@ int removeAllWatchpoints(void) memset(g_watchpointManager.splitWatchpoints, 0, sizeof(g_watchpointManager.splitWatchpoints)); memset(g_combinedWatchpoints, 0, sizeof(g_combinedWatchpoints)); - // TODO: commit and broadcast + commitAndBroadcastWatchpoints(); recursiveSpinlockUnlock(&g_watchpointManager.lock);