1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-19 08:52:25 +00:00

thermosphere: fix continue logic for full-stop & some refactoring

This commit is contained in:
TuxSH 2020-02-02 17:46:17 +00:00
parent ebf8053b42
commit bf7f077432
6 changed files with 31 additions and 19 deletions

View file

@ -124,6 +124,12 @@ void debugManagerSetReportingEnabled(bool enabled)
atomic_store(&g_debugManager.reportingEnabled, enabled); atomic_store(&g_debugManager.reportingEnabled, enabled);
} }
bool debugManagerHasDebugEvent(u32 coreId)
{
bool isPaused = debugManagerIsCorePaused(coreId);
return isPaused && g_debugManager.debugEventInfos[coreId].type != DBGEVENT_NONE;
}
void debugManagerPauseCores(u32 coreList) void debugManagerPauseCores(u32 coreList)
{ {
u64 flags = maskIrq(); u64 flags = maskIrq();
@ -161,7 +167,7 @@ u32 debugManagerGetPausedCoreList(void)
return atomic_load(&g_debugManager.pausedCoreList); return atomic_load(&g_debugManager.pausedCoreList);
} }
DebugEventInfo *debugManagerGetCoreDebugEvent(u32 coreId) DebugEventInfo *debugManagerGetDebugEvent(u32 coreId)
{ {
return &g_debugManager.debugEventInfos[coreId]; return &g_debugManager.debugEventInfos[coreId];
} }
@ -217,7 +223,7 @@ void debugManagerBreakCores(u32 coreList)
if (coreList & ~BIT(coreId)) { if (coreList & ~BIT(coreId)) {
generateSgiForList(ThermosphereSgi_ReportDebuggerBreak, coreList & ~BIT(coreId)); generateSgiForList(ThermosphereSgi_ReportDebuggerBreak, coreList & ~BIT(coreId));
} }
if ((coreList & BIT(coreId)) && !debugManagerIsCorePaused(coreId)) { if ((coreList & BIT(coreId)) && !debugManagerHasDebugEvent(coreId)) {
debugManagerReportEvent(DBGEVENT_DEBUGGER_BREAK); debugManagerReportEvent(DBGEVENT_DEBUGGER_BREAK);
} }

View file

@ -57,6 +57,9 @@ void debugManagerSetReportingEnabled(bool enabled);
// Hypervisor interrupts will be serviced during the pause-wait // Hypervisor interrupts will be serviced during the pause-wait
bool debugManagerHandlePause(void); bool debugManagerHandlePause(void);
DebugEventInfo *debugManagerGetDebugEvent(u32 coreId);
bool debugManagerHasDebugEvent(u32 coreId);
// Note: these functions are not reentrant EXCEPT debugPauseCores(1 << currentCoreId) // Note: these functions are not reentrant EXCEPT debugPauseCores(1 << currentCoreId)
// "Pause" makes sure all cores reaches the pause function before proceeding. // "Pause" makes sure all cores reaches the pause function before proceeding.
// "Unpause" doesn't synchronize, it just makes sure the core resumes & that "pause" can be called again. // "Unpause" doesn't synchronize, it just makes sure the core resumes & that "pause" can be called again.
@ -68,7 +71,6 @@ void debugManagerSetSteppingRange(u32 coreId, uintptr_t startAddr, uintptr_t end
u32 debugManagerGetPausedCoreList(void); u32 debugManagerGetPausedCoreList(void);
DebugEventInfo *debugManagerGetCoreDebugEvent(u32 coreId);
void debugManagerReportEvent(DebugEventType type, ...); void debugManagerReportEvent(DebugEventType type, ...);

View file

@ -191,7 +191,7 @@ void GDB_AttachToContext(GDBContext *ctx)
GDB_BreakAllCores(ctx); GDB_BreakAllCores(ctx);
DebugEventInfo *info = debugManagerGetCoreDebugEvent(currentCoreCtx->coreId); DebugEventInfo *info = debugManagerGetDebugEvent(currentCoreCtx->coreId);
info->preprocessed = true; info->preprocessed = true;
info->handled = true; info->handled = true;
ctx->lastDebugEvent = info; ctx->lastDebugEvent = info;

View file

@ -115,3 +115,8 @@ static inline bool GDB_IsAttached(GDBContext *ctx)
{ {
return ctx->state == GDB_STATE_ATTACHED; return ctx->state == GDB_STATE_ATTACHED;
} }
static inline bool GDB_IsNonStop(GDBContext *ctx)
{
return (ctx->flags & GDB_FLAG_NONSTOP) != 0;
}

View file

@ -196,7 +196,7 @@ int GDB_SendStopReply(GDBContext *ctx, const DebugEventInfo *info, bool asNotifi
} }
case DBGEVENT_OUTPUT_STRING: { case DBGEVENT_OUTPUT_STRING: {
if (!(ctx->flags & GDB_FLAG_NONSTOP)) { if (!GDB_IsNonStop(ctx)) {
uintptr_t addr = info->outputString.address; uintptr_t addr = info->outputString.address;
size_t remaining = info->outputString.size; size_t remaining = info->outputString.size;
size_t sent = 0; size_t sent = 0;
@ -235,9 +235,6 @@ int GDB_SendStopReply(GDBContext *ctx, const DebugEventInfo *info, bool asNotifi
} else if (asNotification) { } else if (asNotification) {
return GDB_SendNotificationPacket(ctx, buf, strlen(buf)); return GDB_SendNotificationPacket(ctx, buf, strlen(buf));
} else { } else {
if (!(ctx->flags & GDB_FLAG_NONSTOP)) {
GDB_MarkDebugEventAcked(ctx, info);
}
return GDB_SendPacket(ctx, buf, strlen(buf)); return GDB_SendPacket(ctx, buf, strlen(buf));
} }
} }
@ -273,7 +270,7 @@ int GDB_TrySignalDebugEvent(GDBContext *ctx, DebugEventInfo *info)
// Are we still paused & has the packet not been handled & are we allowed to send on our own? // Are we still paused & has the packet not been handled & are we allowed to send on our own?
if (shouldSignal && !ctx->sendOwnDebugEventDisallowed && !info->handled && debugManagerIsCorePaused(info->coreId)) { if (shouldSignal && !ctx->sendOwnDebugEventDisallowed && !info->handled && debugManagerIsCorePaused(info->coreId)) {
bool nonStop = (ctx->flags & GDB_FLAG_NONSTOP) != 0; bool nonStop = GDB_IsNonStop(ctx);
info->handled = true; info->handled = true;
// Full-stop mode: stop other cores // Full-stop mode: stop other cores
@ -296,14 +293,14 @@ int GDB_TrySignalDebugEvent(GDBContext *ctx, DebugEventInfo *info)
void GDB_BreakAllCores(GDBContext *ctx) void GDB_BreakAllCores(GDBContext *ctx)
{ {
if (ctx->flags & GDB_FLAG_NONSTOP) { if (GDB_IsNonStop(ctx)) {
debugManagerBreakCores(ctx->attachedCoreList); debugManagerBreakCores(ctx->attachedCoreList);
} else { } else {
// Break all cores too, but mark everything but the first has handled // Break all cores too, but mark everything but the first has handled
debugManagerBreakCores(ctx->attachedCoreList); debugManagerBreakCores(ctx->attachedCoreList);
u32 rem = ctx->attachedCoreList & ~BIT(currentCoreCtx->coreId); u32 rem = ctx->attachedCoreList & ~BIT(currentCoreCtx->coreId);
FOREACH_BIT (tmp, coreId, rem) { FOREACH_BIT (tmp, coreId, rem) {
DebugEventInfo *info = debugManagerGetCoreDebugEvent(coreId); DebugEventInfo *info = debugManagerGetDebugEvent(coreId);
info->handled = true; info->handled = true;
info->preprocessed = true; info->preprocessed = true;
} }
@ -324,7 +321,7 @@ GDB_DECLARE_VERBOSE_HANDLER(Stopped)
if (remaining != 0) { if (remaining != 0) {
// Send one more debug event (marking it as handled) // Send one more debug event (marking it as handled)
u32 coreId = __builtin_ctz(remaining); u32 coreId = __builtin_ctz(remaining);
DebugEventInfo *info = debugManagerGetCoreDebugEvent(coreId); DebugEventInfo *info = debugManagerGetDebugEvent(coreId);
if (GDB_PreprocessDebugEvent(ctx, info)) { if (GDB_PreprocessDebugEvent(ctx, info)) {
ctx->sendOwnDebugEventDisallowed = true; ctx->sendOwnDebugEventDisallowed = true;
@ -342,8 +339,7 @@ GDB_DECLARE_VERBOSE_HANDLER(Stopped)
GDB_DECLARE_HANDLER(GetStopReason) GDB_DECLARE_HANDLER(GetStopReason)
{ {
bool nonStop = (ctx->flags & GDB_FLAG_NONSTOP) != 0; if (!GDB_IsNonStop(ctx)) {
if (!nonStop) {
// Full-stop: // Full-stop:
return GDB_SendStopReply(ctx, ctx->lastDebugEvent, false); return GDB_SendStopReply(ctx, ctx->lastDebugEvent, false);
} else { } else {
@ -384,9 +380,9 @@ GDB_DECLARE_HANDLER(ContinueOrStepDeprecated)
char cmd = ctx->commandData[-1]; char cmd = ctx->commandData[-1];
// This deprecated command should not be permitted in non-stop mode // This deprecated command should not be permitted in non-stop mode
if (ctx->flags & GDB_FLAG_NONSTOP) { /*if (GDB_IsNonStop(ctx)) {
return GDB_ReplyErrno(ctx, EPERM); return GDB_ReplyErrno(ctx, EPERM);
} }*/
if(cmd == 'C' || cmd == 'S') { if(cmd == 'C' || cmd == 'S') {
// Check the presence of the two-digit signature, even if we ignore it. // Check the presence of the two-digit signature, even if we ignore it.
@ -544,7 +540,7 @@ GDB_DECLARE_VERBOSE_HANDLER(Continue)
// "Note: In non-stop mode, a thread is considered running until GDB acknowledges // "Note: In non-stop mode, a thread is considered running until GDB acknowledges
// an asynchronous stop notification for it with the vStopped packet (see Remote Non-Stop)." // an asynchronous stop notification for it with the vStopped packet (see Remote Non-Stop)."
u32 mask = ctx->acknowledgedDebugEventCoreList; u32 mask = GDB_IsNonStop(ctx) ? ctx->acknowledgedDebugEventCoreList : ctx->attachedCoreList;
debugManagerSetSingleStepCoreList(stepCoreList & mask); debugManagerSetSingleStepCoreList(stepCoreList & mask);
debugManagerBreakCores(stopCoreList & ~mask); debugManagerBreakCores(stopCoreList & ~mask);

View file

@ -221,6 +221,7 @@ void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32)
bool isGuestInterrupt = false; bool isGuestInterrupt = false;
bool isMaintenanceInterrupt = false; bool isMaintenanceInterrupt = false;
bool isPaused = false; bool isPaused = false;
bool hasDebugEvent = false;
switch (irqId) { switch (irqId) {
case ThermosphereSgi_ExecuteFunction: case ThermosphereSgi_ExecuteFunction:
@ -237,7 +238,6 @@ void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32)
// See bottom halves // See bottom halves
// Because exceptions (other debug events) are handling w/ interrupts off, if // Because exceptions (other debug events) are handling w/ interrupts off, if
// we get there, there's no race condition possible with debugManagerReportEvent // we get there, there's no race condition possible with debugManagerReportEvent
isPaused = debugManagerIsCorePaused(currentCoreCtx->coreId);
break; break;
case GIC_IRQID_MAINTENANCE: case GIC_IRQID_MAINTENANCE:
isMaintenanceInterrupt = true; isMaintenanceInterrupt = true;
@ -274,12 +274,15 @@ void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32)
recursiveSpinlockUnlock(&g_irqManager.lock); recursiveSpinlockUnlock(&g_irqManager.lock);
isPaused = debugManagerIsCorePaused(currentCoreCtx->coreId);
hasDebugEvent = debugManagerHasDebugEvent(currentCoreCtx->coreId);
if (irqId == ThermosphereSgi_ReportDebuggerBreak) DEBUG("debug event=%d\n", (int)debugManagerGetDebugEvent(currentCoreCtx->coreId)->type);
// Bottom half part // Bottom half part
if (transportIface != NULL) { if (transportIface != NULL) {
exceptionEnterInterruptibleHypervisorCode(); exceptionEnterInterruptibleHypervisorCode();
unmaskIrq(); unmaskIrq();
transportInterfaceIrqHandlerBottomHalf(transportIface); transportInterfaceIrqHandlerBottomHalf(transportIface);
} else if (irqId == ThermosphereSgi_ReportDebuggerBreak && !isPaused) { } else if (irqId == ThermosphereSgi_ReportDebuggerBreak && !hasDebugEvent) {
debugManagerReportEvent(DBGEVENT_DEBUGGER_BREAK); debugManagerReportEvent(DBGEVENT_DEBUGGER_BREAK);
} else if (irqId == ThermosphereSgi_DebuggerContinue && isPaused) { } else if (irqId == ThermosphereSgi_DebuggerContinue && isPaused) {
debugManagerUnpauseCores(BIT(currentCoreCtx->coreId)); debugManagerUnpauseCores(BIT(currentCoreCtx->coreId));