5 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
8 Desc: Macros to handle unix signals
12 #define USE_SA_SIGINFO 0
15 #define SIGCORE_NEED_SA_SIGINFO 1
23 /* Put a value of type SP_TYPE on the stack or get it off the stack. */
24 #define _PUSH(sp,val) \
27 SP_TYPE **stackp = (sp); \
29 **stackp = (SP_TYPE) (val); \
31 #define _POP(sp) (*sp++)
36 #include <bits/sigcontext.h>
37 /* sigcontext_t is the type of the signals' context. Linux offers no way
38 to get this context in a legal way, so I have to use tricks. */
39 typedef @sigcontext@ sigcontext_t;
40 typedef @sighandler@ SignalHandler;
42 /* name and type of the signal handler */
43 #define SIGHANDLER linux_sighandler
44 #define SIGHANDLER_T SignalHandler
47 This macro contains some magic necessary to make it work.
48 The problem is that Linux offers no official way to obtain the
49 signals' context. Linux stores the signals' context on the
50 process' stack. It looks like this:
51 Attention: As of version 2.2 of the Linux kernel there is
52 not enough room on the stack anymore to save
53 any registers on it. So everything has to go into
54 the context structure. Previously PC and FP used
55 to be saved on the stack but now this would over-
56 write some return address.
57 The stack you see below is the stack of the last
58 active task within AROS. The linux kernel puts
59 all kinds of other junk on it.
62 +--------------------------+
63 | last entry before signal |
64 +--------------------------+
66 +--------------------------+
68 +--------------------------+
70 +--------------------------+
73 so the address of the signal context is &sig+1.
77 #define GLOBAL_SIGNAL_INIT \
78 static void sighandler (int sig, sigcontext_t * sc); \
80 static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u) \
82 sighandler(sig, (sigcontext_t *)&u->uc_mcontext); \
87 #define GLOBAL_SIGNAL_INIT \
88 static void sighandler (int sig, sigcontext_t * sc); \
90 static void SIGHANDLER (int sig) \
92 sighandler (sig, (sigcontext_t *)(&sig+1)); \
96 /* Type of the values which can be stored on the stack. A variable
97 which is to be used as a stack pointer must be declared as
101 /* How many general purpose registers are to be saved on the stack
102 when a task switch happens */
103 #define CPU_NUMREGS 0
105 /* Use this structure to save/restore registers if the stack is too
108 struct AROS_cpu_context
110 ULONG regs[9]; /* eip (PC), ebp (FP), eax, ebx, ecx, edx, edi, esi, eflags */
111 struct _fpstate fpstate; /* FPU state */
113 struct AROS_cpu_context * sc;
116 #undef SIZEOF_ALL_REGISTERS
117 #define SIZEOF_ALL_REGISTERS (sizeof (struct AROS_cpu_context))
118 #define GetCpuContext(task) ((struct AROS_cpu_context *)\
119 (GetIntETask(task)->iet_Context))
120 #define GetSP(task) ((SP_TYPE **)&task->tc_SPReg)
123 Macros to access the stack pointer, frame pointer and program
124 counter. The FP is the base address for accesses to arguments
125 and local variables of a function and PC is the current address
128 #define SP(sc) ((sc)->esp)
129 #define FP(sc) ((sc)->ebp)
130 #define PC(sc) ((sc)->eip)
133 Macros to enable or disable all signals after the signal handler
134 has returned and the normal execution commences.
136 #define SC_DISABLE(sc) ((sc)->oldmask = ~0L)
137 #define SC_ENABLE(sc) ((sc)->oldmask = 0L)
140 The names of the general purpose registers which are to be saved.
141 Use R and a number as name, no matter what the real name is.
142 General purpose registers (GPRs) are registers which can be
143 modified by the task (ie. data and address registers) and which are
144 not saved by the CPU when an interrupt happens.
146 #define R0(sc) ((sc)->eax)
147 #define R1(sc) ((sc)->ebx)
148 #define R2(sc) ((sc)->ecx)
149 #define R3(sc) ((sc)->edx)
150 #define R4(sc) ((sc)->edi)
151 #define R5(sc) ((sc)->esi)
152 #define R6(sc) ((sc)->eflags)
155 Save and restore the CPU GPRs in the CPU context
157 #define SAVE_CPU(cc,sc) \
160 (cc)->regs[0] = R0(sc); \
161 (cc)->regs[1] = R1(sc); \
162 (cc)->regs[2] = R2(sc); \
163 (cc)->regs[3] = R3(sc); \
164 (cc)->regs[4] = R4(sc); \
165 (cc)->regs[5] = R5(sc); \
166 (cc)->regs[6] = R6(sc); \
167 (cc)->regs[7] = FP(sc); \
168 (cc)->regs[8] = PC(sc); \
171 #define RESTORE_CPU(cc,sc) \
174 R0(sc) = (cc)->regs[0]; \
175 R1(sc) = (cc)->regs[1]; \
176 R2(sc) = (cc)->regs[2]; \
177 R3(sc) = (cc)->regs[3]; \
178 R4(sc) = (cc)->regs[4]; \
179 R5(sc) = (cc)->regs[5]; \
180 R6(sc) = (cc)->regs[6]; \
181 FP(sc) = (cc)->regs[7]; \
182 PC(sc) = (cc)->regs[8]; \
185 #define SAVE_ERRNO(cc) \
188 (cc)->errno_backup = errno; \
191 #define RESTORE_ERRNO(cc) \
194 errno = (cc)->errno_backup; \
198 It's not possible to save the FPU under linux because linux
199 uses the tasks stack to save the signal context. The signal
200 context conatins the SP *before* the sigcontext was pushed on
201 this stack, so it looks like this:
204 +--------------------------+
205 | last entry before signal |
206 +--------------------------+
207 | empty space | <--- SP
208 +--------------------------+
210 +--------------------------+
214 As you can see, SP points to the empty space. Now this empty space
215 is not very big. It's big enough that one can save the CPU
216 registers but not big enough for the FPU. *sigh*.
218 Attention: The above WAS TRUE for 2.0.x kernels but now the stack layout
219 looks different. See above!
221 Update: We store the registers in our own structure now
227 This macro returns 1 if an FPU is available.
230 # define HAS_FPU(sc) (sc->fpstate)
232 # define HAS_FPU(sc) 0
235 #define SAVE_FPU(cc,sc) \
239 (cc)->fpstate = *(sc)->fpstate; \
242 #define RESTORE_FPU(cc,sc) \
246 *(sc)->fpstate = (cc)->fpstate; \
250 Prepare the stack. This macro is used on the stack before a new
251 task is run for the first time. To create such a macro, you must
252 know how the system uses the stack. On Linux/i386, every stack
253 frame looks like this:
257 +------------------------+
259 +------------------------+
261 +------------------------+
262 | old frame pointer |
263 +------------------------+
265 +------------------------+
267 +------------------------+
270 stack grows from high to
273 The first routine gets no arguments, but if you want to pass
274 some to it, then you must push them on the stack before you
275 call this macro. Note that the arguments must be pushed in
276 reverse order, ie. if you want to call a function like this:
280 then you must prepare the stack like this:
285 PREPARE_INITIAL_FRAME(sp,func);
287 This is because the arguments are fetched relative to the FP
288 (ie. FP[0] is the old frame pointer, FP[1] is the return
289 address, FP[2] is the first argument, FP[3] is the second
294 # define PREPARE_INITIAL_FRAME(sp,pc) \
297 GetCpuContext(task)->regs[7] = 0; \
298 GetCpuContext(task)->regs[8] = (ULONG)pc; \
301 /* Here we have to setup a complete stack frame
302 so Exec_Exception thinks it was called as a
304 #define SETUP_EXCEPTION(sc,arg)\
307 _PUSH(GetSP(SysBase->ThisTask), arg); \
308 _PUSH(GetSP(SysBase->ThisTask), arg); \
312 Prepare the cpu context
317 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
318 asm volatile("fninit\n\t" \
320 "fwait" : "=m" (GetCpuContext(task)->fpstate))
324 #define PREPARE_INITIAL_CONTEXT(task,startpc)
329 This macro is similar to PREPARE_INITIAL_FRAME() but also saves
330 all general purpose registers. Use this macro when you want to
331 leave the current tasks' context to save the registers. Note that
332 the argument "sp" of the macro is just the name of the stack
333 pointer. The macro will load it from the sigcontext "sc". You
334 must store the value of "sp" after the macro and hand it to
335 RESTOREREGS() below to restore this context.
338 #define SAVEREGS(task,sc) \
341 struct AROS_cpu_context *cc = GetCpuContext(task); \
342 SP_TYPE **sp = GetSP(task); \
343 *sp = (SP_TYPE *)SP(sc); \
350 This macro does the opposite to SAVEREGS(). It restores all
351 general purpose registers. After that, you can enter the new
352 tasks' context. Both "sp" and "sc" must be initialized.
353 The macro will save the new SP into the sigcontext "sc".
356 # define RESTOREREGS(task,sc) \
359 struct AROS_cpu_context *cc = GetCpuContext(task); \
361 RESTORE_FPU(cc,sc); \
362 RESTORE_CPU(cc,sc); \
363 SP_TYPE** sp = GetSP(task); \
364 SP(sc) = (typeof(SP(sc))) *sp; \
368 /* This macro prints the current signals' context */
369 #define PRINT_SC(sc) \
370 printf (" SP=%08lx FP=%08lx PC=%08lx FPU=%s\n" \
371 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
372 " R4=%08lx R5=%08lx\n" \
373 , SP(sc), FP(sc), PC(sc) \
374 , HAS_FPU(sc) ? "yes" : "no" \
375 , R0(sc), R1(sc), R2(sc), R3(sc) \
379 /* This macro prints the current stack (after SAVEREGS()) */
380 #define PRINT_CPUCONTEXT(task) \
381 printf (" SP=%08lx FP=%08lx PC=%08lx\n" \
382 " R0=%08x R1=%08x R2=%08x R3=%08x\n" \
383 " R4=%08x R5=%08x\n" \
384 , (*GetSP(task))[ 0] \
385 , (*GetSP(task))[-1] \
386 , (*GetSP(task))[-2] \
387 , GetCpuContext(task)->regs[0] \
388 , GetCpuContext(task)->regs[1] \
389 , GetCpuContext(task)->regs[2] \
390 , GetCpuContext(task)->regs[3] \
391 , GetCpuContext(task)->regs[4] \
392 , GetCpuContext(task)->regs[5] \
395 #endif /* _SIGCORE_H */