5 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
8 Desc: Macros to handle unix signals, x86_64 version.
12 #include <aros/x86_64/cpucontext.h>
14 #ifdef __AROS_EXEC_LIBRARY__
20 /* There's no need for USE_SA_SIGINFO, as we always use SA_SIGINFO
21 on x86_64 - there's no other sane way to get ucontext. */
22 #define SIGCORE_NEED_SA_SIGINFO 1
24 /* Make _GNU_SOURCE work */
26 /* We want to use some predefined register names */
37 #ifndef __KERNEL_STRICT_NAMES
38 #define __KERNEL_STRICT_NAMES
40 #include <bits/sigcontext.h>
42 /* name and type of the signal handler */
43 #define SIGHANDLER linux_sighandler
44 #define SIGHANDLER_T __sighandler_t
47 This macro contains some magic necessary to make it work.
48 The problem is that Linux offers no official way to obtain the
49 signals' context. Linux stores the signals' context on the
50 process' stack. It looks like this:
51 Attention: As of version 2.2 of the Linux kernel there is
52 not enough room on the stack anymore to save
53 any registers on it. So everything has to go into
54 the context structure. Previously PC and FP used
55 to be saved on the stack but now this would over-
56 write some return address.
57 The stack you see below is the stack of the last
58 active task within AROS. The linux kernel puts
59 all kinds of other junk on it.
62 +--------------------------+
63 | last entry before signal |
64 +--------------------------+
66 +--------------------------+
68 +--------------------------+
70 +--------------------------+
73 so the address of the signal context is &sig+1.
75 Well, we use the SIGCORE_NEED_SA_SIGINFO approach, so part of
76 the above is only kept for historical reasons.
79 #define GLOBAL_SIGNAL_INIT(sighandler) \
80 static void sighandler ## _gate (int sig, siginfo_t *blub, void *u) \
86 Macros to access the stack pointer, frame pointer and program
87 counter. The FP is the base address for accesses to arguments
88 and local variables of a function and PC is the current address
92 #define SP(uc) ((uc)->uc_mcontext.gregs[REG_RSP])
93 #define FP(uc) ((uc)->uc_mcontext.gregs[REG_RBP])
94 #define PC(uc) ((uc)->uc_mcontext.gregs[REG_RIP])
97 Macros to enable or disable all signals after the signal handler
98 has returned and the normal execution commences.
100 On Linux x86-64 signal mask is restored from uc_sigmask field of ucontext
103 #define SC_DISABLE(uc) uc->uc_sigmask = KernelBase->kb_PlatformData->sig_int_mask
104 #define SC_ENABLE(uc) pd->iface->SigEmptySet(&uc->uc_sigmask)
107 The names of the general purpose registers which are to be saved.
108 Use R and a number as name, no matter what the real name is.
109 General purpose registers (GPRs) are registers which can be
110 modified by the task (ie. data and address registers) and which are
111 not saved by the CPU when an interrupt happens.
113 #define R0(uc) ((uc)->uc_mcontext.gregs[REG_RAX])
114 #define R1(uc) ((uc)->uc_mcontext.gregs[REG_RBX])
115 #define R2(uc) ((uc)->uc_mcontext.gregs[REG_RCX])
116 #define R3(uc) ((uc)->uc_mcontext.gregs[REG_RDX])
117 #define R4(uc) ((uc)->uc_mcontext.gregs[REG_RDI])
118 #define R5(uc) ((uc)->uc_mcontext.gregs[REG_RSI])
119 #define R6(uc) ((uc)->uc_mcontext.gregs[REG_EFL])
120 #define R8(uc) ((uc)->uc_mcontext.gregs[REG_R8])
121 #define R9(uc) ((uc)->uc_mcontext.gregs[REG_R9])
122 #define R10(uc) ((uc)->uc_mcontext.gregs[REG_R10])
123 #define R11(uc) ((uc)->uc_mcontext.gregs[REG_R11])
124 #define R12(uc) ((uc)->uc_mcontext.gregs[REG_R12])
125 #define R13(uc) ((uc)->uc_mcontext.gregs[REG_R13])
126 #define R14(uc) ((uc)->uc_mcontext.gregs[REG_R14])
127 #define R15(uc) ((uc)->uc_mcontext.gregs[REG_R15])
130 Save and restore the CPU GPRs in the CPU context
132 #define SAVE_CPU(cc, sc) \
139 cc.rflags = R6(sc); \
153 * Restore CPU registers.
154 * Note that we do not restore segment registers because they
155 * are of own use by Linux.
157 #define RESTORE_CPU(cc, sc) \
164 R6(sc) = cc.rflags; \
178 * Save all registers from UNIX signal context to AROS context.
179 * Save also SSE state if the context has buffer. ECF_FPX will be set
180 * if SSE state was copied.
182 #define SAVEREGS(cc, sc) \
183 SAVE_CPU((cc)->regs, sc); \
184 if (sc->uc_mcontext.fpregs && (cc)->regs.FXData) \
186 (cc)->regs.Flags |= ECF_FPX; \
187 CopyMemQuick(sc->uc_mcontext.fpregs, (cc)->regs.FXData, sizeof(struct FPXContext)); \
191 * Restore all registers from AROS context to UNIX signal context.
192 * Check context flags to decide whether to restore SSE or not.
194 #define RESTOREREGS(cc, sc) \
195 RESTORE_CPU((cc)->regs, sc); \
196 if ((cc)->regs.Flags & ECF_FPX) \
197 CopyMemQuick((cc)->regs.FXData, sc->uc_mcontext.fpregs, sizeof(struct FPXContext));
199 /* Print signal context. Used in crash handler. */
200 #define PRINT_SC(sc) \
201 bug (" RSP=%016lx RBP=%016lx RIP=%016lx\n" \
202 " RAX=%016lx RBX=%016lx RCX=%016lx RDX=%016lx\n" \
203 " RDI=%016lx RSI=%016lx RFLAGS=%016lx\n" \
204 " R8 =%016lx R9 =%016lx R10=%016lx R11=%016lx\n" \
205 " R12=%016lx R13=%016lx R14=%016lx R15=%016lx\n" \
206 , SP(sc), FP(sc), PC(sc) \
207 , R0(sc), R1(sc), R2(sc), R3(sc) \
208 , R4(sc), R5(sc), R6(sc), R8(sc), R9(sc) \
209 , R10(sc), R11(sc), R12(sc), R13(sc), R14(sc), R15(sc) \
212 #endif /* __AROS_EXEC_LIBRARY__ */
214 #define EXCEPTIONS_COUNT 17
216 typedef struct ucontext regs_t
;
218 /* Use this structure to save/restore registers */
219 struct AROSCPUContext
221 struct ExceptionContext regs
;
225 #endif /* _SIGCORE_H */