-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hardware debug API: aarch64 and single stepping
Signed-off-by: Alwin Joshy <[email protected]>
- Loading branch information
1 parent
b383b19
commit 54cbc2e
Showing
2 changed files
with
126 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright 2024, UNSW Sydney | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include <autoconf.h> | ||
|
||
#ifdef CONFIG_HARDWARE_DEBUG_API | ||
|
||
#include <sel4/sel4.h> | ||
#include <utils/attribute.h> | ||
|
||
#include <arch/debug.h> | ||
#include "../../../helpers.h" | ||
#include "../../../test.h" | ||
#include "../../../tests/breakpoints.h" | ||
|
||
static int faulter_main(seL4_Word arg0, seL4_Word arg1, seL4_Word arg2, seL4_Word arg3) { | ||
TEST_SINGLE_STEP_ASM(); | ||
/* NOTHING BELOW SHOULD EVER BE REACHED */ | ||
int *ptr = NULL; | ||
*ptr = 0xBEEF; | ||
return 0; | ||
} | ||
|
||
static int handler_main(seL4_Word faulter_tcb, seL4_Word a1, seL4_Word a2, seL4_Word a3) { | ||
seL4_Word sender_badge; | ||
seL4_MessageInfo_t tag; | ||
seL4_Word label; | ||
|
||
/* Wait for the faulter to trigger an event. */ | ||
tag = api_wait(fault_ep_cspath.capPtr, &sender_badge); | ||
ZF_LOGV("Handler got a fault on the ep.\n"); | ||
label = seL4_MessageInfo_get_label(tag); | ||
|
||
/* Check that it is a breakpoint exception */ | ||
if (label != seL4_Fault_DebugException || seL4_GetMR(seL4_DebugException_ExceptionReason) != seL4_InstructionBreakpoint) { | ||
ZF_LOGV("Received exception other than instruction breakpoint exception.\n"); | ||
return -1; | ||
} | ||
|
||
/* Disable the breakpoint and enable single stepping */ | ||
int error = seL4_TCB_UnsetBreakpoint(faulter_tcb, 0); | ||
test_eq(error, 0); | ||
|
||
seL4_TCB_ConfigureSingleStepping_t res = seL4_TCB_ConfigureSingleStepping(faulter_tcb, 0,1); | ||
test_eq(res.error, 0); | ||
|
||
/* Reply to the thread to resume it */ | ||
tag = api_reply_recv(fault_ep_cspath.capPtr, seL4_MessageInfo_new(0, 0, 0, 0), &sender_badge, 0); | ||
label = seL4_MessageInfo_get_label(tag); | ||
|
||
/* Wait for the single step exception */ | ||
fault_data.vaddr = seL4_GetMR(seL4_DebugException_FaultIP); | ||
fault_data.reason = seL4_GetMR(seL4_DebugException_ExceptionReason); | ||
fault_data.vaddr2 = seL4_GetMR(seL4_DebugException_TriggerAddress); | ||
fault_data.bp_num = seL4_GetMR(seL4_DebugException_BreakpointNumber); | ||
|
||
if (label == seL4_Fault_DebugException && | ||
fault_data.reason == seL4_SingleStep && | ||
fault_data.vaddr == (seL4_Word) &TEST_SS_LABEL_TWO) { | ||
|
||
return 0; | ||
} else { | ||
ZF_LOGE("Fault of type %zd received. Vaddr 0x%zx\n", label, fault_data.vaddr); | ||
fault_data.bp_num = 0; | ||
return -1; | ||
} | ||
} | ||
|
||
static int test_single_step_one(struct env *env) { | ||
int error, result; | ||
helper_thread_t faulter_thread, handler_thread; | ||
test_eq(setup_caps_for_test(env), 0); | ||
|
||
create_helper_thread(env, &handler_thread); | ||
set_helper_priority(env, &handler_thread, BREAKPOINT_TEST_HANDLER_PRIO); | ||
|
||
error = setup_faulter_thread_for_test(env, &faulter_thread); | ||
test_eq(error, seL4_NoError); | ||
|
||
/* We want it to run until the first label */ | ||
error = seL4_TCB_SetBreakpoint(get_helper_tcb(&faulter_thread), 0, (seL4_Word) &TEST_SS_LABEL_ONE, | ||
seL4_InstructionBreakpoint, 0, seL4_BreakOnRead); | ||
test_eq(error, seL4_NoError); | ||
|
||
start_helper(env, &handler_thread, &handler_main, get_helper_tcb(&faulter_thread), 0, 0, 0); | ||
start_helper(env, &faulter_thread, &faulter_main, 0, 0, 0, 0); | ||
|
||
result = wait_for_helper(&handler_thread); | ||
|
||
cleanup_helper(env, &faulter_thread); | ||
cleanup_helper(env, &handler_thread); | ||
|
||
/* Ensure the test was a success */ | ||
test_eq(result, 0); | ||
|
||
return sel4test_get_result(); | ||
} | ||
|
||
DEFINE_TEST(SINGLESTEP_001, "Test that single stepping 1 instruction works", | ||
test_single_step_one, config_set(CONFIG_HARDWARE_DEBUG_API)) | ||
|
||
#endif /* CONFIG_HARDWARE_DEBUG_API */ |