Added missing properties.
[AROS.git] / arch / all-linux / kernel / cpu_i386.h
blobb642175b719e2b6e65c90a8393f1855bf1b60b7d
1 #ifndef _SIGCORE_H
2 #define _SIGCORE_H
4 /*
5 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 $Id$
8 Desc: Macros to handle i386 Linux signals
9 Lang: english
12 #include <aros/i386/cpucontext.h>
14 #ifdef __AROS_EXEC_LIBRARY__
16 struct sigcontext;
17 typedef struct sigcontext regs_t;
19 #else
21 #define USE_SA_SIGINFO 0
23 #if USE_SA_SIGINFO
24 #define SIGCORE_NEED_SA_SIGINFO 1
25 #include <ucontext.h>
26 #endif
28 #include <signal.h>
30 /* Include generated fragment */
31 #include <sigcore.h>
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.
52 | |
53 +--------------------------+
54 | last entry before signal |
55 +--------------------------+
56 | signal context |
57 +--------------------------+
58 | signal number |
59 +--------------------------+
60 | return address |
61 +--------------------------+
62 | |
64 so the address of the signal context is &sig+1.
67 #if USE_SA_SIGINFO
68 #define GLOBAL_SIGNAL_INIT(sighandler) \
69 static void sighandler ## _gate (int sig, siginfo_t *blub, struct ucontext *u) \
70 { \
71 sighandler(sig, (regs_t *)&u->uc_mcontext); \
74 #else
76 #define GLOBAL_SIGNAL_INIT(sighandler) \
77 static void sighandler ## _gate (int sig) \
78 { \
79 sighandler (sig, (regs_t *)(&sig+1)); \
81 #endif
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
87 in the program code.
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)
106 #else
107 #define SC_DISABLE(sc) ((sc)->oldmask = KernelBase->kb_PlatformData->sig_int_mask.__val[0])
108 #endif
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) \
128 cc.eax = R0(sc); \
129 cc.ebx = R1(sc); \
130 cc.ecx = R2(sc); \
131 cc.edx = R3(sc); \
132 cc.edi = R4(sc); \
133 cc.esi = R5(sc); \
134 cc.eflags = R6(sc); \
135 cc.ebp = FP(sc); \
136 cc.eip = PC(sc); \
137 cc.esp = SP(sc);
139 #define RESTORE_CPU(cc, sc) \
140 R0(sc) = cc.eax; \
141 R1(sc) = cc.ebx; \
142 R2(sc) = cc.ecx; \
143 R3(sc) = cc.edx; \
144 R4(sc) = cc.edi; \
145 R5(sc) = cc.esi; \
146 R6(sc) = cc.eflags; \
147 FP(sc) = cc.ebp; \
148 PC(sc) = cc.eip; \
149 SP(sc) = cc.esp;
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 +--------------------------+
164 | signal context |
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); \
212 if (sc->fpstate) \
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) \
227 , R4(sc), R5(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 */