5 Copyright © 1995-2001, 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) (*--sp = (SP_TYPE)(val))
25 #define _POP(sp) (*sp++)
30 #include <bits/sigcontext.h>
31 /* sigcontext_t is the type of the signals' context. Linux offers no way
32 to get this context in a legal way, so I have to use tricks. */
33 typedef @sigcontext@ sigcontext_t;
34 typedef @sighandler@ SignalHandler;
36 /* name and type of the signal handler */
37 #define SIGHANDLER linux_sighandler
38 #define SIGHANDLER_T SignalHandler
41 This macro contains some magic necessary to make it work.
42 The problem is that Linux offers no official way to obtain the
43 signals' context. Linux stores the signals' context on the
44 process' stack. It looks like this:
45 Attention: As of version 2.2 of the Linux kernel there is
46 not enough room on the stack anymore to save
47 any registers on it. So everything has to go into
48 the context structure. Previously PC and FP used
49 to be saved on the stack but now this would over-
50 write some return address.
51 The stack you see below is the stack of the last
52 active task within AROS. The linux kernel puts
53 all kinds of other junk on it.
56 +--------------------------+
57 | last entry before signal |
58 +--------------------------+
60 +--------------------------+
62 +--------------------------+
64 +--------------------------+
67 so the address of the signal context is &sig+1.
71 #define GLOBAL_SIGNAL_INIT \
72 static void sighandler (int sig, sigcontext_t * sc); \
74 static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u) \
76 sighandler(sig, (sigcontext_t *)&u->uc_mcontext); \
81 #define GLOBAL_SIGNAL_INIT \
82 static void sighandler (int sig, sigcontext_t * sc); \
84 static void SIGHANDLER (int sig) \
86 sighandler (sig, (sigcontext_t *)(&sig+1)); \
90 /* Type of the values which can be stored on the stack. A variable
91 which is to be used as a stack pointer must be declared as
95 /* How many general purpose registers are to be saved on the stack
96 when a task switch happens */
99 /* Use this structure to save/restore registers if the stack is too
102 struct AROS_cpu_context
104 ULONG regs[17]; /* rip (PC), rbp (FP), rax, rbx, rcx,
105 rdx, rdi, rsi, r8, r9, r10, r11, r12,
106 r13, r14, r15, eflags */
107 struct _fpstate *fpstate; /* FPU state */
111 #define SIZEOF_ALL_REGISTERS (sizeof (struct AROS_cpu_context))
112 #define GetCpuContext(task) ((struct AROS_cpu_context *)\
113 (GetIntETask(task)->iet_Context))
114 #define GetSP(task) (*(SP_TYPE **)&task->tc_SPReg)
117 Macros to access the stack pointer, frame pointer and program
118 counter. The FP is the base address for accesses to arguments
119 and local variables of a function and PC is the current address
122 #define SP(sc) ((sc)->rsp)
123 #define FP(sc) ((sc)->rbp)
124 #define PC(sc) ((sc)->rip)
127 Macros to enable or disable all signals after the signal handler
128 has returned and the normal execution commences.
130 #define SC_DISABLE(sc) ((sc)->oldmask = ~0L)
131 #define SC_ENABLE(sc) ((sc)->oldmask = 0L)
134 The names of the general purpose registers which are to be saved.
135 Use R and a number as name, no matter what the real name is.
136 General purpose registers (GPRs) are registers which can be
137 modified by the task (ie. data and address registers) and which are
138 not saved by the CPU when an interrupt happens.
140 #define R0(sc) ((sc)->rax)
141 #define R1(sc) ((sc)->rbx)
142 #define R2(sc) ((sc)->rcx)
143 #define R3(sc) ((sc)->rdx)
144 #define R4(sc) ((sc)->rdi)
145 #define R5(sc) ((sc)->rsi)
146 #define R6(sc) ((sc)->r8)
147 #define R7(sc) ((sc)->r9)
148 #define R8(sc) ((sc)->r10)
149 #define R9(sc) ((sc)->r11)
150 #define R10(sc) ((sc)->r12)
151 #define R11(sc) ((sc)->r13)
152 #define R12(sc) ((sc)->r14)
153 #define R13(sc) ((sc)->r15)
154 #define R14(sc) ((sc)->eflags)
157 Save and restore the CPU GPRs in the CPU context
159 #define SAVE_CPU(cc,sc) \
162 (cc)->regs[0] = R0(sc); \
163 (cc)->regs[1] = R1(sc); \
164 (cc)->regs[2] = R2(sc); \
165 (cc)->regs[3] = R3(sc); \
166 (cc)->regs[4] = R4(sc); \
167 (cc)->regs[5] = R5(sc); \
168 (cc)->regs[6] = R6(sc); \
169 (cc)->regs[7] = R7(sc); \
170 (cc)->regs[8] = R8(sc); \
171 (cc)->regs[9] = R9(sc); \
172 (cc)->regs[10] = R10(sc); \
173 (cc)->regs[11] = R11(sc); \
174 (cc)->regs[12] = R12(sc); \
175 (cc)->regs[13] = R13(sc); \
176 (cc)->regs[14] = R14(sc); \
177 (cc)->regs[15] = FP(sc); \
178 (cc)->regs[16] = PC(sc); \
181 #define RESTORE_CPU(cc,sc) \
184 R0(sc) = (cc)->regs[0]; \
185 R1(sc) = (cc)->regs[1]; \
186 R2(sc) = (cc)->regs[2]; \
187 R3(sc) = (cc)->regs[3]; \
188 R4(sc) = (cc)->regs[4]; \
189 R5(sc) = (cc)->regs[5]; \
190 R6(sc) = (cc)->regs[6]; \
191 R7(sc) = (cc)->regs[7]; \
192 R8(sc) = (cc)->regs[8]; \
193 R9(sc) = (cc)->regs[9]; \
194 R10(sc) = (cc)->regs[10]; \
195 R11(sc) = (cc)->regs[11]; \
196 R12(sc) = (cc)->regs[12]; \
197 R13(sc) = (cc)->regs[13]; \
198 R14(sc) = (cc)->regs[14]; \
199 FP(sc) = (cc)->regs[15]; \
200 PC(sc) = (cc)->regs[16]; \
203 #define SAVE_ERRNO(cc) \
206 (cc)->errno_backup = errno; \
209 #define RESTORE_ERRNO(cc) \
212 errno = (cc)->errno_backup; \
216 It's not possible to save the FPU under linux because linux
217 uses the tasks stack to save the signal context. The signal
218 context conatins the SP *before* the sigcontext was pushed on
219 this stack, so it looks like this:
222 +--------------------------+
223 | last entry before signal |
224 +--------------------------+
225 | empty space | <--- SP
226 +--------------------------+
228 +--------------------------+
232 As you can see, SP points to the empty space. Now this empty space
233 is not very big. It's big enough that one can save the CPU
234 registers but not big enough for the FPU. *sigh*.
236 Attention: The above WAS TRUE for 2.0.x kernels but now the stack layout
237 looks different. See above!
239 Update: We store the registers in our own structure now
244 This macro returns 1 if an FPU is available.
247 # define HAS_FPU(sc) (sc->fpstate)
249 # define HAS_FPU(sc) 0
252 #define SAVE_FPU(cc,sc) \
256 (cc)->fpstate = (sc)->fpstate; \
259 #define RESTORE_FPU(cc,sc) \
263 (sc)->fpstate = (cc)->fpstate; \
267 Prepare the stack. This macro is used on the stack before a new
268 task is run for the first time. To create such a macro, you must
269 know how the system uses the stack. On Linux/i386, every stack
270 frame looks like this:
274 +------------------------+
276 +------------------------+
278 +------------------------+
279 | old frame pointer |
280 +------------------------+
282 +------------------------+
284 +------------------------+
287 stack grows from high to
290 The first routine gets no arguments, but if you want to pass
291 some to it, then you must push them on the stack before you
292 call this macro. Note that the arguments must be pushed in
293 reverse order, ie. if you want to call a function like this:
297 then you must prepare the stack like this:
302 PREPARE_INITIAL_FRAME(sp,func);
304 This is because the arguments are fetched relative to the FP
305 (ie. FP[0] is the old frame pointer, FP[1] is the return
306 address, FP[2] is the first argument, FP[3] is the second
311 # define PREPARE_INITIAL_FRAME(sp,pc) \
314 GetCpuContext(task)->regs[15] = 0; \
315 GetCpuContext(task)->regs[16] = (ULONG)pc; \
320 Prepare the cpu context
325 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
326 asm volatile("fninit\n\t" \
328 "fwait" : "=m" (GetCpuContext(task)->fpstate))
332 #define PREPARE_INITIAL_CONTEXT(task,startpc)
337 This macro is similar to PREPARE_INITIAL_FRAME() but also saves
338 all general purpose registers. Use this macro when you want to
339 leave the current tasks' context to save the registers. Note that
340 the argument "sp" of the macro is just the name of the stack
341 pointer. The macro will load it from the sigcontext "sc". You
342 must store the value of "sp" after the macro and hand it to
343 RESTOREREGS() below to restore this context.
346 #define SAVEREGS(task,sc) \
349 struct AROS_cpu_context *cc = GetCpuContext(task); \
350 GetSP(task) = (SP_TYPE *)SP(sc); \
357 This macro does the opposite to SAVEREGS(). It restores all
358 general purpose registers. After that, you can enter the new
359 tasks' context. Both "sp" and "sc" must be initialized.
360 The macro will save the new SP into the sigcontext "sc".
363 # define RESTOREREGS(task,sc) \
366 struct AROS_cpu_context *cc = GetCpuContext(task); \
368 RESTORE_FPU(cc,sc); \
369 RESTORE_CPU(cc,sc); \
370 SP(sc) = (typeof(SP(sc)))GetSP(task); \
374 /* This macro prints the current signals' context */
375 #define PRINT_SC(sc) \
376 printf (" SP=%08lx FP=%08lx PC=%08lx FPU=%s\n" \
377 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
378 " R4=%08lx R5=%08lx R6=%08lx R7=%08lx\n" \
379 " R8=%08lx R9=%08lx R10=%08lx R11=%08lx\n" \
380 " R12=%08lx R13=%08lx R14=%08lx\n" \
381 , SP(sc), FP(sc), PC(sc) \
382 , HAS_FPU(sc) ? "yes" : "no" \
383 , R0(sc), R1(sc), R2(sc), R3(sc) \
384 , R4(sc), R5(sc), R6(sc), R7(sc), R8(sc), R9(sc) \
385 , R10(sc), R11(sc), R12(sc), R13(sc), R14(sc) \
388 /* This macro prints the current stack (after SAVEREGS()) */
389 #define PRINT_CPUCONTEXT(task) \
390 printf (" SP=%08lx FP=%08lx PC=%08lx\n" \
391 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
392 " R4=%08lx R5=%08lx\n" \
393 , (ULONG)(GetSP(task)) \
394 , GetCpuContext(task)->regs[15] \
395 , GetCpuContext(task)->regs[16] \
396 , GetCpuContext(task)->regs[0] \
397 , GetCpuContext(task)->regs[1] \
398 , GetCpuContext(task)->regs[2] \
399 , GetCpuContext(task)->regs[3] \
400 , GetCpuContext(task)->regs[4] \
401 , GetCpuContext(task)->regs[5] \
402 , GetCpuContext(task)->regs[6] \
403 , GetCpuContext(task)->regs[7] \
404 , GetCpuContext(task)->regs[8] \
405 , GetCpuContext(task)->regs[9] \
406 , GetCpuContext(task)->regs[10] \
407 , GetCpuContext(task)->regs[11] \
408 , GetCpuContext(task)->regs[12] \
409 , GetCpuContext(task)->regs[13] \
410 , GetCpuContext(task)->regs[14] \
413 #endif /* _SIGCORE_H */