diff --git a/k11_extension/include/debug.h b/k11_extension/include/debug.h
new file mode 100644
index 00000000..437208fb
--- /dev/null
+++ b/k11_extension/include/debug.h
@@ -0,0 +1,39 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2016-2017 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*
+* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+* * Requiring preservation of specified reasonable legal notices or
+* author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+* * Prohibiting misrepresentation of the origin of that material,
+* or requiring that modified versions of such material be marked in
+* reasonable ways as different from the original version.
+*/
+
+#pragma once
+
+#include "types.h"
+#include "globals.h"
+#include "kernel.h"
+#include "utils.h"
+
+extern KRecursiveLock dbgParamsLock;
+extern u32 dbgParamWatchpointId, dbgParamDVA, dbgParamWCR, dbgParamContextId;
+
+KSchedulableInterruptEvent *enableMonitorModeDebugging(KBaseInterruptEvent *this, u32 interruptID);
+KSchedulableInterruptEvent *disableWatchpoint(KBaseInterruptEvent *this, u32 interruptID);
+KSchedulableInterruptEvent *setWatchpointWithContextId(KBaseInterruptEvent *this, u32 interruptID);
diff --git a/k11_extension/source/debug.c b/k11_extension/source/debug.c
new file mode 100644
index 00000000..9473aae2
--- /dev/null
+++ b/k11_extension/source/debug.c
@@ -0,0 +1,147 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2016-2017 Aurora Wright, TuxSH
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*
+* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+* * Requiring preservation of specified reasonable legal notices or
+* author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+* * Prohibiting misrepresentation of the origin of that material,
+* or requiring that modified versions of such material be marked in
+* reasonable ways as different from the original version.
+*/
+
+#include "debug.h"
+#include "memory.h"
+#include "synchronization.h"
+
+KRecursiveLock dbgParamsLock = { NULL };
+u32 dbgParamWatchpointId, dbgParamDVA, dbgParamWCR, dbgParamContextId;
+
+KSchedulableInterruptEvent *enableMonitorModeDebugging(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
+{
+ coreBarrier();
+
+ u32 DSCR;
+ __asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 0" : [val] "=r" (DSCR));
+ DSCR |= 0x8000;
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 0" :: [val] "r" (DSCR));
+
+ __dsb();
+ coreBarrier();
+
+ return NULL;
+}
+
+static void disableWatchpoint0(void)
+{
+ u32 control;
+
+ // WCR0
+ __asm__ __volatile__("mrc p14, 0, %[val], c0, c0, 7" : [val] "=r" (control));
+ control &= ~1;
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (control));
+
+ // BCR4
+ __asm__ __volatile__("mrc p14, 0, %[val], c0, c4, 5" : [val] "=r" (control));
+ control &= ~1;
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (control));
+}
+
+static void disableWatchpoint1(void)
+{
+ u32 control;
+
+ // WCR1
+ __asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 7" : [val] "=r" (control));
+ control &= ~1;
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (control));
+
+ // BCR5
+ __asm__ __volatile__("mrc p14, 0, %[val], c0, c5, 5" : [val] "=r" (control));
+ control &= ~1;
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (control));
+}
+
+KSchedulableInterruptEvent *disableWatchpoint(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
+{
+ coreBarrier();
+
+ if(dbgParamWatchpointId == 0)
+ disableWatchpoint0();
+ else
+ disableWatchpoint1();
+
+ __dsb();
+ coreBarrier();
+
+ return NULL;
+}
+
+static void setWatchpoint0WithContextId(u32 DVA, u32 WCR, u32 contextId)
+{
+ // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
+ u32 BCR =
+ (1 << 21) | /* compare with context ID */
+ (1 << 20) | /* linked (with a WRP in our case) */
+ (0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
+ (3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
+ (1 << 0) ; /* enabled */
+
+ disableWatchpoint0();
+
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 6" :: [val] "r" (DVA));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 4" :: [val] "r" (contextId));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (WCR));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (BCR));
+
+ __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
+}
+
+static void setWatchpoint1WithContextId(u32 DVA, u32 WCR, u32 contextId)
+{
+ // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
+ u32 BCR =
+ (1 << 21) | /* compare with context ID */
+ (1 << 20) | /* linked (with a WRP in our case) */
+ (0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
+ (3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
+ (1 << 0) ; /* enabled */
+
+ disableWatchpoint1();
+
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 6" :: [val] "r" (DVA));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 4" :: [val] "r" (contextId));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (WCR));
+ __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (BCR));
+
+ __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
+}
+
+KSchedulableInterruptEvent *setWatchpointWithContextId(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
+{
+ coreBarrier();
+
+ if(dbgParamWatchpointId == 0)
+ setWatchpoint0WithContextId(dbgParamDVA, dbgParamWCR, dbgParamContextId);
+ else
+ setWatchpoint1WithContextId(dbgParamDVA, dbgParamWCR, dbgParamContextId);
+
+ __dsb();
+ coreBarrier();
+
+ return NULL;
+}
diff --git a/k11_extension/source/svc/KernelSetState.c b/k11_extension/source/svc/KernelSetState.c
index 38a15abc..f5fd1f96 100644
--- a/k11_extension/source/svc/KernelSetState.c
+++ b/k11_extension/source/svc/KernelSetState.c
@@ -27,6 +27,7 @@
#include "svc/KernelSetState.h"
#include "synchronization.h"
#include "ipc.h"
+#include "debug.h"
#include "memory.h"
#define MAX_DEBUG 3
@@ -142,7 +143,41 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
res = SetSyscallDebugEventMask(varg1, (bool)varg2, (const u32 *)varg3);
break;
}
-
+ case 0x10003:
+ {
+ executeFunctionOnCores(enableMonitorModeDebugging, 0xF, 0);
+ break;
+ }
+ case 0x10004:
+ {
+ KRecursiveLock__Lock(&dbgParamsLock);
+ dbgParamWatchpointId = varg1;
+ executeFunctionOnCores(disableWatchpoint, 0xF, 0);
+ KRecursiveLock__Unlock(&dbgParamsLock);
+ break;
+ }
+ case 0x10005:
+ {
+ KRecursiveLock__Lock(&dbgParamsLock);
+ dbgParamWatchpointId = 0;
+ dbgParamDVA = varg1;
+ dbgParamWCR = varg2;
+ dbgParamContextId = varg3;
+ executeFunctionOnCores(setWatchpointWithContextId, 0xF, 0);
+ KRecursiveLock__Unlock(&dbgParamsLock);
+ break;
+ }
+ case 0x10006:
+ {
+ KRecursiveLock__Lock(&dbgParamsLock);
+ dbgParamWatchpointId = 1;
+ dbgParamDVA = varg1;
+ dbgParamWCR = varg2;
+ dbgParamContextId = varg3;
+ executeFunctionOnCores(setWatchpointWithContextId, 0xF, 0);
+ KRecursiveLock__Unlock(&dbgParamsLock);
+ break;
+ }
default:
{
res = KernelSetState(type, varg1, varg2, varg3);
diff --git a/sysmodules/rosalina/source/gdb/watchpoints.c b/sysmodules/rosalina/source/gdb/watchpoints.c
index e52a492a..36a60dc3 100644
--- a/sysmodules/rosalina/source/gdb/watchpoints.c
+++ b/sysmodules/rosalina/source/gdb/watchpoints.c
@@ -55,92 +55,6 @@ typedef struct WatchpointManager
static WatchpointManager manager;
-static void K_EnableMonitorModeDebugging(void)
-{
- __asm__ __volatile__("cpsid aif");
-
- u32 DSCR;
- __asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 0" : [val] "=r" (DSCR));
- DSCR |= 0x8000;
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 0" :: [val] "r" (DSCR));
-}
-
-static void K_DisableWatchpoint(u32 id)
-{
- u32 control;
-
- __asm__ __volatile__("cpsid aif");
-
- if(id == 0)
- {
- // WCR0
- __asm__ __volatile__("mrc p14, 0, %[val], c0, c0, 7" : [val] "=r" (control));
- control &= ~1;
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (control));
-
- // BCR4
- __asm__ __volatile__("mrc p14, 0, %[val], c0, c4, 5" : [val] "=r" (control));
- control &= ~1;
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (control));
- }
- else if(id == 1)
- {
- // WCR1
- __asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 7" : [val] "=r" (control));
- control &= ~1;
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (control));
-
- // BCR5
- __asm__ __volatile__("mrc p14, 0, %[val], c0, c5, 5" : [val] "=r" (control));
- control &= ~1;
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (control));
- }
-}
-
-static void K_SetWatchpoint0WithContextId(u32 DVA, u32 WCR, u32 contextId)
-{
- // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
- u32 BCR =
- (1 << 21) | /* compare with context ID */
- (1 << 20) | /* linked (with a WRP in our case) */
- (0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
- (3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
- (1 << 0) ; /* enabled */
-
- __asm__ __volatile__("cpsid aif");
-
- K_DisableWatchpoint(0);
-
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 6" :: [val] "r" (DVA));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 4" :: [val] "r" (contextId));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (WCR));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (BCR));
-
- __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
-}
-
-static void K_SetWatchpoint1WithContextId(u32 DVA, u32 WCR, u32 contextId)
-{
- // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
- u32 BCR =
- (1 << 21) | /* compare with context ID */
- (1 << 20) | /* linked (with a WRP in our case) */
- (0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
- (3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
- (1 << 0) ; /* enabled */
-
- __asm__ __volatile__("cpsid aif");
-
- K_DisableWatchpoint(1);
-
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 6" :: [val] "r" (DVA));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 4" :: [val] "r" (contextId));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (WCR));
- __asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (BCR));
-
- __asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
-}
-
void GDB_ResetWatchpoints(void)
{
static bool lockInitialized = false;
@@ -151,9 +65,9 @@ void GDB_ResetWatchpoints(void)
}
RecursiveLock_Lock(&watchpointManagerLock);
- svcCustomBackdoor(K_EnableMonitorModeDebugging);
- svcCustomBackdoor(K_DisableWatchpoint, 0);
- svcCustomBackdoor(K_DisableWatchpoint, 1);
+ svcKernelSetState(0x10003); // enable monitor mode debugging
+ svcKernelSetState(0x10004, 0); // disable watchpoint 0
+ svcKernelSetState(0x10004, 1); // disable watchpoint 1
memset(&manager, 0, sizeof(WatchpointManager));
@@ -192,7 +106,7 @@ int GDB_AddWatchpoint(GDBContext *ctx, u32 address, u32 size, WatchpointKind kin
if(R_SUCCEEDED(r))
{
- svcCustomBackdoor(id == 0 ? K_SetWatchpoint0WithContextId : K_SetWatchpoint1WithContextId, address, WCR, (u32)out);
+ svcKernelSetState(id == 0 ? 0x10005 : 0x10006, address, WCR, (u32)out); // set watchpoint
Watchpoint *watchpoint = &manager.watchpoints[id];
manager.total++;
watchpoint->address = address;
@@ -224,7 +138,7 @@ int GDB_RemoveWatchpoint(GDBContext *ctx, u32 address, WatchpointKind kind)
}
else
{
- svcCustomBackdoor(K_DisableWatchpoint, id);
+ svcKernelSetState(0x10004, id); // disable watchpoint
memset(&manager.watchpoints[id], 0, sizeof(Watchpoint));
manager.total--;