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


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>                       << 
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_state {
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  cpl0_ss; /* This is ALWAYS the Stack Segment of the
054                           Kernel context (CPL0    052                           Kernel context (CPL0) of the interrupted
055                           thread, even for a u    053                           thread, even for a user thread */
056   sos_ui16_t  alignment_padding; /* unused */     054   sos_ui16_t  alignment_padding; /* unused */
057   sos_ui32_t  eax;                                055   sos_ui32_t  eax;
058   sos_ui32_t  ebx;                                056   sos_ui32_t  ebx;
059   sos_ui32_t  ecx;                                057   sos_ui32_t  ecx;
060   sos_ui32_t  edx;                                058   sos_ui32_t  edx;
061   sos_ui32_t  esi;                                059   sos_ui32_t  esi;
062   sos_ui32_t  edi;                                060   sos_ui32_t  edi;
063   sos_ui32_t  ebp;                                061   sos_ui32_t  ebp;
064                                                   062 
065   /* MUST NEVER CHANGE (dependent on the IA32     063   /* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
066   sos_ui32_t  error_code;                         064   sos_ui32_t  error_code;
067   sos_vaddr_t eip;                                065   sos_vaddr_t eip;
068   sos_ui32_t  cs; /* 32bits according to the s    066   sos_ui32_t  cs; /* 32bits according to the specs ! However, the CS
069                      register is really 16bits    067                      register is really 16bits long */
070   sos_ui32_t  eflags;                             068   sos_ui32_t  eflags;
071                                                   069 
072   /* (Higher addresses) */                        070   /* (Higher addresses) */
073 } __attribute__((packed));                        071 } __attribute__((packed));
074                                                   072 
075                                                   073 
076 /**                                               074 /**
077  * The CS value pushed on the stack by the CPU    075  * The CS value pushed on the stack by the CPU upon interrupt, and
078  * needed by the iret instruction, is 32bits l    076  * needed by the iret instruction, is 32bits long while the real CPU
079  * CS register is 16bits only: this macro simp    077  * CS register is 16bits only: this macro simply retrieves the CPU
080  * "CS" register value from the CS value pushe    078  * "CS" register value from the CS value pushed on the stack by the
081  * CPU upon interrupt.                            079  * CPU upon interrupt.
082  *                                                080  *
083  * The remaining 16bits pushed by the CPU shou    081  * The remaining 16bits pushed by the CPU should be considered
084  * "reserved" and architecture dependent. IMHO    082  * "reserved" and architecture dependent. IMHO, the specs don't say
085  * anything about them. Considering that some     083  * anything about them. Considering that some architectures generate
086  * non-zero values for these 16bits (at least     084  * non-zero values for these 16bits (at least Cyrix), we'd better
087  * ignore them.                                   085  * ignore them.
088  */                                               086  */
089 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_    087 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_cs_value) \
090   ( (pushed_ui32_cs_value) & 0xffff )             088   ( (pushed_ui32_cs_value) & 0xffff )
091                                                   089 
092                                                   090 
093 /**                                               091 /**
094  * Structure of an interrupted Kernel thread's    092  * Structure of an interrupted Kernel thread's context
095  */                                               093  */
096 struct sos_cpu_kstate                             094 struct sos_cpu_kstate
097 {                                                 095 {
098   struct sos_cpu_state regs;                      096   struct sos_cpu_state regs;
099 } __attribute__((packed));                        097 } __attribute__((packed));
100                                                   098 
101                                                   099 
102 /**                                               100 /**
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    101  * THE main operation of a kernel thread. This routine calls the
243  * kernel thread function start_func and calls    102  * kernel thread function start_func and calls exit_func when
244  * start_func returns.                            103  * start_func returns.
245  */                                               104  */
246 static void core_routine (sos_cpu_kstate_funct    105 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
247                           sos_ui32_t start_arg    106                           sos_ui32_t start_arg,
248                           sos_cpu_kstate_funct    107                           sos_cpu_kstate_function_arg1_t *exit_func,
249                           sos_ui32_t exit_arg)    108                           sos_ui32_t exit_arg)
250      __attribute__((noreturn));                   109      __attribute__((noreturn));
251                                                   110 
252 static void core_routine (sos_cpu_kstate_funct    111 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
253                           sos_ui32_t start_arg    112                           sos_ui32_t start_arg,
254                           sos_cpu_kstate_funct    113                           sos_cpu_kstate_function_arg1_t *exit_func,
255                           sos_ui32_t exit_arg)    114                           sos_ui32_t exit_arg)
256 {                                                 115 {
257   start_func(start_arg);                          116   start_func(start_arg);
258   exit_func(exit_arg);                            117   exit_func(exit_arg);
259                                                   118 
260   SOS_ASSERT_FATAL(! "The exit function of the    119   SOS_ASSERT_FATAL(! "The exit function of the thread should NOT return !");
261   for(;;);                                        120   for(;;);
262 }                                                 121 }
263                                                   122 
264                                                   123 
265 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_s    124 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **ctxt,
266                               sos_cpu_kstate_f    125                               sos_cpu_kstate_function_arg1_t *start_func,
267                               sos_ui32_t  star    126                               sos_ui32_t  start_arg,
268                               sos_vaddr_t stac    127                               sos_vaddr_t stack_bottom,
269                               sos_size_t  stac    128                               sos_size_t  stack_size,
270                               sos_cpu_kstate_f    129                               sos_cpu_kstate_function_arg1_t *exit_func,
271                               sos_ui32_t  exit    130                               sos_ui32_t  exit_arg)
272 {                                                 131 {
273   /* We are initializing a Kernel thread's con    132   /* We are initializing a Kernel thread's context */
274   struct sos_cpu_kstate *kctxt;                   133   struct sos_cpu_kstate *kctxt;
275                                                   134 
276   /* This is a critical internal function, so     135   /* This is a critical internal function, so that it is assumed that
277      the caller knows what he does: we legitim    136      the caller knows what he does: we legitimally assume that values
278      for ctxt, start_func, stack_* and exit_fu    137      for ctxt, start_func, stack_* and exit_func are allways VALID ! */
279                                                   138 
280   /* Setup the stack.                             139   /* Setup the stack.
281    *                                              140    *
282    * On x86, the stack goes downward. Each fra    141    * On x86, the stack goes downward. Each frame is configured this
283    * way (higher addresses first):                142    * way (higher addresses first):
284    *                                              143    *
285    *  - (optional unused space. As of gcc 3.3,    144    *  - (optional unused space. As of gcc 3.3, this space is 24 bytes)
286    *  - arg n                                     145    *  - arg n
287    *  - arg n-1                                   146    *  - arg n-1
288    *  - ...                                       147    *  - ...
289    *  - arg 1                                     148    *  - arg 1
290    *  - return instruction address: The addres    149    *  - return instruction address: The address the function returns to
291    *    once finished                             150    *    once finished
292    *  - local variables                           151    *  - local variables
293    *                                              152    *
294    * The remaining of the code should be read     153    * The remaining of the code should be read from the end upward to
295    * understand how the processor will handle     154    * understand how the processor will handle it.
296    */                                             155    */
297                                                   156 
298   sos_vaddr_t tmp_vaddr = stack_bottom + stack    157   sos_vaddr_t tmp_vaddr = stack_bottom + stack_size;
299   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;     158   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;
300                                                   159 
301   /* If needed, poison the stack */               160   /* If needed, poison the stack */
302 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS    161 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
303   memset((void*)stack_bottom, SOS_CPU_STATE_ST    162   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, stack_size);
304 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STAC    163 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
305   sos_cpu_state_prepare_detect_kernel_stack_ov    164   sos_cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
306 #endif                                            165 #endif
307                                                   166 
308   /* Simulate a call to the core_routine() fun    167   /* Simulate a call to the core_routine() function: prepare its
309      arguments */                                 168      arguments */
310   *(--stack) = exit_arg;                          169   *(--stack) = exit_arg;
311   *(--stack) = (sos_ui32_t)exit_func;             170   *(--stack) = (sos_ui32_t)exit_func;
312   *(--stack) = start_arg;                         171   *(--stack) = start_arg;
313   *(--stack) = (sos_ui32_t)start_func;            172   *(--stack) = (sos_ui32_t)start_func;
314   *(--stack) = 0; /* Return address of core_ro    173   *(--stack) = 0; /* Return address of core_routine => force page fault */
315                                                   174 
316   /*                                              175   /*
317    * Setup the initial context structure, so t    176    * Setup the initial context structure, so that the CPU will execute
318    * the function core_routine() once this new    177    * the function core_routine() once this new context has been
319    * restored on CPU                              178    * restored on CPU
320    */                                             179    */
321                                                   180 
322   /* Compute the base address of the structure    181   /* Compute the base address of the structure, which must be located
323      below the previous elements */               182      below the previous elements */
324   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(s    183   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(struct sos_cpu_kstate);
325   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;      184   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;
326                                                   185 
327   /* Initialize the CPU context structure */      186   /* Initialize the CPU context structure */
328   memset(kctxt, 0x0, sizeof(struct sos_cpu_kst    187   memset(kctxt, 0x0, sizeof(struct sos_cpu_kstate));
329                                                   188 
330   /* Tell the CPU context structure that the f    189   /* Tell the CPU context structure that the first instruction to
331      execute will be that of the core_routine(    190      execute will be that of the core_routine() function */
332   kctxt->regs.eip = (sos_ui32_t)core_routine;     191   kctxt->regs.eip = (sos_ui32_t)core_routine;
333                                                   192 
334   /* Setup the segment registers */               193   /* Setup the segment registers */
335   kctxt->regs.cs                                  194   kctxt->regs.cs
336     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    195     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE); /* Code */
337   kctxt->regs.ds                                  196   kctxt->regs.ds
338     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    197     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
339   kctxt->regs.es                                  198   kctxt->regs.es
340     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    199     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
341   kctxt->regs.cpl0_ss                             200   kctxt->regs.cpl0_ss
342     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO    201     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Stack */
343   /* fs and gs unused for the moment. */          202   /* fs and gs unused for the moment. */
344                                                   203 
345   /* The newly created context is initially in    204   /* The newly created context is initially interruptible */
346   kctxt->regs.eflags = (1 << 9); /* set IF bit    205   kctxt->regs.eflags = (1 << 9); /* set IF bit */
347                                                   206 
348   /* Finally, update the generic kernel/user t    207   /* Finally, update the generic kernel/user thread context */
349   *ctxt = (struct sos_cpu_state*) kctxt;          208   *ctxt = (struct sos_cpu_state*) kctxt;
350                                                   209 
351   return SOS_OK;                                  210   return SOS_OK;
352 }                                                 211 }
353                                                   212 
354                                                   213 
355 sos_ret_t sos_cpu_ustate_init(struct sos_cpu_s << 
356                               sos_uaddr_t  use << 
357                               sos_ui32_t   use << 
358                               sos_ui32_t   use << 
359                               sos_uaddr_t  use << 
360                               sos_vaddr_t  ker << 
361                               sos_size_t   ker << 
362 {                                              << 
363   /* We are initializing a User thread's conte << 
364   struct sos_cpu_ustate *uctxt;                << 
365                                                << 
366   /* This is a critical internal function, so  << 
367      the caller knows what he does: we legitim << 
368      for ctxt, etc. are allways VALID ! */     << 
369                                                << 
370   /* Compute the address of the CPU state to r << 
371      switching to this new user thread */      << 
372   sos_vaddr_t uctxt_vaddr = kernel_stack_botto << 
373                              + kernel_stack_si << 
374                              - sizeof(struct s << 
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_STAC << 
383   sos_cpu_state_prepare_detect_kernel_stack_ov << 
384                                                << 
385 #endif                                         << 
386                                                << 
387   /*                                           << 
388    * Setup the initial context structure, so t << 
389    * the initial registers' value for the user << 
390    * user thread argument is passed in the EAX << 
391    */                                          << 
392                                                << 
393   memset(uctxt, 0x0, sizeof(struct sos_cpu_ust << 
394                                                << 
395   /* Tell the CPU context structure that the f << 
396      execute will be located at user_start_PC  << 
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 no << 
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, SO << 
410   uctxt->regs.ds                               << 
411     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SO << 
412   uctxt->regs.es                               << 
413     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SO << 
414   uctxt->cpl3_ss                               << 
415     = SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, SO << 
416                                                << 
417   /* We need also to update the segment for th << 
418      segment. It will be used when this contex << 
419      CPU: initially it will be executing in ke << 
420      switch immediatly to user mode */         << 
421   uctxt->regs.cpl0_ss                          << 
422     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SO << 
423                                                << 
424   /* fs and gs unused for the moment. */       << 
425                                                << 
426   /* The newly created context is initially in << 
427   uctxt->regs.eflags = (1 << 9); /* set IF bit << 
428                                                << 
429   /* Finally, update the generic kernel/user t << 
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 s << 
438 {                                              << 
439   /* An interrupted user thread has its CS reg << 
440      User code segment */                      << 
441   switch (GET_CPU_CS_REGISTER_VALUE(ctxt->cs)) << 
442     {                                          << 
443     case SOS_BUILD_SEGMENT_REG_VALUE(3, FALSE, << 
444       return TRUE;                             << 
445       break;                                   << 
446                                                << 
447     case SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, << 
448       return FALSE;                            << 
449       break;                                   << 
450                                                << 
451     default:                                   << 
452       SOS_FATAL_ERROR("Invalid saved context C << 
453                       (unsigned) GET_CPU_CS_RE << 
454                       SOS_BUILD_SEGMENT_REG_VA << 
455                       SOS_BUILD_SEGMENT_REG_VA << 
456       break;                                   << 
457     }                                          << 
458                                                << 
459   /* Should never get here */                  << 
460   return -SOS_EFATAL;                          << 
461 }                                              << 
462                                                << 
463                                                << 
464 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_    214 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
465 void                                              215 void
466 sos_cpu_state_prepare_detect_kernel_stack_over    216 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
467                                                   217                                                    sos_vaddr_t stack_bottom,
468                                                   218                                                    sos_size_t stack_size)
469 {                                                 219 {
470   sos_size_t poison_size = SOS_CPU_STATE_DETEC    220   sos_size_t poison_size = SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
471   if (poison_size > stack_size)                   221   if (poison_size > stack_size)
472     poison_size = stack_size;                     222     poison_size = stack_size;
473                                                   223 
474   memset((void*)stack_bottom, SOS_CPU_STATE_ST    224   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, poison_size);
475 }                                                 225 }
476                                                   226 
477                                                   227 
478 void                                              228 void
479 sos_cpu_state_detect_kernel_stack_overflow(con    229 sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
480                                            sos    230                                            sos_vaddr_t stack_bottom,
481                                            sos    231                                            sos_size_t stack_size)
482 {                                                 232 {
483   unsigned char *c;                               233   unsigned char *c;
484   int i;                                          234   int i;
485                                                   235 
486   /* On SOS, "ctxt" corresponds to the address    236   /* On SOS, "ctxt" corresponds to the address of the esp register of
487      the saved context in Kernel mode (always,    237      the saved context in Kernel mode (always, even for the interrupted
488      context of a user thread). Here we make s    238      context of a user thread). Here we make sure that this stack
489      pointer is within the allowed stack area     239      pointer is within the allowed stack area */
490   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stac    240   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stack_bottom);
491   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeo    241   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeof(struct sos_cpu_kstate)
492                    <= stack_bottom + stack_siz    242                    <= stack_bottom + stack_size);
493                                                   243 
494   /* Check that the bottom of the stack has no    244   /* Check that the bottom of the stack has not been altered */
495   for (c = (unsigned char*) stack_bottom, i =     245   for (c = (unsigned char*) stack_bottom, i = 0 ;
496        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_    246        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size) ;
497        c++, i++)                                  247        c++, i++)
498     {                                             248     {
499       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POI    249       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POISON == *c);
500     }                                             250     }
501 }                                                 251 }
502 #endif                                            252 #endif
503                                                   253 
504                                                   254 
505 /* ===========================================    255 /* =======================================================================
506  * Public Accessor functions                      256  * Public Accessor functions
507  */                                               257  */
508                                                   258 
509                                                   259 
510 sos_vaddr_t sos_cpu_context_get_PC(const struc    260 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt)
511 {                                                 261 {
512   SOS_ASSERT_FATAL(NULL != ctxt);                 262   SOS_ASSERT_FATAL(NULL != ctxt);
513                                                   263 
514   /* This is the PC of the interrupted context    264   /* This is the PC of the interrupted context (ie kernel or user
515      context). */                                 265      context). */
516   return ctxt->eip;                               266   return ctxt->eip;
517 }                                                 267 }
518                                                   268 
519                                                   269 
520 sos_vaddr_t sos_cpu_context_get_SP(const struc    270 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt)
521 {                                                 271 {
522   SOS_ASSERT_FATAL(NULL != ctxt);                 272   SOS_ASSERT_FATAL(NULL != ctxt);
523                                                   273 
524   /* 'ctxt' corresponds to the SP of the inter << 
525      mode. We have to test whether the origina << 
526      was that of a kernel or user thread */    << 
527   if (TRUE == sos_cpu_context_is_in_user_mode( << 
528     {                                          << 
529       struct sos_cpu_ustate * uctxt = (struct  << 
530       return uctxt->cpl3_esp;                  << 
531     }                                          << 
532                                                << 
533   /* On SOS, "ctxt" corresponds to the address    274   /* On SOS, "ctxt" corresponds to the address of the esp register of
534      the saved context in Kernel mode (always,    275      the saved context in Kernel mode (always, even for the interrupted
535      context of a user thread). */                276      context of a user thread). */
536   return (sos_vaddr_t)ctxt;                       277   return (sos_vaddr_t)ctxt;
537 }                                                 278 }
538                                                   279 
539                                                   280 
540 sos_ret_t                                      << 
541 sos_cpu_context_set_EX_return_address(struct s << 
542                                       sos_vadd << 
543 {                                              << 
544   ctxt->eip = ret_vaddr;                       << 
545   return SOS_OK;                               << 
546 }                                              << 
547                                                << 
548                                                << 
549 void sos_cpu_context_dump(const struct sos_cpu    281 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt)
550 {                                                 282 {
551   char buf[128];                                  283   char buf[128];
552                                                << 
553   snprintf(buf, sizeof(buf),                      284   snprintf(buf, sizeof(buf),
554            "CPU: eip=%x esp0=%x eflags=%x cs=% !! 285            "CPU: eip=%x esp=%x eflags=%x cs=%x ds=%x ss=%x err=%x",
555            (unsigned)ctxt->eip, (unsigned)ctxt    286            (unsigned)ctxt->eip, (unsigned)ctxt, (unsigned)ctxt->eflags,
556            (unsigned)GET_CPU_CS_REGISTER_VALUE    287            (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs), (unsigned)ctxt->ds,
557            (unsigned)ctxt->cpl0_ss,               288            (unsigned)ctxt->cpl0_ss,
558            (unsigned)ctxt->error_code);           289            (unsigned)ctxt->error_code);
559   if (TRUE == sos_cpu_context_is_in_user_mode( << 
560     {                                          << 
561       struct sos_cpu_ustate * uctxt = (struct  << 
562       snprintf(buf, sizeof(buf),               << 
563                "%s esp3=%x ss3=%x",            << 
564                buf, (unsigned)uctxt->cpl3_esp, << 
565     }                                          << 
566   else                                         << 
567     snprintf(buf, sizeof(buf), "%s [KERNEL MOD << 
568                                                << 
569   sos_bochs_putstring(buf); sos_bochs_putstrin    290   sos_bochs_putstring(buf); sos_bochs_putstring("\n");
570   sos_x86_videomem_putstring(23, 0,               291   sos_x86_videomem_putstring(23, 0,
571                              SOS_X86_VIDEO_FG_ !! 292                           SOS_X86_VIDEO_FG_BLACK | SOS_X86_VIDEO_BG_LTGRAY,
572                              buf);             !! 293                           buf);
573 }                                                 294 }
574                                                   295 
575                                                   296 
576 /* ===========================================    297 /* =======================================================================
577  * Public Accessor functions TO BE USED ONLY B    298  * Public Accessor functions TO BE USED ONLY BY Exception handlers
578  */                                               299  */
579                                                   300 
580                                                   301 
581 sos_ui32_t sos_cpu_context_get_EX_info(const s    302 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt)
582 {                                                 303 {
583   SOS_ASSERT_FATAL(NULL != ctxt);                 304   SOS_ASSERT_FATAL(NULL != ctxt);
584   return ctxt->error_code;                        305   return ctxt->error_code;
585 }                                                 306 }
586                                                   307 
587                                                   308 
588 sos_vaddr_t                                       309 sos_vaddr_t
589 sos_cpu_context_get_EX_faulting_vaddr(const st    310 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt)
590 {                                                 311 {
591   sos_ui32_t cr2;                                 312   sos_ui32_t cr2;
592                                                   313 
593   /*                                              314   /*
594    * See Intel Vol 3 (section 5.14): the addre    315    * See Intel Vol 3 (section 5.14): the address of the faulting
595    * virtual address of a page fault is stored    316    * virtual address of a page fault is stored in the cr2
596    * register.                                    317    * register.
597    *                                              318    *
598    * Actually, we do not store the cr2 registe    319    * Actually, we do not store the cr2 register in a saved
599    * kernel thread's context. So we retrieve t    320    * kernel thread's context. So we retrieve the cr2's value directly
600    * from the processor. The value we retrieve    321    * from the processor. The value we retrieve in an exception handler
601    * is actually the correct one because an ex    322    * is actually the correct one because an exception is synchronous
602    * with the code causing the fault, and cann    323    * with the code causing the fault, and cannot be interrupted since
603    * the IDT entries in SOS are "interrupt gat    324    * the IDT entries in SOS are "interrupt gates" (ie IRQ are
604    * disabled).                                   325    * disabled).
605    */                                             326    */
606   asm volatile ("movl %%cr2, %0"                  327   asm volatile ("movl %%cr2, %0"
607                 :"=r"(cr2)                        328                 :"=r"(cr2)
608                 : );                              329                 : );
609                                                   330 
610   return cr2;                                     331   return cr2;
611 }                                                 332 }
612                                                   333 
613                                                   334 
614 /* ===========================================    335 /* =======================================================================
615  * Public Accessor functions TO BE USED ONLY B << 
616  */                                            << 
617                                                << 
618                                                << 
619 /*                                             << 
620  * By convention, the USER SOS programs always << 
621  * kernel syscall handler: in eax/../edx. For  << 
622  * unused registers are filled with 0s. For mo << 
623  * syscall parameter gives the address of the  << 
624  * remaining arguments. In any case, eax corre << 
625  * IDentifier.                                 << 
626  */                                            << 
627                                                << 
628                                                << 
629 inline                                         << 
630 sos_ret_t sos_syscall_get3args(const struct so << 
631                                /* out */unsign << 
632                                /* out */unsign << 
633                                /* out */unsign << 
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 << 
643                               /* out */unsigne << 
644 {                                              << 
645   unsigned int unused;                         << 
646   return sos_syscall_get3args(user_ctxt, arg1, << 
647 }                                              << 
648                                                << 
649                                                << 
650 sos_ret_t sos_syscall_get2args(const struct so << 
651                                /* out */unsign << 
652                                /* out */unsign << 
653 {                                              << 
654   unsigned int unused;                         << 
655   return sos_syscall_get3args(user_ctxt, arg1, << 
656 }                                              << 
657                                                << 
658                                                << 
659 /*                                             << 
660  * sos_syscall_get3args() is defined in cpu_co << 
661  * to know the structure of a struct spu_state << 
662  */                                            << 
663                                                << 
664 sos_ret_t sos_syscall_get4args(const struct so << 
665                                /* out */unsign << 
666                                /* out */unsign << 
667                                /* out */unsign << 
668                                /* out */unsign << 
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 << 
675      remaining arguments */                    << 
676   retval = sos_syscall_get3args(user_ctxt, arg << 
677                                 (unsigned int  << 
678   if (SOS_OK != retval)                        << 
679     return retval;                             << 
680                                                << 
681   /* Copy the array containing the remaining a << 
682      space */                                  << 
683   retval = sos_memcpy_from_user((sos_vaddr_t)o << 
684                                 (sos_uaddr_t)u << 
685                                 sizeof(other_a << 
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 so << 
696                                /* out */unsign << 
697                                /* out */unsign << 
698                                /* out */unsign << 
699                                /* out */unsign << 
700                                /* out */unsign << 
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 << 
707      remaining arguments */                    << 
708   retval = sos_syscall_get3args(user_ctxt, arg << 
709                                 (unsigned int  << 
710   if (SOS_OK != retval)                        << 
711     return retval;                             << 
712                                                << 
713   /* Copy the array containing the remaining a << 
714      space */                                  << 
715   retval = sos_memcpy_from_user((sos_vaddr_t)o << 
716                                 (sos_uaddr_t)u << 
717                                 sizeof(other_a << 
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 so << 
729                                /* out */unsign << 
730                                /* out */unsign << 
731                                /* out */unsign << 
732                                /* out */unsign << 
733                                /* out */unsign << 
734                                /* out */unsign << 
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 << 
741      remaining arguments */                    << 
742   retval = sos_syscall_get3args(user_ctxt, arg << 
743                                 (unsigned int  << 
744   if (SOS_OK != retval)                        << 
745     return retval;                             << 
746                                                << 
747   /* Copy the array containing the remaining a << 
748      space */                                  << 
749   retval = sos_memcpy_from_user((sos_vaddr_t)o << 
750                                 (sos_uaddr_t)u << 
751                                 sizeof(other_a << 
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 so << 
764                                /* out */unsign << 
765                                /* out */unsign << 
766                                /* out */unsign << 
767                                /* out */unsign << 
768                                /* out */unsign << 
769                                /* out */unsign << 
770                                /* out */unsign << 
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 << 
777      remaining arguments */                    << 
778   retval = sos_syscall_get3args(user_ctxt, arg << 
779                                 (unsigned int  << 
780   if (SOS_OK != retval)                        << 
781     return retval;                             << 
782                                                << 
783   /* Copy the array containing the remaining a << 
784      space */                                  << 
785   retval = sos_memcpy_from_user((sos_vaddr_t)o << 
786                                 (sos_uaddr_t)u << 
787                                 sizeof(other_a << 
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 so << 
801                                /* out */unsign << 
802                                /* out */unsign << 
803                                /* out */unsign << 
804                                /* out */unsign << 
805                                /* out */unsign << 
806                                /* out */unsign << 
807                                /* out */unsign << 
808                                /* out */unsign << 
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 << 
815      remaining arguments */                    << 
816   retval = sos_syscall_get3args(user_ctxt, arg << 
817                                 (unsigned int  << 
818   if (SOS_OK != retval)                        << 
819     return retval;                             << 
820                                                << 
821   /* Copy the array containing the remaining a << 
822      space */                                  << 
823   retval = sos_memcpy_from_user((sos_vaddr_t)o << 
824                                 (sos_uaddr_t)u << 
825                                 sizeof(other_a << 
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 /* =========================================== << 
840  * Backtrace facility. To be used for DEBUGgin    336  * Backtrace facility. To be used for DEBUGging purpose ONLY.
841  */                                               337  */
842                                                   338 
843                                                   339 
844 sos_ui32_t sos_backtrace(const struct sos_cpu_    340 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state,
845                          sos_ui32_t max_depth,    341                          sos_ui32_t max_depth,
846                          sos_vaddr_t stack_bot    342                          sos_vaddr_t stack_bottom,
847                          sos_size_t stack_size    343                          sos_size_t stack_size,
848                          sos_backtrace_callbac    344                          sos_backtrace_callback_t * backtracer,
849                          void *custom_arg)        345                          void *custom_arg)
850 {                                                 346 {
851   int depth;                                      347   int depth;
852   sos_vaddr_t callee_PC, caller_frame;            348   sos_vaddr_t callee_PC, caller_frame;
853                                                   349 
854   /* Cannot backtrace an interrupted user thre << 
855   if ((NULL != cpu_state)                      << 
856       &&                                       << 
857       (TRUE == sos_cpu_context_is_in_user_mode << 
858     {                                          << 
859       return 0;                                << 
860     }                                          << 
861                                                << 
862   /*                                              350   /*
863    * Layout of a frame on the x86 (compiler=gc    351    * Layout of a frame on the x86 (compiler=gcc):
864    *                                              352    *
865    * funcA calls funcB calls funcC                353    * funcA calls funcB calls funcC
866    *                                              354    *
867    *         ....                                 355    *         ....
868    *         funcB Argument 2                     356    *         funcB Argument 2
869    *         funcB Argument 1                     357    *         funcB Argument 1
870    *         funcA Return eip                     358    *         funcA Return eip
871    * frameB: funcA ebp (ie previous stack fram    359    * frameB: funcA ebp (ie previous stack frame)
872    *         ....                                 360    *         ....
873    *         (funcB local variables)              361    *         (funcB local variables)
874    *         ....                                 362    *         ....
875    *         funcC Argument 2                     363    *         funcC Argument 2
876    *         funcC Argument 1                     364    *         funcC Argument 1
877    *         funcB Return eip                     365    *         funcB Return eip
878    * frameC: funcB ebp (ie previous stack fram    366    * frameC: funcB ebp (ie previous stack frame == A0) <---- a frame address
879    *         ....                                 367    *         ....
880    *         (funcC local variables)              368    *         (funcC local variables)
881    *         ....                                 369    *         ....
882    *                                              370    *
883    * The presence of "ebp" on the stack depend    371    * The presence of "ebp" on the stack depends on 2 things:
884    *   + the compiler is gcc                      372    *   + the compiler is gcc
885    *   + the source is compiled WITHOUT the -f    373    *   + the source is compiled WITHOUT the -fomit-frame-pointer option
886    * In the absence of "ebp", chances are high    374    * In the absence of "ebp", chances are high that the value pushed
887    * at that address is outside the stack boun    375    * at that address is outside the stack boundaries, meaning that the
888    * function will return -SOS_ENOSUP.            376    * function will return -SOS_ENOSUP.
889    */                                             377    */
890                                                   378 
891   if (cpu_state)                                  379   if (cpu_state)
892     {                                             380     {
893       callee_PC    = cpu_state->eip;              381       callee_PC    = cpu_state->eip;
894       caller_frame = cpu_state->ebp;              382       caller_frame = cpu_state->ebp;
895     }                                             383     }
896   else                                            384   else
897     {                                             385     {
898       /* Skip the sos_backtrace() frame */        386       /* Skip the sos_backtrace() frame */
899       callee_PC    = (sos_vaddr_t)__builtin_re    387       callee_PC    = (sos_vaddr_t)__builtin_return_address(0);
900       caller_frame = (sos_vaddr_t)__builtin_fr    388       caller_frame = (sos_vaddr_t)__builtin_frame_address(1);
901     }                                             389     }
902                                                   390 
903   for(depth=0 ; depth < max_depth ; depth ++)     391   for(depth=0 ; depth < max_depth ; depth ++)
904     {                                             392     {
905       /* Call the callback */                     393       /* Call the callback */
906       backtracer(callee_PC, caller_frame + 8,     394       backtracer(callee_PC, caller_frame + 8, depth, custom_arg);
907                                                   395 
908       /* If the frame address is funky, don't     396       /* If the frame address is funky, don't go further */
909       if ( (caller_frame < stack_bottom)          397       if ( (caller_frame < stack_bottom)
910            || (caller_frame + 4 >= stack_botto    398            || (caller_frame + 4 >= stack_bottom + stack_size) )
911         return depth;                             399         return depth;
912                                                   400 
913       /* Go to caller frame */                    401       /* Go to caller frame */
914       callee_PC    = *((sos_vaddr_t*) (caller_    402       callee_PC    = *((sos_vaddr_t*) (caller_frame + 4));
915       caller_frame = *((sos_vaddr_t*) caller_f    403       caller_frame = *((sos_vaddr_t*) caller_frame);
916     }                                             404     }
917                                                   405   
918   return depth;                                   406   return depth;
919 }                                              << 
920                                                << 
921                                                << 
922 /* ******************************************* << 
923  * Function to manage the TSS.  This function  << 
924  * it is reserved to the assembler routines de << 
925  * cpu_context_switch.S                        << 
926  *                                             << 
927  * Update the kernel stack address so that the << 
928  * exception return in a correct stack locatio << 
929  * kernel mode.                                << 
930  */                                            << 
931 void                                           << 
932 sos_cpu_context_update_kernel_tss(struct sos_c << 
933 {                                              << 
934   /* next_ctxt corresponds to an interrupted u << 
935   if (sos_cpu_context_is_in_user_mode(next_ctx << 
936     {                                          << 
937       /*                                       << 
938        * Yes: "next_ctxt" is an interrupted us << 
939        * going to switch to user mode ! Setup  << 
940        * that the user thread "next_ctxt" can  << 
941        * stack location when returning in kern << 
942        *                                       << 
943        * This stack location corresponds to th << 
944        * thread once its context has been tran << 
945        * once the CPU has executed all the pop << 
946        * context switch with privilege change. << 
947        */                                      << 
948       kernel_tss.esp0 = ((sos_vaddr_t)next_ctx << 
949                         + sizeof(struct sos_cp << 
950       /* Note: no need to protect this agains  << 
951          allowed to update it by themselves, a << 
952          to block */                           << 
953     }                                          << 
954   else                                         << 
955     {                                          << 
956       /* No: No need to update kernel TSS when << 
957          mode */                               << 
958     }                                          << 
959 }                                                 407 }
                                                      

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