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 ]

001 /* Copyright (C) 2005  David Decotigny
002    Copyright (C) 2000-2004, The KOS team
003 
004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any later version.
008    
009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details.
013    
014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA. 
018 */
019 #ifndef _SOS_CPUCTXT_H_
020 #define _SOS_CPUCTXT_H_
021 
022 
023 /**
024  * @file cpu_context.h
025  *
026  * Low level API to manage kernel and user thread CPU contexts. Should
027  * be some kind of architecture-independent.
028  */
029 
030 #include <sos/types.h>
031 #include <sos/errno.h>
032 
033 
034 /**
035  * Prepare the system to deal with multiple CPU execution contexts
036  */
037 sos_ret_t sos_cpu_context_subsystem_setup();
038 
039 
040 /**
041  * Opaque structure storing the CPU context of an inactive kernel or
042  * user thread, as saved by the low level primitives below or by the
043  * interrupt/exception handlers.
044  *
045  * @note This is an (architecture-independent) forward declaration:
046  * see cpu_context.c and the *.S files for its
047  * (architecture-dependent) definition.
048  */
049 struct sos_cpu_state;
050 
051 
052 /**
053  * The type of the functions passed as arguments to the Kernel thread
054  * related functions.
055  */
056 typedef void (sos_cpu_kstate_function_arg1_t(sos_ui32_t arg1));
057 
058 
059 /**
060  * Function to create an initial context for a kernel thread starting
061  * its execution at function start_func with the argument initial_arg,
062  * and having the stack defined by stack_bottom/stack_size. When the
063  * start_func function returns, the function exit_func is called with
064  * argument exit_arg.
065  *
066  * @param kctxt The kernel thread CPU context to initialize. The
067  * address of the newly-initialized struct sos_cpu_state will be
068  * stored in this variable. The contents of this struct sos_cpu_state
069  * are actually located /inside/ the stack.
070  *
071  * @param start_func The address of the first instruction that will be
072  * executed when this context will be first transferred on
073  * CPU. Practically speaking, this is the address of a function that
074  * is assumed to take 1 argument.
075  *
076  * @param start_arg The value that will be passed as the argument to
077  * start_func when the thread starts. The stack will be setup
078  * accordingly to simulate a real call to the function and really
079  * passing this arguement.
080  *
081  * @param stack_bottom The lowest address of the stack.
082  *
083  * @param stack_size The size of the stack.
084  *
085  * @param exit_func The address of the instruction executed after the
086  * function start_func has returned. This function takes 1 parameter
087  * as argument: exit_arg.
088  *
089  * @param exit_arg The argument passed to the function exit_func.
090  *
091  * @note the newly created context is INTERRUPTIBLE by default !
092  */
093 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **kctxt,
094                               sos_cpu_kstate_function_arg1_t *start_func,
095                               sos_ui32_t  start_arg,
096                               sos_vaddr_t stack_bottom,
097                               sos_size_t  stack_size,
098                               sos_cpu_kstate_function_arg1_t *exit_func,
099                               sos_ui32_t  exit_arg);
100 
101 
102 /**
103  * Function to create an initial context for a user thread starting
104  * its execution at function user_start_PC with the user_start_arg
105  * argument. The address of the user stack before any modification by
106  * the ustate_init() function is given by user_start_SP. The user
107  * thread starts in user space first and needs a kernel stack for
108  * the syscalls and for handling interrupts: the address of this
109  * kernel stack is given by the kernel_stack_* parameters.
110  *
111  * @param uctxt The user thread CPU context to initialize. The
112  * address of the newly-initialized struct sos_cpu_state will be
113  * stored in this variable. The contents of this struct sos_cpu_state
114  * are actually located /inside/ the kernel stack of the thread.
115  *
116  * @param user_start_PC The address of the first instruction that will
117  * be executed in user mode when this context will be first
118  * transferred on CPU. Practically speaking, this is the address of a
119  * function that is assumed to take 1 argument.
120  *
121  * @param user_start_SP The initial user stack address.
122  *
123  * @param user_start_argX The 2 parameters passed to the initial user
124  * thread function (in registers).
125  *
126  * @param kernel_stack_bottom The lowest address of the kernel stack
127  * used to switch to user mode and to handle interrupts/exceptions.
128  *
129  * @param kernel_stack_size The size of the kernel stack (@see
130  * kernel_stack_bottom).
131  *
132  * @note the newly thread context is INTERRUPTIBLE !
133  */
134 sos_ret_t sos_cpu_ustate_init(struct sos_cpu_state **uctxt,
135                               sos_uaddr_t  user_start_PC,
136                               sos_ui32_t   user_start_arg1,
137                               sos_ui32_t   user_start_arg2,
138                               sos_uaddr_t  user_initial_SP,
139                               sos_vaddr_t  kernel_stack_bottom,
140                               sos_size_t   kernel_stack_size);
141 
142 
143 /**
144  * Function that performs an immediate context-switch from one
145  * kernel/user thread to another one. It stores the current executing
146  * context in from_ctxt, and restores to_context on CPU.
147  *
148  * @param from_ctxt The address of the struct sos_cpu_state will be
149  * stored in this variable. Must NOT be NULL.
150  *
151  * @param to_ctxt The CPU will resume its execution with the struct
152  * sos_cpu_state located at this address. Must NOT be NULL.
153  */
154 void sos_cpu_context_switch(struct sos_cpu_state **from_ctxt,
155                             struct sos_cpu_state *to_ctxt);
156 
157 
158 /*
159  * Switch to the new given context (of a kernel/user thread) without
160  * saving the old context (of another kernel/user thread), and call
161  * the function reclaiming_func passing it the recalining_arg
162  * argument. The reclaining function is called from within the stack
163  * of the new context, so that it can (among other things) safely
164  * destroy the stack of the former context.
165  *
166  * @param switch_to_ctxt The context that will be restored on the CPU
167  *
168  * @param reclaiming_func The address of the function that will be
169  * called after having changed the stack, but before restoring the CPU
170  * context to switch_to_ctxt.
171  */
172 void
173 sos_cpu_context_exit_to(struct sos_cpu_state *switch_to_ctxt,
174                         sos_cpu_kstate_function_arg1_t *reclaiming_func,
175                         sos_ui32_t reclaiming_arg) __attribute__((noreturn));
176 
177 /* =======================================================================
178  * Public Accessor functions
179  */
180 
181 
182 /**
183  * Return whether the saved context was in kernel or user context
184  *
185  * @return TRUE when context was interrupted when in user mode, FALSE
186  * when in kernel mode, < 0 on error.
187  */
188 sos_ret_t
189 sos_cpu_context_is_in_user_mode(const struct sos_cpu_state *ctxt);
190 
191 
192 /**
193  * Return Program Counter stored in the saved kernel/user context
194  */
195 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt);
196 
197 
198 /**
199  * Return Stack Pointer stored in the saved kernel/user context
200  */
201 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt);
202 
203 
204 /**
205  * Dump the contents of the CPU context (bochs + x86_videomem)
206  */
207 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt);
208 
209 
210 /* =======================================================================
211  * Public Accessor functions TO BE USED ONLY BY Exception handlers
212  */
213 
214 
215 /**
216  * Return the argument passed by the CPU upon exception, as stored in the
217  * saved context
218  */
219 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt);
220 
221 
222 /**
223  * Return the faulting address of the exception
224  */
225 sos_vaddr_t
226 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt);
227 
228 
229 /**
230  * Change the return address of the given context
231  */
232 sos_ret_t
233 sos_cpu_context_set_EX_return_address(struct sos_cpu_state *ctxt,
234                                       sos_vaddr_t ret_vaddr);
235 
236 
237 /* =======================================================================
238  * Public Accessor functions TO BE USED ONLY BY the SYSCALL handler
239  */
240 
241 /**
242  * Low-level functions used by the syscall handler. They are
243  * responsible for retrieving the arguments passed to the syscall when
244  * a user thread makes a syscall. Some of these arguments are
245  * available as registers' values in the user context, some of them
246  * are user-space addresses given by these registers.
247  *
248  * @return SOS_OK on success, <0 otherwise
249  */
250 sos_ret_t sos_syscall_get1arg(const struct sos_cpu_state *user_ctxt,
251                               /* out */unsigned int *arg1);
252 
253 sos_ret_t sos_syscall_get2args(const struct sos_cpu_state *user_ctxt,
254                                /* out */unsigned int *arg1,
255                                /* out */unsigned int *arg2);
256 
257 sos_ret_t sos_syscall_get3args(const struct sos_cpu_state *user_ctxt,
258                                /* out */unsigned int *arg1,
259                                /* out */unsigned int *arg2,
260                                /* out */unsigned int *arg3);
261 
262 sos_ret_t sos_syscall_get4args(const struct sos_cpu_state *user_ctxt,
263                                /* out */unsigned int *arg1,
264                                /* out */unsigned int *arg2,
265                                /* out */unsigned int *arg3,
266                                /* out */unsigned int *arg4);
267 
268 sos_ret_t sos_syscall_get5args(const struct sos_cpu_state *user_ctxt,
269                                /* out */unsigned int *arg1,
270                                /* out */unsigned int *arg2,
271                                /* out */unsigned int *arg3,
272                                /* out */unsigned int *arg4,
273                                /* out */unsigned int *arg5);
274 
275 sos_ret_t sos_syscall_get6args(const struct sos_cpu_state *user_ctxt,
276                                /* out */unsigned int *arg1,
277                                /* out */unsigned int *arg2,
278                                /* out */unsigned int *arg3,
279                                /* out */unsigned int *arg4,
280                                /* out */unsigned int *arg5,
281                                /* out */unsigned int *arg6);
282 
283 sos_ret_t sos_syscall_get7args(const struct sos_cpu_state *user_ctxt,
284                                /* out */unsigned int *arg1,
285                                /* out */unsigned int *arg2,
286                                /* out */unsigned int *arg3,
287                                /* out */unsigned int *arg4,
288                                /* out */unsigned int *arg5,
289                                /* out */unsigned int *arg6,
290                                /* out */unsigned int *arg7);
291 
292 sos_ret_t sos_syscall_get8args(const struct sos_cpu_state *user_ctxt,
293                                /* out */unsigned int *arg1,
294                                /* out */unsigned int *arg2,
295                                /* out */unsigned int *arg3,
296                                /* out */unsigned int *arg4,
297                                /* out */unsigned int *arg5,
298                                /* out */unsigned int *arg6,
299                                /* out */unsigned int *arg7,
300                                /* out */unsigned int *arg8);
301 
302 
303 /* =======================================================================
304  * Macros controlling stack poisoning.
305  * Stack poisoning can be used to detect:
306  *  - unitialized local variables
307  *  - when the thread might have gone too deep in the stack
308  */
309 /** The signature of the poison */
310 #define SOS_CPU_STATE_STACK_POISON 0xa5
311 
312 /**
313  * When set, mean that the whole stack is poisoned to detect use of
314  * unititialized variables
315  */
316 #define SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
317 /* #undef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS */
318 
319 /**
320  * When set, mean that the bottom of the stack is poisoned to detect
321  * probable stack overflow. Its value indicates the number of bytes
322  * used for this detection.
323  */
324 #define SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW  64
325 /* #undef SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */
326 
327 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
328 void
329 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
330                                                    sos_vaddr_t kernel_stack_bottom,
331                                                    sos_size_t kernel_stack_size);
332 void sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
333                                                 sos_vaddr_t kernel_stack_bottom,
334                                                 sos_size_t kernel_stack_size);
335 #else
336 # define sos_cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
337   ({ /* nop */ })
338 # define sos_cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
339   ({ /* nop */ })
340 #endif
341 
342 
343 /* =======================================================================
344  * Backtrace facility. To be used for DEBUGging purpose ONLY.
345  */
346 
347 
348 /**
349  * The function called at each step of the backtrace iterations
350  *
351  * @param PC The address of the next instruction of the function that
352  * will be executed
353  *
354  * @param params The address of the array of the parameteres that have
355  * been passed to the function considered
356  *
357  * @param depth The index of the iteration (ie the depth of the
358  * current frame into the stack)
359  *
360  * @param custom_arg Whatever you want: this is the argument passed as
361  * custom_arg to sos_backtrace()
362  */
363 typedef void (sos_backtrace_callback_t)(sos_vaddr_t PC,
364                                         sos_vaddr_t params,
365                                         sos_ui32_t depth,
366                                         void *custom_arg);
367 
368 
369 /**
370  * Call the backtracer callback on each frame stored in the cpu_state
371  *
372  * @param cpu_state The CPU context we want to explore. MUST be the
373  * context of a thread in Kernel mode, or NULL. When NULL: backtrace
374  * the current CPU context.
375  *
376  * @param max_depth The maximum number of frames to explore
377  *
378  * @param stack_bottom The lower boundary of the stack. This is used
379  * to make sure that the frame addresses fit inside the stack
380  * boudaries (ie are potentially correct).
381  *
382  * @param stack_size The size of the stack. Same comment.
383  *
384  * @param backtracer The function to call to handle the frame for each
385  * iteration
386  *
387  * @param custom_arg The arg passed as custom_arg to the backtracer
388  *
389  * @return The number of frames explored.
390  *
391  * @note Might be inaccurate when gcc's -fomit-frame-pointer has been
392  * used.
393  */
394 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state,
395                          sos_ui32_t max_depth,
396                          sos_vaddr_t stack_bottom,
397                          sos_size_t stack_size,
398                          sos_backtrace_callback_t * backtracer,
399                          void *custom_arg);
400 
401 #endif /* _SOS_CPUCTXT_H_ */

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