2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Initialize the interface to the "hardware".
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
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"
39 #include <proto/exec.h>
44 #ifdef SIGCORE_NEED_SA_SIGINFO
45 #define SETHANDLER(sa, h) \
46 sa.sa_sigaction = (void *)h ## _gate; \
47 sa.sa_flags |= SA_SIGINFO
49 #define SETHANDLER(sa, h) \
50 sa.sa_handler = (SIGHANDLER_T)h ## _gate;
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 */
67 struct Task
*t
= SysBase
->ThisTask
;
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
;
75 bug("[KRN] No task\n");
78 trapHandler
= SysBase
->TaskTrapCode
;
83 /* Translate UNIX trap number to CPU and exec trap numbers */
84 for (s
= sigs
; s
->sig
!= -1; s
++)
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 */
100 if (s
->CPUTrap
!= -1)
102 if (krnRunExceptionHandlers(s
->CPUTrap
, &ctx
))
103 /* Do not call exec trap handler */
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. */
144 if (!core_Schedule())
147 /* If the task is already in some list with appropriate state, it's SC_SWITCH */
152 /* If the task is removed, it's simply SC_DISPATCH */
157 /* Special state is used for returning from exception */
159 cpu_DispatchContext(task
, regs
);
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? */
172 krnRunIRQHandlers(sig
);
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
;
200 struct SignalTranslation
*s
;
204 D(bug("[KRN] InitCore()\n"));
206 #ifdef HOST_OS_android
207 KernelBase
->kb_PageSize
= *KernelIFace
.__page_size
;
209 KernelBase
->kb_PageSize
= KernelIFace
.getpagesize();
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
));
225 pd
->errnoPtr
= KernelIFace
.__error();
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
;
234 sa
.sa_restorer
= NULL
;
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
);
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
);
268 KernelIFace
.sigaction(SIGIO
, &sa
, NULL
);
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
);
277 SETHANDLER(sa
, core_SysCall
);
278 KernelIFace
.sigaction(SIGUSR1
, &sa
, NULL
);
281 /* We need to start up with disabled interrupts */
282 KernelIFace
.sigprocmask(SIG_BLOCK
, &pd
->sig_int_mask
, NULL
);
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
);
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
);
305 D(bug("[KRN] setitimer() returned %d, errno %d\n", ret
, *pd
->errnoPtr
));
310 ADD2INITLIB(InitCore
, 10);
313 * All syscalls are mapped to single SIGUSR1.
314 * We look at task's tc_State to determine the
317 void krnSysCall(unsigned char n
)
319 DSC(bug("[KRN] SysCall %d\n", n
));
320 KernelIFace
.raise(SIGUSR1
);