|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
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 to create an initial context for a user thread, copy of an 145 * existing user thread context. The user thread needs a kernel stack 146 * for the syscalls and for handling interrupts: the address of this 147 * kernel stack is given by the kernel_stack_* parameters. 148 * 149 * @param uctxt The user thread CPU context to initialize. The 150 * address of the newly-initialized struct sos_cpu_state will be 151 * stored in this variable. The contents of this struct sos_cpu_state 152 * are actually located /inside/ the kernel stack of the thread. 153 * 154 * @param model_uctxt The user thread context that will be copied to 155 * the new user thread context 156 * 157 * @param user_retval The parameter passed to the initial user 158 * thread function. 159 * 160 * @param kernel_stack_bottom The lowest address of the kernel stack 161 * used to switch to user mode and to handle interrupts/exceptions. 162 * 163 * @param kernel_stack_size The size of the kernel stack (@see 164 * kernel_stack_bottom). 165 * 166 * @note the newly thread context is INTERRUPTIBLE ! 167 */ 168 sos_ret_t sos_cpu_ustate_duplicate(struct sos_cpu_state **uctxt, 169 const struct sos_cpu_state *model_uctxt, 170 sos_ui32_t user_retval, 171 sos_vaddr_t kernel_stack_bottom, 172 sos_size_t kernel_stack_size); 173 174 175 /** 176 * Function that performs an immediate context-switch from one 177 * kernel/user thread to another one. It stores the current executing 178 * context in from_ctxt, and restores to_context on CPU. 179 * 180 * @param from_ctxt The address of the struct sos_cpu_state will be 181 * stored in this variable. Must NOT be NULL. 182 * 183 * @param to_ctxt The CPU will resume its execution with the struct 184 * sos_cpu_state located at this address. Must NOT be NULL. 185 */ 186 void sos_cpu_context_switch(struct sos_cpu_state **from_ctxt, 187 struct sos_cpu_state *to_ctxt); 188 189 190 /* 191 * Switch to the new given context (of a kernel/user thread) without 192 * saving the old context (of another kernel/user thread), and call 193 * the function reclaiming_func passing it the recalining_arg 194 * argument. The reclaining function is called from within the stack 195 * of the new context, so that it can (among other things) safely 196 * destroy the stack of the former context. 197 * 198 * @param switch_to_ctxt The context that will be restored on the CPU 199 * 200 * @param reclaiming_func The address of the function that will be 201 * called after having changed the stack, but before restoring the CPU 202 * context to switch_to_ctxt. 203 */ 204 void 205 sos_cpu_context_exit_to(struct sos_cpu_state *switch_to_ctxt, 206 sos_cpu_kstate_function_arg1_t *reclaiming_func, 207 sos_ui32_t reclaiming_arg) __attribute__((noreturn)); 208 209 /* ======================================================================= 210 * Public Accessor functions 211 */ 212 213 214 /** 215 * Return whether the saved context was in kernel or user context 216 * 217 * @return TRUE when context was interrupted when in user mode, FALSE 218 * when in kernel mode, < 0 on error. 219 */ 220 sos_ret_t 221 sos_cpu_context_is_in_user_mode(const struct sos_cpu_state *ctxt); 222 223 224 /** 225 * Return Program Counter stored in the saved kernel/user context 226 */ 227 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt); 228 229 230 /** 231 * Return Stack Pointer stored in the saved kernel/user context 232 */ 233 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt); 234 235 236 /** 237 * Dump the contents of the CPU context (bochs + x86_videomem) 238 */ 239 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt); 240 241 242 /* ======================================================================= 243 * Public Accessor functions TO BE USED ONLY BY Exception handlers 244 */ 245 246 247 /** 248 * Return the argument passed by the CPU upon exception, as stored in the 249 * saved context 250 */ 251 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt); 252 253 254 /** 255 * Return the faulting address of the exception 256 */ 257 sos_vaddr_t 258 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt); 259 260 261 /** 262 * Change the return address of the given context 263 */ 264 sos_ret_t 265 sos_cpu_context_set_EX_return_address(struct sos_cpu_state *ctxt, 266 sos_vaddr_t ret_vaddr); 267 268 269 /* ======================================================================= 270 * Public Accessor functions TO BE USED ONLY BY the SYSCALL handler 271 */ 272 273 /** 274 * Low-level functions used by the syscall handler. They are 275 * responsible for retrieving the arguments passed to the syscall when 276 * a user thread makes a syscall. Some of these arguments are 277 * available as registers' values in the user context, some of them 278 * are user-space addresses given by these registers. 279 * 280 * @return SOS_OK on success, <0 otherwise 281 */ 282 sos_ret_t sos_syscall_get1arg(const struct sos_cpu_state *user_ctxt, 283 /* out */unsigned int *arg1); 284 285 sos_ret_t sos_syscall_get2args(const struct sos_cpu_state *user_ctxt, 286 /* out */unsigned int *arg1, 287 /* out */unsigned int *arg2); 288 289 sos_ret_t sos_syscall_get3args(const struct sos_cpu_state *user_ctxt, 290 /* out */unsigned int *arg1, 291 /* out */unsigned int *arg2, 292 /* out */unsigned int *arg3); 293 294 sos_ret_t sos_syscall_get4args(const struct sos_cpu_state *user_ctxt, 295 /* out */unsigned int *arg1, 296 /* out */unsigned int *arg2, 297 /* out */unsigned int *arg3, 298 /* out */unsigned int *arg4); 299 300 sos_ret_t sos_syscall_get5args(const struct sos_cpu_state *user_ctxt, 301 /* out */unsigned int *arg1, 302 /* out */unsigned int *arg2, 303 /* out */unsigned int *arg3, 304 /* out */unsigned int *arg4, 305 /* out */unsigned int *arg5); 306 307 sos_ret_t sos_syscall_get6args(const struct sos_cpu_state *user_ctxt, 308 /* out */unsigned int *arg1, 309 /* out */unsigned int *arg2, 310 /* out */unsigned int *arg3, 311 /* out */unsigned int *arg4, 312 /* out */unsigned int *arg5, 313 /* out */unsigned int *arg6); 314 315 sos_ret_t sos_syscall_get7args(const struct sos_cpu_state *user_ctxt, 316 /* out */unsigned int *arg1, 317 /* out */unsigned int *arg2, 318 /* out */unsigned int *arg3, 319 /* out */unsigned int *arg4, 320 /* out */unsigned int *arg5, 321 /* out */unsigned int *arg6, 322 /* out */unsigned int *arg7); 323 324 sos_ret_t sos_syscall_get8args(const struct sos_cpu_state *user_ctxt, 325 /* out */unsigned int *arg1, 326 /* out */unsigned int *arg2, 327 /* out */unsigned int *arg3, 328 /* out */unsigned int *arg4, 329 /* out */unsigned int *arg5, 330 /* out */unsigned int *arg6, 331 /* out */unsigned int *arg7, 332 /* out */unsigned int *arg8); 333 334 335 /* ======================================================================= 336 * Macros controlling stack poisoning. 337 * Stack poisoning can be used to detect: 338 * - unitialized local variables 339 * - when the thread might have gone too deep in the stack 340 */ 341 /** The signature of the poison */ 342 #define SOS_CPU_STATE_STACK_POISON 0xa5 343 344 /** 345 * When set, mean that the whole stack is poisoned to detect use of 346 * unititialized variables 347 */ 348 #define SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS 349 /* #undef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS */ 350 351 /** 352 * When set, mean that the bottom of the stack is poisoned to detect 353 * probable stack overflow. Its value indicates the number of bytes 354 * used for this detection. 355 */ 356 #define SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW 64 357 /* #undef SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */ 358 359 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) 360 void 361 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt, 362 sos_vaddr_t kernel_stack_bottom, 363 sos_size_t kernel_stack_size); 364 void sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt, 365 sos_vaddr_t kernel_stack_bottom, 366 sos_size_t kernel_stack_size); 367 #else 368 # define sos_cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ 369 ({ /* nop */ }) 370 # define sos_cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ 371 ({ /* nop */ }) 372 #endif 373 374 375 /* ======================================================================= 376 * Backtrace facility. To be used for DEBUGging purpose ONLY. 377 */ 378 379 380 /** 381 * The function called at each step of the backtrace iterations 382 * 383 * @param PC The address of the next instruction of the function that 384 * will be executed 385 * 386 * @param params The address of the array of the parameteres that have 387 * been passed to the function considered 388 * 389 * @param depth The index of the iteration (ie the depth of the 390 * current frame into the stack) 391 * 392 * @param custom_arg Whatever you want: this is the argument passed as 393 * custom_arg to sos_backtrace() 394 */ 395 typedef void (sos_backtrace_callback_t)(sos_vaddr_t PC, 396 sos_vaddr_t params, 397 sos_ui32_t depth, 398 void *custom_arg); 399 400 401 /** 402 * Call the backtracer callback on each frame stored in the cpu_state 403 * 404 * @param cpu_state The CPU context we want to explore. MUST be the 405 * context of a thread in Kernel mode, or NULL. When NULL: backtrace 406 * the current CPU context. 407 * 408 * @param max_depth The maximum number of frames to explore 409 * 410 * @param stack_bottom The lower boundary of the stack. This is used 411 * to make sure that the frame addresses fit inside the stack 412 * boudaries (ie are potentially correct). 413 * 414 * @param stack_size The size of the stack. Same comment. 415 * 416 * @param backtracer The function to call to handle the frame for each 417 * iteration 418 * 419 * @param custom_arg The arg passed as custom_arg to the backtracer 420 * 421 * @return The number of frames explored. 422 * 423 * @note Might be inaccurate when gcc's -fomit-frame-pointer has been 424 * used. 425 */ 426 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state, 427 sos_ui32_t max_depth, 428 sos_vaddr_t stack_bottom, 429 sos_size_t stack_size, 430 sos_backtrace_callback_t * backtracer, 431 void *custom_arg); 432 433 #endif /* _SOS_CPUCTXT_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |