Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / all-linux / x86_64 / sigcore.h.src
bloba03acfb00f16c27d772d57eab213636e8687193b
1 #ifndef _SIGCORE_H
2 #define _SIGCORE_H
4 /*
5     Copyright © 1995-2001, The AROS Development Team. All rights reserved.
6     $Id$
8     Desc: Macros to handle unix signals
9     Lang: english
12 /* There's no need for USE_SA_SIGINFO, as we always use SA_SIGINFO
13    on x86_64 - there's no other sane way to get ucontext. */ 
14 #define SIGCORE_NEED_SA_SIGINFO 1
15 #include <ucontext.h>
17 #include <signal.h>
18 #include <errno.h>
19 #include <stddef.h>
20 #include "etask.h"
22 /* Put a value of type SP_TYPE on the stack or get it off the stack. */
23 #define _PUSH(sp,val)       (*--sp = (SP_TYPE)(val))
24 #define _POP(sp)            (*sp++)
26 #ifndef _SIGNAL_H
27 #define _SIGNAL_H
28 #endif
29 #include <bits/sigcontext.h>
30 /* sigcontext_t is the type of the signals' context. Linux offers no way
31    to get this context in a legal way, so I have to use tricks. */
32 typedef @sigcontext@ sigcontext_t;
33 typedef @sighandler@ SignalHandler;
35 /* name and type of the signal handler */
36 #define SIGHANDLER      linux_sighandler
37 #define SIGHANDLER_T    SignalHandler
40     This macro contains some magic necessary to make it work.
41     The problem is that Linux offers no official way to obtain the
42     signals' context. Linux stores the signals' context on the
43     process' stack. It looks like this:
44     Attention: As of version 2.2 of the Linux kernel there is
45                not enough room on the stack anymore to save
46                any registers on it. So everything has to go into
47                the context structure. Previously PC and FP used 
48                to be saved on the stack but now this would over-
49                write some return address.
50                The stack you see below is the stack of the last 
51                active task within AROS. The linux kernel puts
52                all kinds of other junk on it.
54                     |                          |
55                     +--------------------------+
56                     | last entry before signal |
57                     +--------------------------+
58                     |      signal context      |
59                     +--------------------------+
60                     |      signal number       |
61                     +--------------------------+
62                     |      return address      | 
63                     +--------------------------+
64                     |                          |
66     so the address of the signal context is &sig+1.
69 #define GLOBAL_SIGNAL_INIT \
70         static void sighandler (int sig, sigcontext_t * sc);                    \
71                                                                                 \
72         static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u)   \
73         {                                                                       \
74             sighandler(sig, (sigcontext_t *)&u->uc_mcontext);                   \
75         }
77 /* Type of the values which can be stored on the stack. A variable
78    which is to be used as a stack pointer must be declared as
79    "SP_TYPE *". */
80 #define SP_TYPE     long
82 /* How many general purpose registers are to be saved on the stack
83    when a task switch happens */
84 #define CPU_NUMREGS             0
86 /* Use this structure to save/restore registers if the stack is too
87    small */
89 struct AROS_cpu_context
91     UQUAD regs[17];          /* rip (PC), rbp (FP), rax, rbx, rcx,
92                              rdx, rdi, rsi, r8, r9, r10, r11, r12,
93                              r13, r14, r15, eflags */
94     struct _fpstate fpstate __attribute__ ((aligned (16))); /* FPU state */
95     struct AROS_cpu_context * sc;
96     int errno_backup;
99 #define SIZEOF_ALL_REGISTERS    (sizeof (struct AROS_cpu_context))
100 #define GetCpuContext(task)     ((struct AROS_cpu_context *)\
101                                 (GetIntETask(task)->iet_Context))
102 #define GetSP(task)             (*(SP_TYPE **)&task->tc_SPReg)
105     Macros to access the stack pointer, frame pointer and program
106     counter. The FP is the base address for accesses to arguments
107     and local variables of a function and PC is the current address
108     in the program code.
110 #define SP(sc)           ((sc)->rsp)
111 #define FP(sc)           ((sc)->rbp)
112 #define PC(sc)           ((sc)->rip)
115     Macros to enable or disable all signals after the signal handler
116     has returned and the normal execution commences.
118     On Linux x86-64 signal mask is restored from uc_sigmask field of ucontext
119     structure. We are computing address of uc_sigmask field from address of 
120     uc_mcontext field given as sc parameter.
122 #define SC_DISABLE(sc) \
123     sigfillset((sigset_t*)((char*) sc + \
124         offsetof(struct ucontext, uc_sigmask) - \
125         offsetof(struct ucontext, uc_mcontext)) \
126     )
128 #define SC_ENABLE(sc) \
129     sigemptyset((sigset_t*)((char*) sc + \
130         offsetof(struct ucontext, uc_sigmask) - \
131         offsetof(struct ucontext, uc_mcontext)) \
132     )
135     The names of the general purpose registers which are to be saved.
136     Use R and a number as name, no matter what the real name is.
137     General purpose registers (GPRs) are registers which can be
138     modified by the task (ie. data and address registers) and which are
139     not saved by the CPU when an interrupt happens.
141 #define R0(sc)           ((sc)->rax)
142 #define R1(sc)           ((sc)->rbx)
143 #define R2(sc)           ((sc)->rcx)
144 #define R3(sc)           ((sc)->rdx)
145 #define R4(sc)           ((sc)->rdi)
146 #define R5(sc)           ((sc)->rsi)
147 #define R6(sc)           ((sc)->r8)
148 #define R7(sc)           ((sc)->r9)
149 #define R8(sc)           ((sc)->r10)
150 #define R9(sc)           ((sc)->r11)
151 #define R10(sc)           ((sc)->r12)
152 #define R11(sc)           ((sc)->r13)
153 #define R12(sc)           ((sc)->r14)
154 #define R13(sc)           ((sc)->r15)
155 #define R14(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] = R7(sc); \
171          (cc)->regs[8] = R8(sc); \
172          (cc)->regs[9] = R9(sc); \
173          (cc)->regs[10] = R10(sc); \
174          (cc)->regs[11] = R11(sc); \
175          (cc)->regs[12] = R12(sc); \
176          (cc)->regs[13] = R13(sc); \
177          (cc)->regs[14] = R14(sc); \
178          (cc)->regs[15] = FP(sc); \
179          (cc)->regs[16] = PC(sc); \
180     } while (0)
181          
182 #define RESTORE_CPU(cc,sc)       \
183     do                           \
184     {                            \
185          R0(sc) = (cc)->regs[0]; \
186          R1(sc) = (cc)->regs[1]; \
187          R2(sc) = (cc)->regs[2]; \
188          R3(sc) = (cc)->regs[3]; \
189          R4(sc) = (cc)->regs[4]; \
190          R5(sc) = (cc)->regs[5]; \
191          R6(sc) = (cc)->regs[6]; \
192          R7(sc) = (cc)->regs[7]; \
193          R8(sc) = (cc)->regs[8]; \
194          R9(sc) = (cc)->regs[9]; \
195          R10(sc) = (cc)->regs[10]; \
196          R11(sc) = (cc)->regs[11]; \
197          R12(sc) = (cc)->regs[12]; \
198          R13(sc) = (cc)->regs[13]; \
199          R14(sc) = (cc)->regs[14]; \
200          FP(sc) = (cc)->regs[15]; \
201          PC(sc) = (cc)->regs[16]; \
202     } while (0)
204 #define SAVE_ERRNO(cc) \
205     do                 \
206     {                  \
207         (cc)->errno_backup = errno; \
208     } while (0) 
209         
210 #define RESTORE_ERRNO(cc) \
211     do                    \
212     {                     \
213         errno = (cc)->errno_backup; \
214     } while (0)
217     It's not possible to save the FPU under linux because linux
218     uses the tasks stack to save the signal context. The signal
219     context conatins the SP *before* the sigcontext was pushed on
220     this stack, so it looks like this:
222                     |                          |
223                     +--------------------------+
224                     | last entry before signal |
225                     +--------------------------+
226                     |       empty space        | <--- SP
227                     +--------------------------+
228                     |      signal context      |
229                     +--------------------------+
230                     |                          |
233     As you can see, SP points to the empty space. Now this empty space
234     is not very big. It's big enough that one can save the CPU
235     registers but not big enough for the FPU. *sigh*.
237     Attention: The above WAS TRUE for 2.0.x kernels but now the stack layout
238                looks different. See above!
240     Update: We store the registers in our own structure now
243 /*  define NO_FPU */
245     This macro returns 1 if an FPU is available.
247 #ifndef NO_FPU
248 #   define HAS_FPU(sc)      (sc->fpstate)
249 #else
250 #   define HAS_FPU(sc)      0
251 #endif
253 #define SAVE_FPU(cc,sc)                         \
254         do                                      \
255         {                                       \
256             if (HAS_FPU(sc))                    \
257                 (cc)->fpstate = *(sc)->fpstate; \
258         } while (0)
260 #define RESTORE_FPU(cc,sc)                      \
261         do                                      \
262         {                                       \
263             if (HAS_FPU(sc))                    \
264                 *(sc)->fpstate = (cc)->fpstate; \
265         } while (0)
268     Prepare the stack. This macro is used on the stack before a new
269     task is run for the first time. To create such a macro, you must
270     know how the system uses the stack. On Linux/i386, every stack
271     frame looks like this:
273                                                  high adresses
274                     |          ...           |
275                     +------------------------+
276                     |       arguments        |
277                     +------------------------+
278                     |     return address     |
279                     +------------------------+
280                     |   old frame pointer    |
281                     +------------------------+
282                     |    local variables     |
283                     +------------------------+
284                     |    saved registers     |
285                     +------------------------+
286                     |          ...           |
287                                                 low addresses
288                                                 stack grows from high to
289                                                 low addresses.
291     The first routine gets no arguments, but if you want to pass
292     some to it, then you must push them on the stack before you
293     call this macro. Note that the arguments must be pushed in
294     reverse order, ie. if you want to call a function like this:
296             func (a,b,c);
298     then you must prepare the stack like this:
300             _PUSH(sp,c);
301             _PUSH(sp,b);
302             _PUSH(sp,a);
303             PREPARE_INITIAL_FRAME(sp,func);
305     This is because the arguments are fetched relative to the FP
306     (ie. FP[0] is the old frame pointer, FP[1] is the return
307     address, FP[2] is the first argument, FP[3] is the second
308     and so on).
312 #   define PREPARE_INITIAL_FRAME(sp,pc)       \
313         do                                    \
314         {                                     \
315             GetCpuContext(task)->regs[15] = 0; \
316             GetCpuContext(task)->regs[16] = (UQUAD)pc; \
317         } while (0)
319 /* Here we have to setup a complete stack frame
320     so Exec_Exception thinks it was called as a
321     normal function. */
322 #define SETUP_EXCEPTION(sc,arg)\
323         do                                        \
324         {                                         \
325             _PUSH(GetSP(SysBase->ThisTask), arg); \
326             _PUSH(GetSP(SysBase->ThisTask), arg); \
327         } while (0)
330     Prepare the cpu context
333 #ifndef NO_FPU
335 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
336    asm volatile("fninit\n\t" \
337                 "fxsave %0\n\t" \
338                 "fwait" : "=m" (GetCpuContext(task)->fpstate))
340 #else
342 #define PREPARE_INITIAL_CONTEXT(task,startpc)
344 #endif
347     Store first six arguments in registers, the rest on stack
350 #define PREPARE_INITIAL_ARGS(task, args, numargs) \
351     UQUAD* regs = GetIntETask (task)->iet_Context;\
352     int argcounter = numargs;                     \
353     while (argcounter > 6)                        \
354         _PUSH(GetSP(task), args[--argcounter]);   \
355     switch (argcounter)                           \
356     {                                             \
357         case 6:                                   \
358             regs[7] = args[5];                    \
359         case 5:                                   \
360             regs[6] = args[4];                    \
361         case 4:                                   \
362             regs[2] = args[3];                    \
363         case 3:                                   \
364             regs[3] = args[2];                    \
365         case 2:                                   \
366             regs[5] = args[1];                    \
367         case 1:                                   \
368             regs[4] = args[0];                    \
369             break;                                \
370     }
373     This macro is similar to PREPARE_INITIAL_FRAME() but also saves
374     all general purpose registers. Use this macro when you want to
375     leave the current tasks' context to save the registers. Note that
376     the argument "sp" of the macro is just the name of the stack
377     pointer. The macro will load it from the sigcontext "sc". You
378     must store the value of "sp" after the macro and hand it to
379     RESTOREREGS() below to restore this context.
382 #define SAVEREGS(task,sc)                                  \
383     do                                                     \
384     {                                                      \
385         struct AROS_cpu_context *cc = GetCpuContext(task); \
386         GetSP(task) = (SP_TYPE *)SP(sc); \
387         SAVE_FPU(cc,sc);                 \
388         SAVE_CPU(cc,sc);                 \
389         SAVE_ERRNO(cc);                  \
390     } while (0)
393     This macro does the opposite to SAVEREGS(). It restores all
394     general purpose registers. After that, you can enter the new
395     tasks' context. Both "sp" and "sc" must be initialized.
396     The macro will save the new SP into the sigcontext "sc".
399 #   define RESTOREREGS(task,sc) \
400     do                                                     \
401     {                                                      \
402         struct AROS_cpu_context *cc = GetCpuContext(task); \
403         RESTORE_ERRNO(cc);    \
404         RESTORE_FPU(cc,sc);   \
405         RESTORE_CPU(cc,sc);   \
406         SP(sc) = (typeof(SP(sc)))GetSP(task); \
407     } while (0)
410     /* This macro prints the current signals' context */
411 #define PRINT_SC(sc) \
412         printf ("    SP=%08lx  FP=%08lx  PC=%08lx  FPU=%s\n" \
413                 "    R0=%08lx  R1=%08lx  R2=%08lx  R3=%08lx\n" \
414                 "    R4=%08lx  R5=%08lx  R6=%08lx  R7=%08lx\n" \
415                 "    R8=%08lx  R9=%08lx  R10=%08lx  R11=%08lx\n" \
416                 "    R12=%08lx  R13=%08lx R14=%08lx\n" \
417             , SP(sc), FP(sc), PC(sc) \
418             , HAS_FPU(sc) ? "yes" : "no" \
419             , R0(sc), R1(sc), R2(sc), R3(sc) \
420             , R4(sc), R5(sc), R6(sc), R7(sc), R8(sc), R9(sc) \
421             , R10(sc), R11(sc), R12(sc), R13(sc), R14(sc) \
422         )
424     /* This macro prints the current stack (after SAVEREGS()) */
425 #define PRINT_CPUCONTEXT(task) \
426         printf ("    SP=%08lx  FP=%08lx  PC=%08lx\n" \
427                 "    R0=%08lx  R1=%08lx  R2=%08lx  R3=%08lx\n" \
428                 "    R4=%08lx  R5=%08lx\n" \
429             , (ULONG)(GetSP(task)) \
430             , GetCpuContext(task)->regs[15] \
431             , GetCpuContext(task)->regs[16] \
432             , GetCpuContext(task)->regs[0] \
433             , GetCpuContext(task)->regs[1] \
434             , GetCpuContext(task)->regs[2] \
435             , GetCpuContext(task)->regs[3] \
436             , GetCpuContext(task)->regs[4] \
437             , GetCpuContext(task)->regs[5] \
438             , GetCpuContext(task)->regs[6] \
439             , GetCpuContext(task)->regs[7] \
440             , GetCpuContext(task)->regs[8] \
441             , GetCpuContext(task)->regs[9] \
442             , GetCpuContext(task)->regs[10] \
443             , GetCpuContext(task)->regs[11] \
444             , GetCpuContext(task)->regs[12] \
445             , GetCpuContext(task)->regs[13] \
446             , GetCpuContext(task)->regs[14] \
447         )
449 #endif /* _SIGCORE_H */