summaryrefslogtreecommitdiff
path: root/sos-code-article6.5/hwcore/cpu_context.h
blob: 43b371848893278f85c7e578be28e3f2165b6361 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* Copyright (C) 2005  David Decotigny
   Copyright (C) 2000-2004, The KOS team

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   USA. 
*/
#ifndef _SOS_CPUCTXT_H_
#define _SOS_CPUCTXT_H_


/**
 * @file cpu_context.h
 *
 * Low level API to manage kernel and user thread CPU contexts. Should
 * be some kind of architecture-independent.
 */

#include <sos/types.h>
#include <sos/errno.h>


/**
 * Opaque structure storing the CPU context of an inactive kernel or
 * user thread, as saved by the low level primitives below or by the
 * interrupt/exception handlers.
 *
 * @note This is an (architecture-independent) forward declaration:
 * see cpu_context.c and the *.S files for its
 * (architecture-dependent) definition.
 */
struct sos_cpu_state;


/**
 * The type of the functions passed as arguments to the Kernel thread
 * related functions.
 */
typedef void (sos_cpu_kstate_function_arg1_t(sos_ui32_t arg1));


/**
 * Function to create an initial context for a kernel thread starting
 * its execution at function start_func with the argument initial_arg,
 * and having the stack defined by stack_bottom/stack_size. When the
 * start_func function returns, the function exit_func is called with
 * argument exit_arg.
 *
 * @param kctxt The kernel thread CPU context to initialize. The
 * address of the newly-initialized struct sos_cpu_state will be
 * stored in this variable. The contents of this struct sos_cpu_state
 * are actually located /inside/ the stack.
 *
 * @param start_func The address of the first instruction that will be
 * executed when this context will be first transferred on
 * CPU. Practically speaking, this is the address of a function that
 * is assumed to take 1 argument.
 *
 * @param start_arg The value that will be passed as the argument to
 * start_func when the thread starts. The stack will be setup
 * accordingly to simulate a real call to the function and really
 * passing this arguement.
 *
 * @param stack_bottom The lowest address of the stack.
 *
 * @param stack_size The size of the stack.
 *
 * @param exit_func The address of the instruction executed after the
 * function start_func has returned. This function takes 1 parameter
 * as argument: exit_arg.
 *
 * @param exit_arg The argument passed to the function exit_func.
 *
 * @note the newly created context is INTERRUPTIBLE by default !
 */
sos_ret_t sos_cpu_kstate_init(struct sos_cpu_state **kctxt,
			      sos_cpu_kstate_function_arg1_t *start_func,
			      sos_ui32_t  start_arg,
			      sos_vaddr_t stack_bottom,
			      sos_size_t  stack_size,
			      sos_cpu_kstate_function_arg1_t *exit_func,
			      sos_ui32_t  exit_arg);


/**
 * Function that performs an immediate context-switch from one
 * kernel/user thread to another one. It stores the current executing
 * context in from_ctxt, and restores to_context on CPU.
 *
 * @param from_ctxt The address of the struct sos_cpu_state will be
 * stored in this variable. Must NOT be NULL.
 *
 * @param to_ctxt The CPU will resume its execution with the struct
 * sos_cpu_state located at this address. Must NOT be NULL.
 */
void sos_cpu_context_switch(struct sos_cpu_state **from_ctxt,
			    struct sos_cpu_state *to_ctxt);


/*
 * Switch to the new given context (of a kernel/user thread) without
 * saving the old context (of another kernel/user thread), and call
 * the function reclaiming_func passing it the recalining_arg
 * argument. The reclaining function is called from within the stack
 * of the new context, so that it can (among other things) safely
 * destroy the stack of the former context.
 *
 * @param switch_to_ctxt The context that will be restored on the CPU
 *
 * @param reclaiming_func The address of the function that will be
 * called after having changed the stack, but before restoring the CPU
 * context to switch_to_ctxt.
 */
void
sos_cpu_context_exit_to(struct sos_cpu_state *switch_to_ctxt,
			sos_cpu_kstate_function_arg1_t *reclaiming_func,
			sos_ui32_t reclaiming_arg) __attribute__((noreturn));

/* =======================================================================
 * Public Accessor functions
 */


/**
 * Return Program Counter stored in the saved kernel/user context
 */
sos_vaddr_t sos_cpu_context_get_PC(const struct sos_cpu_state *ctxt);


/**
 * Return Stack Pointer stored in the saved kernel/user context
 */
sos_vaddr_t sos_cpu_context_get_SP(const struct sos_cpu_state *ctxt);


/**
 * Dump the contents of the CPU context (bochs + x86_videomem)
 */
void sos_cpu_context_dump(const struct sos_cpu_state *ctxt);


/* =======================================================================
 * Public Accessor functions TO BE USED ONLY BY Exception handlers
 */


/**
 * Return the argument passed by the CPU upon exception, as stored in the
 * saved context
 */
sos_ui32_t sos_cpu_context_get_EX_info(const struct sos_cpu_state *ctxt);


/**
 * Return the faulting address of the exception
 */
sos_vaddr_t
sos_cpu_context_get_EX_faulting_vaddr(const struct sos_cpu_state *ctxt);


/* =======================================================================
 * Macros controlling stack poisoning.
 * Stack poisoning can be used to detect:
 *  - unitialized local variables
 *  - when the thread might have gone too deep in the stack
 */
/** The signature of the poison */
#define SOS_CPU_STATE_STACK_POISON 0xa5

/**
 * When set, mean that the whole stack is poisoned to detect use of
 * unititialized variables
 */
#define SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS
/* #undef SOS_CPU_STATE_DETECT_UNINIT_KERNEL_VARS */

/**
 * When set, mean that the bottom of the stack is poisoned to detect
 * probable stack overflow. Its value indicates the number of bytes
 * used for this detection.
 */
#define SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW  64
/* #undef SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW */

#if defined(SOS_CPU_STATE_DETECT_KERNEL_STACK_OVERFLOW)
void
sos_cpu_state_prepare_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
						   sos_vaddr_t kernel_stack_bottom,
						   sos_size_t kernel_stack_size);
void sos_cpu_state_detect_kernel_stack_overflow(const struct sos_cpu_state *ctxt,
						sos_vaddr_t kernel_stack_bottom,
						sos_size_t kernel_stack_size);
#else
# define sos_cpu_state_prepare_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
  ({ /* nop */ })
# define sos_cpu_state_detect_kernel_stack_overflow(ctxt,stkbottom,stksize) \
  ({ /* nop */ })
#endif


/* =======================================================================
 * Backtrace facility. To be used for DEBUGging purpose ONLY.
 */


/**
 * The function called at each step of the backtrace iterations
 *
 * @param PC The address of the next instruction of the function that
 * will be executed
 *
 * @param params The address of the array of the parameteres that have
 * been passed to the function considered
 *
 * @param depth The index of the iteration (ie the depth of the
 * current frame into the stack)
 *
 * @param custom_arg Whatever you want: this is the argument passed as
 * custom_arg to sos_backtrace()
 */
typedef void (sos_backtrace_callback_t)(sos_vaddr_t PC,
					sos_vaddr_t params,
					sos_ui32_t depth,
					void *custom_arg);


/**
 * Call the backtracer callback on each frame stored in the cpu_state
 *
 * @param cpu_state The CPU context we want to explore. MUST be the
 * context of a thread in Kernel mode, or NULL. When NULL: backtrace
 * the current CPU context.
 *
 * @param max_depth The maximum number of frames to explore
 *
 * @param stack_bottom The lower boundary of the stack. This is used
 * to make sure that the frame addresses fit inside the stack
 * boudaries (ie are potentially correct).
 *
 * @param stack_size The size of the stack. Same comment.
 *
 * @param backtracer The function to call to handle the frame for each
 * iteration
 *
 * @param custom_arg The arg passed as custom_arg to the backtracer
 *
 * @return The number of frames explored.
 *
 * @note Might be inaccurate when gcc's -fomit-frame-pointer has been
 * used.
 */
sos_ui32_t sos_backtrace(const struct sos_cpu_state *cpu_state,
			 sos_ui32_t max_depth,
			 sos_vaddr_t stack_bottom,
			 sos_size_t stack_size,
			 sos_backtrace_callback_t * backtracer,
			 void *custom_arg);

#endif /* _SOS_CPUCTXT_H_ */