Enable FIQ interrupt handling on BCM mailboxes. Each CPU core has four of them and...
[AROS.git] / arch / arm-native / kernel / kernel_startup.c
blob01aa22a89e31a2e85183c7b0f39800479d487c56
1 /*
2 Copyright © 2013-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
8 #include <aros/kernel.h>
9 #include <aros/symbolsets.h>
11 #include <aros/arm/cpucontext.h>
13 #include <aros/cpu.h>
15 #include <exec/memory.h>
16 #include <exec/memheaderext.h>
17 #include <exec/tasks.h>
18 #include <exec/alerts.h>
19 #include <exec/execbase.h>
20 #include <asm/io.h>
21 #include <proto/kernel.h>
22 #include <proto/exec.h>
23 #include <strings.h>
25 #include "exec_intern.h"
26 #include "etask.h"
28 #include "tlsf.h"
30 #include "kernel_intern.h"
31 #include "kernel_debug.h"
32 #include "kernel_romtags.h"
34 #include "exec_platform.h"
36 #if defined(__AROSEXEC_SMP__)
37 extern void Kernel_40_KrnSpinInit(spinlock_t *, void *);
38 #endif
40 extern struct TagItem *BootMsg;
42 void __attribute__((used)) kernel_cstart(struct TagItem *msg);
44 uint32_t stack[AROS_STACKSIZE] __attribute__((used,aligned(16)));
45 static uint32_t stack_super[AROS_STACKSIZE] __attribute__((used,aligned(16)));
47 static uint32_t stack_fiq[1024] __attribute__((used,aligned(16)));
49 asm (
50 ".section .aros.init,\"ax\"\n\t"
51 ".globl start\n\t"
52 ".type start,%function\n"
53 "start:\n"
54 " push {r0} \n"
55 " bl __clear_bss \n"
56 " pop {r0} \n"
57 " cps #0x1f \n" /* system mode */
58 " ldr sp, stack_end \n"
59 " cps #0x11 \n" /* fiq mode */
60 " ldr sp, stack_fiq_end \n"
61 " cps #0x13 \n" /* SVC (supervisor) mode */
62 " ldr sp, stack_super_end \n"
63 " b kernel_cstart \n"
65 ".string \"Native/CORE v3 (" __DATE__ ")\"" "\n\t\n\t"
68 static uint32_t * const stack_end __attribute__((used, section(".aros.init"))) = &stack[AROS_STACKSIZE - sizeof(IPTR)];
69 static uint32_t * const stack_super_end __attribute__((used, section(".aros.init"))) = &stack_super[AROS_STACKSIZE - sizeof(IPTR)];
70 static uint32_t * const stack_fiq_end __attribute__((used, section(".aros.init"))) = &stack_fiq[1024 - sizeof(IPTR)];
73 struct ARM_Implementation __arm_arosintern __attribute__((aligned(4), section(".data"))) = {0,0,NULL,NULL};
74 struct ExecBase *SysBase __attribute__((section(".data"))) = NULL;
76 static void __attribute__((used)) __clear_bss(struct TagItem *msg)
78 struct KernelBSS *bss = (struct KernelBSS *)krnGetTagData(KRN_KernelBss, 0, msg);
79 register unsigned int dest;
80 unsigned int length;
82 if (bss)
84 while (bss->addr && bss->len)
86 dest = (unsigned int)bss->addr;
87 length = bss->len;
89 // If the start address is unaligned, fill in the first 1-3 bytes until it is
90 while((dest & 3) && length)
92 *((unsigned char *)dest) = 0;
93 dest++;
94 length--;
97 // Fill in the remaining 32-bit word-aligned memory locations
98 while(length & 0xfffffffc)
100 *((unsigned int *)dest) = 0;
101 dest += 4;
102 length -= 4;
105 // Deal with the remaining 1-3 bytes, if any
106 while(length)
108 dest++;
109 length--;
110 *((unsigned char *)dest) = 0;
112 bss++;
117 extern uint32_t __arm_affinitymask;
119 void __attribute__((used)) kernel_cstart(struct TagItem *msg)
121 UWORD *ranges[3];
122 struct MinList memList;
123 struct MemHeader *mh;
124 struct MemChunk *mc;
125 long unsigned int memlower = 0, memupper = 0, protlower = 0, protupper = 0;
126 char *cmdline = NULL;
127 BootMsg = msg;
128 tls_t *__tls;
130 // Probe the ARM core
131 cpu_Probe(&__arm_arosintern);
133 // Probe the ARM Implementation/Platform
134 __arm_arosintern.ARMI_Platform = 0;
135 while(msg->ti_Tag != TAG_DONE)
137 switch (msg->ti_Tag)
139 case KRN_Platform:
140 __arm_arosintern.ARMI_Platform = msg->ti_Data;
141 break;
143 msg++;
145 msg = BootMsg;
147 platform_Init(&__arm_arosintern, msg);
149 if (__arm_arosintern.ARMI_LED_Toggle)
151 if (__arm_arosintern.ARMI_Delay)
152 __arm_arosintern.ARMI_Delay(100000);
153 __arm_arosintern.ARMI_LED_Toggle(ARM_LED_POWER, ARM_LED_OFF);
156 cpu_Init(&__arm_arosintern, msg);
158 if (__arm_arosintern.ARMI_LED_Toggle)
160 if (__arm_arosintern.ARMI_Delay)
161 __arm_arosintern.ARMI_Delay(100000);
162 __arm_arosintern.ARMI_LED_Toggle(ARM_LED_POWER, ARM_LED_ON);
165 /* NB: the bootstrap has conveniently setup the framebuffer
166 and initialised the serial port and led for us */
168 while(msg->ti_Tag != TAG_DONE)
170 switch (msg->ti_Tag)
172 case KRN_CmdLine:
173 // RelocateStringData(tag);
174 cmdline = (char *)msg->ti_Data;
175 break;
176 case KRN_MEMLower:
177 memlower = msg->ti_Data;
178 break;
179 case KRN_MEMUpper:
180 memupper = msg->ti_Data;
181 break;
182 case KRN_ProtAreaStart:
183 protlower = msg->ti_Data;
184 break;
185 case KRN_ProtAreaEnd:
186 // Page align
187 protupper = (msg->ti_Data + 4095) & ~4095;
188 break;
189 case KRN_KernelBase:
191 * KRN_KernelBase is actually a border between read-only
192 * (code) and read-write (data) sections of the kickstart.
193 * read-write section goes to lower addresses from this one,
194 * so we align it upwards in order not to make part of RW data
195 * read-only.
197 // addr = AROS_ROUNDUP2(msg->ti_Data, PAGE_SIZE);
198 break;
200 msg++;
202 msg = BootMsg;
204 __tls = (void *)protupper;
205 protupper += (sizeof(tls_t) + 4095) & ~4095;
207 __tls->KernelBase = NULL;
208 __tls->SysBase = NULL;
209 __tls->ThisTask = NULL;
211 D(bug("[KRN] AROS ARM Native Kernel built on %s\n", __DATE__));
213 D(bug("[KRN] Entered kernel_cstart @ 0x%p, BootMsg @ 0x%p\n", kernel_cstart, BootMsg));
215 asm volatile("mcr p15, 0, %0, c13, c0, 3" : : "r"(__tls));
218 if (__arm_arosintern.ARMI_PutChar)
220 bug("[KRN] Using PutChar implementation @ %p\n", __arm_arosintern.ARMI_PutChar);
222 bug("[KRN] Boot CPU TLS @ 0x%p\n", __tls);
225 core_SetupIntr();
227 if (__arm_arosintern.ARMI_LED_Toggle)
228 __arm_arosintern.ARMI_LED_Toggle(ARM_LED_POWER, ARM_LED_OFF);
230 D(bug("[KRN] Platform initialised\n"));
231 D(bug("[KRN] Affinity mask %08x\n", __arm_affinitymask));
233 if (__arm_arosintern.ARMI_Delay)
234 __arm_arosintern.ARMI_Delay(1500);
236 if (__arm_arosintern.ARMI_LED_Toggle)
237 __arm_arosintern.ARMI_LED_Toggle(ARM_LED_POWER, ARM_LED_ON);
239 D(bug("[KRN] Preparing memory 0x%p -> 0x%p\n", memlower, memupper));
240 D(bug("[KRN] (protected area 0x%p -> 0x%p)\n", protlower, protupper));
242 NEWLIST(&memList);
244 if (memlower >= protlower)
245 memlower = protupper;
247 mh = (struct MemHeader *)memlower;
249 if (cmdline && strstr(cmdline, "notlsf"))
251 #if (0)
252 krnCreateMemHeader("System Memory", 0, mh, (memupper - memlower), MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL);
254 if (memlower < protlower)
256 // AllocAbs(protupper-protlower, (void *)protlower);
258 #endif
260 else
262 /* Initialize TLSF memory allocator */
263 krnCreateTLSFMemHeader("System Memory", 0, mh, (memupper - memlower), MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL);
264 if (memlower < protlower)
266 /* Protect the bootstrap area from further use. AllocAbs will do the trick */
267 ((struct MemHeaderExt *)mh)->mhe_AllocAbs((struct MemHeaderExt *)mh, protupper-protlower, (void *)protlower);
271 ranges[0] = (UWORD *)krnGetTagData(KRN_KernelLowest, 0, msg);
272 ranges[1] = (UWORD *)krnGetTagData(KRN_KernelHighest, 0, msg);
273 ranges[2] = (UWORD *)-1;
275 D(bug("[KRN] Preparing ExecBase (memheader @ 0x%p)\n", mh));
276 krnPrepareExecBase(ranges, mh, BootMsg);
278 __tls->SysBase = SysBase;
279 D(bug("[KRN] SysBase @ 0x%p\n", SysBase));
281 #if defined(__AROSEXEC_SMP__)
282 /* Initialise exec spinlocks */
283 Kernel_40_KrnSpinInit(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL);
284 Kernel_40_KrnSpinInit(&PrivExecBase(SysBase)->TaskWaitSpinLock, NULL);
285 #endif
288 * Make kickstart code area read-only.
289 * We do it only after ExecBase creation because SysBase pointer is put
290 * into .rodata. This way we prevent it from ocassional modification by buggy software.
292 // core_ProtKernelArea(addr, kick_highest - addr, 1, 0, 1);
294 D(bug("[KRN] InitCode(RTF_SINGLETASK) ... \n"));
295 InitCode(RTF_SINGLETASK, 0);
297 D(bug("[KRN] Dropping into USER mode ... \n"));
298 asm("cps %[mode_user]\n" : : [mode_user] "I" (CPUMODE_USER)); /* switch to user mode */
300 D(bug("[KRN] InitCode(RTF_COLDSTART) ...\n"));
301 InitCode(RTF_COLDSTART, 0);
303 /* The above should not return */
304 krnPanic(KernelBase, "System Boot Failed!");
307 DEFINESET(ARMPLATFORMS);