define __KERNEL_STRICT_NAMES to avoid inclusion of kernel types on systems that carry...
[cake.git] / arch / all-linux / i386 / sigcore.h.src
blobe47573c71d74fa44ca365ee58e0179f56b41bde7
1 #ifndef _SIGCORE_H
2 #define _SIGCORE_H
4 /*
5     Copyright © 1995-2009, The AROS Development Team. All rights reserved.
6     $Id$
8     Desc: Macros to handle unix signals
9     Lang: english
12 #define USE_SA_SIGINFO 0
14 #if USE_SA_SIGINFO
15 #define SIGCORE_NEED_SA_SIGINFO 1
16 #include <ucontext.h>
17 #endif
19 #include <signal.h>
20 #include <errno.h>
21 #include "etask.h"
23 /* Put a value of type SP_TYPE on the stack or get it off the stack. */
24 #define _PUSH(sp,val)              \
25     do                             \
26     {                              \
27        SP_TYPE **stackp = (sp);    \
28        --*stackp;                  \
29        **stackp = (SP_TYPE) (val); \
30     } while (0)
31 #define _POP(sp)            (*sp++)
33 #ifndef _SIGNAL_H
34 #define _SIGNAL_H
35 #endif
36 #ifndef __KERNEL_STRICT_NAMES
37 #define __KERNEL_STRICT_NAMES
38 #endif
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.
64                     |                          |
65                     +--------------------------+
66                     | last entry before signal |
67                     +--------------------------+
68                     |      signal context      |
69                     +--------------------------+
70                     |      signal number       |
71                     +--------------------------+
72                     |      return address      | 
73                     +--------------------------+
74                     |                          |
76     so the address of the signal context is &sig+1.
79 #if USE_SA_SIGINFO
80 #define GLOBAL_SIGNAL_INIT \
81         static void sighandler (int sig, sigcontext_t * sc);                    \
82                                                                                 \
83         static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u)   \
84         {                                                                       \
85             sighandler(sig, (sigcontext_t *)&u->uc_mcontext);                   \
86         }
88 #else
90 #define GLOBAL_SIGNAL_INIT \
91         static void sighandler (int sig, sigcontext_t * sc);    \
92                                                                 \
93         static void SIGHANDLER (int sig)                        \
94         {                                                       \
95             sighandler (sig, (sigcontext_t *)(&sig+1));         \
96         }
97 #endif
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
101    "SP_TYPE *". */
102 #define SP_TYPE     long
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
109    small */
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 */
115     int                       errno_backup;
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
129     in the program code.
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)          \
161     do                           \
162     {                            \
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); \
172     } while (0)
173          
174 #define RESTORE_CPU(cc,sc)       \
175     do                           \
176     {                            \
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]; \
186     } while (0)
188 #define SAVE_ERRNO(cc) \
189     do                 \
190     {                  \
191         (cc)->errno_backup = errno; \
192     } while (0) 
193         
194 #define RESTORE_ERRNO(cc) \
195     do                    \
196     {                     \
197         errno = (cc)->errno_backup; \
198     } while (0)
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:
206                     |                          |
207                     +--------------------------+
208                     | last entry before signal |
209                     +--------------------------+
210                     |       empty space        | <--- SP
211                     +--------------------------+
212                     |      signal context      |
213                     +--------------------------+
214                     |                          |
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
227 //#   define NO_FPU
230     This macro returns 1 if an FPU is available.
232 #ifndef NO_FPU
233 #   define HAS_FPU(sc)      (sc->fpstate)
234 #else
235 #   define HAS_FPU(sc)      0
236 #endif
238 #define SAVE_FPU(cc,sc)                         \
239         do                                      \
240         {                                       \
241             if (HAS_FPU(sc))                    \
242                 (cc)->fpstate = *(sc)->fpstate; \
243         } while (0)
245 #define RESTORE_FPU(cc,sc)                      \
246         do                                      \
247         {                                       \
248             if (HAS_FPU(sc))                    \
249                 *(sc)->fpstate = (cc)->fpstate; \
250         } while (0)
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:
258                                                  high adresses
259                     |          ...           |
260                     +------------------------+
261                     |       arguments        |
262                     +------------------------+
263                     |     return address     |
264                     +------------------------+
265                     |   old frame pointer    |
266                     +------------------------+
267                     |    local variables     |
268                     +------------------------+
269                     |    saved registers     |
270                     +------------------------+
271                     |          ...           |
272                                                 low addresses
273                                                 stack grows from high to
274                                                 low addresses.
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:
281             func (a,b,c);
283     then you must prepare the stack like this:
285             _PUSH(sp,c);
286             _PUSH(sp,b);
287             _PUSH(sp,a);
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
293     and so on).
297 #   define PREPARE_INITIAL_FRAME(sp,pc)       \
298         do                                    \
299         {                                     \
300             GetCpuContext(task)->regs[7] = 0; \
301             GetCpuContext(task)->regs[8] = (ULONG)pc; \
302         } while (0)
304 /* Here we have to setup a complete stack frame
305     so Exec_Exception thinks it was called as a
306     normal function. */
307 #define SETUP_EXCEPTION(sc,arg)\
308         do                                        \
309         {                                         \
310             _PUSH(GetSP(SysBase->ThisTask), arg); \
311             _PUSH(GetSP(SysBase->ThisTask), arg); \
312         } while (0)
315     Prepare the cpu context
318 #ifndef NO_FPU
320 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
321    asm volatile("fninit\n\t" \
322                 "fnsave %0\n\t" \
323                 "fwait" : "=m" (GetCpuContext(task)->fpstate))
325 #else
327 #define PREPARE_INITIAL_CONTEXT(task,startpc)
329 #endif
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)                                  \
342     do                                                     \
343     {                                                      \
344         struct AROS_cpu_context *cc = GetCpuContext(task); \
345         SP_TYPE **sp = GetSP(task);      \
346         *sp = (SP_TYPE *)SP(sc);         \
347         SAVE_FPU(cc,sc);                 \
348         SAVE_CPU(cc,sc);                 \
349         SAVE_ERRNO(cc);                  \
350     } while (0)
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) \
360     do                                                     \
361     {                                                      \
362         struct AROS_cpu_context *cc = GetCpuContext(task); \
363         RESTORE_ERRNO(cc);    \
364         RESTORE_FPU(cc,sc);   \
365         RESTORE_CPU(cc,sc);   \
366         SP_TYPE** sp = GetSP(task);    \
367         SP(sc) = (typeof(SP(sc))) *sp; \
368     } while (0)
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) \
379             , R4(sc), R5(sc) \
380         )
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] \
396         )
398 #endif /* _SIGCORE_H */