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:
parent
ebf8053b42
commit
bf7f077432
6 changed files with 31 additions and 19 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, ...);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in a new issue