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);
242 wrspr(CCR1
, rdspr(CCR1
) | (0x80000000 >> 24));
244 /* First message after FPU is enabled, otherwise illegal instruction */
245 D(bug("[KRN] Sam440 Kernel built on %s\n", __DATE__
));
251 wrspr(SPRG4
, 0); /* Clear KernelBase */
252 wrspr(SPRG5
, 0); /* Clear SysBase */
254 D(bug("[KRN] Kernel resource pre-exec init\n"));
255 D(bug("[KRN] MSR=%08x CRR0=%08x CRR1=%08x\n", rdmsr(), rdspr(CCR0
), rdspr(CCR1
)));
256 D(bug("[KRN] USB config %08x\n", rddcr(SDR0_USB0
)));
258 D(bug("[KRN] msg @ %p\n", msg
));
259 D(bug("[KRN] Copying msg data\n"));
260 while(msg
->ti_Tag
!= TAG_DONE
)
264 if (tmp
->ti_Tag
== KRN_CmdLine
)
266 strcpy(CmdLine
, (char*) msg
->ti_Data
);
267 tmp
->ti_Data
= (STACKIPTR
) CmdLine
;
268 D(bug("[KRN] CmdLine: %s\n", tmp
->ti_Data
));
270 else if (tmp
->ti_Tag
== KRN_BootLoader
)
272 tmp
->ti_Data
= (STACKIPTR
) memlo
;
273 strcpy((char*)tmp
->ti_Data
, (const char*) msg
->ti_Data
);
274 memlo
+= (strlen((char *)memlo
) + 4) & ~3;
275 D(bug("[KRN] BootLoader: %s\n", tmp
->ti_Data
));
277 else if (tmp
->ti_Tag
== KRN_DebugInfo
)
280 struct MinList
*mlist
= (struct MinList
*)tmp
->ti_Data
;
283 D(bug("[KRN] DebugInfo at %08x\n", mlist
));
285 modlist
= (struct MinList
*)memlo
;
286 memlo
+= sizeof(*modlist
);
289 mod
= (module_t
*)memlo
;
291 ListLength(mlist
, modlength
);
292 memlo
= (uintptr_t)&mod
[modlength
];
294 D(bug("[KRN] Bootstrap loaded debug info for %d modules\n", modlength
));
295 /* Copy the module entries */
296 for (i
=0; i
< modlength
; i
++)
298 module_t
*m
= (module_t
*)REMHEAD(mlist
);
300 ULONG str_l
= ~0, str_h
= 0;
302 D(bug("[KRN] Module %s\n", m
->m_name
));
304 /* Discover size of the string table */
305 ForeachNode(&m
->m_symbols
, sym
) {
306 ULONG end
= (ULONG
)sym
->s_name
+ strlen(sym
->s_name
) + 1 + 1;
307 if ((ULONG
)sym
->s_name
< str_l
)
308 str_l
= (ULONG
)sym
->s_name
;
316 mod
[i
].m_lowest
= m
->m_lowest
;
317 mod
[i
].m_highest
= m
->m_highest
;
318 mod
[i
].m_str
= (char *)memlo
;
319 memcpy(mod
[i
].m_str
, (char *)str_l
, str_h
- str_l
);
320 memlo
+= ((str_h
- str_l
) + 3) & ~3;
321 mod
[i
].m_name
= (char *)memlo
;
322 memlo
+= (strlen(m
->m_name
) + 4) & ~3;
323 strcpy(mod
[i
].m_name
, m
->m_name
);
325 NEWLIST(&mod
[i
].m_symbols
);
327 ForeachNode(&m
->m_symbols
, sym
)
329 symbol_t
*newsym
= (symbol_t
*)memlo
;
330 memlo
+= sizeof(symbol_t
);
332 newsym
->s_name
= (IPTR
)sym
->s_name
- str_l
+ mod
[i
].m_str
;
333 newsym
->s_lowest
= sym
->s_lowest
;
334 newsym
->s_highest
= sym
->s_highest
;
336 ADDTAIL(&mod
[i
].m_symbols
, newsym
);
339 ADDTAIL(modlist
, &mod
[i
]);
342 D(bug("[KRN] Debug info uses %d KB of memory\n", ((intptr_t)memlo
- (intptr_t)modlist
) >> 10));
343 D(bug("[KRN] Debug info relocated from %p to %p\n", tmp
->ti_Data
, modlist
));
345 /* Ugh. Parthenope doesn't use the ELF_ModuleInfo format.
346 * Prevent debug.library from becoming confused.
355 memlo
= (memlo
+ 4095) & ~4095;
357 BootMsg
= tmp_struct
.bootup_tags
;
358 D(bug("[KRN] BootMsg @ %p\n", BootMsg
));
360 /* Do a slightly more sophisticated MMU map */
364 /* Initialize exec.library */
365 exec_main(BootMsg
, NULL
);
367 bug("[KRN] Uhm? Nothing to do?\n[KRN] STOPPED\n");
370 * Do never ever try to return. This code would attempt to go back to the physical address
371 * of asm trampoline, not the virtual one!
376 void SetupClocking440(struct PlatformData
*pd
)
379 wrdcr(CPR0_CFGADDR
, CPR0_PLLD0
);
380 uint32_t reg
= rddcr(CPR0_CFGDATA
);
382 uint32_t fbdv
= (reg
>> 24) & 0x1f;
385 uint32_t fwdva
= (reg
>> 16) & 0x1f;
388 uint32_t fwdvb
= (reg
>> 8) & 7;
391 uint32_t lfbdv
= reg
& 0x3f;
395 /* OPB clock divisor */
396 wrdcr(CPR0_CFGADDR
, CPR0_OPBD0
);
397 reg
= rddcr(CPR0_CFGDATA
);
398 uint32_t opbdv0
= (reg
>> 24) & 3;
402 /* Peripheral clock divisor */
403 wrdcr(CPR0_CFGADDR
, CPR0_PERD0
);
404 reg
= rddcr(CPR0_CFGDATA
);
405 uint32_t perdv0
= (reg
>> 24) & 7;
409 /* PCI clock divisor */
410 wrdcr(CPR0_CFGADDR
, CPR0_SPCID
);
411 reg
= rddcr(CPR0_CFGDATA
);
412 uint32_t spcid0
= (reg
>> 24) & 3;
416 /* Primary B divisor */
417 wrdcr(CPR0_CFGADDR
, CPR0_PRIMBD0
);
418 reg
= rddcr(CPR0_CFGDATA
);
419 uint32_t prbdv0
= (reg
>> 24) & 7;
423 /* All divisors there. Read PLL control register and calculate the m value (see 44ep.book) */
424 wrdcr(CPR0_CFGADDR
, CPR0_PLLC0
);
425 reg
= rddcr(CPR0_CFGDATA
);
427 switch ((reg
>> 24) & 3) /* Feedback selector */
429 case 0:/* PLL output (A or B) */
430 if ((reg
& 0x20000000)) /* PLLOUTB */
431 m
= lfbdv
* fbdv
* fwdvb
;
433 m
= lfbdv
* fbdv
* fwdva
;
438 m
= perdv0
* opbdv0
* fwdvb
;
441 uint32_t vco
= (m
* 66666666) + m
/2;
442 pd
->pd_CPUFreq
= vco
/ fwdva
;
443 pd
->pd_PLBFreq
= vco
/ fwdvb
/ perdv0
;
444 pd
->pd_OPBFreq
= pd
->pd_PLBFreq
/ opbdv0
;
445 pd
->pd_EPBFreq
= pd
->pd_PLBFreq
/ perdv0
;
446 pd
->pd_PCIFreq
= pd
->pd_PLBFreq
/ spcid0
;
449 * Slow down the decrement interrupt a bit. Rough guess is that UBoot has left us with
450 * 1kHz DEC counter. Enable decrementer timer and automatic reload of decrementer value.
452 wrspr(DECAR
, pd
->pd_OPBFreq
/ 50);
453 wrspr(TCR
, rdspr(TCR
) | TCR_DIE
| TCR_ARE
);
457 const uint8_t fbdv_map
[256] = {
458 1, 123, 117, 251, 245, 69, 111, 125,
459 119, 95, 105, 197, 239, 163, 63, 253,
460 247, 187, 57, 223, 233, 207, 157, 71,
461 113, 15, 89, 37, 191, 19, 99, 127,
462 121, 109, 93, 61, 185, 155, 13, 97,
463 107, 11, 9, 81, 31, 49, 83, 199,
464 241, 33, 181, 143, 217, 173, 51, 165,
465 65, 85, 151, 147, 227, 41, 201, 255,
466 249, 243, 195, 237, 221, 231, 35, 189,
467 59, 183, 79, 29, 141, 215, 145, 225,
468 235, 219, 27, 139, 137, 135, 175, 209,
469 159, 53, 45, 177, 211, 23, 167, 73,
470 115, 67, 103, 161, 55, 205, 87, 17,
471 91, 153, 7, 47, 179, 171, 149, 39,
472 193, 229, 77, 213, 25, 133, 43, 21,
473 101, 203, 5, 169, 75, 131, 3, 129,
474 1, 250, 244, 124, 118, 196, 238, 252,
475 246, 222, 232, 70, 112, 36, 190, 126,
476 120, 60, 184, 96, 106, 80, 30, 198,
477 240, 142, 216, 164, 64, 146, 226, 254,
478 248, 236, 220, 188, 58, 28, 140, 224,
479 234, 138, 136, 208, 158, 176, 210, 72,
480 114, 160, 54, 16, 90, 46, 178, 38,
481 192, 212, 24, 20, 100, 168, 74, 128,
482 122, 116, 68, 110, 94, 104, 162, 62,
483 186, 56, 206, 156, 14, 88, 18, 98,
484 108, 92, 154, 12, 10, 8, 48, 82,
485 32, 180, 172, 50, 84, 150, 40, 200,
486 242, 194, 230, 34, 182, 78, 214, 144,
487 218, 26, 134, 174, 52, 44, 22, 166,
488 66, 102, 204, 86, 152, 6, 170, 148,
489 228, 76, 132, 42, 202, 4, 130, 2,
492 static const uint8_t fwdv_map
[16] = {
493 1, 2, 14, 9, 4, 11, 16, 13,
494 12, 5, 6, 15, 10, 7, 8, 3,
497 void SetupClocking460(struct PlatformData
*pd
)
502 wrdcr(CPR0_CFGADDR
, CPR0_PLLD
);
503 reg
= rddcr(CPR0_CFGDATA
);
505 uint32_t fbdv
= fbdv_map
[(reg
>> 24) & 0xff];
506 uint32_t fwdva
= fwdv_map
[((reg
>> 16) & 0xf)];
507 uint32_t fwdvb
= fwdv_map
[(reg
>> 8) & 0xf];
508 (void)fwdvb
; // Unused
510 /* Early PLL divisor */
511 wrdcr(CPR0_CFGADDR
, CPR0_PLBED
);
512 reg
= rddcr(CPR0_CFGDATA
);
513 uint32_t plbed
= (reg
>> 24) & 0x7;
517 /* OPB clock divisor */
518 wrdcr(CPR0_CFGADDR
, CPR0_OPBD
);
519 reg
= rddcr(CPR0_CFGDATA
);
520 uint32_t opbd
= (reg
>> 24) & 3;
524 /* Peripheral clock divisor */
525 wrdcr(CPR0_CFGADDR
, CPR0_PERD
);
526 reg
= rddcr(CPR0_CFGDATA
);
527 uint32_t perd
= (reg
>> 24) & 3;
531 /* AHB clock divisor */
532 wrdcr(CPR0_CFGADDR
, CPR0_AHBD
);
533 reg
= rddcr(CPR0_CFGDATA
);
534 uint32_t ahbd
= (reg
>> 24) & 1;
538 /* All divisors there.
539 * Read PLL control register and calculate the m value
541 wrdcr(CPR0_CFGADDR
, CPR0_PLLC
);
542 reg
= rddcr(CPR0_CFGDATA
);
545 if (((reg
>> 24) & 3) == 0) {
546 /* PLL internal feedback */
549 /* PLL Per-Clock feedback */
550 m
= fwdva
* plbed
* opbd
* ahbd
;
553 D(bug("fbdv %d, fwdva = %d, fwdvb = %d\n", fbdv
, fwdva
, fwdvb
));
554 D(bug("plbed %d, opbd = %d, perd = %d, ahbd = %d\n",
555 plbed
, opbd
, perd
, ahbd
));
557 uint64_t vco
= m
* 55000000;
558 pd
->pd_CPUFreq
= vco
/ fwdva
;
559 pd
->pd_PLBFreq
= vco
/ fwdva
/ plbed
;
560 pd
->pd_OPBFreq
= pd
->pd_PLBFreq
/ opbd
;
561 pd
->pd_EPBFreq
= pd
->pd_OPBFreq
/ perd
;
562 pd
->pd_PCIFreq
= pd
->pd_PLBFreq
/ ahbd
;
565 * Slow down the decrement interrupt a bit. Rough guess is that UBoot has left us with
566 * 1kHz DEC counter. Enable decrementer timer and automatic reload of decrementer value.
568 wrspr(DECAR
, pd
->pd_OPBFreq
/ 5);
569 wrspr(TCR
, rdspr(TCR
) | TCR_DIE
| TCR_ARE
);
570 wrspr(CCR1
, rdspr(CCR1
) & ~(0x80000000 >> 24));
573 static int Kernel_Init(LIBBASETYPEPTR LIBBASE
)
576 struct PlatformData
*pd
;
578 uintptr_t krn_lowest
= krnGetTagData(KRN_KernelLowest
, 0, BootMsg
);
579 uintptr_t krn_highest
= krnGetTagData(KRN_KernelHighest
, 0, BootMsg
);
581 D(bug("[KRN] Entered Kernel_Init()\n"));
582 /* Get the PLB and CPU speed */
584 pd
= AllocMem(sizeof(struct PlatformData
), MEMF_PUBLIC
|MEMF_CLEAR
);
588 LIBBASE
->kb_PlatformData
= pd
;
590 /* Stash the PVR value */
591 pd
->pd_PVR
= rdspr(PVR
);
592 D(bug("[KRN] PVR: 0x%08x\n", pd
->pd_PVR
));
594 if (krnIsPPC440(pd
->pd_PVR
)) {
595 SetupClocking440(pd
);
596 } else if (krnIsPPC460(pd
->pd_PVR
)) {
597 SetupClocking460(pd
);
599 bug("kernel.resource: Unknown PVR model 0x%08x\n", pd
->pd_PVR
);
603 D(bug("[KRN] CPU Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_CPUFreq
/ 1000000));
604 D(bug("[KRN] PLB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_PLBFreq
/ 1000000));
605 D(bug("[KRN] OPB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_OPBFreq
/ 1000000));
606 D(bug("[KRN] EPB Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_EPBFreq
/ 1000000));
607 D(bug("[KRN] PCI Speed: %dMz\n", LIBBASE
->kb_PlatformData
->pd_PCIFreq
/ 1000000));
609 /* 4K granularity for data sections */
610 krn_lowest
&= 0xfffff000;
611 /* 64K granularity for code sections */
612 krn_highest
= (krn_highest
+ 0xffff) & 0xffff0000;
614 D(bug("[KRN] Allowing userspace to flush caches\n"));
615 wrspr(MMUCR
, rdspr(MMUCR
) & ~0x000c0000);
617 for (i
=0; i
< 16; i
++)
618 NEWLIST(&LIBBASE
->kb_Exceptions
[i
]);
620 for (i
=0; i
< 64; i
++)
621 NEWLIST(&LIBBASE
->kb_Interrupts
[i
]);
623 LIBBASE
->kb_ContextSize
= sizeof(context_t
);
625 D(bug("[KRN] Setting DebugInfo to %p\n", modlist
));
626 LIBBASE
->kb_PlatformData
->pd_DebugInfo
= (APTR
)modlist
;
628 D(bug("[KRN] Preparing kernel private memory\n"));
631 * Add MemHeader about kernel memory to public MemList to avoid invalid
632 * pointer debug messages for pointer that reference correctly into these
635 krnCreateMemHeader("Kernel Memory", -10, (APTR
)memlo
, krn_lowest
- ((uintptr_t)memlo
& 0x00ffffff), MEMF_FAST
| MEMF_KICK
| MEMF_LOCAL
| MEMF_24BITDMA
);
636 krnCreateROMHeader("Kernel Reserved",
637 (APTR
)0xff000000, (APTR
)(memlo
- 1));
638 krnCreateROMHeader("Kernel Code + Data Sections",
639 (APTR
) ((uintptr_t) 0xff000000 + krn_lowest
- 1),
640 (APTR
) ((uintptr_t) 0xff000000 + krn_highest
- 1));
643 * kernel.resource is ready to run, leave supervisor mode. External interrupts
644 * will be enabled during late exec init.
647 wrmsr(rdmsr() | MSR_PR
);
648 D(bug("[KRN] Entered user mode \n"));
653 ADD2INITLIB(Kernel_Init
, 0)