2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
8 #include <aros/kernel.h>
9 #include <aros/libcall.h>
10 #include <aros/symbolsets.h>
12 #include <exec/libraries.h>
13 #include <exec/execbase.h>
14 #include <aros/debug.h>
15 #include <exec/memory.h>
17 #include <utility/tagitem.h>
18 #include <asm/amcc440.h>
22 #include <proto/exec.h>
24 #include LC_LIBDEFS_FILE
25 #include <kernel_romtags.h>
26 #include "kernel_intern.h"
28 /* forward declarations */
29 static void __attribute__((used
)) kernel_cstart(struct TagItem
*msg
);
31 extern void exec_main(struct TagItem
*msg
, void *entry
);
33 /* A very very very.....
36 * The AROS kernel gets executed at this place. The stack is unknown here, might be
37 * set properly up, might be totally broken aswell and thus one cannot trust the contents
38 * of %r1 register. Even worse, the kernel has been relocated most likely to some virtual
39 * address and the MMU mapping might not be ready now.
41 * The strategy is to create one MMU entry first, mapping first 16MB of ram into last 16MB
42 * of address space in one turn and then making proper MMU map once the bss sections are cleared
43 * and the startup routine in C is executed. This "trick" assumes two evil things:
44 * - the kernel will be loaded (and will fit completely) within first 16MB of RAM, and
45 * - the kernel will be mapped into top (last 16MB) of memory.
50 asm(".section .aros.init,\"ax\"\n\t"
52 ".type start,@function\n"
54 "mr %r29,%r3\n\t" /* Don't forget the message */
55 "lis %r5,0x4152\n\t" /* Load AROS magic value */
56 "ori %r5,%r5,0x4f53\n\t"
57 "cmpw %r5,%r4\n\t" /* Check if it was passed as 2nd parameter */
58 "bnelr\n\t" /* No, then return to caller */
59 "lis %r9,0xff00\n\t" /* Virtual address 0xff000000 */
60 "li %r10,0\n\t" /* Physical address 0x00000000 */
61 "ori %r9,%r9,0x0270\n\t" /* 16MB page. Valid one */
62 "li %r11,0x043f\n\t" /* Write through cache. RWX enabled :) */
63 "li %r0,0\n\t" /* TLB entry number 0 */
65 "tlbwe %r10,%r0,1\n\t"
66 "tlbwe %r11,%r0,2\n\t"
67 "isync\n\t" /* Invalidate shadow TLB's */
68 "li %r9,0; mttbl %r9; mttbu %r9; mttbl %r9\n\t"
69 "lis %r9,tmp_stack_end@ha\n\t" /* Use temporary stack while clearing BSS */
70 "lwz %r1,tmp_stack_end@l(%r9)\n\t"
71 "bl __clear_bss_tagged\n\t" /* Clear 'em ALL!!! */
72 "lis %r11,target_address@ha\n\t" /* Load the address of init code in C */
73 "mr %r3,%r29\n\t" /* restore the message */
74 "lwz %r11,target_address@l(%r11)\n\t"
75 "lis %r9,stack_end@ha\n\t" /* Use brand new stack to do evil things */
77 "lwz %r1,stack_end@l(%r9)\n\t"
78 "bctr\n\t" /* And start the game... */
79 ".string \"Native/CORE v3 (" __DATE__
")\""
83 static void __attribute__((used
)) __clear_bss_tagged(struct TagItem
*msg
)
85 struct KernelBSS
*bss
= (struct KernelBSS
*) krnGetTagData(KRN_KernelBss
, 0, msg
);
91 struct TagItem bootup_tags
[64];
92 uint32_t tmp_stack
[128];
93 } tmp_struct
__attribute__((used
, section(".data"), aligned(16)));
94 static const uint32_t *tmp_stack_end
__attribute__((used
, section(".text"))) = &tmp_struct
.tmp_stack
[124];
95 static uint32_t stack
[STACK_SIZE
] __attribute__((used
, aligned(16)));
96 static const uint32_t *stack_end
__attribute__((used
, section(".text"))) = &stack
[STACK_SIZE
-4];
97 static const void *target_address
__attribute__((used
, section(".text"))) = (void*)kernel_cstart
;
98 static char CmdLine
[200] __attribute__((used
));
100 struct MinList
*modlist
;
102 struct ExecBase
*SysBase
;
104 static uint32_t exec_SelectMbs440(uint32_t bcr
)
108 wrdcr(SDRAM0_CFGADDR
, bcr
);
109 val
= rddcr(SDRAM0_CFGDATA
);
111 switch (val
& SDRAM_SDSZ_MASK
)
113 case SDRAM_SDSZ_256MB
: return 256;
114 case SDRAM_SDSZ_128MB
: return 128;
115 case SDRAM_SDSZ_64MB
: return 64;
116 case SDRAM_SDSZ_32MB
: return 32;
117 case SDRAM_SDSZ_16MB
: return 16;
118 case SDRAM_SDSZ_8MB
: return 8;
124 static uint32_t exec_SelectMbs460(uint32_t val
)
126 D(bug("[%s] DCR 0x%08x\n", __func__
, val
));
127 switch (val
& MQ0_BASSZ_MASK
)
129 case MQ0_BASSZ_4096MB
: return 4096;
130 case MQ0_BASSZ_2048MB
: return 2048;
131 case MQ0_BASSZ_1024MB
: return 1024;
132 case MQ0_BASSZ_512MB
: return 512;
133 case MQ0_BASSZ_256MB
: return 256;
134 case MQ0_BASSZ_128MB
: return 128;
135 case MQ0_BASSZ_64MB
: return 64;
136 case MQ0_BASSZ_32MB
: return 32;
137 case MQ0_BASSZ_16MB
: return 16;
138 case MQ0_BASSZ_8MB
: return 8;
144 /* Detect and report amount of available memory in mega bytes via device control register bus */
145 static uint32_t exec_GetMemory()
148 uint32_t pvr
= rdspr(PVR
);
150 if (krnIsPPC440(pvr
)) {
151 mem
+= exec_SelectMbs440(SDRAM0_B0CR
);
152 mem
+= exec_SelectMbs440(SDRAM0_B1CR
);
153 mem
+= exec_SelectMbs440(SDRAM0_B2CR
);
154 mem
+= exec_SelectMbs440(SDRAM0_B3CR
);
155 } else if (krnIsPPC460(pvr
)) {
156 /* Hmm. Probably a 460EX */
157 mem
+= exec_SelectMbs460(rddcr(MQ0_B0BAS
));
158 mem
+= exec_SelectMbs460(rddcr(MQ0_B1BAS
));
159 mem
+= exec_SelectMbs460(rddcr(MQ0_B2BAS
));
160 mem
+= exec_SelectMbs460(rddcr(MQ0_B3BAS
));
162 bug("Memory: Unrecognized PVR model 0x%08x\n", pvr
);
163 bug("Memory: Assuming you have 64M of RAM\n");
170 void exec_main(struct TagItem
*msg
, void *entry
)
173 uint32_t mem
, krnLowest
, krnHighest
, memLowest
;
174 struct MemHeader
*mh
;
176 D(bug("[exec] AROS for Sam440 - The AROS Research OS\n"));
178 /* Prepare the exec base */
179 D(bug("[exec] Preparing the ExecBase...\n"));
181 /* Get the kernel memory locations */
182 krnLowest
= krnGetTagData(KRN_KernelLowest
, 0, msg
);
183 krnHighest
= krnGetTagData(KRN_KernelHighest
, 0, msg
);
185 memLowest
= (krnHighest
+ 0xffff) & 0xffff0000;
187 D(bug("[exec] Kernel and romtags: @%p - %p\n", krnLowest
, krnHighest
));
188 D(bug("[exec] Create memory header @%p - %p\n", memLowest
, 0x01000000-1));
189 krnCreateMemHeader("RAM", -10, (APTR
)(memLowest
), 0x01000000 - (IPTR
)memLowest
,
190 MEMF_CHIP
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
| MEMF_24BITDMA
);
192 memrange
[0] = (UWORD
*)(krnLowest
+ 0xff000000);
193 memrange
[1] = (UWORD
*)(krnHighest
+ 0xff000000);
194 memrange
[2] = (UWORD
*)-1;
196 mh
= (struct MemHeader
*)memLowest
;
198 D(bug("[exec] Prepare exec base in %p\n", mh
));
199 krnPrepareExecBase(memrange
, mh
, msg
);
200 D(bug("[exec] ExecBase at %08x\n", SysBase
));
202 /* Set up %r2 to point to SysBase
203 * For now, this is only used by the mmu_handler
204 * to patch up the damage that Parthenope does
205 * when it loads modules, and assumes that
206 * &SysBase == (void **)4;
208 asm volatile ("mr %%r2, %0\n" :: "r"(SysBase
));
210 mem
= exec_GetMemory();
211 D(bug("[exec] Adding memory (%uM)\n", mem
));
213 AddMemList((mem
- 16) * 1024*1024,
214 MEMF_FAST
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
,
219 D(bug("[exec] InitCode(RTF_SINGLETASK)\n"));
220 InitCode(RTF_SINGLETASK
, 0);
222 D(bug("[exec] InitCode(RTF_COLDSTART)\n"));
223 InitCode(RTF_COLDSTART
, 0);
225 D(bug("[exec] I should never get here...\n"));
229 static void __attribute__((used
)) kernel_cstart(struct TagItem
*msg
)
231 struct TagItem
*tmp
= tmp_struct
.bootup_tags
;
234 /* Lowest usable kernel memory */
237 /* Disable interrupts and let FPU work */
238 wrmsr((rdmsr() & ~(MSR_CE
| MSR_EE
| MSR_ME
)) | MSR_FP
);
241 wrspr(CCR0
, rdspr(CCR0
) & ~0x00100000);
243 /* First message after FPU is enabled, otherwise illegal instruction */
244 D(bug("[KRN] Sam440 Kernel built on %s\n", __DATE__
));
250 wrspr(SPRG4
, 0); /* Clear KernelBase */
251 wrspr(SPRG5
, 0); /* Clear SysBase */
253 D(bug("[KRN] Kernel resource pre-exec init\n"));
254 D(bug("[KRN] MSR=%08x CRR0=%08x CRR1=%08x\n", rdmsr(), rdspr(CCR0
), rdspr(CCR1
)));
255 D(bug("[KRN] USB config %08x\n", rddcr(SDR0_USB0
)));
257 D(bug("[KRN] msg @ %p\n", msg
));
258 D(bug("[KRN] Copying msg data\n"));
259 while(msg
->ti_Tag
!= TAG_DONE
)
263 if (tmp
->ti_Tag
== KRN_CmdLine
)
265 strcpy(CmdLine
, (char*) msg
->ti_Data
);
266 tmp
->ti_Data
= (STACKIPTR
) CmdLine
;
267 D(bug("[KRN] CmdLine: %s\n", tmp
->ti_Data
));
269 else if (tmp
->ti_Tag
== KRN_BootLoader
)
271 tmp
->ti_Data
= (STACKIPTR
) memlo
;
272 strcpy((char*)tmp
->ti_Data
, (const char*) msg
->ti_Data
);
273 memlo
+= (strlen((char *)memlo
) + 4) & ~3;
274 D(bug("[KRN] BootLoader: %s\n", tmp
->ti_Data
));
276 else if (tmp
->ti_Tag
== KRN_DebugInfo
)
279 struct MinList
*mlist
= (struct MinList
*)tmp
->ti_Data
;
282 D(bug("[KRN] DebugInfo at %08x\n", mlist
));
284 modlist
= (struct MinList
*)memlo
;
285 memlo
+= sizeof(*modlist
);
288 mod
= (module_t
*)memlo
;
290 ListLength(mlist
, modlength
);
291 memlo
= (uintptr_t)&mod
[modlength
];
293 D(bug("[KRN] Bootstrap loaded debug info for %d modules\n", modlength
));
294 /* Copy the module entries */
295 for (i
=0; i
< modlength
; i
++)
297 module_t
*m
= (module_t
*)REMHEAD(mlist
);
299 ULONG str_l
= ~0, str_h
= 0;
301 D(bug("[KRN] Module %s\n", m
->m_name
));
303 /* Discover size of the string table */
304 ForeachNode(&m
->m_symbols
, sym
) {
305 ULONG end
= (ULONG
)sym
->s_name
+ strlen(sym
->s_name
) + 1 + 1;
306 if ((ULONG
)sym
->s_name
< str_l
)
307 str_l
= (ULONG
)sym
->s_name
;
315 mod
[i
].m_lowest
= m
->m_lowest
;
316 mod
[i
].m_highest
= m
->m_highest
;
317 mod
[i
].m_str
= (char *)memlo
;
318 memcpy(mod
[i
].m_str
, (char *)str_l
, str_h
- str_l
);
319 memlo
+= ((str_h
- str_l
) + 3) & ~3;
320 mod
[i
].m_name
= (char *)memlo
;
321 memlo
+= (strlen(m
->m_name
) + 4) & ~3;
322 strcpy(mod
[i
].m_name
, m
->m_name
);
324 NEWLIST(&mod
[i
].m_symbols
);
326 ForeachNode(&m
->m_symbols
, sym
)
328 symbol_t
*newsym
= (symbol_t
*)memlo
;
329 memlo
+= sizeof(symbol_t
);
331 newsym
->s_name
= (IPTR
)sym
->s_name
- str_l
+ mod
[i
].m_str
;
332 newsym
->s_lowest
= sym
->s_lowest
;
333 newsym
->s_highest
= sym
->s_highest
;
335 ADDTAIL(&mod
[i
].m_symbols
, newsym
);
338 ADDTAIL(modlist
, &mod
[i
]);
341 D(bug("[KRN] Debug info uses %d KB of memory\n", ((intptr_t)memlo
- (intptr_t)modlist
) >> 10));
342 D(bug("[KRN] Debug info relocated from %p to %p\n", tmp
->ti_Data
, modlist
));
344 /* Ugh. Parthenope doesn't use the ELF_ModuleInfo format.
345 * Prevent debug.library from becoming confused.
354 memlo
= (memlo
+ 4095) & ~4095;
356 BootMsg
= tmp_struct
.bootup_tags
;
357 D(bug("[KRN] BootMsg @ %p\n", BootMsg
));
359 /* Do a slightly more sophisticated MMU map */
363 /* Initialize exec.library */
364 exec_main(BootMsg
, NULL
);
366 bug("[KRN] Uhm? Nothing to do?\n[KRN] STOPPED\n");
369 * Do never ever try to return. This code would attempt to go back to the physical address
370 * of asm trampoline, not the virtual one!
375 void SetupClocking440(struct PlatformData
*pd
)
378 wrdcr(CPR0_CFGADDR
, CPR0_PLLD0
);
379 uint32_t reg
= rddcr(CPR0_CFGDATA
);
381 uint32_t fbdv
= (reg
>> 24) & 0x1f;
384 uint32_t fwdva
= (reg
>> 16) & 0x1f;
387 uint32_t fwdvb
= (reg
>> 8) & 7;
390 uint32_t lfbdv
= reg
& 0x3f;
394 /* OPB clock divisor */
395 wrdcr(CPR0_CFGADDR
, CPR0_OPBD0
);
396 reg
= rddcr(CPR0_CFGDATA
);
397 uint32_t opbdv0
= (reg
>> 24) & 3;
401 /* Peripheral clock divisor */
402 wrdcr(CPR0_CFGADDR
, CPR0_PERD0
);
403 reg
= rddcr(CPR0_CFGDATA
);
404 uint32_t perdv0
= (reg
>> 24) & 7;
408 /* PCI clock divisor */
409 wrdcr(CPR0_CFGADDR
, CPR0_SPCID
);
410 reg
= rddcr(CPR0_CFGDATA
);
411 uint32_t spcid0
= (reg
>> 24) & 3;
415 /* Primary B divisor */
416 wrdcr(CPR0_CFGADDR
, CPR0_PRIMBD0
);
417 reg
= rddcr(CPR0_CFGDATA
);
418 uint32_t prbdv0
= (reg
>> 24) & 7;
422 /* All divisors there. Read PLL control register and calculate the m value (see 44ep.book) */
423 wrdcr(CPR0_CFGADDR
, CPR0_PLLC0
);
424 reg
= rddcr(CPR0_CFGDATA
);
426 switch ((reg
>> 24) & 3) /* Feedback selector */
428 case 0:/* PLL output (A or B) */
429 if ((reg
& 0x20000000)) /* PLLOUTB */
430 m
= lfbdv
* fbdv
* fwdvb
;
432 m
= lfbdv
* fbdv
* fwdva
;
437 m
= perdv0
* opbdv0
* fwdvb
;
440 uint32_t vco
= (m
* 66666666) + m
/2;
441 pd
->pd_CPUFreq
= vco
/ fwdva
;
442 pd
->pd_PLBFreq
= vco
/ fwdvb
/ perdv0
;
443 pd
->pd_OPBFreq
= pd
->pd_PLBFreq
/ opbdv0
;
444 pd
->pd_EPBFreq
= pd
->pd_PLBFreq
/ perdv0
;
445 pd
->pd_PCIFreq
= pd
->pd_PLBFreq
/ spcid0
;
448 * Slow down the decrement interrupt a bit. Rough guess is that UBoot has left us with
449 * 1kHz DEC counter. Enable decrementer timer and automatic reload of decrementer value.
452 wrspr(TCR
, reg
& ~(TCR_DIE
| TCR_ARE
));
453 wrspr(CCR1
, rdspr(CCR1
) | (0x80000000 >> 24));
454 wrspr(DECAR
, pd
->pd_OPBFreq
/ 50);
455 wrspr(TCR
, reg
| TCR_DIE
| TCR_ARE
);
459 const uint8_t fbdv_map
[256] = {
460 1, 123, 117, 251, 245, 69, 111, 125,
461 119, 95, 105, 197, 239, 163, 63, 253,
462 247, 187, 57, 223, 233, 207, 157, 71,
463 113, 15, 89, 37, 191, 19, 99, 127,
464 121, 109, 93, 61, 185, 155, 13, 97,
465 107, 11, 9, 81, 31, 49, 83, 199,
466 241, 33, 181, 143, 217, 173, 51, 165,
467 65, 85, 151, 147, 227, 41, 201, 255,
468 249, 243, 195, 237, 221, 231, 35, 189,
469 59, 183, 79, 29, 141, 215, 145, 225,
470 235, 219, 27, 139, 137, 135, 175, 209,
471 159, 53, 45, 177, 211, 23, 167, 73,
472 115, 67, 103, 161, 55, 205, 87, 17,
473 91, 153, 7, 47, 179, 171, 149, 39,
474 193, 229, 77, 213, 25, 133, 43, 21,
475 101, 203, 5, 169, 75, 131, 3, 129,
476 1, 250, 244, 124, 118, 196, 238, 252,
477 246, 222, 232, 70, 112, 36, 190, 126,
478 120, 60, 184, 96, 106, 80, 30, 198,
479 240, 142, 216, 164, 64, 146, 226, 254,
480 248, 236, 220, 188, 58, 28, 140, 224,
481 234, 138, 136, 208, 158, 176, 210, 72,
482 114, 160, 54, 16, 90, 46, 178, 38,
483 192, 212, 24, 20, 100, 168, 74, 128,
484 122, 116, 68, 110, 94, 104, 162, 62,
485 186, 56, 206, 156, 14, 88, 18, 98,
486 108, 92, 154, 12, 10, 8, 48, 82,
487 32, 180, 172, 50, 84, 150, 40, 200,
488 242, 194, 230, 34, 182, 78, 214, 144,
489 218, 26, 134, 174, 52, 44, 22, 166,
490 66, 102, 204, 86, 152, 6, 170, 148,
491 228, 76, 132, 42, 202, 4, 130, 2,
494 static const uint8_t fwdv_map
[16] = {
495 1, 2, 14, 9, 4, 11, 16, 13,
496 12, 5, 6, 15, 10, 7, 8, 3,
499 void SetupClocking460(struct PlatformData
*pd
)
504 wrdcr(CPR0_CFGADDR
, CPR0_PLLD
);
505 reg
= rddcr(CPR0_CFGDATA
);
507 uint32_t fbdv
= fbdv_map
[(reg
>> 24) & 0xff];
508 uint32_t fwdva
= fwdv_map
[((reg
>> 16) & 0xf)];
509 uint32_t fwdvb
= fwdv_map
[(reg
>> 8) & 0xf];
510 (void)fwdvb
; // Unused
512 /* Early PLL divisor */
513 wrdcr(CPR0_CFGADDR
, CPR0_PLBED
);
514 reg
= rddcr(CPR0_CFGDATA
);
515 uint32_t plbed
= (reg
>> 24) & 7;
519 /* OPB clock divisor */
520 wrdcr(CPR0_CFGADDR
, CPR0_OPBD
);
521 reg
= rddcr(CPR0_CFGDATA
);
522 uint32_t opbd
= (reg
>> 24) & 3;
526 /* Peripheral clock divisor */
527 wrdcr(CPR0_CFGADDR
, CPR0_PERD
);
528 reg
= rddcr(CPR0_CFGDATA
);
529 uint32_t perd
= (reg
>> 24) & 3;
533 /* AHB clock divisor */
534 wrdcr(CPR0_CFGADDR
, CPR0_AHBD
);
535 reg
= rddcr(CPR0_CFGDATA
);
536 uint32_t ahbd
= (reg
>> 24) & 1;
540 /* All divisors there.
541 * Read PLL control register and calculate the m value
543 wrdcr(CPR0_CFGADDR
, CPR0_PLLC
);
544 reg
= rddcr(CPR0_CFGDATA
);
547 if (((reg
>> 24) & 3) == 0) {
548 /* PLL internal feedback */
551 /* PLL Per-Clock feedback */
552 m
= fwdva
* plbed
* opbd
* perd
;
555 D(bug("fbdv %d, fwdva = %d, fwdvb = %d\n", fbdv
, fwdva
, fwdvb
));
556 D(bug("plbed %d, opbd = %d, perd = %d, ahbd = %d\n",
557 plbed
, opbd
, perd
, ahbd
));
559 /* FIXME: Some boards have 50Mhz and others 55MHz. How to distinguish? */
560 uint64_t vco
= m
* 50000000 + m
/ 2;
561 pd
->pd_CPUFreq
= vco
/ fwdva
;
562 pd
->pd_PLBFreq
= vco
/ fwdva
/ plbed
;
563 pd
->pd_OPBFreq
= pd
->pd_PLBFreq
/ opbd
;
564 pd
->pd_EPBFreq
= pd
->pd_OPBFreq
/ perd
;
565 pd
->pd_PCIFreq
= pd
->pd_PLBFreq
/ ahbd
;
567 /* Set decrementer interrupt to fire at a frequency of 50 Hz.*/
569 wrspr(TCR
, reg
& ~(TCR_DIE
| TCR_ARE
));
570 wrspr(CCR1
, rdspr(CCR1
) & ~(0x80000000 >> 24));
571 wrspr(DECAR
, pd
->pd_CPUFreq
/ 50);
572 /* Enable decrementer timer interrupt and automatic reload of decrementer value. */
573 wrspr(TCR
, reg
| TCR_DIE
| TCR_ARE
);
576 static int Kernel_Init(LIBBASETYPEPTR LIBBASE
)
579 struct PlatformData
*pd
;
581 uintptr_t krn_lowest
= krnGetTagData(KRN_KernelLowest
, 0, BootMsg
);
582 uintptr_t krn_highest
= krnGetTagData(KRN_KernelHighest
, 0, BootMsg
);
584 D(bug("[KRN] Entered Kernel_Init()\n"));
585 /* Get the PLB and CPU speed */
587 pd
= AllocMem(sizeof(struct PlatformData
), MEMF_PUBLIC
|MEMF_CLEAR
);
591 LIBBASE
->kb_PlatformData
= pd
;
593 /* Stash the PVR value */
594 pd
->pd_PVR
= rdspr(PVR
);
595 D(bug("[KRN] PVR: 0x%08x\n", pd
->pd_PVR
));
597 if (krnIsPPC440(pd
->pd_PVR
)) {
598 SetupClocking440(pd
);
599 } else if (krnIsPPC460(pd
->pd_PVR
)) {
600 SetupClocking460(pd
);
602 bug("kernel.resource: Unknown PVR model 0x%08x\n", pd
->pd_PVR
);
606 D(bug("[KRN] CPU Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_CPUFreq
/ 1000000));
607 D(bug("[KRN] PLB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_PLBFreq
/ 1000000));
608 D(bug("[KRN] OPB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_OPBFreq
/ 1000000));
609 D(bug("[KRN] EPB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_EPBFreq
/ 1000000));
610 D(bug("[KRN] PCI Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_PCIFreq
/ 1000000));
612 /* 4K granularity for data sections */
613 krn_lowest
&= 0xfffff000;
614 /* 64K granularity for code sections */
615 krn_highest
= (krn_highest
+ 0xffff) & 0xffff0000;
617 D(bug("[KRN] Allowing userspace to flush caches\n"));
618 wrspr(MMUCR
, rdspr(MMUCR
) & ~0x000c0000);
620 for (i
=0; i
< 16; i
++)
621 NEWLIST(&LIBBASE
->kb_Exceptions
[i
]);
623 for (i
=0; i
< 64; i
++)
624 NEWLIST(&LIBBASE
->kb_Interrupts
[i
]);
626 LIBBASE
->kb_ContextSize
= sizeof(context_t
);
628 D(bug("[KRN] Setting DebugInfo to %p\n", modlist
));
629 LIBBASE
->kb_PlatformData
->pd_DebugInfo
= (APTR
)modlist
;
631 D(bug("[KRN] Preparing kernel private memory\n"));
634 * Add MemHeader about kernel memory to public MemList to avoid invalid
635 * pointer debug messages for pointer that reference correctly into these
638 krnCreateMemHeader("Kernel Memory", -10, (APTR
)memlo
, krn_lowest
- ((uintptr_t)memlo
& 0x00ffffff), MEMF_FAST
| MEMF_KICK
| MEMF_LOCAL
| MEMF_24BITDMA
);
639 krnCreateROMHeader("Kernel Reserved",
640 (APTR
)0xff000000, (APTR
)(memlo
- 1));
641 krnCreateROMHeader("Kernel Code + Data Sections",
642 (APTR
) ((uintptr_t) 0xff000000 + krn_lowest
- 1),
643 (APTR
) ((uintptr_t) 0xff000000 + krn_highest
- 1));
646 * kernel.resource is ready to run, leave supervisor mode. External interrupts
647 * will be enabled during late exec init.
650 wrmsr(rdmsr() | MSR_PR
);
651 D(bug("[KRN] Entered user mode \n"));
656 ADD2INITLIB(Kernel_Init
, 0)