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 #ifndef __KERNEL_STRICT_NAMES
37 #define __KERNEL_STRICT_NAMES
39 #include <bits/sigcontext.h>
40 /* sigcontext_t is the type of the signals' context. Linux offers no way
41 to get this context in a legal way, so I have to use tricks. */
42 typedef @sigcontext@ sigcontext_t;
43 typedef @sighandler@ SignalHandler;
45 /* name and type of the signal handler */
46 #define SIGHANDLER linux_sighandler
47 #define SIGHANDLER_T SignalHandler
50 This macro contains some magic necessary to make it work.
51 The problem is that Linux offers no official way to obtain the
52 signals' context. Linux stores the signals' context on the
53 process' stack. It looks like this:
54 Attention: As of version 2.2 of the Linux kernel there is
55 not enough room on the stack anymore to save
56 any registers on it. So everything has to go into
57 the context structure. Previously PC and FP used
58 to be saved on the stack but now this would over-
59 write some return address.
60 The stack you see below is the stack of the last
61 active task within AROS. The linux kernel puts
62 all kinds of other junk on it.
65 +--------------------------+
66 | last entry before signal |
67 +--------------------------+
69 +--------------------------+
71 +--------------------------+
73 +--------------------------+
76 so the address of the signal context is &sig+1.
80 #define GLOBAL_SIGNAL_INIT \
81 static void sighandler (int sig, sigcontext_t * sc); \
83 static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u) \
85 sighandler(sig, (sigcontext_t *)&u->uc_mcontext); \
90 #define GLOBAL_SIGNAL_INIT \
91 static void sighandler (int sig, sigcontext_t * sc); \
93 static void SIGHANDLER (int sig) \
95 sighandler (sig, (sigcontext_t *)(&sig+1)); \
99 /* Type of the values which can be stored on the stack. A variable
100 which is to be used as a stack pointer must be declared as
104 /* How many general purpose registers are to be saved on the stack
105 when a task switch happens */
106 #define CPU_NUMREGS 0
108 /* Use this structure to save/restore registers if the stack is too
111 struct AROS_cpu_context
113 ULONG regs[9]; /* eip (PC), ebp (FP), eax, ebx, ecx, edx, edi, esi, eflags */
114 struct _fpstate fpstate; /* FPU state */
116 struct AROS_cpu_context * sc;
119 #undef SIZEOF_ALL_REGISTERS
120 #define SIZEOF_ALL_REGISTERS (sizeof (struct AROS_cpu_context))
121 #define GetCpuContext(task) ((struct AROS_cpu_context *)\
122 (GetIntETask(task)->iet_Context))
123 #define GetSP(task) ((SP_TYPE **)&task->tc_SPReg)
126 Macros to access the stack pointer, frame pointer and program
127 counter. The FP is the base address for accesses to arguments
128 and local variables of a function and PC is the current address
131 #define SP(sc) ((sc)->esp)
132 #define FP(sc) ((sc)->ebp)
133 #define PC(sc) ((sc)->eip)
136 Macros to enable or disable all signals after the signal handler
137 has returned and the normal execution commences.
139 #define SC_DISABLE(sc) ((sc)->oldmask = ~0L)
140 #define SC_ENABLE(sc) ((sc)->oldmask = 0L)
143 The names of the general purpose registers which are to be saved.
144 Use R and a number as name, no matter what the real name is.
145 General purpose registers (GPRs) are registers which can be
146 modified by the task (ie. data and address registers) and which are
147 not saved by the CPU when an interrupt happens.
149 #define R0(sc) ((sc)->eax)
150 #define R1(sc) ((sc)->ebx)
151 #define R2(sc) ((sc)->ecx)
152 #define R3(sc) ((sc)->edx)
153 #define R4(sc) ((sc)->edi)
154 #define R5(sc) ((sc)->esi)
155 #define R6(sc) ((sc)->eflags)
158 Save and restore the CPU GPRs in the CPU context
160 #define SAVE_CPU(cc,sc) \
163 (cc)->regs[0] = R0(sc); \
164 (cc)->regs[1] = R1(sc); \
165 (cc)->regs[2] = R2(sc); \
166 (cc)->regs[3] = R3(sc); \
167 (cc)->regs[4] = R4(sc); \
168 (cc)->regs[5] = R5(sc); \
169 (cc)->regs[6] = R6(sc); \
170 (cc)->regs[7] = FP(sc); \
171 (cc)->regs[8] = PC(sc); \
174 #define RESTORE_CPU(cc,sc) \
177 R0(sc) = (cc)->regs[0]; \
178 R1(sc) = (cc)->regs[1]; \
179 R2(sc) = (cc)->regs[2]; \
180 R3(sc) = (cc)->regs[3]; \
181 R4(sc) = (cc)->regs[4]; \
182 R5(sc) = (cc)->regs[5]; \
183 R6(sc) = (cc)->regs[6]; \
184 FP(sc) = (cc)->regs[7]; \
185 PC(sc) = (cc)->regs[8]; \
188 #define SAVE_ERRNO(cc) \
191 (cc)->errno_backup = errno; \
194 #define RESTORE_ERRNO(cc) \
197 errno = (cc)->errno_backup; \
201 It's not possible to save the FPU under linux because linux
202 uses the tasks stack to save the signal context. The signal
203 context conatins the SP *before* the sigcontext was pushed on
204 this stack, so it looks like this:
207 +--------------------------+
208 | last entry before signal |
209 +--------------------------+
210 | empty space | <--- SP
211 +--------------------------+
213 +--------------------------+
217 As you can see, SP points to the empty space. Now this empty space
218 is not very big. It's big enough that one can save the CPU
219 registers but not big enough for the FPU. *sigh*.
221 Attention: The above WAS TRUE for 2.0.x kernels but now the stack layout
222 looks different. See above!
224 Update: We store the registers in our own structure now
230 This macro returns 1 if an FPU is available.
233 # define HAS_FPU(sc) (sc->fpstate)
235 # define HAS_FPU(sc) 0
238 #define SAVE_FPU(cc,sc) \
242 (cc)->fpstate = *(sc)->fpstate; \
245 #define RESTORE_FPU(cc,sc) \
249 *(sc)->fpstate = (cc)->fpstate; \
253 Prepare the stack. This macro is used on the stack before a new
254 task is run for the first time. To create such a macro, you must
255 know how the system uses the stack. On Linux/i386, every stack
256 frame looks like this:
260 +------------------------+
262 +------------------------+
264 +------------------------+
265 | old frame pointer |
266 +------------------------+
268 +------------------------+
270 +------------------------+
273 stack grows from high to
276 The first routine gets no arguments, but if you want to pass
277 some to it, then you must push them on the stack before you
278 call this macro. Note that the arguments must be pushed in
279 reverse order, ie. if you want to call a function like this:
283 then you must prepare the stack like this:
288 PREPARE_INITIAL_FRAME(sp,func);
290 This is because the arguments are fetched relative to the FP
291 (ie. FP[0] is the old frame pointer, FP[1] is the return
292 address, FP[2] is the first argument, FP[3] is the second
297 # define PREPARE_INITIAL_FRAME(sp,pc) \
300 GetCpuContext(task)->regs[7] = 0; \
301 GetCpuContext(task)->regs[8] = (ULONG)pc; \
304 /* Here we have to setup a complete stack frame
305 so Exec_Exception thinks it was called as a
307 #define SETUP_EXCEPTION(sc,arg)\
310 _PUSH(GetSP(SysBase->ThisTask), arg); \
311 _PUSH(GetSP(SysBase->ThisTask), arg); \
315 Prepare the cpu context
320 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
321 asm volatile("fninit\n\t" \
323 "fwait" : "=m" (GetCpuContext(task)->fpstate))
327 #define PREPARE_INITIAL_CONTEXT(task,startpc)
332 This macro is similar to PREPARE_INITIAL_FRAME() but also saves
333 all general purpose registers. Use this macro when you want to
334 leave the current tasks' context to save the registers. Note that
335 the argument "sp" of the macro is just the name of the stack
336 pointer. The macro will load it from the sigcontext "sc". You
337 must store the value of "sp" after the macro and hand it to
338 RESTOREREGS() below to restore this context.
341 #define SAVEREGS(task,sc) \
344 struct AROS_cpu_context *cc = GetCpuContext(task); \
345 SP_TYPE **sp = GetSP(task); \
346 *sp = (SP_TYPE *)SP(sc); \
353 This macro does the opposite to SAVEREGS(). It restores all
354 general purpose registers. After that, you can enter the new
355 tasks' context. Both "sp" and "sc" must be initialized.
356 The macro will save the new SP into the sigcontext "sc".
359 # define RESTOREREGS(task,sc) \
362 struct AROS_cpu_context *cc = GetCpuContext(task); \
364 RESTORE_FPU(cc,sc); \
365 RESTORE_CPU(cc,sc); \
366 SP_TYPE** sp = GetSP(task); \
367 SP(sc) = (typeof(SP(sc))) *sp; \
371 /* This macro prints the current signals' context */
372 #define PRINT_SC(sc) \
373 printf (" SP=%08lx FP=%08lx PC=%08lx FPU=%s\n" \
374 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
375 " R4=%08lx R5=%08lx\n" \
376 , SP(sc), FP(sc), PC(sc) \
377 , HAS_FPU(sc) ? "yes" : "no" \
378 , R0(sc), R1(sc), R2(sc), R3(sc) \
382 /* This macro prints the current stack (after SAVEREGS()) */
383 #define PRINT_CPUCONTEXT(task) \
384 printf (" SP=%08lx FP=%08lx PC=%08lx\n" \
385 " R0=%08x R1=%08x R2=%08x R3=%08x\n" \
386 " R4=%08x R5=%08x\n" \
387 , (*GetSP(task))[ 0] \
388 , (*GetSP(task))[-1] \
389 , (*GetSP(task))[-2] \
390 , GetCpuContext(task)->regs[0] \
391 , GetCpuContext(task)->regs[1] \
392 , GetCpuContext(task)->regs[2] \
393 , GetCpuContext(task)->regs[3] \
394 , GetCpuContext(task)->regs[4] \
395 , GetCpuContext(task)->regs[5] \
398 #endif /* _SIGCORE_H */