i386: Move _CPU_Context_Initialize()

Update #2468.
This commit is contained in:
Sebastian Huber
2017-06-09 08:17:59 +02:00
parent f256685aa3
commit cb0d9a0747
2 changed files with 65 additions and 46 deletions

View File

@@ -114,6 +114,62 @@ void _CPU_Initialize(void)
#endif #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 _CPU_ISR_Get_level( void )
{ {
uint32_t level; uint32_t level;

View File

@@ -433,52 +433,15 @@ uint32_t _CPU_ISR_Get_level( void );
#ifndef ASM #ifndef ASM
/* void _CPU_Context_Initialize(
* Stack alignment note: Context_Control *the_context,
* void *stack_area_begin,
* We want the stack to look to the '_entry_point' routine size_t stack_area_size,
* like an ordinary stack frame as if '_entry_point' was uint32_t new_level,
* called from C-code. void (*entry_point)( void ),
* Note that '_entry_point' is jumped-to by the 'ret' bool is_fp,
* instruction returning from _CPU_Context_switch() or void *tls_area
* _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.
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point, _is_fp, _tls_area ) \
do { \
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; \
} while (0)
#define _CPU_Context_Restart_self( _the_context ) \ #define _CPU_Context_Restart_self( _the_context ) \
_CPU_Context_restore( (_the_context) ); _CPU_Context_restore( (_the_context) );