- Set a default PCM volume so that something can be heard when driver is
[AROS.git] / arch / all-unix / kernel / kernel.c
blob8536ed4dac32035d7d73ac683f2b6734890f4088
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/types.h>
10 #include <exec/interrupts.h>
11 #include <exec/execbase.h>
12 #include <exec/alerts.h>
13 #include <aros/asmcall.h>
14 #include <aros/atomic.h>
15 #include <aros/symbolsets.h>
16 #include <hardware/intbits.h>
18 #define timeval sys_timeval
19 #include "etask.h"
21 #include <stdarg.h>
23 #include "hostinterface.h"
24 #include "kernel_base.h"
25 #include "kernel_debug.h"
26 #include "kernel_intr.h"
27 #include "kernel_intern.h"
28 #include "kernel_interrupts.h"
29 #include "kernel_scheduler.h"
30 #include "kernel_timer.h"
32 #include <stdio.h>
33 #include <string.h>
34 #include <signal.h>
35 #include <sys/time.h>
36 #include <unistd.h>
37 #undef timeval
39 #include <proto/exec.h>
41 #define D(x)
42 #define DSC(x)
44 #ifdef SIGCORE_NEED_SA_SIGINFO
45 #define SETHANDLER(sa, h) \
46 sa.sa_sigaction = (void *)h ## _gate; \
47 sa.sa_flags |= SA_SIGINFO
48 #else
49 #define SETHANDLER(sa, h) \
50 sa.sa_handler = (SIGHANDLER_T)h ## _gate;
51 #endif
53 static void core_Trap(int sig, regs_t *regs)
55 void (*trapHandler)(unsigned long, struct AROSCPUContext *) = NULL;
56 struct SignalTranslation *s;
57 struct AROSCPUContext ctx;
59 /* Just for completeness */
60 krnRunIRQHandlers(sig);
62 bug("[KRN] Trap signal %d, SysBase %p, KernelBase %p\n", sig, SysBase, KernelBase);
64 /* Find out trap handler for caught task */
65 if (SysBase)
67 struct Task *t = SysBase->ThisTask;
69 if (t)
71 bug("[KRN] %s %p (%s)\n", t->tc_Node.ln_Type == NT_TASK ? "Task":"Process", t, t->tc_Node.ln_Name ? t->tc_Node.ln_Name : "--unknown--");
72 trapHandler = t->tc_TrapCode;
74 else
75 bug("[KRN] No task\n");
77 if (!trapHandler)
78 trapHandler = SysBase->TaskTrapCode;
81 PRINT_SC(regs);
83 /* Translate UNIX trap number to CPU and exec trap numbers */
84 for (s = sigs; s->sig != -1; s++)
86 if (sig == s->sig)
87 break;
91 * Initialize all context area to zero, this is important since it may include pointers to FPU state buffers.
92 * TODO: FPU state also can be interesting for debuggers, we need to prepare space for it too. Needs to be
93 * enclosed in some macros.
95 memset(&ctx, 0, sizeof(ctx));
97 /* Trap handler expects struct ExceptionContext, so we have to convert regs_t to it */
98 SAVEREGS(&ctx, regs);
100 if (s->CPUTrap != -1)
102 if (krnRunExceptionHandlers(s->CPUTrap, &ctx))
103 /* Do not call exec trap handler */
104 trapHandler = NULL;
107 if (trapHandler && (s->AmigaTrap != -1))
108 /* Call our trap handler. Note that we may return, this means that the handler has
109 fixed the problem somehow and we may safely continue */
110 trapHandler(s->AmigaTrap, &ctx);
112 /* Trap handler(s) have possibly modified the context, so
113 we convert it back before returning */
114 RESTOREREGS(&ctx, regs);
118 * We do not have enough user-defined signals to map
119 * them to four required syscalls (CAUSE, SCHEDULE,
120 * SWITCH, DISPATCH). We get around this by assigning
121 * CAUSE to SIGUSR2 and others to SIGUSR1.
123 * What action is to be taken upon SIGUSR1 can be
124 * figured out by looking at caller task's state.
125 * exec.library calls KrnDispatch() only after task
126 * has been actually disposed, with state set to TS_REMOVED.
127 * Similarly, KrnSwitch() is called only in Wait(), after
128 * setting state to TS_WAIT. In other cases it's KrnSchedule().
130 static void core_SysCall(int sig, regs_t *regs)
132 struct Task *task = SysBase->ThisTask;
134 AROS_ATOMIC_INC(KernelBase->kb_PlatformData->supervisor);
136 DSC(bug("[KRN] core_SysCall entered\n"));
138 krnRunIRQHandlers(sig);
140 switch(task->tc_State)
142 /* A running task needs to be put into TaskReady list first. It's SC_SCHEDULE. */
143 case TS_RUN:
144 if (!core_Schedule())
145 break;
147 /* If the task is already in some list with appropriate state, it's SC_SWITCH */
148 case TS_READY:
149 case TS_WAIT:
150 cpu_Switch(regs);
152 /* If the task is removed, it's simply SC_DISPATCH */
153 case TS_REMOVED:
154 cpu_Dispatch(regs);
155 break;
157 /* Special state is used for returning from exception */
158 case TS_EXCEPT:
159 cpu_DispatchContext(task, regs);
160 break;
163 AROS_ATOMIC_DEC(KernelBase->kb_PlatformData->supervisor);
166 static void core_IRQ(int sig, regs_t *sc)
168 AROS_ATOMIC_INC(KernelBase->kb_PlatformData->supervisor);
170 /* Just additional protection - what if there's more than 32 signals? */
171 if (sig < IRQ_COUNT)
172 krnRunIRQHandlers(sig);
174 if (sig == SIGALRM)
175 core_TimerTick();
177 if (KernelBase->kb_PlatformData->supervisor == 1)
178 core_ExitInterrupt(sc);
180 AROS_ATOMIC_DEC(KernelBase->kb_PlatformData->supervisor);
184 * This is from sigcore.h - it brings in the definition of the
185 * systems initial signal handler, which simply calls
186 * sighandler(int signum, regs_t sigcontext)
188 GLOBAL_SIGNAL_INIT(core_Trap)
189 GLOBAL_SIGNAL_INIT(core_SysCall)
190 GLOBAL_SIGNAL_INIT(core_IRQ)
192 extern struct HostInterface *HostIFace;
194 /* Set up the kernel. */
195 static int InitCore(struct KernelBase *KernelBase)
197 struct PlatformData *pd;
198 struct itimerval interval;
199 struct sigaction sa;
200 struct SignalTranslation *s;
201 sigset_t tmp_mask;
202 int ret;
204 D(bug("[KRN] InitCore()\n"));
206 #ifdef HOST_OS_android
207 KernelBase->kb_PageSize = *KernelIFace.__page_size;
208 #else
209 KernelBase->kb_PageSize = KernelIFace.getpagesize();
210 AROS_HOST_BARRIER
211 #endif
212 D(bug("[KRN] Memory page size is %u\n", KernelBase->kb_PageSize));
215 * We allocate PlatformData separately from KernelBase because
216 * its definition relies on host includes (sigset_t), and
217 * we don't want generic code to depend on host includes
219 pd = AllocMem(sizeof(struct PlatformData), MEMF_ANY);
220 D(bug("[KRN] PlatformData %p\n", pd));
221 if (!pd)
222 return FALSE;
224 pd->supervisor = 0;
225 pd->errnoPtr = KernelIFace.__error();
226 AROS_HOST_BARRIER
227 KernelBase->kb_PlatformData = pd;
229 /* We only want signal that we can handle at the moment */
230 SIGFILLSET(&pd->sig_int_mask);
231 SIGEMPTYSET(&sa.sa_mask);
232 sa.sa_flags = SA_RESTART;
233 #ifdef HOST_OS_linux
234 sa.sa_restorer = NULL;
235 #endif
238 * These ones we consider as processor traps.
239 * They are not be blocked by KrnCli()
241 SETHANDLER(sa, core_Trap);
242 for (s = sigs; s->sig != -1; s++)
244 KernelIFace.sigaction(s->sig, &sa, NULL);
245 AROS_HOST_BARRIER
246 SIGDELSET(&pd->sig_int_mask, s->sig);
249 /* SIGUSRs are software interrupts, we also never block them */
250 SIGDELSET(&pd->sig_int_mask, SIGUSR1);
251 SIGDELSET(&pd->sig_int_mask, SIGUSR2);
252 /* We want to be able to interrupt AROS using Ctrl-C in its console,
253 so exclude SIGINT too. */
254 SIGDELSET(&pd->sig_int_mask, SIGINT);
257 * Any interrupt including software one must disable
258 * all interrupts. Otherwise one interrupt may happen
259 * between interrupt handler entry and supervisor count
260 * increment. This can cause bad things in cpu_Dispatch()
262 sa.sa_mask = pd->sig_int_mask;
264 /* Install interrupt handlers */
265 SETHANDLER(sa, core_IRQ);
266 KernelIFace.sigaction(SIGALRM, &sa, NULL);
267 AROS_HOST_BARRIER
268 KernelIFace.sigaction(SIGIO , &sa, NULL);
269 AROS_HOST_BARRIER
271 /* Software IRQs do not need to block themselves. Anyway we know when we send them. */
272 sa.sa_flags |= SA_NODEFER;
274 KernelIFace.sigaction(SIGUSR2, &sa, NULL);
275 AROS_HOST_BARRIER
277 SETHANDLER(sa, core_SysCall);
278 KernelIFace.sigaction(SIGUSR1, &sa, NULL);
279 AROS_HOST_BARRIER
281 /* We need to start up with disabled interrupts */
282 KernelIFace.sigprocmask(SIG_BLOCK, &pd->sig_int_mask, NULL);
283 AROS_HOST_BARRIER
286 * Explicitly make sure that SIGUSR1 and SIGUSR2 are enabled.
287 * This effectively kicks DalvikVM's ass on Android and takes SIGUSR1 away
288 * from its "signal catcher". On other platforms this at least should not harm.
289 * I also added SIGUSR2, just in case.
291 SIGEMPTYSET(&tmp_mask);
292 SIGADDSET(&tmp_mask, SIGUSR1);
293 SIGADDSET(&tmp_mask, SIGUSR2);
294 KernelIFace.sigprocmask(SIG_UNBLOCK, &tmp_mask, NULL);
295 AROS_HOST_BARRIER
297 /* Set up the "pseudo" vertical blank interrupt. */
298 D(bug("[InitCore] Timer frequency is %d\n", SysBase->ex_EClockFrequency));
299 interval.it_interval.tv_sec = interval.it_value.tv_sec = 0;
300 interval.it_interval.tv_usec =
301 interval.it_value.tv_usec = 1000000 / SysBase->ex_EClockFrequency;
303 ret = KernelIFace.setitimer(ITIMER_REAL, &interval, NULL);
304 AROS_HOST_BARRIER
305 D(bug("[KRN] setitimer() returned %d, errno %d\n", ret, *pd->errnoPtr));
307 return !ret;
310 ADD2INITLIB(InitCore, 10);
313 * All syscalls are mapped to single SIGUSR1.
314 * We look at task's tc_State to determine the
315 * needed action
317 void krnSysCall(unsigned char n)
319 DSC(bug("[KRN] SysCall %d\n", n));
320 KernelIFace.raise(SIGUSR1);
321 AROS_HOST_BARRIER