5 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
8 Desc: Macros to handle i386 Linux signals
12 #include <aros/i386/cpucontext.h>
14 #ifdef __AROS_EXEC_LIBRARY__
17 typedef struct sigcontext regs_t
;
21 #define USE_SA_SIGINFO 0
24 #define SIGCORE_NEED_SA_SIGINFO 1
30 /* Include generated fragment */
33 /* name and type of the signal handler */
34 #define SIGHANDLER linux_sighandler
35 #define SIGHANDLER_T SignalHandler
38 This macro contains some magic necessary to make it work.
39 The problem is that Linux offers no official way to obtain the
40 signals' context. Linux stores the signals' context on the
41 process' stack. It looks like this:
42 Attention: As of version 2.2 of the Linux kernel there is
43 not enough room on the stack anymore to save
44 any registers on it. So everything has to go into
45 the context structure. Previously PC and FP used
46 to be saved on the stack but now this would over-
47 write some return address.
48 The stack you see below is the stack of the last
49 active task within AROS. The linux kernel puts
50 all kinds of other junk on it.
53 +--------------------------+
54 | last entry before signal |
55 +--------------------------+
57 +--------------------------+
59 +--------------------------+
61 +--------------------------+
64 so the address of the signal context is &sig+1.
68 #define GLOBAL_SIGNAL_INIT(sighandler) \
69 static void sighandler ## _gate (int sig, siginfo_t *blub, struct ucontext *u) \
71 sighandler(sig, (regs_t *)&u->uc_mcontext); \
76 #define GLOBAL_SIGNAL_INIT(sighandler) \
77 static void sighandler ## _gate (int sig) \
79 sighandler (sig, (regs_t *)(&sig+1)); \
84 Macros to access the stack pointer, frame pointer and program
85 counter. The FP is the base address for accesses to arguments
86 and local variables of a function and PC is the current address
90 #define SP(sc) ((sc)->esp)
91 #define FP(sc) ((sc)->ebp)
92 #define PC(sc) ((sc)->eip)
95 Macros to enable or disable all signals after the signal handler
96 has returned and the normal execution commences.
98 WARNING!!! If you change #define USE_SA_SIGINFO to 1, this will
99 stop working! In this case Linux will use ucontext->uc_sigmask
100 to store original signal mask. See x86-64 and PPC implementation
101 of these macros for examples.
103 #ifdef HOST_OS_android
104 /* In Android's Bionic sigset_t is simply unsigned long */
105 #define SC_DISABLE(sc) ((sc)->oldmask = KernelBase->kb_PlatformData->sig_int_mask)
107 #define SC_DISABLE(sc) ((sc)->oldmask = KernelBase->kb_PlatformData->sig_int_mask.__val[0])
109 #define SC_ENABLE(sc) ((sc)->oldmask = 0L)
112 The names of the general purpose registers which are to be saved.
113 Use R and a number as name, no matter what the real name is.
114 General purpose registers (GPRs) are registers which can be
115 modified by the task (ie. data and address registers) and which are
116 not saved by the CPU when an interrupt happens.
118 #define R0(sc) ((sc)->eax)
119 #define R1(sc) ((sc)->ebx)
120 #define R2(sc) ((sc)->ecx)
121 #define R3(sc) ((sc)->edx)
122 #define R4(sc) ((sc)->edi)
123 #define R5(sc) ((sc)->esi)
124 #define R6(sc) ((sc)->eflags)
126 /* Save and restore the CPU GPRs in the CPU context */
127 #define SAVE_CPU(cc, sc) \
134 cc.eflags = R6(sc); \
139 #define RESTORE_CPU(cc, sc) \
146 R6(sc) = cc.eflags; \
153 It's not possible to save the FPU under linux because linux
154 uses the tasks stack to save the signal context. The signal
155 context conatins the SP *before* the sigcontext was pushed on
156 this stack, so it looks like this:
159 +--------------------------+
160 | last entry before signal |
161 +--------------------------+
162 | empty space | <--- SP
163 +--------------------------+
165 +--------------------------+
169 As you can see, SP points to the empty space. Now this empty space
170 is not very big. It's big enough that one can save the CPU
171 registers but not big enough for the FPU. *sigh*.
173 Attention: The above WAS TRUE for 2.0.x kernels but now the stack layout
174 looks different. See above!
176 Update: We store the registers in our own structure now
179 /* Allocate legacy 80087 frame together with SSE frame */
180 #define USE_LEGACY_8087
182 /* Allocate 112 bytes for 8087 frame. It contains host_specific portion (status and magic). */
183 #define SIZEOF_8087_FRAME 112
186 * This macro saves all registers. Use this macro when you
187 * want to leave the current task's context.
188 * If will also save FPU and SSE areas (if possible) and
189 * set appropriate context flags to indicate this.
191 #define SAVEREGS(cc, sc) \
192 SAVE_CPU((cc)->regs, sc); \
193 if ((cc)->regs.FPData && sc->fpstate) \
195 (cc)->regs.Flags |= ECF_FPU; \
196 CopyMemQuick(sc->fpstate, (cc)->regs.FPData, SIZEOF_8087_FRAME); \
197 if ((cc)->regs.FXData && (sc->fpstate->magic != 0xFFFF)) \
199 (cc)->regs.Flags |= ECF_FPX; \
200 CopyMemQuick(sc->fpstate->_fxsr_env, (cc)->regs.FXData, sizeof(struct FPXContext)); \
205 * This macro does the opposite to SAVEREGS(). It restores all registers.
206 * After that, you can enter the new task's context.
207 * FPU and SSE areas will be restored only if they were present in the
208 * saved context. This should be indicated by context's flags.
210 #define RESTOREREGS(cc, sc) \
211 RESTORE_CPU((cc)->regs, sc); \
214 if ((cc)->regs.Flags & ECF_FPU) \
215 CopyMemQuick((cc)->regs.FPData, sc->fpstate, SIZEOF_8087_FRAME); \
216 if ((cc)->regs.Flags & ECF_FPX) \
217 CopyMemQuick((cc)->regs.FXData, sc->fpstate->_fxsr_env, sizeof(struct FPXContext)); \
220 /* This macro prints the current signals' context */
221 #define PRINT_SC(sc) \
222 bug (" SP=%08lx FP=%08lx PC=%08lx\n" \
223 " R0=%08lx R1=%08lx R2=%08lx R3=%08lx\n" \
224 " R4=%08lx R5=%08lx\n" \
225 , SP(sc), FP(sc), PC(sc) \
226 , R0(sc), R1(sc), R2(sc), R3(sc) \
230 #endif /* __AROS_EXEC_LIBRARY__ */
232 #define EXCEPTIONS_COUNT 17
234 /* Use this structure to save/restore registers */
235 struct AROSCPUContext
237 struct ExceptionContext regs
; /* Public portion */
238 int errno_backup
; /* Host-specific stuff, private */
241 #endif /* _SIGCORE_H */