thermosphere: implement stop point broadcast

This commit is contained in:
TuxSH 2019-08-13 00:14:56 +02:00
parent b2c5ef2611
commit 1775d59977
3 changed files with 71 additions and 22 deletions

View file

@ -39,6 +39,19 @@ void initBreakpoints(void)
recursiveSpinlockUnlock(&g_breakpointManager.lock); 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) static DebugRegisterPair *allocateBreakpoint(void)
{ {
u32 pos = __builtin_ffs(g_breakpointManager.allocationBitmap); u32 pos = __builtin_ffs(g_breakpointManager.allocationBitmap);
@ -107,9 +120,9 @@ int addBreakpoint(u64 addr)
regs->vr = addr; regs->vr = addr;
recursiveSpinlockUnlock(&g_breakpointManager.lock); commitAndBroadcastBreakpoints();
// TODO commit & broadcast recursiveSpinlockUnlock(&g_breakpointManager.lock);
return 0; return 0;
} }
@ -126,9 +139,9 @@ int removeBreakpoint(u64 addr)
} }
freeBreakpoint(regs - &g_breakpointManager.breakpoints[0]); freeBreakpoint(regs - &g_breakpointManager.breakpoints[0]);
recursiveSpinlockUnlock(&g_breakpointManager.lock);
// TODO commit & broadcast commitAndBroadcastBreakpoints();
recursiveSpinlockUnlock(&g_breakpointManager.lock);
return 0; return 0;
} }
@ -139,7 +152,7 @@ int removeAllBreakpoints(void)
g_breakpointManager.allocationBitmap = BIT(g_breakpointManager.maxBreakpoints) - 1; g_breakpointManager.allocationBitmap = BIT(g_breakpointManager.maxBreakpoints) - 1;
memset(g_breakpointManager.breakpoints, 0, sizeof(g_breakpointManager.breakpoints)); memset(g_breakpointManager.breakpoints, 0, sizeof(g_breakpointManager.breakpoints));
// TODO: commit & broadcast commitAndBroadcastBreakpoints();
recursiveSpinlockUnlock(&g_breakpointManager.lock); recursiveSpinlockUnlock(&g_breakpointManager.lock);

View file

@ -54,7 +54,7 @@ static size_t findClosestSoftwareBreakpointSlot(u64 address)
return b; return b;
} }
static bool doApplySoftwareBreakpoint(size_t id) static inline bool doApplySoftwareBreakpoint(size_t id)
{ {
SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id];
if (bp->applied) { if (bp->applied) {
@ -71,7 +71,19 @@ static bool doApplySoftwareBreakpoint(size_t id)
return false; 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]; SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id];
if (!bp->applied) { if (!bp->applied) {
@ -86,30 +98,40 @@ static bool doRevertSoftwareBreakpoint(size_t id)
return false; 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) bool applyAllSoftwareBreakpoints(void)
{ {
recursiveSpinlockLock(&g_softwareBreakpointManager.lock); u64 flags = recursiveSpinlockLockMaskIrq(&g_softwareBreakpointManager.lock);
bool ret = true; bool ret = true;
for (size_t i = 0; i < g_softwareBreakpointManager.numBreakpoints; i++) { 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; return ret;
} }
bool revertAllSoftwareBreakpoints(void) bool revertAllSoftwareBreakpoints(void)
{ {
recursiveSpinlockLock(&g_softwareBreakpointManager.lock); u64 flags = recursiveSpinlockLockMaskIrq(&g_softwareBreakpointManager.lock);
bool ret = true; bool ret = true;
for (size_t i = 0; i < g_softwareBreakpointManager.numBreakpoints; i++) { 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; return ret;
} }
@ -142,7 +164,7 @@ int addSoftwareBreakpoint(u64 addr, bool persistent)
bp->applied = false; bp->applied = false;
bp->uid = 0x2000 + g_softwareBreakpointManager.bpUniqueCounter++; 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 // 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); recursiveSpinlockUnlock(&g_softwareBreakpointManager.lock);
@ -166,7 +188,7 @@ int removeSoftwareBreakpoint(u64 addr, bool keepPersistent)
SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id];
if (!keepPersistent || !bp->persistent) { 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 // 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++) { for (size_t id = 0; id < g_softwareBreakpointManager.numBreakpoints; id++) {
SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id]; SoftwareBreakpoint *bp = &g_softwareBreakpointManager.breakpoints[id];
if (!keepPersistent || !bp->persistent) { 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 // Note: no way to handle breakpoint failing to revert on 1+ core but not all, we need to assume operation succeeds
} }
} }

View file

@ -46,6 +46,19 @@ void initWatchpoints(void)
recursiveSpinlockUnlock(&g_watchpointManager.lock); 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) static DebugRegisterPair *findCombinedWatchpoint(u64 addr)
{ {
addr &= ~7ull; addr &= ~7ull;
@ -256,9 +269,9 @@ int addWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction)
return -EINVAL; return -EINVAL;
} }
recursiveSpinlockUnlock(&g_watchpointManager.lock); commitAndBroadcastWatchpoints();
// TODO: commit and broadcast recursiveSpinlockUnlock(&g_watchpointManager.lock);
return 0; return 0;
} }
@ -294,9 +307,10 @@ int removeWatchpoint(u64 addr, size_t size, WatchpointLoadStoreControl direction
recursiveSpinlockUnlock(&g_watchpointManager.lock); recursiveSpinlockUnlock(&g_watchpointManager.lock);
return -ENOENT; return -ENOENT;
} }
recursiveSpinlockUnlock(&g_watchpointManager.lock);
// TODO: commit and broadcast commitAndBroadcastWatchpoints();
recursiveSpinlockUnlock(&g_watchpointManager.lock);
return 0; return 0;
} }
@ -312,7 +326,7 @@ int removeAllWatchpoints(void)
memset(g_watchpointManager.splitWatchpoints, 0, sizeof(g_watchpointManager.splitWatchpoints)); memset(g_watchpointManager.splitWatchpoints, 0, sizeof(g_watchpointManager.splitWatchpoints));
memset(g_combinedWatchpoints, 0, sizeof(g_combinedWatchpoints)); memset(g_combinedWatchpoints, 0, sizeof(g_combinedWatchpoints));
// TODO: commit and broadcast commitAndBroadcastWatchpoints();
recursiveSpinlockUnlock(&g_watchpointManager.lock); recursiveSpinlockUnlock(&g_watchpointManager.lock);