Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:26

0001 /*
0002  * Copyright (c) 2018 Amaan Cheval <amaan.cheval@gmail.com>
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  * 1. Redistributions of source code must retain the above copyright
0008  *    notice, this list of conditions and the following disclaimer.
0009  * 2. Redistributions in binary form must reproduce the above copyright
0010  *    notice, this list of conditions and the following disclaimer in the
0011  *    documentation and/or other materials provided with the distribution.
0012  *
0013  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0014  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0016  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0017  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0018  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0019  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0020  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0021  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0022  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0023  * SUCH DAMAGE.
0024  */
0025 
0026 #include <rtems/score/cpu.h>
0027 #include <rtems/score/tls.h>
0028 
0029 /*
0030  * Stack alignment note:
0031  *
0032  * Per the x86-64 SysV ABI, the stack frame layout is as follows:
0033  *       optional args
0034  *       ------        (16-byte alignment boundary)
0035  * RSP-> return_addr   (RSP is moved lower as needed for this frame)
0036  *
0037  * Per the ABI:
0038  *
0039  *  > The end of the input argument area shall be aligned on a 16 (32 or 64, if
0040  *    __m256 or __m512 is passed on stack) byte boundary.
0041  *
0042  *  > In other words, the value (%rsp + 8) is always a multiple of 16 (32 or 64)
0043  *    when control is transferred to the function entry point.
0044  *
0045  * We want the stack to look to the '_entry_point' routine
0046  * like an ordinary stack frame as if '_entry_point' was
0047  * called from C-code.
0048  * Note that '_entry_point' is jumped-to by the 'ret'
0049  * instruction returning from _CPU_Context_switch() or
0050  * _CPU_Context_restore() thus popping the _entry_point
0051  * from the stack.
0052  *
0053  * Hence we must initialize the stack as follows
0054  *
0055  *         [arg0 (aligned)]:  n/a
0056  *         [ret. addr     ]:  NULL
0057  * RSP->   [jump-target   ]:  _entry_point
0058  *
0059  * When Context_switch returns it pops the _entry_point from
0060  * the stack which then finds a standard layout.
0061  */
0062 void _CPU_Context_Initialize(
0063   Context_Control *the_context,
0064   void *stack_area_begin,
0065   size_t stack_area_size,
0066   uint32_t new_level,
0067   void (*entry_point)( void ),
0068   bool is_fp,
0069   void *tls_area
0070 )
0071 {
0072   uintptr_t _stack;
0073   uintptr_t tcb;
0074 
0075   /* avoid warning for being unused */
0076   (void) is_fp;
0077 
0078   if ( new_level ) {
0079     the_context->rflags = CPU_EFLAGS_INTERRUPTS_OFF;
0080   }
0081   else {
0082     the_context->rflags = CPU_EFLAGS_INTERRUPTS_ON;
0083   }
0084 
0085   _stack  = ((uintptr_t) stack_area_begin) + stack_area_size;
0086   _stack &= ~(CPU_STACK_ALIGNMENT - 1);
0087   _stack -= CPU_STACK_ALIGNMENT; /* fake return address for entry_point's frame;
0088                                   * this allows rsp+8 to be an aligned boundary */
0089   *((void (**)(void)) _stack) = entry_point;
0090 
0091   the_context->rbp     = (void *) 0;
0092   the_context->rsp     = (void *) _stack;
0093 
0094   if (tls_area != NULL) {
0095     tcb = (uintptr_t) _TLS_Initialize_area(tls_area);
0096   } else {
0097     tcb = 0;
0098   }
0099   the_context->fs = tcb;
0100 }