SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

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

Diff markup

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


001 /* Copyright (C) 2000-2004, The KOS team       !! 001 /* Copyright (C) 2005  David Decotigny
002    Copyright (C) 1999  Free Software Foundatio !! 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                                                   026 
027 #include "cpu_context.h"                          027 #include "cpu_context.h"
028                                                   028 
029                                                   029 
030 /**                                               030 /**
031  * Here is the definition of a CPU context for    031  * Here is the definition of a CPU context for IA32 processors. This
032  * is a SOS convention, not a specification gi    032  * is a SOS convention, not a specification given by the IA32
033  * spec. However there is a strong constraint     033  * spec. However there is a strong constraint related to the x86
034  * interrupt handling specification: the top o    034  * interrupt handling specification: the top of the stack MUST be
035  * compatible with the 'iret' instruction, ie     035  * compatible with the 'iret' instruction, ie there must be the
036  * err_code (might be 0), eip, cs and eflags o    036  * err_code (might be 0), eip, cs and eflags of the destination
037  * context in that order (see Intel x86 specs     037  * context in that order (see Intel x86 specs vol 3, figure 5-4).
038  *                                                038  *
039  * @note IMPORTANT: This definition MUST be co    039  * @note IMPORTANT: This definition MUST be consistent with the way
040  * the registers are stored on the stack in       040  * the registers are stored on the stack in
041  * irq_wrappers.S/exception_wrappers.S !!! Hen    041  * irq_wrappers.S/exception_wrappers.S !!! Hence the constraint above.
042  */                                               042  */
043 struct sos_cpu_kstate {                        !! 043 struct sos_cpu_state {
044   /* (Lower addresses) */                         044   /* (Lower addresses) */
045                                                   045 
046   /* These are SOS convention */                  046   /* These are SOS convention */
047   sos_ui16_t  gs;                                 047   sos_ui16_t  gs;
048   sos_ui16_t  fs;                                 048   sos_ui16_t  fs;
049   sos_ui16_t  es;                                 049   sos_ui16_t  es;
050   sos_ui16_t  ds;                                 050   sos_ui16_t  ds;
051   sos_ui16_t  ss;                              !! 051   sos_ui16_t  cpl0_ss; /* This is ALWAYS the Stack Segment of the
                                                   >> 052                           Kernel context (CPL0) of the interrupted
                                                   >> 053                           thread, even for a user thread */
052   sos_ui16_t  alignment_padding; /* unused */     054   sos_ui16_t  alignment_padding; /* unused */
053   sos_ui32_t  eax;                                055   sos_ui32_t  eax;
054   sos_ui32_t  ebx;                                056   sos_ui32_t  ebx;
055   sos_ui32_t  ecx;                                057   sos_ui32_t  ecx;
056   sos_ui32_t  edx;                                058   sos_ui32_t  edx;
057   sos_ui32_t  esi;                                059   sos_ui32_t  esi;
058   sos_ui32_t  edi;                                060   sos_ui32_t  edi;
059   sos_ui32_t  ebp;                                061   sos_ui32_t  ebp;
060                                                   062 
061   /* MUST NEVER CHANGE (dependent on the IA32     063   /* MUST NEVER CHANGE (dependent on the IA32 iret instruction) */
062   sos_ui32_t  error_code;                         064   sos_ui32_t  error_code;
063   sos_vaddr_t eip;                                065   sos_vaddr_t eip;
064   sos_ui32_t  cs;                              !! 066   sos_ui32_t  cs; /* 32bits according to the specs ! However, the CS
                                                   >> 067                      register is really 16bits long */
065   sos_ui32_t  eflags;                             068   sos_ui32_t  eflags;
066                                                   069 
067   /* (Higher addresses) */                        070   /* (Higher addresses) */
068 } __attribute__((packed));                        071 } __attribute__((packed));
069                                                   072 
070                                                   073 
                                                   >> 074 /**
                                                   >> 075  * The CS value pushed on the stack by the CPU upon interrupt, and
                                                   >> 076  * needed by the iret instruction, is 32bits long while the real CPU
                                                   >> 077  * CS register is 16bits only: this macro simply retrieves the CPU
                                                   >> 078  * "CS" register value from the CS value pushed on the stack by the
                                                   >> 079  * CPU upon interrupt.
                                                   >> 080  *
                                                   >> 081  * The remaining 16bits pushed by the CPU should be considered
                                                   >> 082  * "reserved" and architecture dependent. IMHO, the specs don't say
                                                   >> 083  * anything about them. Considering that some architectures generate
                                                   >> 084  * non-zero values for these 16bits (at least Cyrix), we'd better
                                                   >> 085  * ignore them.
                                                   >> 086  */
                                                   >> 087 #define GET_CPU_CS_REGISTER_VALUE(pushed_ui32_cs_value) \
                                                   >> 088   ( (pushed_ui32_cs_value) & 0xffff )
                                                   >> 089 
                                                   >> 090 
                                                   >> 091 /**
                                                   >> 092  * Structure of an interrupted Kernel thread's context
                                                   >> 093  */
                                                   >> 094 struct sos_cpu_kstate
                                                   >> 095 {
                                                   >> 096   struct sos_cpu_state regs;
                                                   >> 097 } __attribute__((packed));
                                                   >> 098 
                                                   >> 099 
                                                   >> 100 /**
                                                   >> 101  * THE main operation of a kernel thread. This routine calls the
                                                   >> 102  * kernel thread function start_func and calls exit_func when
                                                   >> 103  * start_func returns.
                                                   >> 104  */
071 static void core_routine (sos_cpu_kstate_funct    105 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
072                           sos_ui32_t start_arg    106                           sos_ui32_t start_arg,
073                           sos_cpu_kstate_funct    107                           sos_cpu_kstate_function_arg1_t *exit_func,
074                           sos_ui32_t exit_arg)    108                           sos_ui32_t exit_arg)
075      __attribute__((noreturn));                   109      __attribute__((noreturn));
076                                                   110 
077 static void core_routine (sos_cpu_kstate_funct    111 static void core_routine (sos_cpu_kstate_function_arg1_t *start_func,
078                           sos_ui32_t start_arg    112                           sos_ui32_t start_arg,
079                           sos_cpu_kstate_funct    113                           sos_cpu_kstate_function_arg1_t *exit_func,
080                           sos_ui32_t exit_arg)    114                           sos_ui32_t exit_arg)
081 {                                                 115 {
082   start_func(start_arg);                          116   start_func(start_arg);
083   exit_func(exit_arg);                            117   exit_func(exit_arg);
084                                                   118 
085   SOS_ASSERT_FATAL(! "The exit function of the    119   SOS_ASSERT_FATAL(! "The exit function of the thread should NOT return !");
086   for(;;);                                        120   for(;;);
087 }                                                 121 }
088                                                   122 
089                                                   123 
090 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_k !! 124 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **ctxt,
091                               sos_cpu_kstate_f    125                               sos_cpu_kstate_function_arg1_t *start_func,
092                               sos_ui32_t  star    126                               sos_ui32_t  start_arg,
093                               sos_vaddr_t stac    127                               sos_vaddr_t stack_bottom,
094                               sos_size_t  stac    128                               sos_size_t  stack_size,
095                               sos_cpu_kstate_f    129                               sos_cpu_kstate_function_arg1_t *exit_func,
096                               sos_ui32_t  exit    130                               sos_ui32_t  exit_arg)
097 {                                                 131 {
                                                   >> 132   /* We are initializing a Kernel thread's context */
                                                   >> 133   struct sos_cpu_kstate *kctxt;
                                                   >> 134 
098   /* This is a critical internal function, so     135   /* This is a critical internal function, so that it is assumed that
099      the caller knows what he does: we legitim    136      the caller knows what he does: we legitimally assume that values
100      for ctxt, start_func, stack_* and exit_fu    137      for ctxt, start_func, stack_* and exit_func are allways VALID ! */
101                                                   138 
102   /* Setup the stack.                             139   /* Setup the stack.
103    *                                              140    *
104    * On x86, the stack goes downward. Each fra    141    * On x86, the stack goes downward. Each frame is configured this
105    * way (higher addresses first):                142    * way (higher addresses first):
106    *                                              143    *
107    *  - (optional unused space. As of gcc 3.3,    144    *  - (optional unused space. As of gcc 3.3, this space is 24 bytes)
108    *  - arg n                                     145    *  - arg n
109    *  - arg n-1                                   146    *  - arg n-1
110    *  - ...                                       147    *  - ...
111    *  - arg 1                                     148    *  - arg 1
112    *  - return instruction address: The addres    149    *  - return instruction address: The address the function returns to
113    *    once finished                             150    *    once finished
114    *  - local variables                           151    *  - local variables
115    *                                              152    *
116    * The remaining of the code should be read     153    * The remaining of the code should be read from the end upward to
117    * understand how the processor will handle     154    * understand how the processor will handle it.
118    */                                             155    */
119                                                   156 
120   sos_vaddr_t tmp_vaddr = stack_bottom + stack    157   sos_vaddr_t tmp_vaddr = stack_bottom + stack_size;
121   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;     158   sos_ui32_t *stack = (sos_ui32_t*)tmp_vaddr;
122                                                   159 
123   /* If needed, poison the stack */               160   /* If needed, poison the stack */
124 #ifdef SOS_CPU_KSTATE_DETECT_UNINIT_VARS       !! 161 #ifdef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
125   memset((void*)stack_bottom, SOS_CPU_KSTATE_S !! 162   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, stack_size);
126 #elif defined(SOS_CPU_KSTATE_DETECT_STACK_OVER !! 163 #elif defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
127   sos_cpu_kstate_prepare_detect_stack_overflow !! 164   sos_cpu_state_prepare_detect_kernel_stack_overflow(stack_bottom, stack_size);
128 #endif                                            165 #endif
129                                                   166 
130   /* Simulate a call to the core_routine() fun    167   /* Simulate a call to the core_routine() function: prepare its
131      arguments */                                 168      arguments */
132   *(--stack) = exit_arg;                          169   *(--stack) = exit_arg;
133   *(--stack) = (sos_ui32_t)exit_func;             170   *(--stack) = (sos_ui32_t)exit_func;
134   *(--stack) = start_arg;                         171   *(--stack) = start_arg;
135   *(--stack) = (sos_ui32_t)start_func;            172   *(--stack) = (sos_ui32_t)start_func;
136   *(--stack) = 0; /* Return address of core_ro    173   *(--stack) = 0; /* Return address of core_routine => force page fault */
137                                                   174 
138   /*                                              175   /*
139    * Setup the initial context structure, so t    176    * Setup the initial context structure, so that the CPU will execute
140    * the function core_routine() once this new    177    * the function core_routine() once this new context has been
141    * restored on CPU                              178    * restored on CPU
142    */                                             179    */
143                                                   180 
144   /* Compute the base address of the structure    181   /* Compute the base address of the structure, which must be located
145      below the previous elements */               182      below the previous elements */
146   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(s    183   tmp_vaddr  = ((sos_vaddr_t)stack) - sizeof(struct sos_cpu_kstate);
147   *ctxt = (struct sos_cpu_kstate*)tmp_vaddr;   !! 184   kctxt = (struct sos_cpu_kstate*)tmp_vaddr;
148                                                   185 
149   /* Initialize the CPU context structure */      186   /* Initialize the CPU context structure */
150   memset(*ctxt, 0x0, sizeof(struct sos_cpu_kst !! 187   memset(kctxt, 0x0, sizeof(struct sos_cpu_kstate));
151                                                   188 
152   /* Tell the CPU context structure that the f    189   /* Tell the CPU context structure that the first instruction to
153      execute will be that of the core_routine(    190      execute will be that of the core_routine() function */
154   (*ctxt)->eip = (sos_ui32_t)core_routine;     !! 191   kctxt->regs.eip = (sos_ui32_t)core_routine;
155                                                   192 
156   /* Setup the segment registers */               193   /* Setup the segment registers */
157   (*ctxt)->cs  = SOS_BUILD_SEGMENT_REG_VALUE(0 !! 194   kctxt->regs.cs
158   (*ctxt)->ds  = SOS_BUILD_SEGMENT_REG_VALUE(0 !! 195     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KCODE); /* Code */
159   (*ctxt)->es  = SOS_BUILD_SEGMENT_REG_VALUE(0 !! 196   kctxt->regs.ds
160   (*ctxt)->ss  = SOS_BUILD_SEGMENT_REG_VALUE(0 !! 197     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
                                                   >> 198   kctxt->regs.es
                                                   >> 199     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Data */
                                                   >> 200   kctxt->regs.cpl0_ss
                                                   >> 201     = SOS_BUILD_SEGMENT_REG_VALUE(0, FALSE, SOS_SEG_KDATA); /* Stack */
161   /* fs and gs unused for the moment. */          202   /* fs and gs unused for the moment. */
162                                                   203 
163   /* The newly created context is initially in    204   /* The newly created context is initially interruptible */
164   (*ctxt)->eflags = (1 << 9); /* set IF bit */ !! 205   kctxt->regs.eflags = (1 << 9); /* set IF bit */
                                                   >> 206 
                                                   >> 207   /* Finally, update the generic kernel/user thread context */
                                                   >> 208   *ctxt = (struct sos_cpu_state*) kctxt;
165                                                   209 
166   return SOS_OK;                                  210   return SOS_OK;
167 }                                                 211 }
168                                                   212 
169                                                   213 
170 #if defined(SOS_CPU_KSTATE_DETECT_STACK_OVERFL !! 214 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
171 void                                              215 void
172 sos_cpu_kstate_prepare_detect_stack_overflow(c !! 216 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
173                                              s !! 217                                                    sos_vaddr_t stack_bottom,
174                                              s !! 218                                                    sos_size_t stack_size)
175 {                                                 219 {
176   sos_size_t poison_size = SOS_CPU_KSTATE_DETE !! 220   sos_size_t poison_size = SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW;
177   if (poison_size > stack_size)                   221   if (poison_size > stack_size)
178     poison_size = stack_size;                     222     poison_size = stack_size;
179                                                   223 
180   memset((void*)stack_bottom, SOS_CPU_KSTATE_S !! 224   memset((void*)stack_bottom, SOS_CPU_STATE_STACK_POISON, poison_size);
181 }                                                 225 }
182                                                   226 
183                                                   227 
184 void                                              228 void
185 sos_cpu_kstate_detect_stack_overflow(const str !! 229 sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
186                                      sos_vaddr !! 230                                            sos_vaddr_t stack_bottom,
187                                      sos_size_ !! 231                                            sos_size_t stack_size)
188 {                                                 232 {
189   unsigned char *c;                               233   unsigned char *c;
190   int i;                                          234   int i;
191                                                   235 
                                                   >> 236   /* On SOS, "ctxt" corresponds to the address of the esp register of
                                                   >> 237      the saved context in Kernel mode (always, even for the interrupted
                                                   >> 238      context of a user thread). Here we make sure that this stack
                                                   >> 239      pointer is within the allowed stack area */
192   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stac    240   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) >= stack_bottom);
193   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeo    241   SOS_ASSERT_FATAL(((sos_vaddr_t)ctxt) + sizeof(struct sos_cpu_kstate)
194                    <= stack_bottom + stack_siz    242                    <= stack_bottom + stack_size);
                                                   >> 243 
                                                   >> 244   /* Check that the bottom of the stack has not been altered */
195   for (c = (unsigned char*) stack_bottom, i =     245   for (c = (unsigned char*) stack_bottom, i = 0 ;
196        (i < SOS_CPU_KSTATE_DETECT_STACK_OVERFL !! 246        (i < SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) && (i < stack_size) ;
197        c++, i++)                                  247        c++, i++)
198     {                                             248     {
199       SOS_ASSERT_FATAL(SOS_CPU_KSTATE_STACK_PO !! 249       SOS_ASSERT_FATAL(SOS_CPU_STATE_STACK_POISON == *c);
200     }                                             250     }
201 }                                                 251 }
202 #endif                                            252 #endif
203                                                   253 
204                                                   254 
205 sos_vaddr_t sos_cpu_kstate_get_PC(const struct !! 255 /* =======================================================================
                                                   >> 256  * Public Accessor functions
                                                   >> 257  */
                                                   >> 258 
                                                   >> 259 
                                                   >> 260 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt)
206 {                                                 261 {
207   SOS_ASSERT_FATAL(NULL != ctxt);                 262   SOS_ASSERT_FATAL(NULL != ctxt);
                                                   >> 263 
                                                   >> 264   /* This is the PC of the interrupted context (ie kernel or user
                                                   >> 265      context). */
208   return ctxt->eip;                               266   return ctxt->eip;
209 }                                                 267 }
210                                                   268 
211                                                   269 
212 sos_vaddr_t sos_cpu_kstate_get_SP(const struct !! 270 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt)
213 {                                                 271 {
214   SOS_ASSERT_FATAL(NULL != ctxt);                 272   SOS_ASSERT_FATAL(NULL != ctxt);
                                                   >> 273 
                                                   >> 274   /* On SOS, "ctxt" corresponds to the address of the esp register of
                                                   >> 275      the saved context in Kernel mode (always, even for the interrupted
                                                   >> 276      context of a user thread). */
215   return (sos_vaddr_t)ctxt;                       277   return (sos_vaddr_t)ctxt;
216 }                                                 278 }
217                                                   279 
218                                                   280 
219 void sos_cpu_kstate_dump(const struct sos_cpu_ !! 281 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt)
220 {                                                 282 {
221   char buf[128];                                  283   char buf[128];
222   snprintf(buf, sizeof(buf),                      284   snprintf(buf, sizeof(buf),
223            "CPU: eip=%x esp=%x eflags=%x cs=%x    285            "CPU: eip=%x esp=%x eflags=%x cs=%x ds=%x ss=%x err=%x",
224            (unsigned)ctxt->eip, (unsigned)ctxt    286            (unsigned)ctxt->eip, (unsigned)ctxt, (unsigned)ctxt->eflags,
225            (unsigned)ctxt->cs, (unsigned)ctxt- !! 287            (unsigned)GET_CPU_CS_REGISTER_VALUE(ctxt->cs), (unsigned)ctxt->ds,
                                                   >> 288            (unsigned)ctxt->cpl0_ss,
226            (unsigned)ctxt->error_code);           289            (unsigned)ctxt->error_code);
227   sos_bochs_putstring(buf); sos_bochs_putstrin    290   sos_bochs_putstring(buf); sos_bochs_putstring("\n");
228   sos_x86_videomem_putstring(23, 0,               291   sos_x86_videomem_putstring(23, 0,
229                           SOS_X86_VIDEO_FG_BLA    292                           SOS_X86_VIDEO_FG_BLACK | SOS_X86_VIDEO_BG_LTGRAY,
230                           buf);                   293                           buf);
231 }                                                 294 }
232                                                   295 
233                                                   296 
234 sos_ui32_t sos_cpu_kstate_get_EX_info(const st !! 297 /* =======================================================================
                                                   >> 298  * Public Accessor functions TO BE USED ONLY BY Exception handlers
                                                   >> 299  */
                                                   >> 300 
                                                   >> 301 
                                                   >> 302 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt)
235 {                                                 303 {
236   SOS_ASSERT_FATAL(NULL != ctxt);                 304   SOS_ASSERT_FATAL(NULL != ctxt);
237   return ctxt->error_code;                        305   return ctxt->error_code;
238 }                                                 306 }
239                                                   307 
240                                                   308 
241 sos_vaddr_t                                       309 sos_vaddr_t
242 sos_cpu_kstate_get_EX_faulting_vaddr(const str !! 310 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt)
243 {                                                 311 {
244   sos_ui32_t cr2;                                 312   sos_ui32_t cr2;
245                                                   313 
246   /* See Intel Vol 3 (section 5.14): the addre !! 314   /*
247      virtual address of a page fault is stored !! 315    * See Intel Vol 3 (section 5.14): the address of the faulting
                                                   >> 316    * virtual address of a page fault is stored in the cr2
                                                   >> 317    * register.
                                                   >> 318    *
                                                   >> 319    * Actually, we do not store the cr2 register in a saved
                                                   >> 320    * kernel thread's context. So we retrieve the cr2's value directly
                                                   >> 321    * from the processor. The value we retrieve in an exception handler
                                                   >> 322    * is actually the correct one because an exception is synchronous
                                                   >> 323    * with the code causing the fault, and cannot be interrupted since
                                                   >> 324    * the IDT entries in SOS are "interrupt gates" (ie IRQ are
                                                   >> 325    * disabled).
                                                   >> 326    */
248   asm volatile ("movl %%cr2, %0"                  327   asm volatile ("movl %%cr2, %0"
249                 :"=r"(cr2)                        328                 :"=r"(cr2)
250                 : );                              329                 : );
251                                                   330 
252   return cr2;                                     331   return cr2;
253 }                                                 332 }
254                                                   333 
255                                                   334 
256 sos_ui32_t sos_backtrace(const struct sos_cpu_ !! 335 /* =======================================================================
                                                   >> 336  * Backtrace facility. To be used for DEBUGging purpose ONLY.
                                                   >> 337  */
                                                   >> 338 
                                                   >> 339 
                                                   >> 340 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state,
257                          sos_ui32_t max_depth,    341                          sos_ui32_t max_depth,
258                          sos_vaddr_t stack_bot    342                          sos_vaddr_t stack_bottom,
259                          sos_size_t stack_size    343                          sos_size_t stack_size,
260                          sos_backtrace_callbac    344                          sos_backtrace_callback_t * backtracer,
261                          void *custom_arg)        345                          void *custom_arg)
262 {                                                 346 {
263   int depth;                                      347   int depth;
264   sos_vaddr_t callee_PC, caller_frame;            348   sos_vaddr_t callee_PC, caller_frame;
265                                                   349 
266   /*                                              350   /*
267    * Layout of a frame on the x86 (compiler=gc    351    * Layout of a frame on the x86 (compiler=gcc):
268    *                                              352    *
269    * funcA calls funcB calls funcC                353    * funcA calls funcB calls funcC
270    *                                              354    *
271    *         ....                                 355    *         ....
272    *         funcB Argument 2                     356    *         funcB Argument 2
273    *         funcB Argument 1                     357    *         funcB Argument 1
274    *         funcA Return eip                     358    *         funcA Return eip
275    * frameB: funcA ebp (ie previous stack fram    359    * frameB: funcA ebp (ie previous stack frame)
276    *         ....                                 360    *         ....
277    *         (funcB local variables)              361    *         (funcB local variables)
278    *         ....                                 362    *         ....
279    *         funcC Argument 2                     363    *         funcC Argument 2
280    *         funcC Argument 1                     364    *         funcC Argument 1
281    *         funcB Return eip                     365    *         funcB Return eip
282    * frameC: funcB ebp (ie previous stack fram    366    * frameC: funcB ebp (ie previous stack frame == A0) <---- a frame address
283    *         ....                                 367    *         ....
284    *         (funcC local variables)              368    *         (funcC local variables)
285    *         ....                                 369    *         ....
286    *                                              370    *
287    * The presence of "ebp" on the stack depend    371    * The presence of "ebp" on the stack depends on 2 things:
288    *   + the compiler is gcc                      372    *   + the compiler is gcc
289    *   + the source is compiled WITHOUT the -f    373    *   + the source is compiled WITHOUT the -fomit-frame-pointer option
290    * In the absence of "ebp", chances are high    374    * In the absence of "ebp", chances are high that the value pushed
291    * at that address is outside the stack boun    375    * at that address is outside the stack boundaries, meaning that the
292    * function will return -SOS_ENOSUP.            376    * function will return -SOS_ENOSUP.
293    */                                             377    */
294                                                   378 
295   if (cpu_kstate)                              !! 379   if (cpu_state)
296     {                                             380     {
297       callee_PC    = cpu_kstate->eip;          !! 381       callee_PC    = cpu_state->eip;
298       caller_frame = cpu_kstate->ebp;          !! 382       caller_frame = cpu_state->ebp;
299     }                                             383     }
300   else                                            384   else
301     {                                             385     {
302       /* Skip the sos_backtrace() frame */        386       /* Skip the sos_backtrace() frame */
303       callee_PC    = (sos_vaddr_t)__builtin_re    387       callee_PC    = (sos_vaddr_t)__builtin_return_address(0);
304       caller_frame = (sos_vaddr_t)__builtin_fr    388       caller_frame = (sos_vaddr_t)__builtin_frame_address(1);
305     }                                             389     }
306                                                   390 
307   for(depth=0 ; depth < max_depth ; depth ++)     391   for(depth=0 ; depth < max_depth ; depth ++)
308     {                                             392     {
309       /* Call the callback */                     393       /* Call the callback */
310       backtracer(callee_PC, caller_frame + 8,     394       backtracer(callee_PC, caller_frame + 8, depth, custom_arg);
311                                                   395 
312       /* If the frame address is funky, don't     396       /* If the frame address is funky, don't go further */
313       if ( (caller_frame < stack_bottom)          397       if ( (caller_frame < stack_bottom)
314            || (caller_frame + 4 >= stack_botto    398            || (caller_frame + 4 >= stack_bottom + stack_size) )
315         return depth;                             399         return depth;
316                                                   400 
317       /* Go to caller frame */                    401       /* Go to caller frame */
318       callee_PC    = *((sos_vaddr_t*) (caller_    402       callee_PC    = *((sos_vaddr_t*) (caller_frame + 4));
319       caller_frame = *((sos_vaddr_t*) caller_f    403       caller_frame = *((sos_vaddr_t*) caller_frame);
320     }                                             404     }
321                                                   405   
322   return depth;                                   406   return depth;
323 }                                                 407 }
                                                      

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