|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
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 #ifndef _SOS_CPUCTXT_H_ 019 #ifndef _SOS_CPUCTXT_H_ 020 #define _SOS_CPUCTXT_H_ 020 #define _SOS_CPUCTXT_H_ 021 021 022 022 023 /** 023 /** 024 * @file cpu_context.h 024 * @file cpu_context.h 025 * 025 * 026 * Low level API to manage kernel and user thr 026 * Low level API to manage kernel and user thread CPU contexts. Should 027 * be some kind of architecture-independent. 027 * be some kind of architecture-independent. 028 */ 028 */ 029 029 030 #include <sos/types.h> 030 #include <sos/types.h> 031 #include <sos/errno.h> 031 #include <sos/errno.h> 032 032 033 033 034 /** 034 /** 035 * Prepare the system to deal with multiple CP << 036 */ << 037 sos_ret_t sos_cpu_context_subsystem_setup(void << 038 << 039 << 040 /** << 041 * Opaque structure storing the CPU context of 035 * Opaque structure storing the CPU context of an inactive kernel or 042 * user thread, as saved by the low level prim 036 * user thread, as saved by the low level primitives below or by the 043 * interrupt/exception handlers. 037 * interrupt/exception handlers. 044 * 038 * 045 * @note This is an (architecture-independent) 039 * @note This is an (architecture-independent) forward declaration: 046 * see cpu_context.c and the *.S files for its 040 * see cpu_context.c and the *.S files for its 047 * (architecture-dependent) definition. 041 * (architecture-dependent) definition. 048 */ 042 */ 049 struct sos_cpu_state; 043 struct sos_cpu_state; 050 044 051 045 052 /** 046 /** 053 * The type of the functions passed as argumen 047 * The type of the functions passed as arguments to the Kernel thread 054 * related functions. 048 * related functions. 055 */ 049 */ 056 typedef void (sos_cpu_kstate_function_arg1_t(s 050 typedef void (sos_cpu_kstate_function_arg1_t(sos_ui32_t arg1)); 057 051 058 052 059 /** 053 /** 060 * Function to create an initial context for a 054 * Function to create an initial context for a kernel thread starting 061 * its execution at function start_func with t 055 * its execution at function start_func with the argument initial_arg, 062 * and having the stack defined by stack_botto 056 * and having the stack defined by stack_bottom/stack_size. When the 063 * start_func function returns, the function e 057 * start_func function returns, the function exit_func is called with 064 * argument exit_arg. 058 * argument exit_arg. 065 * 059 * 066 * @param kctxt The kernel thread CPU context 060 * @param kctxt The kernel thread CPU context to initialize. The 067 * address of the newly-initialized struct sos 061 * address of the newly-initialized struct sos_cpu_state will be 068 * stored in this variable. The contents of th 062 * stored in this variable. The contents of this struct sos_cpu_state 069 * are actually located /inside/ the stack. 063 * are actually located /inside/ the stack. 070 * 064 * 071 * @param start_func The address of the first 065 * @param start_func The address of the first instruction that will be 072 * executed when this context will be first tr 066 * executed when this context will be first transferred on 073 * CPU. Practically speaking, this is the addr 067 * CPU. Practically speaking, this is the address of a function that 074 * is assumed to take 1 argument. 068 * is assumed to take 1 argument. 075 * 069 * 076 * @param start_arg The value that will be pas 070 * @param start_arg The value that will be passed as the argument to 077 * start_func when the thread starts. The stac 071 * start_func when the thread starts. The stack will be setup 078 * accordingly to simulate a real call to the 072 * accordingly to simulate a real call to the function and really 079 * passing this arguement. 073 * passing this arguement. 080 * 074 * 081 * @param stack_bottom The lowest address of t 075 * @param stack_bottom The lowest address of the stack. 082 * 076 * 083 * @param stack_size The size of the stack. 077 * @param stack_size The size of the stack. 084 * 078 * 085 * @param exit_func The address of the instruc 079 * @param exit_func The address of the instruction executed after the 086 * function start_func has returned. This func 080 * function start_func has returned. This function takes 1 parameter 087 * as argument: exit_arg. 081 * as argument: exit_arg. 088 * 082 * 089 * @param exit_arg The argument passed to the 083 * @param exit_arg The argument passed to the function exit_func. 090 * 084 * 091 * @note the newly created context is INTERRUP 085 * @note the newly created context is INTERRUPTIBLE by default ! 092 */ 086 */ 093 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_s 087 sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **kctxt, 094 sos_cpu_kstate_f 088 sos_cpu_kstate_function_arg1_t *start_func, 095 sos_ui32_t star 089 sos_ui32_t start_arg, 096 sos_vaddr_t stac 090 sos_vaddr_t stack_bottom, 097 sos_size_t stac 091 sos_size_t stack_size, 098 sos_cpu_kstate_f 092 sos_cpu_kstate_function_arg1_t *exit_func, 099 sos_ui32_t exit 093 sos_ui32_t exit_arg); 100 094 101 095 102 /** 096 /** 103 * Function to create an initial context for a << 104 * its execution at function user_start_PC wit << 105 * argument. The address of the user stack bef << 106 * the ustate_init() function is given by user << 107 * thread starts in user space first and needs << 108 * the syscalls and for handling interrupts: t << 109 * kernel stack is given by the kernel_stack_* << 110 * << 111 * @param uctxt The user thread CPU context to << 112 * address of the newly-initialized struct sos << 113 * stored in this variable. The contents of th << 114 * are actually located /inside/ the kernel st << 115 * << 116 * @param user_start_PC The address of the fir << 117 * be executed in user mode when this context << 118 * transferred on CPU. Practically speaking, t << 119 * function that is assumed to take 1 argument << 120 * << 121 * @param user_start_SP The initial user stack << 122 * << 123 * @param user_start_argX The 2 parameters pas << 124 * thread function (in registers). << 125 * << 126 * @param kernel_stack_bottom The lowest addre << 127 * used to switch to user mode and to handle i << 128 * << 129 * @param kernel_stack_size The size of the ke << 130 * kernel_stack_bottom). << 131 * << 132 * @note the newly thread context is INTERRUPT << 133 */ << 134 sos_ret_t sos_cpu_ustate_init(struct sos_cpu_s << 135 sos_uaddr_t use << 136 sos_ui32_t use << 137 sos_ui32_t use << 138 sos_uaddr_t use << 139 sos_vaddr_t ker << 140 sos_size_t ker << 141 << 142 << 143 /** << 144 * Function to create an initial context for a << 145 * existing user thread context. The user thre << 146 * for the syscalls and for handling interrupt << 147 * kernel stack is given by the kernel_stack_* << 148 * << 149 * @param uctxt The user thread CPU context to << 150 * address of the newly-initialized struct sos << 151 * stored in this variable. The contents of th << 152 * are actually located /inside/ the kernel st << 153 * << 154 * @param model_uctxt The user thread context << 155 * the new user thread context << 156 * << 157 * @param user_retval The parameter passed to << 158 * thread function. << 159 * << 160 * @param kernel_stack_bottom The lowest addre << 161 * used to switch to user mode and to handle i << 162 * << 163 * @param kernel_stack_size The size of the ke << 164 * kernel_stack_bottom). << 165 * << 166 * @note the newly thread context is INTERRUPT << 167 */ << 168 sos_ret_t sos_cpu_ustate_duplicate(struct sos_ << 169 const struc << 170 sos_ui32_t << 171 sos_vaddr_t << 172 sos_size_t << 173 << 174 << 175 /** << 176 * Function that performs an immediate context 097 * Function that performs an immediate context-switch from one 177 * kernel/user thread to another one. It store 098 * kernel/user thread to another one. It stores the current executing 178 * context in from_ctxt, and restores to_conte 099 * context in from_ctxt, and restores to_context on CPU. 179 * 100 * 180 * @param from_ctxt The address of the struct 101 * @param from_ctxt The address of the struct sos_cpu_state will be 181 * stored in this variable. Must NOT be NULL. 102 * stored in this variable. Must NOT be NULL. 182 * 103 * 183 * @param to_ctxt The CPU will resume its exec 104 * @param to_ctxt The CPU will resume its execution with the struct 184 * sos_cpu_state located at this address. Must 105 * sos_cpu_state located at this address. Must NOT be NULL. 185 */ 106 */ 186 void sos_cpu_context_switch(struct sos_cpu_sta 107 void sos_cpu_context_switch(struct sos_cpu_state **from_ctxt, 187 struct sos_cpu_sta 108 struct sos_cpu_state *to_ctxt); 188 109 189 110 190 /* 111 /* 191 * Switch to the new given context (of a kerne 112 * Switch to the new given context (of a kernel/user thread) without 192 * saving the old context (of another kernel/u 113 * saving the old context (of another kernel/user thread), and call 193 * the function reclaiming_func passing it the 114 * the function reclaiming_func passing it the recalining_arg 194 * argument. The reclaining function is called 115 * argument. The reclaining function is called from within the stack 195 * of the new context, so that it can (among o 116 * of the new context, so that it can (among other things) safely 196 * destroy the stack of the former context. 117 * destroy the stack of the former context. 197 * 118 * 198 * @param switch_to_ctxt The context that will 119 * @param switch_to_ctxt The context that will be restored on the CPU 199 * 120 * 200 * @param reclaiming_func The address of the f 121 * @param reclaiming_func The address of the function that will be 201 * called after having changed the stack, but 122 * called after having changed the stack, but before restoring the CPU 202 * context to switch_to_ctxt. 123 * context to switch_to_ctxt. 203 */ 124 */ 204 void 125 void 205 sos_cpu_context_exit_to(struct sos_cpu_state * 126 sos_cpu_context_exit_to(struct sos_cpu_state *switch_to_ctxt, 206 sos_cpu_kstate_functio 127 sos_cpu_kstate_function_arg1_t *reclaiming_func, 207 sos_ui32_t reclaiming_ 128 sos_ui32_t reclaiming_arg) __attribute__((noreturn)); 208 129 209 /* =========================================== 130 /* ======================================================================= 210 * Public Accessor functions 131 * Public Accessor functions 211 */ 132 */ 212 133 213 134 214 /** 135 /** 215 * Return whether the saved context was in ker << 216 * << 217 * @return TRUE when context was interrupted w << 218 * when in kernel mode, < 0 on error. << 219 */ << 220 sos_ret_t << 221 sos_cpu_context_is_in_user_mode(const struct s << 222 << 223 << 224 /** << 225 * Return Program Counter stored in the saved 136 * Return Program Counter stored in the saved kernel/user context 226 */ 137 */ 227 sos_vaddr_t sos_cpu_context_get_PC(const struc 138 sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt); 228 139 229 140 230 /** 141 /** 231 * Return Stack Pointer stored in the saved ke 142 * Return Stack Pointer stored in the saved kernel/user context 232 */ 143 */ 233 sos_vaddr_t sos_cpu_context_get_SP(const struc 144 sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt); 234 145 235 146 236 /** 147 /** 237 * Dump the contents of the CPU context (bochs 148 * Dump the contents of the CPU context (bochs + x86_videomem) 238 */ 149 */ 239 void sos_cpu_context_dump(const struct sos_cpu 150 void sos_cpu_context_dump(const struct sos_cpu_state *ctxt); 240 151 241 152 242 /* =========================================== 153 /* ======================================================================= 243 * Public Accessor functions TO BE USED ONLY B 154 * Public Accessor functions TO BE USED ONLY BY Exception handlers 244 */ 155 */ 245 156 246 157 247 /** 158 /** 248 * Return the argument passed by the CPU upon 159 * Return the argument passed by the CPU upon exception, as stored in the 249 * saved context 160 * saved context 250 */ 161 */ 251 sos_ui32_t sos_cpu_context_get_EX_info(const s 162 sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt); 252 163 253 164 254 /** 165 /** 255 * Return the faulting address of the exceptio 166 * Return the faulting address of the exception 256 */ 167 */ 257 sos_vaddr_t 168 sos_vaddr_t 258 sos_cpu_context_get_EX_faulting_vaddr(const st 169 sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt); 259 << 260 << 261 /** << 262 * Change the return address of the given cont << 263 */ << 264 sos_ret_t << 265 sos_cpu_context_set_EX_return_address(struct s << 266 sos_vadd << 267 << 268 << 269 /* =========================================== << 270 * Public Accessor functions TO BE USED ONLY B << 271 */ << 272 << 273 /** << 274 * Low-level functions used by the syscall han << 275 * responsible for retrieving the arguments pa << 276 * a user thread makes a syscall. Some of thes << 277 * available as registers' values in the user << 278 * are user-space addresses given by these reg << 279 * << 280 * @return SOS_OK on success, <0 otherwise << 281 */ << 282 sos_ret_t sos_syscall_get1arg(const struct sos << 283 /* out */unsigne << 284 << 285 sos_ret_t sos_syscall_get2args(const struct so << 286 /* out */unsign << 287 /* out */unsign << 288 << 289 sos_ret_t sos_syscall_get3args(const struct so << 290 /* out */unsign << 291 /* out */unsign << 292 /* out */unsign << 293 << 294 sos_ret_t sos_syscall_get4args(const struct so << 295 /* out */unsign << 296 /* out */unsign << 297 /* out */unsign << 298 /* out */unsign << 299 << 300 sos_ret_t sos_syscall_get5args(const struct so << 301 /* out */unsign << 302 /* out */unsign << 303 /* out */unsign << 304 /* out */unsign << 305 /* out */unsign << 306 << 307 sos_ret_t sos_syscall_get6args(const struct so << 308 /* out */unsign << 309 /* out */unsign << 310 /* out */unsign << 311 /* out */unsign << 312 /* out */unsign << 313 /* out */unsign << 314 << 315 sos_ret_t sos_syscall_get7args(const struct so << 316 /* out */unsign << 317 /* out */unsign << 318 /* out */unsign << 319 /* out */unsign << 320 /* out */unsign << 321 /* out */unsign << 322 /* out */unsign << 323 << 324 sos_ret_t sos_syscall_get8args(const struct so << 325 /* out */unsign << 326 /* out */unsign << 327 /* out */unsign << 328 /* out */unsign << 329 /* out */unsign << 330 /* out */unsign << 331 /* out */unsign << 332 /* out */unsign << 333 170 334 171 335 /* =========================================== 172 /* ======================================================================= 336 * Macros controlling stack poisoning. 173 * Macros controlling stack poisoning. 337 * Stack poisoning can be used to detect: 174 * Stack poisoning can be used to detect: 338 * - unitialized local variables 175 * - unitialized local variables 339 * - when the thread might have gone too deep 176 * - when the thread might have gone too deep in the stack 340 */ 177 */ 341 /** The signature of the poison */ 178 /** The signature of the poison */ 342 #define SOS_CPU_STATE_STACK_POISON 0xa5 179 #define SOS_CPU_STATE_STACK_POISON 0xa5 343 180 344 /** 181 /** 345 * When set, mean that the whole stack is pois 182 * When set, mean that the whole stack is poisoned to detect use of 346 * unititialized variables 183 * unititialized variables 347 */ 184 */ 348 #define SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VAR 185 #define SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS 349 /* #undef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_V 186 /* #undef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS */ 350 187 351 /** 188 /** 352 * When set, mean that the bottom of the stack 189 * When set, mean that the bottom of the stack is poisoned to detect 353 * probable stack overflow. Its value indicate 190 * probable stack overflow. Its value indicates the number of bytes 354 * used for this detection. 191 * used for this detection. 355 */ 192 */ 356 #define SOS_CPU_STATE_DETECT_KERNEL_STACK_OVER 193 #define SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW 64 357 /* #undef SOS_CPU_STATE_DETECT_KERNEL_STACK_OV 194 /* #undef SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */ 358 195 359 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_ 196 #if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW) 360 void 197 void 361 sos_cpu_state_prepare_detect_kernel_stack_over 198 sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt, 362 199 sos_vaddr_t kernel_stack_bottom, 363 200 sos_size_t kernel_stack_size); 364 void sos_cpu_state_detect_kernel_stack_overflo 201 void sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt, 365 202 sos_vaddr_t kernel_stack_bottom, 366 203 sos_size_t kernel_stack_size); 367 #else 204 #else 368 # define sos_cpu_state_prepare_detect_kernel_s 205 # define sos_cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ 369 ({ /* nop */ }) 206 ({ /* nop */ }) 370 # define sos_cpu_state_detect_kernel_stack_ove 207 # define sos_cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \ 371 ({ /* nop */ }) 208 ({ /* nop */ }) 372 #endif 209 #endif 373 210 374 211 375 /* =========================================== 212 /* ======================================================================= 376 * Backtrace facility. To be used for DEBUGgin 213 * Backtrace facility. To be used for DEBUGging purpose ONLY. 377 */ 214 */ 378 215 379 216 380 /** 217 /** 381 * The function called at each step of the bac 218 * The function called at each step of the backtrace iterations 382 * 219 * 383 * @param PC The address of the next instructi 220 * @param PC The address of the next instruction of the function that 384 * will be executed 221 * will be executed 385 * 222 * 386 * @param params The address of the array of t 223 * @param params The address of the array of the parameteres that have 387 * been passed to the function considered 224 * been passed to the function considered 388 * 225 * 389 * @param depth The index of the iteration (ie 226 * @param depth The index of the iteration (ie the depth of the 390 * current frame into the stack) 227 * current frame into the stack) 391 * 228 * 392 * @param custom_arg Whatever you want: this i 229 * @param custom_arg Whatever you want: this is the argument passed as 393 * custom_arg to sos_backtrace() 230 * custom_arg to sos_backtrace() 394 */ 231 */ 395 typedef void (sos_backtrace_callback_t)(sos_va 232 typedef void (sos_backtrace_callback_t)(sos_vaddr_t PC, 396 sos_va 233 sos_vaddr_t params, 397 sos_ui 234 sos_ui32_t depth, 398 void * 235 void *custom_arg); 399 236 400 237 401 /** 238 /** 402 * Call the backtracer callback on each frame 239 * Call the backtracer callback on each frame stored in the cpu_state 403 * 240 * 404 * @param cpu_state The CPU context we want to 241 * @param cpu_state The CPU context we want to explore. MUST be the 405 * context of a thread in Kernel mode, or NULL 242 * context of a thread in Kernel mode, or NULL. When NULL: backtrace 406 * the current CPU context. 243 * the current CPU context. 407 * 244 * 408 * @param max_depth The maximum number of fram 245 * @param max_depth The maximum number of frames to explore 409 * 246 * 410 * @param stack_bottom The lower boundary of t 247 * @param stack_bottom The lower boundary of the stack. This is used 411 * to make sure that the frame addresses fit i 248 * to make sure that the frame addresses fit inside the stack 412 * boudaries (ie are potentially correct). 249 * boudaries (ie are potentially correct). 413 * 250 * 414 * @param stack_size The size of the stack. Sa 251 * @param stack_size The size of the stack. Same comment. 415 * 252 * 416 * @param backtracer The function to call to h 253 * @param backtracer The function to call to handle the frame for each 417 * iteration 254 * iteration 418 * 255 * 419 * @param custom_arg The arg passed as custom_ 256 * @param custom_arg The arg passed as custom_arg to the backtracer 420 * 257 * 421 * @return The number of frames explored. 258 * @return The number of frames explored. 422 * 259 * 423 * @note Might be inaccurate when gcc's -fomit 260 * @note Might be inaccurate when gcc's -fomit-frame-pointer has been 424 * used. 261 * used. 425 */ 262 */ 426 sos_ui32_t sos_backtrace(const struct sos_cpu_ 263 sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state, 427 sos_ui32_t max_depth, 264 sos_ui32_t max_depth, 428 sos_vaddr_t stack_bot 265 sos_vaddr_t stack_bottom, 429 sos_size_t stack_size 266 sos_size_t stack_size, 430 sos_backtrace_callbac 267 sos_backtrace_callback_t * backtracer, 431 void *custom_arg); 268 void *custom_arg); 432 269 433 #endif /* _SOS_CPUCTXT_H_ */ 270 #endif /* _SOS_CPUCTXT_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |