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 8) and /hwcore/cpu_context.c (Article 6)


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

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