added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / all-linux / x86_64 / sigcore.h.src
blob13dc39a63a9db68ea20abbfed63ca265baf7a2db
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 #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)       (*--sp = (SP_TYPE)(val))
25 #define _POP(sp)            (*sp++)
27 #ifndef _SIGNAL_H
28 #define _SIGNAL_H
29 #endif
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.
55                     |                          |
56                     +--------------------------+
57                     | last entry before signal |
58                     +--------------------------+
59                     |      signal context      |
60                     +--------------------------+
61                     |      signal number       |
62                     +--------------------------+
63                     |      return address      | 
64                     +--------------------------+
65                     |                          |
67     so the address of the signal context is &sig+1.
70 #if USE_SA_SIGINFO
71 #define GLOBAL_SIGNAL_INIT \
72         static void sighandler (int sig, sigcontext_t * sc);                    \
73                                                                                 \
74         static void SIGHANDLER (int sig, siginfo_t *blub, struct ucontext *u)   \
75         {                                                                       \
76             sighandler(sig, (sigcontext_t *)&u->uc_mcontext);                   \
77         }
79 #else
81 #define GLOBAL_SIGNAL_INIT \
82         static void sighandler (int sig, sigcontext_t * sc);    \
83                                                                 \
84         static void SIGHANDLER (int sig)                        \
85         {                                                       \
86             sighandler (sig, (sigcontext_t *)(&sig+1));         \
87         }
88 #endif
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
92    "SP_TYPE *". */
93 #define SP_TYPE     long
95 /* How many general purpose registers are to be saved on the stack
96    when a task switch happens */
97 #define CPU_NUMREGS             0
99 /* Use this structure to save/restore registers if the stack is too
100    small */
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 */
108     int errno_backup;
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
120     in the program code.
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)          \
160     do                           \
161     {                            \
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); \
179     } while (0)
180          
181 #define RESTORE_CPU(cc,sc)       \
182     do                           \
183     {                            \
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]; \
201     } while (0)
203 #define SAVE_ERRNO(cc) \
204     do                 \
205     {                  \
206         (cc)->errno_backup = errno; \
207     } while (0) 
208         
209 #define RESTORE_ERRNO(cc) \
210     do                    \
211     {                     \
212         errno = (cc)->errno_backup; \
213     } while (0)
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:
221                     |                          |
222                     +--------------------------+
223                     | last entry before signal |
224                     +--------------------------+
225                     |       empty space        | <--- SP
226                     +--------------------------+
227                     |      signal context      |
228                     +--------------------------+
229                     |                          |
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
242 /*  define NO_FPU */
244     This macro returns 1 if an FPU is available.
246 #ifndef NO_FPU
247 #   define HAS_FPU(sc)      (sc->fpstate)
248 #else
249 #   define HAS_FPU(sc)      0
250 #endif
252 #define SAVE_FPU(cc,sc)                         \
253         do                                      \
254         {                                       \
255             if (HAS_FPU(sc))                    \
256                 (cc)->fpstate = (sc)->fpstate; \
257         } while (0)
259 #define RESTORE_FPU(cc,sc)                      \
260         do                                      \
261         {                                       \
262             if (HAS_FPU(sc))                    \
263                 (sc)->fpstate = (cc)->fpstate; \
264         } while (0)
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:
272                                                  high adresses
273                     |          ...           |
274                     +------------------------+
275                     |       arguments        |
276                     +------------------------+
277                     |     return address     |
278                     +------------------------+
279                     |   old frame pointer    |
280                     +------------------------+
281                     |    local variables     |
282                     +------------------------+
283                     |    saved registers     |
284                     +------------------------+
285                     |          ...           |
286                                                 low addresses
287                                                 stack grows from high to
288                                                 low addresses.
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:
295             func (a,b,c);
297     then you must prepare the stack like this:
299             _PUSH(sp,c);
300             _PUSH(sp,b);
301             _PUSH(sp,a);
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
307     and so on).
311 #   define PREPARE_INITIAL_FRAME(sp,pc)       \
312         do                                    \
313         {                                     \
314             GetCpuContext(task)->regs[15] = 0; \
315             GetCpuContext(task)->regs[16] = (ULONG)pc; \
316         } while (0)
320     Prepare the cpu context
323 #ifndef NO_FPU
325 #define PREPARE_INITIAL_CONTEXT(task,startpc) \
326    asm volatile("fninit\n\t" \
327                 "fnsave %0\n\t" \
328                 "fwait" : "=m" (GetCpuContext(task)->fpstate))
330 #else
332 #define PREPARE_INITIAL_CONTEXT(task,startpc)
334 #endif
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)                                  \
347     do                                                     \
348     {                                                      \
349         struct AROS_cpu_context *cc = GetCpuContext(task); \
350         GetSP(task) = (SP_TYPE *)SP(sc); \
351         SAVE_FPU(cc,sc);                 \
352         SAVE_CPU(cc,sc);                 \
353         SAVE_ERRNO(cc);                  \
354     } while (0)
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) \
364     do                                                     \
365     {                                                      \
366         struct AROS_cpu_context *cc = GetCpuContext(task); \
367         RESTORE_ERRNO(cc);    \
368         RESTORE_FPU(cc,sc);   \
369         RESTORE_CPU(cc,sc);   \
370         SP(sc) = (typeof(SP(sc)))GetSP(task); \
371     } while (0)
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) \
386         )
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] \
411         )
413 #endif /* _SIGCORE_H */