Correctly access platform data via function argument.
[AROS.git] / arch / ppc-sam440 / kernel / kernel_startup.c
blob33843d63930f184fe48ea87ba15d82297c5ac21a
1 #define DEBUG 1
3 #include <aros/kernel.h>
4 #include <aros/libcall.h>
5 #include <aros/symbolsets.h>
6 #include <inttypes.h>
7 #include <exec/libraries.h>
8 #include <exec/execbase.h>
9 #include <aros/debug.h>
10 #include <exec/memory.h>
11 #include "memory.h"
12 #include <utility/tagitem.h>
13 #include <asm/amcc440.h>
14 #include <asm/io.h>
15 #include <strings.h>
17 #include <proto/exec.h>
19 #include LC_LIBDEFS_FILE
20 #include <kernel_romtags.h>
21 #include "kernel_intern.h"
23 /* forward declarations */
24 static void __attribute__((used)) kernel_cstart(struct TagItem *msg);
26 extern void exec_main(struct TagItem *msg, void *entry);
28 /* A very very very.....
29 * ... very ugly code.
31 * The AROS kernel gets executed at this place. The stack is unknown here, might be
32 * set properly up, might be totally broken aswell and thus one cannot trust the contents
33 * of %r1 register. Even worse, the kernel has been relocated most likely to some virtual
34 * address and the MMU mapping might not be ready now.
36 * The strategy is to create one MMU entry first, mapping first 16MB of ram into last 16MB
37 * of address space in one turn and then making proper MMU map once the bss sections are cleared
38 * and the startup routine in C is executed. This "trick" assumes two evil things:
39 * - the kernel will be loaded (and will fit completely) within first 16MB of RAM, and
40 * - the kernel will be mapped into top (last 16MB) of memory.
42 * Yes, I'm evil ;)
43 */
45 asm(".section .aros.init,\"ax\"\n\t"
46 ".globl start\n\t"
47 ".type start,@function\n"
48 "start:\n\t"
49 "mr %r29,%r3\n\t" /* Don't forget the message */
50 "lis %r5,0x4152\n\t" /* Load AROS magic value */
51 "ori %r5,%r5,0x4f53\n\t"
52 "cmpw %r5,%r4\n\t" /* Check if it was passed as 2nd parameter */
53 "bnelr\n\t" /* No, then return to caller */
54 "lis %r9,0xff00\n\t" /* Virtual address 0xff000000 */
55 "li %r10,0\n\t" /* Physical address 0x00000000 */
56 "ori %r9,%r9,0x0270\n\t" /* 16MB page. Valid one */
57 "li %r11,0x043f\n\t" /* Write through cache. RWX enabled :) */
58 "li %r0,0\n\t" /* TLB entry number 0 */
59 "tlbwe %r9,%r0,0\n\t"
60 "tlbwe %r10,%r0,1\n\t"
61 "tlbwe %r11,%r0,2\n\t"
62 "isync\n\t" /* Invalidate shadow TLB's */
63 "li %r9,0; mttbl %r9; mttbu %r9; mttbl %r9\n\t"
64 "lis %r9,tmp_stack_end@ha\n\t" /* Use temporary stack while clearing BSS */
65 "lwz %r1,tmp_stack_end@l(%r9)\n\t"
66 "bl __clear_bss_tagged\n\t" /* Clear 'em ALL!!! */
67 "lis %r11,target_address@ha\n\t" /* Load the address of init code in C */
68 "mr %r3,%r29\n\t" /* restore the message */
69 "lwz %r11,target_address@l(%r11)\n\t"
70 "lis %r9,stack_end@ha\n\t" /* Use brand new stack to do evil things */
71 "mtctr %r11\n\t"
72 "lwz %r1,stack_end@l(%r9)\n\t"
73 "bctr\n\t" /* And start the game... */
74 ".string \"Native/CORE v3 (" __DATE__ ")\""
75 "\n\t.text\n\t"
78 static void __attribute__((used)) __clear_bss_tagged(struct TagItem *msg)
80 struct KernelBSS *bss = (struct KernelBSS *) krnGetTagData(KRN_KernelBss, 0, msg);
82 __clear_bss(bss);
85 static union {
86 struct TagItem bootup_tags[64];
87 uint32_t tmp_stack [128];
88 } tmp_struct __attribute__((used, section(".data"), aligned(16)));
89 static const uint32_t *tmp_stack_end __attribute__((used, section(".text"))) = &tmp_struct.tmp_stack[124];
90 static uint32_t stack[STACK_SIZE] __attribute__((used, aligned(16)));
91 static uint32_t stack_super[STACK_SIZE] __attribute__((used, aligned(16)));
92 static const uint32_t *stack_end __attribute__((used, section(".text"))) = &stack[STACK_SIZE-4];
93 static const void *target_address __attribute__((used, section(".text"))) = (void*)kernel_cstart;
94 static char CmdLine[200] __attribute__((used));
96 module_t * modlist;
97 uint32_t modlength;
98 uintptr_t memlo;
99 struct ExecBase *SysBase;
101 static uint32_t exec_SelectMbs440(uint32_t bcr)
103 uint32_t val;
105 wrdcr(SDRAM0_CFGADDR, bcr);
106 val = rddcr(SDRAM0_CFGDATA);
108 switch (val & SDRAM_SDSZ_MASK)
110 case SDRAM_SDSZ_256MB: return 256;
111 case SDRAM_SDSZ_128MB: return 128;
112 case SDRAM_SDSZ_64MB: return 64;
113 case SDRAM_SDSZ_32MB: return 32;
114 case SDRAM_SDSZ_16MB: return 16;
115 case SDRAM_SDSZ_8MB: return 8;
118 return 0;
121 static uint32_t exec_SelectMbs460(uint32_t val)
123 D(bug("[%s] DCR 0x%08x\n", __func__, val));
124 switch (val & MQ0_BASSZ_MASK)
126 case MQ0_BASSZ_4096MB: return 4096;
127 case MQ0_BASSZ_2048MB: return 2048;
128 case MQ0_BASSZ_1024MB: return 1024;
129 case MQ0_BASSZ_512MB: return 512;
130 case MQ0_BASSZ_256MB: return 256;
131 case MQ0_BASSZ_128MB: return 128;
132 case MQ0_BASSZ_64MB: return 64;
133 case MQ0_BASSZ_32MB: return 32;
134 case MQ0_BASSZ_16MB: return 16;
135 case MQ0_BASSZ_8MB: return 8;
138 return 0;
141 /* Detect and report amount of available memory in mega bytes via device control register bus */
142 static uint32_t exec_GetMemory()
144 uint32_t mem = 0;
145 uint32_t pvr = rdspr(PVR);
147 if (krnIsPPC440(pvr)) {
148 mem += exec_SelectMbs440(SDRAM0_B0CR);
149 mem += exec_SelectMbs440(SDRAM0_B1CR);
150 mem += exec_SelectMbs440(SDRAM0_B2CR);
151 mem += exec_SelectMbs440(SDRAM0_B3CR);
152 } else if (krnIsPPC460(pvr)) {
153 /* Hmm. Probably a 460EX */
154 mem += exec_SelectMbs460(rddcr(MQ0_B0BAS));
155 mem += exec_SelectMbs460(rddcr(MQ0_B1BAS));
156 mem += exec_SelectMbs460(rddcr(MQ0_B2BAS));
157 mem += exec_SelectMbs460(rddcr(MQ0_B3BAS));
158 } else {
159 bug("Memory: Unrecognized PVR model 0x%08x\n", pvr);
160 bug("Memory: Assuming you have 64M of RAM\n");
161 mem = 64;
164 return mem;
167 void exec_main(struct TagItem *msg, void *entry)
169 UWORD *memrange[3];
170 uint32_t mem, krnLowest, krnHighest;
171 struct MemHeader *mh;
173 D(bug("[exec] AROS for Sam440 - The AROS Research OS\n"));
175 /* Prepare the exec base */
176 D(bug("[exec] Preparing the ExecBase...\n"));
178 /* Get the kernel memory locations */
179 krnLowest = krnGetTagData(KRN_KernelLowest, 0, msg);
180 krnHighest = (krnGetTagData(KRN_KernelHighest, 0, msg) + 0xffff) & 0xffff0000;
181 D(bug("[exec] Create memory header @%p - %p\n", krnHighest, 0x01000000-1));
182 krnCreateMemHeader("RAM", -10, (APTR)(krnHighest), 0x01000000 - (IPTR)krnHighest,
183 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA);
185 memrange[0] = (UWORD *)(krnLowest + 0xff000000);
186 memrange[1] = (UWORD *)(krnHighest + 0xff000000);
187 memrange[2] = (UWORD *)-1;
189 mh = (struct MemHeader *)krnHighest;
191 D(bug("[exec] Prepare exec base in %p\n", mh));
192 krnPrepareExecBase(memrange, mh, msg);
193 wrspr(SPRG5, SysBase);
194 D(bug("[exec] ExecBase at %08x\n", SysBase));
196 mem = exec_GetMemory();
197 D(bug("[exec] Adding memory (%uM)\n", mem));
199 AddMemList((mem - 16) * 1024*1024,
200 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
202 (APTR)0x01000000,
203 "Fast RAM");
205 D(bug("[exec] InitCode(RTF_SINGLETASK)\n"));
206 InitCode(RTF_SINGLETASK, 0);
208 D(bug("[exec] InitCode(RTF_COLDSTART)\n"));
209 InitCode(RTF_COLDSTART, 0);
211 D(bug("[exec] I should never get here...\n"));
215 static void __attribute__((used)) kernel_cstart(struct TagItem *msg)
217 struct TagItem *tmp = tmp_struct.bootup_tags;
219 /* Lowest usable kernel memory */
220 memlo = 0xff000000;
222 /* Disable interrupts and let FPU work */
223 wrmsr((rdmsr() & ~(MSR_CE | MSR_EE | MSR_ME)) | MSR_FP);
225 /* Enable FPU */
226 wrspr(CCR0, rdspr(CCR0) & ~0x00100000);
227 wrspr(CCR1, rdspr(CCR1) | (0x80000000 >> 24));
229 /* First message after FPU is enabled, otherwise illegal instruction */
230 D(bug("[KRN] Sam440 Kernel built on %s\n", __DATE__));
232 /* Set supervisor stack */
233 wrspr(SPRG0, (uint32_t)&stack_super[STACK_SIZE-4]);
235 wrspr(SPRG4, 0); /* Clear KernelBase */
236 wrspr(SPRG5, 0); /* Clear SysBase */
238 D(bug("[KRN] Kernel resource pre-exec init\n"));
239 D(bug("[KRN] MSR=%08x CRR0=%08x CRR1=%08x\n", rdmsr(), rdspr(CCR0), rdspr(CCR1)));
240 D(bug("[KRN] USB config %08x\n", rddcr(SDR0_USB0)));
242 D(bug("[KRN] msg @ %p\n", msg));
243 D(bug("[KRN] Copying msg data\n"));
244 while(msg->ti_Tag != TAG_DONE)
246 *tmp = *msg;
248 if (tmp->ti_Tag == KRN_CmdLine)
250 strcpy(CmdLine, (char*) msg->ti_Data);
251 tmp->ti_Data = (STACKIPTR) CmdLine;
252 D(bug("[KRN] CmdLine %s\n", tmp->ti_Data));
254 else if (tmp->ti_Tag == KRN_BootLoader)
256 tmp->ti_Data = (STACKIPTR) memlo;
257 memlo += (strlen((char *)memlo) + 4) & ~3;
258 strcpy((char*)tmp->ti_Data, (const char*) msg->ti_Data);
260 else if (tmp->ti_Tag == KRN_DebugInfo)
262 int i;
263 struct MinList *mlist = (struct MinList *)tmp->ti_Data;
265 D(bug("[KRN] DebugInfo at %08x\n", mlist));
267 module_t *mod = (module_t *)memlo;
269 ListLength(mlist, modlength);
270 modlist = mod;
272 memlo = (uintptr_t)&mod[modlength];
274 D(bug("[KRN] Bootstrap loaded debug info for %d modules\n", modlength));
275 /* Copy the module entries */
276 for (i=0; i < modlength; i++)
278 module_t *m = (module_t *)REMHEAD(mlist);
279 symbol_t *sym;
281 mod[i].m_lowest = m->m_lowest;
282 mod[i].m_highest = m->m_highest;
283 mod[i].m_str = NULL;
284 NEWLIST(&mod[i].m_symbols);
285 mod[i].m_name = (char *)memlo;
286 memlo += (strlen(m->m_name) + 4) & ~3;
287 strcpy(mod[i].m_name, m->m_name);
289 D(bug("[KRN] Module %s\n", m->m_name));
291 ForeachNode(&m->m_symbols, sym)
293 symbol_t *newsym = (symbol_t *)memlo;
294 memlo += sizeof(symbol_t);
296 newsym->s_name = (char *)memlo;
297 memlo += (strlen(sym->s_name)+4)&~3;
298 strcpy(newsym->s_name, sym->s_name);
300 newsym->s_lowest = sym->s_lowest;
301 newsym->s_highest = sym->s_highest;
303 ADDTAIL(&mod[i].m_symbols, newsym);
307 D(bug("[KRN] Debug info uses %d KB of memory\n", ((intptr_t)memlo - (intptr_t)mod) >> 10));
311 ++tmp;
312 ++msg;
315 memlo = (memlo + 4095) & ~4095;
317 BootMsg = tmp_struct.bootup_tags;
318 D(bug("[KRN] BootMsg @ %p\n", BootMsg));
320 /* Do a slightly more sophisticated MMU map */
321 mmu_init(BootMsg);
322 intr_init();
325 /* Initialize exec.library */
326 exec_main(BootMsg, NULL);
328 goSuper();
329 D(bug("[KRN] Uhm? Nothing to do?\n[KRN] STOPPED\n"));
332 * Do never ever try to return. This code would attempt to go back to the physical address
333 * of asm trampoline, not the virtual one!
335 while(1) {
336 wrmsr(rdmsr() | MSR_POW);
340 void SetupClocking440(struct PlatformData *pd)
342 /* PLL divisors */
343 wrdcr(CPR0_CFGADDR, CPR0_PLLD0);
344 uint32_t reg = rddcr(CPR0_CFGDATA);
346 uint32_t fbdv = (reg >> 24) & 0x1f;
347 if (fbdv == 0)
348 fbdv = 32;
349 uint32_t fwdva = (reg >> 16) & 0x1f;
350 if (fwdva == 0)
351 fwdva = 16;
352 uint32_t fwdvb = (reg >> 8) & 7;
353 if (fwdvb == 0)
354 fwdvb = 8;
355 uint32_t lfbdv = reg & 0x3f;
356 if (lfbdv == 0)
357 lfbdv = 64;
359 /* OPB clock divisor */
360 wrdcr(CPR0_CFGADDR, CPR0_OPBD0);
361 reg = rddcr(CPR0_CFGDATA);
362 uint32_t opbdv0 = (reg >> 24) & 3;
363 if (opbdv0 == 0)
364 opbdv0 = 4;
366 /* Peripheral clock divisor */
367 wrdcr(CPR0_CFGADDR, CPR0_PERD0);
368 reg = rddcr(CPR0_CFGDATA);
369 uint32_t perdv0 = (reg >> 24) & 7;
370 if (perdv0 == 0)
371 perdv0 = 8;
373 /* PCI clock divisor */
374 wrdcr(CPR0_CFGADDR, CPR0_SPCID);
375 reg = rddcr(CPR0_CFGDATA);
376 uint32_t spcid0 = (reg >> 24) & 3;
377 if (spcid0 == 0)
378 spcid0 = 4;
380 /* Primary B divisor */
381 wrdcr(CPR0_CFGADDR, CPR0_PRIMBD0);
382 reg = rddcr(CPR0_CFGDATA);
383 uint32_t prbdv0 = (reg >> 24) & 7;
384 if (prbdv0 == 0)
385 prbdv0 = 8;
387 /* All divisors there. Read PLL control register and calculate the m value (see 44ep.book) */
388 wrdcr(CPR0_CFGADDR, CPR0_PLLC0);
389 reg = rddcr(CPR0_CFGDATA);
390 uint32_t m;
391 switch ((reg >> 24) & 3) /* Feedback selector */
393 case 0: /* PLL output (A or B) */
394 if ((reg & 0x20000000)) /* PLLOUTB */
395 m = lfbdv * fbdv * fwdvb;
396 else
397 m = lfbdv * fbdv * fwdva;
398 break;
399 case 1: /* CPU */
400 m = fbdv * fwdva;
401 default:
402 m = perdv0 * opbdv0 * fwdvb;
405 uint32_t vco = (m * 66666666) + m/2;
406 pd->pd_CPUFreq = vco / fwdva;
407 pd->pd_PLBFreq = vco / fwdvb / perdv0;
408 pd->pd_OPBFreq = pd->pd_PLBFreq / opbdv0;
409 pd->pd_EPBFreq = pd->pd_PLBFreq / perdv0;
410 pd->pd_PCIFreq = pd->pd_PLBFreq / spcid0;
413 * Slow down the decrement interrupt a bit. Rough guess is that UBoot has left us with
414 * 1kHz DEC counter. Enable decrementer timer and automatic reload of decrementer value.
416 wrspr(DECAR, pd->pd_OPBFreq / 50);
417 wrspr(TCR, rdspr(TCR) | TCR_DIE | TCR_ARE);
421 const uint8_t fbdv_map[256] = {
422 1, 123, 117, 251, 245, 69, 111, 125,
423 119, 95, 105, 197, 239, 163, 63, 253,
424 247, 187, 57, 223, 233, 207, 157, 71,
425 113, 15, 89, 37, 191, 19, 99, 127,
426 121, 109, 93, 61, 185, 155, 13, 97,
427 107, 11, 9, 81, 31, 49, 83, 199,
428 241, 33, 181, 143, 217, 173, 51, 165,
429 65, 85, 151, 147, 227, 41, 201, 255,
430 249, 243, 195, 237, 221, 231, 35, 189,
431 59, 183, 79, 29, 141, 215, 145, 225,
432 235, 219, 27, 139, 137, 135, 175, 209,
433 159, 53, 45, 177, 211, 23, 167, 73,
434 115, 67, 103, 161, 55, 205, 87, 17,
435 91, 153, 7, 47, 179, 171, 149, 39,
436 193, 229, 77, 213, 25, 133, 43, 21,
437 101, 203, 5, 169, 75, 131, 3, 129,
438 1, 250, 244, 124, 118, 196, 238, 252,
439 246, 222, 232, 70, 112, 36, 190, 126,
440 120, 60, 184, 96, 106, 80, 30, 198,
441 240, 142, 216, 164, 64, 146, 226, 254,
442 248, 236, 220, 188, 58, 28, 140, 224,
443 234, 138, 136, 208, 158, 176, 210, 72,
444 114, 160, 54, 16, 90, 46, 178, 38,
445 192, 212, 24, 20, 100, 168, 74, 128,
446 122, 116, 68, 110, 94, 104, 162, 62,
447 186, 56, 206, 156, 14, 88, 18, 98,
448 108, 92, 154, 12, 10, 8, 48, 82,
449 32, 180, 172, 50, 84, 150, 40, 200,
450 242, 194, 230, 34, 182, 78, 214, 144,
451 218, 26, 134, 174, 52, 44, 22, 166,
452 66, 102, 204, 86, 152, 6, 170, 148,
453 228, 76, 132, 42, 202, 4, 130, 2,
456 static const uint8_t fwdv_map[16] = {
457 1, 2, 14, 9, 4, 11, 16, 13,
458 12, 5, 6, 15, 10, 7, 8, 3,
461 void SetupClocking460(struct PlatformData *pd)
463 uint32_t reg;
465 /* PLL divisors */
466 wrdcr(CPR0_CFGADDR, CPR0_PLLD);
467 reg = rddcr(CPR0_CFGDATA);
469 uint32_t fbdv = fbdv_map[(reg >> 24) & 0xff];
470 uint32_t fwdva = fwdv_map[((reg >> 16) & 0xf)];
471 uint32_t fwdvb = fwdv_map[(reg >> 8) & 0xf];
472 (void)fwdvb; // Unused
474 /* Early PLL divisor */
475 wrdcr(CPR0_CFGADDR, CPR0_PLBED);
476 reg = rddcr(CPR0_CFGDATA);
477 uint32_t plbed = (reg >> 24) & 0x7;
478 if (plbed == 0)
479 plbed = 8;
481 /* OPB clock divisor */
482 wrdcr(CPR0_CFGADDR, CPR0_OPBD);
483 reg = rddcr(CPR0_CFGDATA);
484 uint32_t opbd = (reg >> 24) & 3;
485 if (opbd == 0)
486 opbd = 4;
488 /* Peripheral clock divisor */
489 wrdcr(CPR0_CFGADDR, CPR0_PERD);
490 reg = rddcr(CPR0_CFGDATA);
491 uint32_t perd = (reg >> 24) & 3;
492 if (perd == 0)
493 perd = 4;
495 /* AHB clock divisor */
496 wrdcr(CPR0_CFGADDR, CPR0_AHBD);
497 reg = rddcr(CPR0_CFGDATA);
498 uint32_t ahbd = (reg >> 24) & 1;
499 if (ahbd == 0)
500 ahbd = 2;
502 /* All divisors there.
503 * Read PLL control register and calculate the m value
505 wrdcr(CPR0_CFGADDR, CPR0_PLLC);
506 reg = rddcr(CPR0_CFGDATA);
508 uint32_t m;
509 if (((reg >> 24) & 3) == 0) {
510 /* PLL internal feedback */
511 m = fbdv;
512 } else {
513 /* PLL Per-Clock feedback */
514 m = fwdva * plbed * opbd * ahbd;
517 D(bug("fbdv %d, fwdva = %d, fwdvb = %d\n", fbdv, fwdva, fwdvb));
518 D(bug("plbed %d, opbd = %d, perd = %d, ahbd = %d\n",
519 plbed, opbd, perd, ahbd));
521 uint64_t vco = (m * 50000000) + m/2;
522 pd->pd_CPUFreq = vco / fwdva;
523 pd->pd_PLBFreq = vco / fwdva / plbed;
524 pd->pd_OPBFreq = pd->pd_PLBFreq / opbd;
525 pd->pd_EPBFreq = pd->pd_OPBFreq / perd;
526 pd->pd_PCIFreq = pd->pd_PLBFreq / ahbd;
529 * Slow down the decrement interrupt a bit. Rough guess is that UBoot has left us with
530 * 1kHz DEC counter. Enable decrementer timer and automatic reload of decrementer value.
532 wrspr(DECAR, pd->pd_OPBFreq / 50);
533 wrspr(TCR, rdspr(TCR) | TCR_DIE | TCR_ARE);
536 struct MemHeader mh;
538 static int Kernel_Init(LIBBASETYPEPTR LIBBASE)
540 int i;
541 struct PlatformData *pd;
542 struct ExecBase *SysBase = getSysBase();
544 uintptr_t krn_lowest = krnGetTagData(KRN_KernelLowest, 0, BootMsg);
545 uintptr_t krn_highest = krnGetTagData(KRN_KernelHighest, 0, BootMsg);
547 D(bug("Kernel_Init Entered\n"));
548 /* Get the PLB and CPU speed */
550 pd = AllocMem(sizeof(struct PlatformData), MEMF_PUBLIC|MEMF_CLEAR);
551 if (!pd)
552 return FALSE;
554 LIBBASE->kb_PlatformData = pd;
556 /* Stash the PVR value */
557 pd->pd_PVR = rdspr(PVR);
558 D(bug("[KRN] PVR: 0x%08x\n", pd->pd_PVR));
560 if (krnIsPPC440(pd->pd_PVR)) {
561 SetupClocking440(pd);
562 } else if (krnIsPPC460(pd->pd_PVR)) {
563 SetupClocking460(pd);
564 } else {
565 bug("kernel.resource: Unknown PVR model 0x%08x\n", pd->pd_PVR);
566 for (;;);
569 D(bug("[KRN] Kernel resource post-exec init\n"));
571 D(bug("[KRN] CPU Speed: %dMz\n", LIBBASE->kb_PlatformData->pd_CPUFreq / 1000000));
572 D(bug("[KRN] PLB Speed: %dMz\n", LIBBASE->kb_PlatformData->pd_PLBFreq / 1000000));
573 D(bug("[KRN] OPB Speed: %dMz\n", LIBBASE->kb_PlatformData->pd_OPBFreq / 1000000));
574 D(bug("[KRN] EPB Speed: %dMz\n", LIBBASE->kb_PlatformData->pd_EPBFreq / 1000000));
575 D(bug("[KRN] PCI Speed: %dMz\n", LIBBASE->kb_PlatformData->pd_PCIFreq / 1000000));
577 /* 4K granularity for data sections */
578 krn_lowest &= 0xfffff000;
579 /* 64K granularity for code sections */
580 krn_highest = (krn_highest + 0xffff) & 0xffff0000;
583 * Set the KernelBase into SPRG4. At this stage the SPRG5 should be already set by
584 * exec.library itself.
586 wrspr(SPRG4, LIBBASE);
588 D(bug("[KRN] Allowing userspace to flush caches\n"));
589 wrspr(MMUCR, rdspr(MMUCR) & ~0x000c0000);
591 for (i=0; i < 16; i++)
592 NEWLIST(&LIBBASE->kb_Exceptions[i]);
594 for (i=0; i < 64; i++)
595 NEWLIST(&LIBBASE->kb_Interrupts[i]);
597 LIBBASE->kb_ContextSize = sizeof(context_t);
599 NEWLIST(&LIBBASE->kb_PlatformData->pd_Modules);
601 D(bug("[KRN] Preparing kernel private memory "));
602 /* Prepare MemHeader structure to allocate from private low memory */
603 mh.mh_Node.ln_Type = NT_MEMORY;
604 mh.mh_Node.ln_Pri = -128;
605 mh.mh_Node.ln_Name = "Kernel Memory";
606 mh.mh_Attributes = MEMF_FAST | MEMF_KICK | MEMF_LOCAL;
607 mh.mh_First = (struct MemChunk *)memlo;
608 mh.mh_Lower = mh.mh_First;
609 mh.mh_Upper = (APTR) ((uintptr_t) 0xff000000 + krn_lowest - 1);
611 mh.mh_Free = (uintptr_t)mh.mh_Upper - (uintptr_t)mh.mh_Lower + 1;
612 mh.mh_First->mc_Next = NULL;
613 mh.mh_First->mc_Bytes = mh.mh_Free;
615 D(bug("[KRN] %08x - %08x, %d KB free\n", mh.mh_Lower, mh.mh_Upper, mh.mh_Free >> 10));
617 LIBBASE->kb_PlatformData->pd_SupervisorMem = &mh;
620 * Add MemHeader about kernel memory to public MemList to avoid invalid
621 * pointer debug messages for pointer that reference correctly into these
622 * mem regions.
624 struct MemHeader *mh;
625 mh = AllocMem(sizeof(struct MemHeader), MEMF_PUBLIC);
626 mh->mh_Node.ln_Type = NT_MEMORY;
627 mh->mh_Node.ln_Pri = -128;
628 mh->mh_Node.ln_Name = "Kernel Memory, Code + Data Sections";
629 mh->mh_Attributes = MEMF_FAST | MEMF_KICK | MEMF_LOCAL;
630 mh->mh_First = NULL;
631 mh->mh_Free = 0;
632 mh->mh_Lower = LIBBASE->kb_PlatformData->pd_SupervisorMem;
633 mh->mh_Upper = (APTR) ((uintptr_t) 0xff000000 + krn_highest - 1);
635 Enqueue(&SysBase->MemList, &mh->mh_Node);
638 * kernel.resource is ready to run. Enable external interrupts and leave
639 * supervisor mode.
641 wrmsr(rdmsr() | MSR_EE);
642 D(bug("[KRN] Interrupts enabled\n"));
644 goUser();
645 D(bug("[KRN] Entered user mode \n"));
647 return TRUE;
650 ADD2INITLIB(Kernel_Init, 0)