summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/i386/cpu.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-06-09 08:17:59 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-06-09 08:28:46 +0200
commitcb0d9a0747b1be84fb669b1c71e55bf0d860d2f8 (patch)
tree888c5825faa3dba0c163e4b2744b6ba71d395ddf /cpukit/score/cpu/i386/cpu.c
parentbsp/psim: Include missing <sys/param.h> (diff)
downloadrtems-cb0d9a0747b1be84fb669b1c71e55bf0d860d2f8.tar.bz2
i386: Move _CPU_Context_Initialize()
Update #2468.
Diffstat (limited to '')
-rw-r--r--cpukit/score/cpu/i386/cpu.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c
index 447d8ae273..804afb1647 100644
--- a/cpukit/score/cpu/i386/cpu.c
+++ b/cpukit/score/cpu/i386/cpu.c
@@ -114,6 +114,62 @@ void _CPU_Initialize(void)
#endif
}
+/*
+ * Stack alignment note:
+ *
+ * We want the stack to look to the '_entry_point' routine
+ * like an ordinary stack frame as if '_entry_point' was
+ * called from C-code.
+ * Note that '_entry_point' is jumped-to by the 'ret'
+ * instruction returning from _CPU_Context_switch() or
+ * _CPU_Context_restore() thus popping the _entry_point
+ * from the stack.
+ * However, _entry_point expects a frame to look like this:
+ *
+ * args [_Thread_Handler expects no args, however]
+ * ------ (alignment boundary)
+ * SP-> return_addr return here when _entry_point returns which (never happens)
+ *
+ *
+ * Hence we must initialize the stack as follows
+ *
+ * [arg1 ]: n/a
+ * [arg0 (aligned)]: n/a
+ * [ret. addr ]: NULL
+ * SP-> [jump-target ]: _entry_point
+ *
+ * When Context_switch returns it pops the _entry_point from
+ * the stack which then finds a standard layout.
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ void *_stack_base,
+ size_t _size,
+ uint32_t _isr,
+ void (*_entry_point)( void ),
+ bool is_fp,
+ void *tls_area
+)
+{
+ uint32_t _stack;
+
+ (void) is_fp; /* avoid warning for being unused */
+
+ if ( _isr ) {
+ the_context->eflags = CPU_EFLAGS_INTERRUPTS_OFF;
+ } else {
+ the_context->eflags = CPU_EFLAGS_INTERRUPTS_ON;
+ }
+
+ _stack = ((uint32_t)(_stack_base)) + (_size);
+ _stack &= ~ (CPU_STACK_ALIGNMENT - 1);
+ _stack -= 2*sizeof(proc_ptr*); /* see above for why we need to do this */
+ *((proc_ptr *)(_stack)) = (_entry_point);
+ the_context->ebp = (void *) 0;
+ the_context->esp = (void *) _stack;
+}
+
uint32_t _CPU_ISR_Get_level( void )
{
uint32_t level;