mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-10-06 10:59:48 +08:00
testsuites/validation: Take the interrupted stack
ScoreIsrValIsr checks that the context which an interrupt during the multitasking start interrupted ran on the stack of the thread which was running. A wrapper of the interrupt dispatch of the architecture takes the address of that stack, and there is one for six architectures only. Everywhere else the address stays zero, the check cannot pass, and it reports nothing but a line number, which says neither that the architecture is unsupported nor what was expected. Add the wrapper for mips, i386 and x86_64, and say in the check what a zero address means, so that the next port is told why it fails rather than left to find out. The frame which the mips dispatch receives is built on the stack of the interrupted context, so the address of the frame is an address within that stack. Its stack pointer member is not used. Only the path which the debugger stub takes fills it, and the interrupt path leaves it zero. The two x86 ports keep the frame base of the interrupted context in the frame pointer register and may then switch to the interrupt stack, so the wrapper has to take the value before the compiler establishes a frame of its own. A register variable does not do that, because the compiler emits its prologue first and the wrapper then reads its own frame. They get the same treatment as sparc, which has the problem for the same reason. Close #5712. Assisted-by: Claude:claude-opus-5 claude-code Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
This commit is contained in:
committed by
Joel Sherrill
parent
ccc830b004
commit
d0545d272c
@@ -12,6 +12,9 @@ ldflags:
|
||||
- -Wl,--wrap=bsp_interrupt_dispatch
|
||||
- -Wl,--wrap=bsp_interrupt_handler_default
|
||||
- -Wl,--wrap=bsp_interrupt_spurious
|
||||
- -Wl,--wrap=amd64_dispatch_isr
|
||||
- -Wl,--wrap=BSP_dispatch_isr
|
||||
- -Wl,--wrap=mips_vector_isr_handlers
|
||||
- -Wl,--wrap=_RISCV_Interrupt_dispatch
|
||||
- -Wl,--wrap=_SPARC_Interrupt_dispatch
|
||||
links: []
|
||||
|
||||
@@ -214,6 +214,87 @@ __asm__ (
|
||||
);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The interrupt prologue of these two ports leaves the frame base of the
|
||||
* interrupted context in the frame pointer register and may then switch to
|
||||
* the interrupt stack, so the value has to be taken before the compiler
|
||||
* establishes a frame of its own. A register variable cannot do that.
|
||||
*/
|
||||
#if defined(__i386__)
|
||||
void __real_BSP_dispatch_isr( int vector );
|
||||
|
||||
static RTEMS_USED void InterruptDispatch( int vector, uintptr_t sp )
|
||||
{
|
||||
if ( interrupted_stack_at_multitasking_start == 0 ) {
|
||||
interrupted_stack_at_multitasking_start = sp;
|
||||
}
|
||||
|
||||
__real_BSP_dispatch_isr( vector );
|
||||
}
|
||||
|
||||
__asm__ (
|
||||
"\t.section\t\".text\"\n"
|
||||
"\t.align\t4\n"
|
||||
"\t.globl\t__wrap_BSP_dispatch_isr\n"
|
||||
"\t.type\t__wrap_BSP_dispatch_isr, @function\n"
|
||||
"__wrap_BSP_dispatch_isr:\n"
|
||||
"\tpushl\t%ebp\n"
|
||||
"\tpushl\t8(%esp)\n"
|
||||
"\tcall\tInterruptDispatch\n"
|
||||
"\taddl\t$8, %esp\n"
|
||||
"\tret\n"
|
||||
"\t.previous\n"
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
void __real_amd64_dispatch_isr( rtems_vector_number vector );
|
||||
|
||||
static RTEMS_USED void InterruptDispatch(
|
||||
rtems_vector_number vector,
|
||||
uintptr_t sp
|
||||
)
|
||||
{
|
||||
if ( interrupted_stack_at_multitasking_start == 0 ) {
|
||||
interrupted_stack_at_multitasking_start = sp;
|
||||
}
|
||||
|
||||
__real_amd64_dispatch_isr( vector );
|
||||
}
|
||||
|
||||
__asm__ (
|
||||
"\t.section\t\".text\"\n"
|
||||
"\t.align\t8\n"
|
||||
"\t.globl\t__wrap_amd64_dispatch_isr\n"
|
||||
"\t.type\t__wrap_amd64_dispatch_isr, @function\n"
|
||||
"__wrap_amd64_dispatch_isr:\n"
|
||||
"\tmovq\t%rbp, %rsi\n"
|
||||
"\tjmp\tInterruptDispatch\n"
|
||||
"\t.previous\n"
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
void __real_mips_vector_isr_handlers( CPU_Interrupt_frame *frame );
|
||||
|
||||
void __wrap_mips_vector_isr_handlers( CPU_Interrupt_frame *frame );
|
||||
|
||||
void __wrap_mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
|
||||
{
|
||||
if ( interrupted_stack_at_multitasking_start == 0 ) {
|
||||
/*
|
||||
* The frame is built on the stack of the interrupted context, so its own
|
||||
* address is an address within that stack. The stack pointer member of
|
||||
* the frame is not used: the interrupt path never fills it, only the path
|
||||
* which the debugger stub takes does.
|
||||
*/
|
||||
interrupted_stack_at_multitasking_start = (uintptr_t) frame;
|
||||
}
|
||||
|
||||
__real_mips_vector_isr_handlers( frame );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ISRHandler( void *arg )
|
||||
{
|
||||
uintptr_t begin;
|
||||
@@ -271,7 +352,12 @@ static void ScoreIsrValIsr_Action_0( void )
|
||||
* Check that stack of the interrupted context was valid when an interrupt
|
||||
* was serviced during the multitasking start.
|
||||
*/
|
||||
T_true( interrupted_stack_at_multitasking_start_is_valid );
|
||||
T_true(
|
||||
interrupted_stack_at_multitasking_start_is_valid,
|
||||
"the stack of the interrupted context was not the stack of the running"
|
||||
" thread; a zero means that the interrupt dispatch of this architecture"
|
||||
" has no wrapper in this test and the address was never taken"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user