SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /hwcore/cpu_context.c (Article 6.5) and /hwcore/cpu_context.c (Article 7)


001 /* Copyright (C) 2005  David Decotigny            001 /* Copyright (C) 2005  David Decotigny
002    Copyright (C) 2000-2004, The KOS team          002    Copyright (C) 2000-2004, The KOS team
003                                                   003 
004    This program is free software; you can redi    004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU Genera    005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundatio    006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any lat    007    of the License, or (at your option) any later version.
008                                                   008    
009    This program is distributed in the hope tha    009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the     010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR    011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details    012    GNU General Public License for more details.
013                                                   013    
014    You should have received a copy of the GNU     014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to t    015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 3    016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA.                                           017    USA. 
018 */                                                018 */
019                                                   019 
020                                                   020 
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/klibc.h>                            022 #include <sos/klibc.h>
023 #include <drivers/bochs.h>                        023 #include <drivers/bochs.h>
024 #include <drivers/x86_videomem.h>                 024 #include <drivers/x86_videomem.h>
025 #include <hwcore/segment.h>                       025 #include <hwcore/segment.h>
                                                   >> 026 #include <hwcore/gdt.h>
                                                   >> 027 #include <sos/uaccess.h>
026                                                   028 
027 #include "cpu_context.h"                          029 #include "cpu_context.h"
028                                                   030 
029                                                   031 
030 /**                                               032 /**
031  * Here is the definition of a CPU context for    033  * Here is the definition of a CPU context for IA32 processors. This
032  * is a SOS convention, not a specification gi    034  * is a SOS convention, not a specification given by the IA32
033  * spec. However there is a strong constraint     035  * spec. However there is a strong constraint related to the x86
034  * interrupt handling specification: the top o    036  * interrupt handling specification: the top of the stack MUST be
035  * compatible with the 'iret' instruction, ie     037  * compatible with the 'iret' instruction, ie there must be the
036  * err_code (might be 0), eip, cs and eflags o    038  * err_code (might be 0), eip, cs and eflags of the destination
037  * context in that order (see Intel x86 specs     039  * context in that order (see Intel x86 specs vol 3, figure 5-4).
038  *                                                040  *
039  * @note IMPORTANT: This definition MUST be co    041  * @note IMPORTANT: This definition MUST be consistent with the way
040  * the registers are stored on the stack in       042  * the registers are stored on the stack in
041  * irq_wrappers.S/exception_wrappers.S !!! Hen    043  * irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above.
042  */                                               044  */
043 struct sos_cpu_state {                            045 struct sos_cpu_state {
044   /* (Lower addresses) */                         046   /* (Lower addresses) */
045                                                   047 
046   /* These are SOS convention */                  048   /* These are SOS convention */
047   sos_ui16_t  gs;                                 049   sos_ui16_t  gs;
048   sos_ui16_t  fs;                                 050   sos_ui16_t  fs;
049   sos_ui16_t  es;                                 051   sos_ui16_t  es;
050   sos_ui16_t  ds;                                 052   sos_ui16_t  ds;
051   sos_ui16_t  cpl0_ss; /* This is ALWAYS the S    053   sos_ui16_t  cpl0_ss; /* This is ALWAYS the Stack Segment of the
052                           Kernel context (CPL0    054                           Kernel context (CPL0) of the interrupted
053                           thread, even for a u    055                           thread, even for a user thread */
054   sos_ui16_t  alignment_padding; /* unused */     056   sos_ui16_t  alignment_padding; /* unused */
055   sos_ui32_t  eax;                                057   sos_ui32_t  eax;
056   sos_ui32_t  ebx;                                058   sos_ui32_t  ebx;
057   sos_ui32_t  ecx;                                059   sos_ui32_t  ecx;
058   sos_ui32_t  edx;                                060   sos_ui32_t  edx;
059   sos_ui32_t  esi;                                061   sos_ui32_t  esi;
060   sos_ui32_t  edi;                                062   sos_ui32_t  edi;
061   sos_ui32_t  ebp;                                063   sos_ui32_t  ebp;
062                                                   064 
063   /* MUST NEVER CHANGE (dependent on the IA32     065   /* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
064   sos_ui32_t  error_code;                         066   sos_ui32_t  error_code;
065   sos_vaddr_t eip;                                067   sos_vaddr_t eip;
066   sos_ui32_t  cs; /* 32bits according to the s    068   sos_ui32_t  cs; /* 32bits according to the specs ! However, the CS
067                      register is really 16bits    069                      register is really 16bits long */
068   sos_ui32_t  eflags;                             070   sos_ui32_t  eflags;
069                                                   071 
070   /* (Higher addresses) */                        072   /* (Higher addresses) */
071 } __attribute__((packed));                        073 } __attribute__((packed));
072                                                   074 
073                                                   075 
074 /**                                               076 /**
075  * The CS value pushed on the stack by the CPU    077  * The CS value pushed on the stack by the CPU upon interrupt, and
076  * needed by the iret instruction, is 32bits l    078  * needed by the iret instruction, is 32bits long while the real CPU
077  * CS register is 16bits only: this macro simp    079  * CS register is 16bits only: this macro simply retrieves the CPU
078  * "CS" register value from the CS value pushe    080  * "CS" register value from the CS value pushed on the stack by the
079  * CPU upon interrupt.                            081  * CPU upon interrupt.
080  *                                                082  *
081  * The remaining 16bits pushed by the CPU shou    083  * The remaining 16bits pushed by the CPU should be considered
082  * "reserved" and architecture dependent. IMHO    084  * "reserved" and architecture dependent. IMHO, the specs don't say
083  * anything about them. Considering that some     085  * anything about them. Considering that some architectures generate
084  * non-zero values for these 16bits (at least     086  * non-zero values for these 16bits (at least Cyrix), we'd better
085  * ignore them.                                   087  * ignore them.
086  */                                               088  */
087 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_    089 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_cs_value) \
088   ( (pushed_ui32_cs_value) & 0xffff )             090   ( (pushed_ui32_cs_value) & 0xffff )
089                                                   091 
090                                                   092 
091 /**                                               093 /**
092  * Structure of an interrupted Kernel thread's    094  * Structure of an interrupted Kernel thread's context
093  */                                               095  */
094 struct sos_cpu_kstate                             096 struct sos_cpu_kstate
095 {                                                 097 {
096   struct sos_cpu_state regs;                      098   struct sos_cpu_state regs;
097 } __attribute__((packed));                        099 } __attribute__((packed));
098                                                   100 
099                                                   101 
100 /**                                               102 /**
                                                   >> 103  * Structure of an interrupted User thread's context. This is almost
                                                   >> 104  * the same as a kernel context, except that 2 additional values are
                                                   >> 105  * pushed on the stack before the eflags/cs/eip of the interrupted
                                                   >> 106  * context: the stack configuration of the interrupted user context.
                                                   >> 107  *
                                                   >> 108  * @see Section 6.4.1 of Intel x86 vol 1
                                                   >> 109  */
                                                   >> 110 struct sos_cpu_ustate
                                                   >> 111 {
                                                   >> 112   struct sos_cpu_state regs;
                                                   >> 113   struct
                                                   >> 114   {
                                                   >> 115     sos_ui32_t cpl3_esp;
                                                   >> 116     sos_ui16_t cpl3_ss;
                                                   >> 117   };
                                                   >> 118 } __attribute__((packed));
                                                   >> 119 
                                                   >> 120 
                                                   >> 121 /*
                                                   >> 122  * Structure of a Task State Segment on the x86 Architecture.
                                                   >> 123  *
                                                   >> 124  * @see Intel x86 spec vol 3, figure 6-2
                                                   >> 125  *
                                                   >> 126  * @note Such a data structure should not cross any page boundary (see
                                                   >> 127  * end of section 6.2.1 of Intel spec vol 3). This is the reason why
                                                   >> 128  * we tell gcc to align it on a 128B boundary (its size is 104B, which
                                                   >> 129  * is <= 128).
                                                   >> 130  */
                                                   >> 131 struct x86_tss {
                                                   >> 132 
                                                   >> 133   /**
                                                   >> 134    * Intel provides a way for a task to switch to another in an
                                                   >> 135    * automatic way (call gates). In this case, the back_link field
                                                   >> 136    * stores the source TSS of the context switch. This allows to
                                                   >> 137    * easily implement coroutines, task backtracking, ... In SOS we
                                                   >> 138    * don't use TSS for the context switch purpouse, so we always
                                                   >> 139    * ignore this field.
                                                   >> 140    * (+0)
                                                   >> 141    */
                                                   >> 142   sos_ui16_t back_link;
                                                   >> 143 
                                                   >> 144   sos_ui16_t reserved1;
                                                   >> 145 
                                                   >> 146   /* CPL0 saved context. (+4) */
                                                   >> 147   sos_vaddr_t esp0;
                                                   >> 148   sos_ui16_t ss0;
                                                   >> 149 
                                                   >> 150   sos_ui16_t reserved2;
                                                   >> 151 
                                                   >> 152   /* CPL1 saved context. (+12) */
                                                   >> 153   sos_vaddr_t esp1;
                                                   >> 154   sos_ui16_t ss1;
                                                   >> 155 
                                                   >> 156   sos_ui16_t reserved3;
                                                   >> 157 
                                                   >> 158   /* CPL2 saved context. (+20) */
                                                   >> 159   sos_vaddr_t esp2;
                                                   >> 160   sos_ui16_t ss2;
                                                   >> 161 
                                                   >> 162   sos_ui16_t reserved4;
                                                   >> 163 
                                                   >> 164   /* Interrupted context's saved registers. (+28) */
                                                   >> 165   sos_vaddr_t cr3;
                                                   >> 166   sos_vaddr_t eip;
                                                   >> 167   sos_ui32_t eflags;
                                                   >> 168   sos_ui32_t eax;
                                                   >> 169   sos_ui32_t ecx;
                                                   >> 170   sos_ui32_t edx;
                                                   >> 171   sos_ui32_t ebx;
                                                   >> 172   sos_ui32_t esp;
                                                   >> 173   sos_ui32_t ebp;
                                                   >> 174   sos_ui32_t esi;
                                                   >> 175   sos_ui32_t edi;
                                                   >> 176 
                                                   >> 177   /* +72 */
                                                   >> 178   sos_ui16_t es;
                                                   >> 179   sos_ui16_t reserved5;
                                                   >> 180 
                                                   >> 181   /* +76 */
                                                   >> 182   sos_ui16_t cs;
                                                   >> 183   sos_ui16_t reserved6;
                                                   >> 184 
                                                   >> 185   /* +80 */
                                                   >> 186   sos_ui16_t ss;
                                                   >> 187   sos_ui16_t reserved7;
                                                   >> 188 
                                                   >> 189   /* +84 */
                                                   >> 190   sos_ui16_t ds;
                                                   >> 191   sos_ui16_t reserved8;
                                                   >> 192 
                                                   >> 193   /* +88 */
                                                   >> 194   sos_ui16_t fs;
                                                   >> 195   sos_ui16_t reserved9;
                                                   >> 196 
                                                   >> 197   /* +92 */
                                                   >> 198   sos_ui16_t gs;
                                                   >> 199   sos_ui16_t reserved10;
                                                   >> 200 
                                                   >> 201   /* +96 */
                                                   >> 202   sos_ui16_t ldtr;
                                                   >> 203   sos_ui16_t reserved11;
                                                   >> 204 
                                                   >> 205   /* +100 */
                                                   >> 206   sos_ui16_t debug_trap_flag :1;
                                                   >> 207   sos_ui16_t reserved12      :15;
                                                   >> 208   sos_ui16_t iomap_base_addr;
                                                   >> 209 
                                                   >> 210   /* 104 */
                                                   >> 211 } __attribute__((packed, aligned(128)));
                                                   >> 212 
                                                   >> 213 
                                                   >> 214 static struct x86_tss kernel_tss;
                                                   >> 215 
                                                   >> 216 
                                                   >> 217 sos_ret_t sos_cpu_context_subsystem_setup()
                                                   >> 218 {
                                                   >> 219   /* Reset the kernel TSS */
                                                   >> 220   memset(&kernel_tss, 0x0, sizeof(kernel_tss));
                                                   >> 221 
                                                   >> 222   /**
                                                   >> 223    * Now setup the kernel TSS.
                                                   >> 224    *
                                                   >> 225    * Considering the privilege change method we choose (cpl3 -> cpl0
                                                   >> 226    * through a software interrupt), we don't need to initialize a
                                                   >> 227    * full-fledged TSS. See section 6.4.1 of Intel x86 vol 1. Actually,
                                                   >> 228    * only a correct value for the kernel esp and ss are required (aka
                                                   >> 229    * "ss0" and "esp0" fields). Since the esp0 will have to be updated
                                                   >> 230    * at privilege change time, we don't have to set it up now.
                                                   >> 231    */
                                                   >> 232   kernel_tss.ss0 = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA);
                                                   >> 233 
                                                   >> 234   /* Register this TSS into the gdt */
                                                   >> 235   sos_gdt_register_kernel_tss((sos_vaddr_t) &kernel_tss);
                                                   >> 236 
                                                   >> 237   return SOS_OK;
                                                   >> 238 }
                                                   >> 239 
                                                   >> 240 
                                                   >> 241 /**
101  * THE main operation of a kernel thread. This    242  * THE main operation of a kernel thread. This routine calls the
102  * kernel thread function start_func and calls    243  * kernel thread function start_func and calls exit_func when
103  * start_func returns.                            244  * start_func returns.
104  */                                               245  */
105 static void core_routine (sos_cpu_kstate_funct    246 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
106                           sos_ui32_t start_arg    247                           sos_ui32_t start_arg,
107                           sos_cpu_kstate_funct    248                           sos_cpu_kstate_function_arg1_t *exit_func,
108                           sos_ui32_t exit_arg)    249                           sos_ui32_t exit_arg)
109      __attribute__((noreturn));                   250      __attribute__((noreturn));
110                                                   251 
111 static void core_routine (sos_cpu_kstate_funct    252 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
112                           sos_ui32_t start_arg    253                           sos_ui32_t start_arg,
113                           sos_cpu_kstate_funct    254                           sos_cpu_kstate_function_arg1_t *exit_func,
114                           sos_ui32_t exit_arg)    255                           sos_ui32_t exit_arg)
115 {                                                 256 {
116   start_func(start_arg);                          257   start_func(start_arg);
117   exit_func(exit_arg);                            258   exit_func(exit_arg);
118                                                   259 
119   SOS_ASSERT_FATAL(! "The exit function of the    260   SOS_ASSERT_FATAL(! "The exit function of the thread should NOT return !");
120   for(;;);                                        261   for(;;);
121 }                                                 262 }
122                                                   263 
123                                                   264 
124 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_s    265 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **ctxt,
125                               sos_cpu_kstate_f    266                               sos_cpu_kstate_function_arg1_t *start_func,
126                               sos_ui32_t  star    267                               sos_ui32_t  start_arg,
127                               sos_vaddr_t stac    268                               sos_vaddr_t stack_bottom,
128                               sos_size_t  stac    269                               sos_size_t  stack_size,
129                               sos_cpu_kstate_f    270                               sos_cpu_kstate_function_arg1_t *exit_func,
130                               sos_ui32_t  exit    271                               sos_ui32_t  exit_arg)
131 {                                                 272 {
132   /* We are initializing a Kernel thread's con    273   /* We are initializing a Kernel thread's context */
133   struct sos_cpu_kstate *kctxt;                   274   struct sos_cpu_kstate *kctxt;
134                                                   275 
135   /* This is a critical internal function, so     276   /* This is a critical internal function, so that it is assumed that
136      the caller knows what he does: we legitim    277      the caller knows what he does: we legitimally assume that values
137      for ctxt, start_func, stack_* and exit_fu    278      for ctxt, start_func, stack_* and exit_func are allways VALID ! */
138                                                   279 
139   /* Setup the stack.                             280   /* Setup the stack.
140    *                                              281    *
141    * On x86, the stack goes downward. Each fra    282    * On x86, the stack goes downward. Each frame is configured this
142    * way (higher addresses first):                283    * way (higher addresses first):
143    *                                              284    *
144    *  - (optional unused space. As of gcc 3.3,    285    *  - (optional unused space. As of gcc 3.3, this space is 24 bytes)
145    *  - arg n                                     286    *  - arg n
146    *  - arg n-1                                   287    *  - arg n-1
147    *  - ...                                       288    *  - ...
148    *  - arg 1                                     289    *  - arg 1
149    *  - return instruction address: The addres    290    *  - return instruction address: The address the function returns to
150    *    once finished                             291    *    once finished
151    *  - local variables                           292    *  - local variables
152    *                                              293    *
153    * The remaining of the code should be read     294    * The remaining of the code should be read from the end upward to
154    * understand how the processor will handle     295    * understand how the processor will handle it.
155    */                                             296    */
156                                                   297 
157   sos_vaddr_t tmp_vaddr = stack_bottom + stack    298   sos_vaddr_t tmp_vaddr = stack_bottom + stack_size;
158   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;     299   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;
159                                                   300 
160   /* If needed, poison the stack */               301   /* If needed, poison the stack */
161 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS    302 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
162   memset((void*)stack_bottom, SOS_CPU_STATE_ST    303   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, stack_size);
163 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STAC    304 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
164   sos_cpu_state_prepare_detect_kernel_stack_ov    305   sos_cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
165 #endif                                            306 #endif
166                                                   307 
167   /* Simulate a call to the core_routine() fun    308   /* Simulate a call to the core_routine() function: prepare its
168      arguments */                                 309      arguments */
169   *(--stack) = exit_arg;                          310   *(--stack) = exit_arg;
170   *(--stack) = (sos_ui32_t)exit_func;             311   *(--stack) = (sos_ui32_t)exit_func;
171   *(--stack) = start_arg;                         312   *(--stack) = start_arg;
172   *(--stack) = (sos_ui32_t)start_func;            313   *(--stack) = (sos_ui32_t)start_func;
173   *(--stack) = 0; /* Return address of core_ro    314   *(--stack) = 0; /* Return address of core_routine => force page fault */
174                                                   315 
175   /*                                              316   /*
176    * Setup the initial context structure, so t    317    * Setup the initial context structure, so that the CPU will execute
177    * the function core_routine() once this new    318    * the function core_routine() once this new context has been
178    * restored on CPU                              319    * restored on CPU
179    */                                             320    */
180                                                   321 
181   /* Compute the base address of the structure    322   /* Compute the base address of the structure, which must be located
182      below the previous elements */               323      below the previous elements */
183   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(s    324   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(struct sos_cpu_kstate);
184   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;      325   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;
185                                                   326 
186   /* Initialize the CPU context structure */      327   /* Initialize the CPU context structure */
187   memset(kctxt, 0x0, sizeof(struct sos_cpu_kst    328   memset(kctxt, 0x0, sizeof(struct sos_cpu_kstate));
188                                                   329 
189   /* Tell the CPU context structure that the f    330   /* Tell the CPU context structure that the first instruction to
190      execute will be that of the core_routine(    331      execute will be that of the core_routine() function */
191   kctxt->regs.eip = (sos_ui32_t)core_routine;     332   kctxt->regs.eip = (sos_ui32_t)core_routine;
192                                                   333 
193   /* Setup the segment registers */               334   /* Setup the segment registers */
194   kctxt->regs.cs                                  335   kctxt->regs.cs
195     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    336     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE); /* Code */
196   kctxt->regs.ds                                  337   kctxt->regs.ds
197     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    338     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
198   kctxt->regs.es                                  339   kctxt->regs.es
199     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    340     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
200   kctxt->regs.cpl0_ss                             341   kctxt->regs.cpl0_ss
201     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    342     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Stack */
202   /* fs and gs unused for the moment. */          343   /* fs and gs unused for the moment. */
203                                                   344 
204   /* The newly created context is initially in    345   /* The newly created context is initially interruptible */
205   kctxt->regs.eflags = (1 << 9); /* set IF bit    346   kctxt->regs.eflags = (1 << 9); /* set IF bit */
206                                                   347 
207   /* Finally, update the generic kernel/user t    348   /* Finally, update the generic kernel/user thread context */
208   *ctxt = (struct sos_cpu_state*) kctxt;          349   *ctxt = (struct sos_cpu_state*) kctxt;
209                                                   350 
210   return SOS_OK;                                  351   return SOS_OK;
211 }                                                 352 }
212                                                   353 
213                                                   354 
                                                   >> 355 sos_ret_t sos_cpu_ustate_init(struct sos_cpu_state **ctxt,
                                                   >> 356                               sos_uaddr_t  user_start_PC,
                                                   >> 357                               sos_ui32_t   user_start_arg1,
                                                   >> 358                               sos_ui32_t   user_start_arg2,
                                                   >> 359                               sos_uaddr_t  user_initial_SP,
                                                   >> 360                               sos_vaddr_t  kernel_stack_bottom,
                                                   >> 361                               sos_size_t   kernel_stack_size)
                                                   >> 362 {
                                                   >> 363   /* We are initializing a User thread's context */
                                                   >> 364   struct sos_cpu_ustate *uctxt;
                                                   >> 365 
                                                   >> 366   /* This is a critical internal function, so that it is assumed that
                                                   >> 367      the caller knows what he does: we legitimally assume that values
                                                   >> 368      for ctxt, etc. are allways VALID ! */
                                                   >> 369 
                                                   >> 370   /* Compute the address of the CPU state to restore on CPU when
                                                   >> 371      switching to this new user thread */
                                                   >> 372   sos_vaddr_t uctxt_vaddr = kernel_stack_bottom
                                                   >> 373                              + kernel_stack_size
                                                   >> 374                              - sizeof(struct sos_cpu_ustate);
                                                   >> 375   uctxt = (struct sos_cpu_ustate*)uctxt_vaddr;
                                                   >> 376 
                                                   >> 377   /* If needed, poison the kernel stack */
                                                   >> 378 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
                                                   >> 379   memset((void*)kernel_stack_bottom,
                                                   >> 380          SOS_CPU_STATE_STACK_POISON,
                                                   >> 381          kernel_stack_size);
                                                   >> 382 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
                                                   >> 383   sos_cpu_state_prepare_detect_kernel_stack_overflow(kernel_stack_bottom,
                                                   >> 384                                                      kernel_stack_size);
                                                   >> 385 #endif
                                                   >> 386 
                                                   >> 387   /*
                                                   >> 388    * Setup the initial context structure, so that the CPU will restore
                                                   >> 389    * the initial registers' value for the user thread. The
                                                   >> 390    * user thread argument is passed in the EAX register.
                                                   >> 391    */
                                                   >> 392 
                                                   >> 393   memset(uctxt, 0x0, sizeof(struct sos_cpu_ustate));
                                                   >> 394   
                                                   >> 395   /* Tell the CPU context structure that the first instruction to
                                                   >> 396      execute will be located at user_start_PC (in user space) */
                                                   >> 397   uctxt->regs.eip = (sos_ui32_t)user_start_PC;
                                                   >> 398   
                                                   >> 399   /* Tell the CPU where will be the user stack */
                                                   >> 400   uctxt->cpl3_esp = user_initial_SP;
                                                   >> 401 
                                                   >> 402   /* The parameter to the start function is not passed by the stack to
                                                   >> 403      avoid a possible page fault */
                                                   >> 404   uctxt->regs.eax = user_start_arg1;
                                                   >> 405   uctxt->regs.ebx = user_start_arg2;
                                                   >> 406 
                                                   >> 407   /* Setup the segment registers */
                                                   >> 408   uctxt->regs.cs
                                                   >> 409     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UCODE); /* Code */
                                                   >> 410   uctxt->regs.ds
                                                   >> 411     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UDATA); /* Data */
                                                   >> 412   uctxt->regs.es
                                                   >> 413     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UDATA); /* Data */
                                                   >> 414   uctxt->cpl3_ss
                                                   >> 415     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UDATA); /* User Stack */
                                                   >> 416 
                                                   >> 417   /* We need also to update the segment for the kernel stack
                                                   >> 418      segment. It will be used when this context will be restored on
                                                   >> 419      CPU: initially it will be executing in kernel mode and will
                                                   >> 420      switch immediatly to user mode */
                                                   >> 421   uctxt->regs.cpl0_ss
                                                   >> 422     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Kernel Stack */
                                                   >> 423 
                                                   >> 424   /* fs and gs unused for the moment. */
                                                   >> 425 
                                                   >> 426   /* The newly created context is initially interruptible */
                                                   >> 427   uctxt->regs.eflags = (1 << 9); /* set IF bit */
                                                   >> 428 
                                                   >> 429   /* Finally, update the generic kernel/user thread context */
                                                   >> 430   *ctxt = (struct sos_cpu_state*) uctxt;
                                                   >> 431 
                                                   >> 432   return SOS_OK;
                                                   >> 433 }
                                                   >> 434 
                                                   >> 435 
                                                   >> 436 sos_ret_t
                                                   >> 437 sos_cpu_context_is_in_user_mode(const struct sos_cpu_state *ctxt)
                                                   >> 438 {
                                                   >> 439   /* An interrupted user thread has its CS register set to that of the
                                                   >> 440      User code segment */
                                                   >> 441   switch (GET_CPU_CS_REGISTER_VALUE(ctxt->cs))
                                                   >> 442     {
                                                   >> 443     case SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UCODE):
                                                   >> 444       return TRUE;
                                                   >> 445       break;
                                                   >> 446 
                                                   >> 447     case SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE):
                                                   >> 448       return FALSE;
                                                   >> 449       break;
                                                   >> 450 
                                                   >> 451     default:
                                                   >> 452       SOS_FATAL_ERROR("Invalid saved context Code segment register: 0x%x (k=%x, u=%x) !",
                                                   >> 453                       (unsigned) GET_CPU_CS_REGISTER_VALUE(ctxt->cs),
                                                   >> 454                       SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE),
                                                   >> 455                       SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SOS_SEG_UCODE));
                                                   >> 456       break;
                                                   >> 457     }
                                                   >> 458 
                                                   >> 459   /* Should never get here */
                                                   >> 460   return -SOS_EFATAL;
                                                   >> 461 }
                                                   >> 462 
                                                   >> 463 
214 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_    464 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
215 void                                              465 void
216 sos_cpu_state_prepare_detect_kernel_stack_over    466 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
217                                                   467                                                    sos_vaddr_t stack_bottom,
218                                                   468                                                    sos_size_t stack_size)
219 {                                                 469 {
220   sos_size_t poison_size = SOS_CPU_STATE_DETEC    470   sos_size_t poison_size = SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
221   if (poison_size > stack_size)                   471   if (poison_size > stack_size)
222     poison_size = stack_size;                     472     poison_size = stack_size;
223                                                   473 
224   memset((void*)stack_bottom, SOS_CPU_STATE_ST    474   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, poison_size);
225 }                                                 475 }
226                                                   476 
227                                                   477 
228 void                                              478 void
229 sos_cpu_state_detect_kernel_stack_overflow(con    479 sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
230                                            sos    480                                            sos_vaddr_t stack_bottom,
231                                            sos    481                                            sos_size_t stack_size)
232 {                                                 482 {
233   unsigned char *c;                               483   unsigned char *c;
234   int i;                                          484   int i;
235                                                   485 
236   /* On SOS, "ctxt" corresponds to the address    486   /* On SOS, "ctxt" corresponds to the address of the esp register of
237      the saved context in Kernel mode (always,    487      the saved context in Kernel mode (always, even for the interrupted
238      context of a user thread). Here we make s    488      context of a user thread). Here we make sure that this stack
239      pointer is within the allowed stack area     489      pointer is within the allowed stack area */
240   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stac    490   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stack_bottom);
241   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeo    491   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeof(struct sos_cpu_kstate)
242                    <= stack_bottom + stack_siz    492                    <= stack_bottom + stack_size);
243                                                   493 
244   /* Check that the bottom of the stack has no    494   /* Check that the bottom of the stack has not been altered */
245   for (c = (unsigned char*) stack_bottom, i =     495   for (c = (unsigned char*) stack_bottom, i = 0 ;
246        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_    496        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size) ;
247        c++, i++)                                  497        c++, i++)
248     {                                             498     {
249       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POI    499       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POISON == *c);
250     }                                             500     }
251 }                                                 501 }
252 #endif                                            502 #endif
253                                                   503 
254                                                   504 
255 /* ===========================================    505 /* =======================================================================
256  * Public Accessor functions                      506  * Public Accessor functions
257  */                                               507  */
258                                                   508 
259                                                   509 
260 sos_vaddr_t sos_cpu_context_get_PC(const struc    510 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt)
261 {                                                 511 {
262   SOS_ASSERT_FATAL(NULL != ctxt);                 512   SOS_ASSERT_FATAL(NULL != ctxt);
263                                                   513 
264   /* This is the PC of the interrupted context    514   /* This is the PC of the interrupted context (ie kernel or user
265      context). */                                 515      context). */
266   return ctxt->eip;                               516   return ctxt->eip;
267 }                                                 517 }
268                                                   518 
269                                                   519 
270 sos_vaddr_t sos_cpu_context_get_SP(const struc    520 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt)
271 {                                                 521 {
272   SOS_ASSERT_FATAL(NULL != ctxt);                 522   SOS_ASSERT_FATAL(NULL != ctxt);
273                                                   523 
                                                   >> 524   /* 'ctxt' corresponds to the SP of the interrupted context, in Kernel
                                                   >> 525      mode. We have to test whether the original interrupted context
                                                   >> 526      was that of a kernel or user thread */
                                                   >> 527   if (TRUE == sos_cpu_context_is_in_user_mode(ctxt))
                                                   >> 528     {
                                                   >> 529       struct sos_cpu_ustate * uctxt = (struct sos_cpu_ustate*)ctxt;
                                                   >> 530       return uctxt->cpl3_esp;
                                                   >> 531     }
                                                   >> 532 
274   /* On SOS, "ctxt" corresponds to the address    533   /* On SOS, "ctxt" corresponds to the address of the esp register of
275      the saved context in Kernel mode (always,    534      the saved context in Kernel mode (always, even for the interrupted
276      context of a user thread). */                535      context of a user thread). */
277   return (sos_vaddr_t)ctxt;                       536   return (sos_vaddr_t)ctxt;
278 }                                                 537 }
279                                                   538 
280                                                   539 
                                                   >> 540 sos_ret_t
                                                   >> 541 sos_cpu_context_set_EX_return_address(struct sos_cpu_state *ctxt,
                                                   >> 542                                       sos_vaddr_t ret_vaddr)
                                                   >> 543 {
                                                   >> 544   ctxt->eip = ret_vaddr;
                                                   >> 545   return SOS_OK;
                                                   >> 546 }
                                                   >> 547 
                                                   >> 548 
281 void sos_cpu_context_dump(const struct sos_cpu    549 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt)
282 {                                                 550 {
283   char buf[128];                                  551   char buf[128];
                                                   >> 552 
284   snprintf(buf, sizeof(buf),                      553   snprintf(buf, sizeof(buf),
285            "CPU: eip=%x esp=%x eflags=%x cs=%x !! 554            "CPU: eip=%x esp0=%x eflags=%x cs=%x ds=%x ss0=%x err=%x",
286            (unsigned)ctxt->eip, (unsigned)ctxt    555            (unsigned)ctxt->eip, (unsigned)ctxt, (unsigned)ctxt->eflags,
287            (unsigned)GET_CPU_CS_REGISTER_VALUE    556            (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs), (unsigned)ctxt->ds,
288            (unsigned)ctxt->cpl0_ss,               557            (unsigned)ctxt->cpl0_ss,
289            (unsigned)ctxt->error_code);           558            (unsigned)ctxt->error_code);
                                                   >> 559   if (TRUE == sos_cpu_context_is_in_user_mode(ctxt))
                                                   >> 560     {
                                                   >> 561       struct sos_cpu_ustate * uctxt = (struct sos_cpu_ustate*)ctxt;
                                                   >> 562       snprintf(buf, sizeof(buf),
                                                   >> 563                "%s esp3=%x ss3=%x",
                                                   >> 564                buf, (unsigned)uctxt->cpl3_esp, (unsigned)uctxt->cpl3_ss);
                                                   >> 565     }
                                                   >> 566   else
                                                   >> 567     snprintf(buf, sizeof(buf), "%s [KERNEL MODE]", buf);
                                                   >> 568 
290   sos_bochs_putstring(buf); sos_bochs_putstrin    569   sos_bochs_putstring(buf); sos_bochs_putstring("\n");
291   sos_x86_videomem_putstring(23, 0,               570   sos_x86_videomem_putstring(23, 0,
292                           SOS_X86_VIDEO_FG_BLA !! 571                              SOS_X86_VIDEO_FG_BLACK | SOS_X86_VIDEO_BG_LTGRAY,
293                           buf);                !! 572                              buf);
294 }                                                 573 }
295                                                   574 
296                                                   575 
297 /* ===========================================    576 /* =======================================================================
298  * Public Accessor functions TO BE USED ONLY B    577  * Public Accessor functions TO BE USED ONLY BY Exception handlers
299  */                                               578  */
300                                                   579 
301                                                   580 
302 sos_ui32_t sos_cpu_context_get_EX_info(const s    581 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt)
303 {                                                 582 {
304   SOS_ASSERT_FATAL(NULL != ctxt);                 583   SOS_ASSERT_FATAL(NULL != ctxt);
305   return ctxt->error_code;                        584   return ctxt->error_code;
306 }                                                 585 }
307                                                   586 
308                                                   587 
309 sos_vaddr_t                                       588 sos_vaddr_t
310 sos_cpu_context_get_EX_faulting_vaddr(const st    589 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt)
311 {                                                 590 {
312   sos_ui32_t cr2;                                 591   sos_ui32_t cr2;
313                                                   592 
314   /*                                              593   /*
315    * See Intel Vol 3 (section 5.14): the addre    594    * See Intel Vol 3 (section 5.14): the address of the faulting
316    * virtual address of a page fault is stored    595    * virtual address of a page fault is stored in the cr2
317    * register.                                    596    * register.
318    *                                              597    *
319    * Actually, we do not store the cr2 registe    598    * Actually, we do not store the cr2 register in a saved
320    * kernel thread's context. So we retrieve t    599    * kernel thread's context. So we retrieve the cr2's value directly
321    * from the processor. The value we retrieve    600    * from the processor. The value we retrieve in an exception handler
322    * is actually the correct one because an ex    601    * is actually the correct one because an exception is synchronous
323    * with the code causing the fault, and cann    602    * with the code causing the fault, and cannot be interrupted since
324    * the IDT entries in SOS are "interrupt gat    603    * the IDT entries in SOS are "interrupt gates" (ie IRQ are
325    * disabled).                                   604    * disabled).
326    */                                             605    */
327   asm volatile ("movl %%cr2, %0"                  606   asm volatile ("movl %%cr2, %0"
328                 :"=r"(cr2)                        607                 :"=r"(cr2)
329                 : );                              608                 : );
330                                                   609 
331   return cr2;                                     610   return cr2;
332 }                                                 611 }
333                                                   612 
334                                                   613 
335 /* ===========================================    614 /* =======================================================================
                                                   >> 615  * Public Accessor functions TO BE USED ONLY BY the SYSCALL handler
                                                   >> 616  */
                                                   >> 617 
                                                   >> 618 
                                                   >> 619 /*
                                                   >> 620  * By convention, the USER SOS programs always pass 4 arguments to the
                                                   >> 621  * kernel syscall handler: in eax/../edx. For less arguments, the
                                                   >> 622  * unused registers are filled with 0s. For more arguments, the 4th
                                                   >> 623  * syscall parameter gives the address of the array containing the
                                                   >> 624  * remaining arguments. In any case, eax corresponds to the syscall
                                                   >> 625  * IDentifier.
                                                   >> 626  */
                                                   >> 627 
                                                   >> 628 
                                                   >> 629 inline
                                                   >> 630 sos_ret_t sos_syscall_get3args(const struct sos_cpu_state *user_ctxt,
                                                   >> 631                                /* out */unsigned int *arg1,
                                                   >> 632                                /* out */unsigned int *arg2,
                                                   >> 633                                /* out */unsigned int *arg3)
                                                   >> 634 {
                                                   >> 635   *arg1 = user_ctxt->ebx;
                                                   >> 636   *arg2 = user_ctxt->ecx;
                                                   >> 637   *arg3 = user_ctxt->edx; 
                                                   >> 638   return SOS_OK;
                                                   >> 639 }
                                                   >> 640 
                                                   >> 641 
                                                   >> 642 sos_ret_t sos_syscall_get1arg(const struct sos_cpu_state *user_ctxt,
                                                   >> 643                               /* out */unsigned int *arg1)
                                                   >> 644 {
                                                   >> 645   unsigned int unused;
                                                   >> 646   return sos_syscall_get3args(user_ctxt, arg1, & unused, & unused);
                                                   >> 647 }
                                                   >> 648 
                                                   >> 649 
                                                   >> 650 sos_ret_t sos_syscall_get2args(const struct sos_cpu_state *user_ctxt,
                                                   >> 651                                /* out */unsigned int *arg1,
                                                   >> 652                                /* out */unsigned int *arg2)
                                                   >> 653 {
                                                   >> 654   unsigned int unused;
                                                   >> 655   return sos_syscall_get3args(user_ctxt, arg1, arg2, & unused);
                                                   >> 656 }
                                                   >> 657 
                                                   >> 658 
                                                   >> 659 /*
                                                   >> 660  * sos_syscall_get3args() is defined in cpu_context.c because it needs
                                                   >> 661  * to know the structure of a struct spu_state
                                                   >> 662  */
                                                   >> 663 
                                                   >> 664 sos_ret_t sos_syscall_get4args(const struct sos_cpu_state *user_ctxt,
                                                   >> 665                                /* out */unsigned int *arg1,
                                                   >> 666                                /* out */unsigned int *arg2,
                                                   >> 667                                /* out */unsigned int *arg3,
                                                   >> 668                                /* out */unsigned int *arg4)
                                                   >> 669 {
                                                   >> 670   sos_uaddr_t  uaddr_other_args;
                                                   >> 671   unsigned int other_args[2];
                                                   >> 672   sos_ret_t    retval;
                                                   >> 673 
                                                   >> 674   /* Retrieve the 3 arguments. The last one is an array containing the
                                                   >> 675      remaining arguments */
                                                   >> 676   retval = sos_syscall_get3args(user_ctxt, arg1, arg2,
                                                   >> 677                                 (unsigned int *)& uaddr_other_args);
                                                   >> 678   if (SOS_OK != retval)
                                                   >> 679     return retval;
                                                   >> 680   
                                                   >> 681   /* Copy the array containing the remaining arguments from user
                                                   >> 682      space */
                                                   >> 683   retval = sos_memcpy_from_user((sos_vaddr_t)other_args,
                                                   >> 684                                 (sos_uaddr_t)uaddr_other_args,
                                                   >> 685                                 sizeof(other_args));
                                                   >> 686   if (sizeof(other_args) != retval)
                                                   >> 687     return -SOS_EFAULT;
                                                   >> 688 
                                                   >> 689   *arg3 = other_args[0];
                                                   >> 690   *arg4 = other_args[1];
                                                   >> 691   return SOS_OK;
                                                   >> 692 }
                                                   >> 693 
                                                   >> 694 
                                                   >> 695 sos_ret_t sos_syscall_get5args(const struct sos_cpu_state *user_ctxt,
                                                   >> 696                                /* out */unsigned int *arg1,
                                                   >> 697                                /* out */unsigned int *arg2,
                                                   >> 698                                /* out */unsigned int *arg3,
                                                   >> 699                                /* out */unsigned int *arg4,
                                                   >> 700                                /* out */unsigned int *arg5)
                                                   >> 701 {
                                                   >> 702   sos_uaddr_t  uaddr_other_args;
                                                   >> 703   unsigned int other_args[3];
                                                   >> 704   sos_ret_t    retval;
                                                   >> 705 
                                                   >> 706   /* Retrieve the 3 arguments. The last one is an array containing the
                                                   >> 707      remaining arguments */
                                                   >> 708   retval = sos_syscall_get3args(user_ctxt, arg1, arg2,
                                                   >> 709                                 (unsigned int *)& uaddr_other_args);
                                                   >> 710   if (SOS_OK != retval)
                                                   >> 711     return retval;
                                                   >> 712   
                                                   >> 713   /* Copy the array containing the remaining arguments from user
                                                   >> 714      space */
                                                   >> 715   retval = sos_memcpy_from_user((sos_vaddr_t)other_args,
                                                   >> 716                                 (sos_uaddr_t)uaddr_other_args,
                                                   >> 717                                 sizeof(other_args));
                                                   >> 718   if (sizeof(other_args) != retval)
                                                   >> 719     return -SOS_EFAULT;
                                                   >> 720 
                                                   >> 721   *arg3 = other_args[0];
                                                   >> 722   *arg4 = other_args[1];
                                                   >> 723   *arg5 = other_args[2];
                                                   >> 724   return SOS_OK;
                                                   >> 725 }
                                                   >> 726 
                                                   >> 727 
                                                   >> 728 sos_ret_t sos_syscall_get6args(const struct sos_cpu_state *user_ctxt,
                                                   >> 729                                /* out */unsigned int *arg1,
                                                   >> 730                                /* out */unsigned int *arg2,
                                                   >> 731                                /* out */unsigned int *arg3,
                                                   >> 732                                /* out */unsigned int *arg4,
                                                   >> 733                                /* out */unsigned int *arg5,
                                                   >> 734                                /* out */unsigned int *arg6)
                                                   >> 735 {
                                                   >> 736   sos_uaddr_t  uaddr_other_args;
                                                   >> 737   unsigned int other_args[4];
                                                   >> 738   sos_ret_t    retval;
                                                   >> 739 
                                                   >> 740   /* Retrieve the 3 arguments. The last one is an array containing the
                                                   >> 741      remaining arguments */
                                                   >> 742   retval = sos_syscall_get3args(user_ctxt, arg1, arg2,
                                                   >> 743                                 (unsigned int *)& uaddr_other_args);
                                                   >> 744   if (SOS_OK != retval)
                                                   >> 745     return retval;
                                                   >> 746   
                                                   >> 747   /* Copy the array containing the remaining arguments from user
                                                   >> 748      space */
                                                   >> 749   retval = sos_memcpy_from_user((sos_vaddr_t)other_args,
                                                   >> 750                                 (sos_uaddr_t)uaddr_other_args,
                                                   >> 751                                 sizeof(other_args));
                                                   >> 752   if (sizeof(other_args) != retval)
                                                   >> 753     return -SOS_EFAULT;
                                                   >> 754 
                                                   >> 755   *arg3 = other_args[0];
                                                   >> 756   *arg4 = other_args[1];
                                                   >> 757   *arg5 = other_args[2];
                                                   >> 758   *arg6 = other_args[3];
                                                   >> 759   return SOS_OK;
                                                   >> 760 }
                                                   >> 761 
                                                   >> 762 
                                                   >> 763 sos_ret_t sos_syscall_get7args(const struct sos_cpu_state *user_ctxt,
                                                   >> 764                                /* out */unsigned int *arg1,
                                                   >> 765                                /* out */unsigned int *arg2,
                                                   >> 766                                /* out */unsigned int *arg3,
                                                   >> 767                                /* out */unsigned int *arg4,
                                                   >> 768                                /* out */unsigned int *arg5,
                                                   >> 769                                /* out */unsigned int *arg6,
                                                   >> 770                                /* out */unsigned int *arg7)
                                                   >> 771 {
                                                   >> 772   sos_uaddr_t  uaddr_other_args;
                                                   >> 773   unsigned int other_args[5];
                                                   >> 774   sos_ret_t    retval;
                                                   >> 775 
                                                   >> 776   /* Retrieve the 3 arguments. The last one is an array containing the
                                                   >> 777      remaining arguments */
                                                   >> 778   retval = sos_syscall_get3args(user_ctxt, arg1, arg2,
                                                   >> 779                                 (unsigned int *)& uaddr_other_args);
                                                   >> 780   if (SOS_OK != retval)
                                                   >> 781     return retval;
                                                   >> 782   
                                                   >> 783   /* Copy the array containing the remaining arguments from user
                                                   >> 784      space */
                                                   >> 785   retval = sos_memcpy_from_user((sos_vaddr_t)other_args,
                                                   >> 786                                 (sos_uaddr_t)uaddr_other_args,
                                                   >> 787                                 sizeof(other_args));
                                                   >> 788   if (sizeof(other_args) != retval)
                                                   >> 789     return -SOS_EFAULT;
                                                   >> 790 
                                                   >> 791   *arg3 = other_args[0];
                                                   >> 792   *arg4 = other_args[1];
                                                   >> 793   *arg5 = other_args[2];
                                                   >> 794   *arg6 = other_args[3];
                                                   >> 795   *arg7 = other_args[4];
                                                   >> 796   return SOS_OK;
                                                   >> 797 }
                                                   >> 798 
                                                   >> 799 
                                                   >> 800 sos_ret_t sos_syscall_get8args(const struct sos_cpu_state *user_ctxt,
                                                   >> 801                                /* out */unsigned int *arg1,
                                                   >> 802                                /* out */unsigned int *arg2,
                                                   >> 803                                /* out */unsigned int *arg3,
                                                   >> 804                                /* out */unsigned int *arg4,
                                                   >> 805                                /* out */unsigned int *arg5,
                                                   >> 806                                /* out */unsigned int *arg6,
                                                   >> 807                                /* out */unsigned int *arg7,
                                                   >> 808                                /* out */unsigned int *arg8)
                                                   >> 809 {
                                                   >> 810   sos_uaddr_t  uaddr_other_args;
                                                   >> 811   unsigned int other_args[6];
                                                   >> 812   sos_ret_t    retval;
                                                   >> 813 
                                                   >> 814   /* Retrieve the 3 arguments. The last one is an array containing the
                                                   >> 815      remaining arguments */
                                                   >> 816   retval = sos_syscall_get3args(user_ctxt, arg1, arg2,
                                                   >> 817                                 (unsigned int *)& uaddr_other_args);
                                                   >> 818   if (SOS_OK != retval)
                                                   >> 819     return retval;
                                                   >> 820   
                                                   >> 821   /* Copy the array containing the remaining arguments from user
                                                   >> 822      space */
                                                   >> 823   retval = sos_memcpy_from_user((sos_vaddr_t)other_args,
                                                   >> 824                                 (sos_uaddr_t)uaddr_other_args,
                                                   >> 825                                 sizeof(other_args));
                                                   >> 826   if (sizeof(other_args) != retval)
                                                   >> 827     return -SOS_EFAULT;
                                                   >> 828 
                                                   >> 829   *arg3 = other_args[0];
                                                   >> 830   *arg4 = other_args[1];
                                                   >> 831   *arg5 = other_args[2];
                                                   >> 832   *arg6 = other_args[3];
                                                   >> 833   *arg7 = other_args[4];
                                                   >> 834   *arg8 = other_args[5];
                                                   >> 835   return SOS_OK;
                                                   >> 836 }
                                                   >> 837 
                                                   >> 838 
                                                   >> 839 /* =======================================================================
336  * Backtrace facility. To be used for DEBUGgin    840  * Backtrace facility. To be used for DEBUGging purpose ONLY.
337  */                                               841  */
338                                                   842 
339                                                   843 
340 sos_ui32_t sos_backtrace(const struct sos_cpu_    844 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state,
341                          sos_ui32_t max_depth,    845                          sos_ui32_t max_depth,
342                          sos_vaddr_t stack_bot    846                          sos_vaddr_t stack_bottom,
343                          sos_size_t stack_size    847                          sos_size_t stack_size,
344                          sos_backtrace_callbac    848                          sos_backtrace_callback_t * backtracer,
345                          void *custom_arg)        849                          void *custom_arg)
346 {                                                 850 {
347   int depth;                                      851   int depth;
348   sos_vaddr_t callee_PC, caller_frame;            852   sos_vaddr_t callee_PC, caller_frame;
349                                                   853 
                                                   >> 854   /* Cannot backtrace an interrupted user thread ! */
                                                   >> 855   if ((NULL != cpu_state)
                                                   >> 856       &&
                                                   >> 857       (TRUE == sos_cpu_context_is_in_user_mode(cpu_state)))
                                                   >> 858     {
                                                   >> 859       return 0;
                                                   >> 860     }
                                                   >> 861   
350   /*                                              862   /*
351    * Layout of a frame on the x86 (compiler=gc    863    * Layout of a frame on the x86 (compiler=gcc):
352    *                                              864    *
353    * funcA calls funcB calls funcC                865    * funcA calls funcB calls funcC
354    *                                              866    *
355    *         ....                                 867    *         ....
356    *         funcB Argument 2                     868    *         funcB Argument 2
357    *         funcB Argument 1                     869    *         funcB Argument 1
358    *         funcA Return eip                     870    *         funcA Return eip
359    * frameB: funcA ebp (ie previous stack fram    871    * frameB: funcA ebp (ie previous stack frame)
360    *         ....                                 872    *         ....
361    *         (funcB local variables)              873    *         (funcB local variables)
362    *         ....                                 874    *         ....
363    *         funcC Argument 2                     875    *         funcC Argument 2
364    *         funcC Argument 1                     876    *         funcC Argument 1
365    *         funcB Return eip                     877    *         funcB Return eip
366    * frameC: funcB ebp (ie previous stack fram    878    * frameC: funcB ebp (ie previous stack frame == A0) <---- a frame address
367    *         ....                                 879    *         ....
368    *         (funcC local variables)              880    *         (funcC local variables)
369    *         ....                                 881    *         ....
370    *                                              882    *
371    * The presence of "ebp" on the stack depend    883    * The presence of "ebp" on the stack depends on 2 things:
372    *   + the compiler is gcc                      884    *   + the compiler is gcc
373    *   + the source is compiled WITHOUT the -f    885    *   + the source is compiled WITHOUT the -fomit-frame-pointer option
374    * In the absence of "ebp", chances are high    886    * In the absence of "ebp", chances are high that the value pushed
375    * at that address is outside the stack boun    887    * at that address is outside the stack boundaries, meaning that the
376    * function will return -SOS_ENOSUP.            888    * function will return -SOS_ENOSUP.
377    */                                             889    */
378                                                   890 
379   if (cpu_state)                                  891   if (cpu_state)
380     {                                             892     {
381       callee_PC    = cpu_state->eip;              893       callee_PC    = cpu_state->eip;
382       caller_frame = cpu_state->ebp;              894       caller_frame = cpu_state->ebp;
383     }                                             895     }
384   else                                            896   else
385     {                                             897     {
386       /* Skip the sos_backtrace() frame */        898       /* Skip the sos_backtrace() frame */
387       callee_PC    = (sos_vaddr_t)__builtin_re    899       callee_PC    = (sos_vaddr_t)__builtin_return_address(0);
388       caller_frame = (sos_vaddr_t)__builtin_fr    900       caller_frame = (sos_vaddr_t)__builtin_frame_address(1);
389     }                                             901     }
390                                                   902 
391   for(depth=0 ; depth < max_depth ; depth ++)     903   for(depth=0 ; depth < max_depth ; depth ++)
392     {                                             904     {
393       /* Call the callback */                     905       /* Call the callback */
394       backtracer(callee_PC, caller_frame + 8,     906       backtracer(callee_PC, caller_frame + 8, depth, custom_arg);
395                                                   907 
396       /* If the frame address is funky, don't     908       /* If the frame address is funky, don't go further */
397       if ( (caller_frame < stack_bottom)          909       if ( (caller_frame < stack_bottom)
398            || (caller_frame + 4 >= stack_botto    910            || (caller_frame + 4 >= stack_bottom + stack_size) )
399         return depth;                             911         return depth;
400                                                   912 
401       /* Go to caller frame */                    913       /* Go to caller frame */
402       callee_PC    = *((sos_vaddr_t*) (caller_    914       callee_PC    = *((sos_vaddr_t*) (caller_frame + 4));
403       caller_frame = *((sos_vaddr_t*) caller_f    915       caller_frame = *((sos_vaddr_t*) caller_frame);
404     }                                             916     }
405                                                   917   
406   return depth;                                   918   return depth;
                                                   >> 919 }
                                                   >> 920 
                                                   >> 921 
                                                   >> 922 /* *************************************************************
                                                   >> 923  * Function to manage the TSS.  This function is not really "public":
                                                   >> 924  * it is reserved to the assembler routines defined in
                                                   >> 925  * cpu_context_switch.S
                                                   >> 926  *
                                                   >> 927  * Update the kernel stack address so that the IRQ, syscalls and
                                                   >> 928  * exception return in a correct stack location when coming back into
                                                   >> 929  * kernel mode.
                                                   >> 930  */
                                                   >> 931 void
                                                   >> 932 sos_cpu_context_update_kernel_tss(struct sos_cpu_state *next_ctxt)
                                                   >> 933 {
                                                   >> 934   /* next_ctxt corresponds to an interrupted user thread ? */
                                                   >> 935   if (sos_cpu_context_is_in_user_mode(next_ctxt))
                                                   >> 936     {
                                                   >> 937       /*
                                                   >> 938        * Yes: "next_ctxt" is an interrupted user thread => we are
                                                   >> 939        * going to switch to user mode ! Setup the stack address so
                                                   >> 940        * that the user thread "next_ctxt" can come back to the correct
                                                   >> 941        * stack location when returning in kernel mode.
                                                   >> 942        *
                                                   >> 943        * This stack location corresponds to the SP of the next user
                                                   >> 944        * thread once its context has been transferred on the CPU, ie
                                                   >> 945        * once the CPU has executed all the pop/iret instruction of the
                                                   >> 946        * context switch with privilege change.
                                                   >> 947        */
                                                   >> 948       kernel_tss.esp0 = ((sos_vaddr_t)next_ctxt)
                                                   >> 949                         + sizeof(struct sos_cpu_ustate);
                                                   >> 950       /* Note: no need to protect this agains IRQ because IRQs are not
                                                   >> 951          allowed to update it by themselves, and they are not allowed
                                                   >> 952          to block */
                                                   >> 953     }
                                                   >> 954   else
                                                   >> 955     {
                                                   >> 956       /* No: No need to update kernel TSS when we stay in kernel
                                                   >> 957          mode */
                                                   >> 958     }
407 }                                                 959 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]