wip.
[AROS.git] / arch / all-unix / kernel / kernel.c
blobb06f452739016621bbf5b4212932ef2f2f25fae4
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Initialize the interface to the "hardware".
6 Lang: english
7 */
9 #include <exec/interrupts.h>
10 #include <exec/execbase.h>
11 #include <aros/asmcall.h>
12 #include <aros/atomic.h>
13 #include <aros/symbolsets.h>
14 #include <hardware/intbits.h>
15 #include <proto/exec.h>
16 #include <proto/hostlib.h>
18 #define timeval sys_timeval
20 #include "hostinterface.h"
21 #include "kernel_base.h"
22 #include "kernel_debug.h"
23 #include "kernel_globals.h"
24 #include "kernel_intr.h"
25 #include "kernel_intern.h"
26 #include "kernel_interrupts.h"
27 #include "kernel_scheduler.h"
28 #include "kernel_unix.h"
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <signal.h>
34 #include <unistd.h>
36 #undef timeval
38 #define D(x)
39 #define DSC(x)
41 #ifdef SIGCORE_NEED_SA_SIGINFO
42 #define SETHANDLER(sa, h) \
43 sa.sa_sigaction = h ## _gate; \
44 sa.sa_flags |= SA_SIGINFO
45 #else
46 #define SETHANDLER(sa, h) \
47 sa.sa_handler = h ## _gate;
48 #endif
50 static void core_TrapHandler(int sig, regs_t *regs)
52 struct KernelBase *KernelBase = getKernelBase();
53 const struct SignalTranslation *s;
54 short amigaTrap;
55 struct AROSCPUContext ctx;
57 SUPERVISOR_ENTER;
59 /* Just for completeness */
60 krnRunIRQHandlers(KernelBase, sig);
62 bug("[KRN] Trap signal %d, SysBase %p, KernelBase %p\n", sig, SysBase, KernelBase);
63 PRINT_SC(regs);
65 /* Translate UNIX trap number to CPU and exec trap numbers */
66 for (s = sigs; s->sig != -1; s++)
68 if (sig == s->sig)
69 break;
73 * Trap handler expects struct ExceptionContext, so we have to convert regs_t to it.
74 * But first initialize all context area to zero, this is important since it may include
75 * pointers to FPU state buffers.
76 * TODO: FPU state also can be interesting for debuggers, we need to prepare space for it
77 * too. Needs to be enclosed in some macros.
79 memset(&ctx, 0, sizeof(ctx));
80 SAVEREGS(&ctx, regs);
82 amigaTrap = s->AmigaTrap;
83 if (s->CPUTrap != -1)
85 if (krnRunExceptionHandlers(KernelBase, s->CPUTrap, &ctx))
86 /* Do not call exec trap handler */
87 amigaTrap = -1;
91 * Call exec trap handler if needed.
92 * Note that it may return, this means that the it has
93 * fixed the problem somehow and we may safely continue.
95 if (amigaTrap != -1)
96 core_Trap(amigaTrap, &ctx);
98 /* Trap handler(s) have possibly modified the context, so
99 we convert it back before returning */
100 RESTOREREGS(&ctx, regs);
102 SUPERVISOR_LEAVE;
105 static void core_IRQ(int sig, regs_t *sc)
107 struct KernelBase *KernelBase = getKernelBase();
109 SUPERVISOR_ENTER;
111 /* Just additional protection - what if there's more than 32 signals? */
112 if (sig < IRQ_COUNT)
113 krnRunIRQHandlers(KernelBase, sig);
115 if (UKB(KernelBase)->SupervisorCount == 1)
116 core_ExitInterrupt(sc);
118 SUPERVISOR_LEAVE;
122 * This is from sigcore.h - it brings in the definition of the
123 * systems initial signal handler, which simply calls
124 * sighandler(int signum, regs_t sigcontext)
126 GLOBAL_SIGNAL_INIT(core_TrapHandler)
127 GLOBAL_SIGNAL_INIT(core_SysCall)
128 GLOBAL_SIGNAL_INIT(core_IRQ)
130 /* libc functions that we use */
131 static const char *kernel_functions[] =
133 "raise",
134 "sigprocmask",
135 "sigsuspend",
136 "sigaction",
137 "mprotect",
138 "read",
139 "fcntl",
140 "mmap",
141 "munmap",
142 #ifdef HOST_OS_linux
143 "__errno_location",
144 #else
145 #ifdef HOST_OS_android
146 "__errno",
147 #else
148 "__error",
149 #endif
150 #endif
151 #ifdef HOST_OS_android
152 "sigwait",
153 #else
154 "sigemptyset",
155 "sigfillset",
156 "sigaddset",
157 "sigdelset",
158 #endif
159 NULL
163 * Our post-SINGLETASK initialization code.
164 * At this point we are starting up interrupt subsystem.
165 * We have hostlib.resource and can use it in order to pick up all needed host OS functions.
167 int core_Start(void *libc)
169 struct KernelBase *KernelBase = getKernelBase();
170 struct PlatformData *pd = KernelBase->kb_PlatformData;
171 APTR HostLibBase;
172 struct sigaction sa = {};
173 const struct SignalTranslation *s;
174 sigset_t tmp_mask;
175 ULONG r;
177 /* We have hostlib.resource. Obtain the complete set of needed functions. */
178 HostLibBase = OpenResource("hostlib.resource");
179 if (!HostLibBase)
181 krnPanic(KernelBase, "Failed to open hostlib.resource");
182 return FALSE;
185 pd->iface = (struct KernelInterface *)HostLib_GetInterface(libc, kernel_functions, &r);
186 if (!pd->iface)
188 krnPanic(KernelBase, "Failed to allocate host-side libc interface");
189 return FALSE;
192 if (r)
194 krnPanic(KernelBase, "Failed to resove %u functions from host libc", r);
195 return FALSE;
198 /* Cache errno pointer, for context switching */
199 pd->errnoPtr = pd->iface->__error();
200 AROS_HOST_BARRIER
202 #if DEBUG
203 /* Pass unhandled exceptions to the debugger, if present */
204 SIGEMPTYSET(&pd->sig_int_mask);
205 #else
206 /* We only want signal that we can handle at the moment */
207 SIGFILLSET(&pd->sig_int_mask);
208 #endif
209 SIGEMPTYSET(&sa.sa_mask);
210 sa.sa_flags = SA_RESTART;
213 * These ones we consider as processor traps.
214 * They are not be blocked by KrnCli()
216 SETHANDLER(sa, core_TrapHandler);
217 for (s = sigs; s->sig != -1; s++)
219 pd->iface->sigaction(s->sig, &sa, NULL);
220 AROS_HOST_BARRIER
221 SIGDELSET(&pd->sig_int_mask, s->sig);
224 /* SIGUSRs are software interrupts, we also never block them */
225 SIGDELSET(&pd->sig_int_mask, SIGUSR1);
226 SIGDELSET(&pd->sig_int_mask, SIGUSR2);
227 /* We want to be able to interrupt AROS using Ctrl-C in its console,
228 so exclude SIGINT too. */
229 SIGDELSET(&pd->sig_int_mask, SIGINT);
232 * Any interrupt including software one must disable
233 * all interrupts. Otherwise one interrupt may happen
234 * between interrupt handler entry and supervisor count
235 * increment. This can cause bad things in cpu_Dispatch()
237 sa.sa_mask = pd->sig_int_mask;
239 /* Install interrupt handlers */
240 SETHANDLER(sa, core_IRQ);
241 #if DEBUG
242 /* Use VTALRM instead of ALRM during debugging, so
243 * that stepping though code won't have to deal
244 * with constant SIGALRM processing.
246 * NOTE: This will cause the AROS clock to march slower
247 * than the host clock in debug builds!
249 pd->iface->sigaction(SIGVTALRM, &sa, NULL);
250 AROS_HOST_BARRIER
251 #else
252 pd->iface->sigaction(SIGALRM, &sa, NULL);
253 AROS_HOST_BARRIER
254 #endif
255 pd->iface->sigaction(SIGIO , &sa, NULL);
256 AROS_HOST_BARRIER
258 /* Software IRQs do not need to block themselves. Anyway we know when we send them. */
259 sa.sa_flags |= SA_NODEFER;
261 pd->iface->sigaction(SIGUSR2, &sa, NULL);
262 AROS_HOST_BARRIER
264 SETHANDLER(sa, core_SysCall);
265 pd->iface->sigaction(SIGUSR1, &sa, NULL);
266 AROS_HOST_BARRIER
268 /* We need to start up with disabled interrupts */
269 pd->iface->sigprocmask(SIG_BLOCK, &pd->sig_int_mask, NULL);
270 AROS_HOST_BARRIER
273 * Explicitly make sure that SIGUSR1 and SIGUSR2 are enabled.
274 * This effectively kicks DalvikVM's ass on Android and takes SIGUSR1 away
275 * from its "signal catcher". On other platforms this at least should not harm.
276 * I also added SIGUSR2, just in case.
278 SIGEMPTYSET(&tmp_mask);
279 SIGADDSET(&tmp_mask, SIGUSR1);
280 SIGADDSET(&tmp_mask, SIGUSR2);
281 pd->iface->sigprocmask(SIG_UNBLOCK, &tmp_mask, NULL);
282 AROS_HOST_BARRIER
284 return TRUE;
288 * All syscalls are mapped to single SIGUSR1. We look at task's tc_State
289 * to determine the needed action.
290 * This is not inlined because actual SIGUSR1 number is host-specific, it can
291 * differ between different UNIX variants, and even between different ports of the same
292 * OS (e. g. Linux). We need host OS includes in order to get the proper definition, and
293 * we include them only in arch-specific code.
295 void unix_SysCall(unsigned char n, struct KernelBase *KernelBase)
297 DSC(bug("[KRN] SysCall %d\n", n));
299 KernelBase->kb_PlatformData->iface->raise(SIGUSR1);
300 AROS_HOST_BARRIER