2 #include <aros/debug.h>
5 #include <asm/segments.h>
7 #include <aros/symbolsets.h>
8 #include <exec/lists.h>
10 #include <utility/tagitem.h>
12 #include <proto/exec.h>
13 #include <proto/kernel.h>
17 #include "kernel_intern.h"
18 #include "../bootstrap/multiboot.h"
19 #include LC_LIBDEFS_FILE
23 asm(".section .aros.init,\"ax\"\n\t"
25 ".type start64,@function\n"
26 "start64: movq tmp_stack_end(%rip),%rsp\n\t"
28 "call __clear_bss\n\t"
30 "movq stack_end(%rip), %rsp\n\t"
31 "movq target_address(%rip), %rsi\n\t"
33 ".string \"Native/CORE v3 (" __DATE__
")\""
37 void __clear_bss(struct TagItem
*msg
)
39 struct KernelBSS
*bss
;
40 bss
= krnGetTagData(KRN_KernelBss
, 0, msg
);
46 bzero(bss
->addr
, bss
->len
);
54 static int Kernel_Init(LIBBASETYPEPTR LIBBASE
)
57 TLS_SET(KernelBase
, LIBBASE
);
58 struct ExecBase
*SysBase
= TLS_GET(SysBase
);
60 LIBBASE
->kb_XTPIC_Mask
= 0xfffb;
62 for (i
=0; i
< 256; i
++)
64 NEWLIST(&LIBBASE
->kb_Intr
[i
]);
68 LIBBASE
->kb_Intr
[i
].lh_Type
= KBL_XTPIC
;
71 LIBBASE
->kb_Intr
[i
].lh_Type
= KBL_APIC
;
74 LIBBASE
->kb_Intr
[i
].lh_Type
= KBL_INTERNAL
;
80 uint32_t *localAPIC
= (uint32_t*)0xfee00320;
82 D(bug("[Kernel] Post-exec init\n"));
84 LIBBASE
->kb_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
, 8192, 4096);
85 D(bug("[Kernel] MemPool=%012p\n", LIBBASE
->kb_MemPool
));
87 asm volatile ("movl %0,(%1)"::"r"(0),"r"(0xfee000b0));
89 D(bug("[Kernel] APIC SVR=%08x\n", *(uint32_t*)0xfee000f0));
90 D(bug("[Kernel] APIC ESR=%08x\n", *(uint32_t*)0xfee00280));
91 D(bug("[Kernel] APIC TPR=%08x\n", *(uint32_t*)0xfee00080));
92 D(bug("[Kernel] APIC ICR=%08x%08x\n", *(uint32_t*)0xfee00314, *(uint32_t*)0xfee00310));
93 D(bug("[Kernel] APIC Timer divide=%08x\n", *(uint32_t*)0xfee003e0));
94 D(bug("[Kernel] APIC Timer config=%08x\n", *(uint32_t*)0xfee00320));
96 asm volatile ("movl %0,(%1)"::"r"(0x000000fe),"r"(0xfee00320));
97 //*(volatile uint32_t *)localAPIC = 0x000000fe;
98 D(bug("[Kernel] APIC Timer config=%08x\n", *(uint32_t*)0xfee00320));
100 D(bug("[Kernel] APIC Initial count=%08x\n", *(uint32_t*)0xfee00380));
101 D(bug("[Kernel] APIC Current count=%08x\n", *(uint32_t*)0xfee00390));
102 *(uint32_t*)0xfee00380 = 0x11111111;
103 asm volatile ("movl %0,(%1)"::"r"(0x000200fe),"r"(0xfee00320));
104 D(bug("[Kernel] APIC Timer config=%08x\n", *(uint32_t*)0xfee00320));
106 for (i=0; i < 0x10000000; i++) asm volatile("nop;");
108 D(bug("[Kernel] APIC Initial count=%08x\n", *(uint32_t*)0xfee00380));
109 D(bug("[Kernel] APIC Current count=%08x\n", *(uint32_t*)0xfee00390));
110 for (i=0; i < 0x1000000; i++) asm volatile("nop;");
111 D(bug("[Kernel] APIC Initial count=%08x\n", *(uint32_t*)0xfee00380));
112 D(bug("[Kernel] APIC Current count=%08x\n", *(uint32_t*)0xfee00390));
114 for (i=0; i < 0x1000000; i++) asm volatile("nop;"); */
117 ADD2INITLIB(Kernel_Init
, 0)
119 static struct TagItem
*BootMsg
;
120 static struct vbe_controller vbectrl
;
121 static struct vbe_mode vbemd
;
122 static char cmdLine
[200];
125 int kernel_cstart(struct TagItem
*msg
, void *entry
)
127 rkprintf("[Kernel] Booting into kernel.resource...\n");
128 struct TagItem
*tag
= krnFindTagItem(KRN_CmdLine
, msg
);
129 intptr_t addr
= krnGetTagData(KRN_KernelBase
, 0, msg
);
130 intptr_t len
= krnGetTagData(KRN_KernelHighest
, 0, msg
) - addr
;
132 /* Enable fxsave/fxrstor */
133 wrcr(cr4
, rdcr(cr4
) | _CR4_OSFXSR
| _CR4_OSXMMEXCPT
);
137 if (tag
->ti_Data
!= (IPTR
)cmdLine
) {
138 strncpy(cmdLine
, tag
->ti_Data
, 200);
139 tag
->ti_Data
= (IPTR
)cmdLine
;
143 tag
= krnFindTagItem(KRN_VBEModeInfo
, msg
);
146 if (tag
->ti_Data
!= (IPTR
)&vbemd
) {
147 bcopy(tag
->ti_Data
, &vbemd
, sizeof(vbemd
));
148 tag
->ti_Data
= (IPTR
)&vbemd
;
152 tag
= krnFindTagItem(KRN_VBEControllerInfo
, msg
);
155 if (tag
->ti_Data
!= (IPTR
)&vbectrl
) {
156 bcopy(tag
->ti_Data
, &vbectrl
, sizeof(vbectrl
));
157 tag
->ti_Data
= (IPTR
)&vbectrl
;
163 /* Set TSS, GDT, LDT and MMU up */
168 core_ProtKernelArea(addr
, len
, 1, 0, 1);
171 core_ProtKernelArea(0, 1, 0, 0, 0);
173 (rkprintf("[Kernel] APIC_BASE_MSR=%016p\n", rdmsrq(27)));
175 /* Setu the 8259 up */
176 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0x20)); /* Initialization sequence for 8259A-1 */
177 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0xa0)); /* Initialization sequence for 8259A-2 */
178 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x20),"i"(0x21)); /* IRQs at 0x20 - 0x27 */
179 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x28),"i"(0xa1)); /* IRQs at 0x28 - 0x2f */
180 asm("outb %b0,%b1\n\tcall delay": :"a"((char)0x04),"i"(0x21)); /* 8259A-1 is master */
181 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x02),"i"(0xa1)); /* 8259A-2 is slave */
182 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0x21)); /* 8086 mode for both */
183 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0xa1));
184 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0x21)); /* Enable cascade int */
185 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0xa1)); /* Mask all interrupts */
187 rkprintf("[Kernel] Interrupts redirected. We will go back in a minute ;)\n");
188 rkprintf("[Kernel] Booting exec.library\n\n");
190 return exec_main(msg
, entry
);
194 /* Small delay routine used by exec_cinit initializer */
195 asm("\ndelay:\t.short 0x00eb\n\tretq");
197 static uint64_t __attribute__((used
)) tmp_stack
[128]={01,};
198 static const uint64_t *tmp_stack_end
__attribute__((used
, section(".text"))) = &tmp_stack
[120];
199 static uint64_t stack
[STACK_SIZE
] __attribute__((used
));
200 static uint64_t stack_panic
[STACK_SIZE
] __attribute__((used
));
201 static uint64_t stack_super
[STACK_SIZE
] __attribute__((used
));
202 static uint64_t stack_ring1
[STACK_SIZE
] __attribute__((used
));
204 static const uint64_t *stack_end
__attribute__((used
, section(".text"))) = &stack
[STACK_SIZE
-16];
205 static const void *target_address
__attribute__((section(".text"),used
)) = (void*)kernel_cstart
;
207 static struct int_gate_64bit IGATES
[256] __attribute__((used
,aligned(256)));
208 static struct tss_64bit TSS
__attribute__((used
,aligned(128)));
210 struct segment_desc seg0
; /* seg 0x00 */
211 struct segment_desc super_cs
; /* seg 0x08 */
212 struct segment_desc super_ds
; /* seg 0x10 */
213 struct segment_desc user_cs32
; /* seg 0x18 */
214 struct segment_desc user_ds
; /* seg 0x20 */
215 struct segment_desc user_cs
; /* seg 0x28 */
216 struct segment_desc tss_low
; /* seg 0x30 */
217 struct segment_ext tss_high
;
218 struct segment_desc gs
; /* seg 0x40 */
219 struct segment_desc ldt
; /* seg 0x48 */
220 } GDT
__attribute__((used
,aligned(128)));
224 uint16_t size
__attribute__((packed
));
225 uint64_t base
__attribute__((packed
));
227 GDT_sel
= {sizeof(GDT
)-1, (uint64_t)&GDT
};
229 static tls_t system_tls
;
233 /* Supervisor segments */
234 GDT
.super_cs
.type
=0x1a; /* code segment */
235 GDT
.super_cs
.dpl
=0; /* supervisor level */
236 GDT
.super_cs
.p
=1; /* present */
237 GDT
.super_cs
.l
=1; /* long (64-bit) one */
238 GDT
.super_cs
.d
=0; /* must be zero */
239 GDT
.super_cs
.limit_low
=0xffff;
240 GDT
.super_cs
.limit_high
=0xf;
243 GDT
.super_ds
.type
=0x12; /* data segment */
244 GDT
.super_ds
.p
=1; /* present */
245 GDT
.super_ds
.limit_low
=0xffff;
246 GDT
.super_ds
.limit_high
=0xf;
250 /* User mode segments */
251 GDT
.user_cs
.type
=0x1a; /* code segment */
252 GDT
.user_cs
.dpl
=3; /* User level */
253 GDT
.user_cs
.p
=1; /* present */
254 GDT
.user_cs
.l
=1; /* long mode */
255 GDT
.user_cs
.d
=0; /* must be zero */
256 GDT
.user_cs
.limit_low
=0xffff;
257 GDT
.user_cs
.limit_high
=0xf;
260 GDT
.user_cs32
.type
=0x1a; /* code segment for legacy 32-bit code. NOT USED YET! */
261 GDT
.user_cs32
.dpl
=3; /* user elvel */
262 GDT
.user_cs32
.p
=1; /* present */
263 GDT
.user_cs32
.l
=0; /* 32-bit mode */
264 GDT
.user_cs32
.d
=1; /* 32-bit code */
265 GDT
.user_cs32
.limit_low
=0xffff;
266 GDT
.user_cs32
.limit_high
=0xf;
269 GDT
.user_ds
.type
=0x12; /* data segment */
270 GDT
.user_ds
.dpl
=3; /* user elvel */
271 GDT
.user_ds
.p
=1; /* present */
272 GDT
.user_ds
.limit_low
=0xffff;
273 GDT
.user_ds
.limit_high
=0xf;
277 /* Task State Segment */
278 GDT
.tss_low
.type
=0x09; /* 64-bit TSS */
279 GDT
.tss_low
.limit_low
=sizeof(TSS
)-1;
280 GDT
.tss_low
.base_low
=((unsigned int)&TSS
) & 0xffff;
281 GDT
.tss_low
.base_mid
=(((unsigned int)&TSS
) >> 16) & 0xff;
282 GDT
.tss_low
.dpl
=3; /* User mode task */
283 GDT
.tss_low
.p
=1; /* present */
284 GDT
.tss_low
.limit_high
=((sizeof(TSS
)-1) >> 16) & 0x0f;
285 GDT
.tss_low
.base_high
=(((unsigned int)&TSS
) >> 24) & 0xff;
286 GDT
.tss_high
.base_ext
= 0; /* is within 4GB :-D */
288 intptr_t tls_ptr
= (intptr_t)&system_tls
;
290 GDT
.gs
.type
=0x12; /* data segment */
291 GDT
.gs
.dpl
=3; /* user elvel */
292 GDT
.gs
.p
=1; /* present */
293 GDT
.gs
.base_low
= tls_ptr
& 0xffff;
294 GDT
.gs
.base_mid
= (tls_ptr
>> 16) & 0xff;
295 GDT
.gs
.base_high
= (tls_ptr
>> 24) & 0xff;
299 system_tls
.SysBase
= (struct ExecBase
*)0x12345678;
301 TSS
.ist1
= (uint64_t)&stack_panic
[STACK_SIZE
-2];
302 TSS
.rsp0
= (uint64_t)&stack_super
[STACK_SIZE
-2];
303 TSS
.rsp1
= (uint64_t)&stack_ring1
[STACK_SIZE
-2];
305 rkprintf("[Kernel] Reloading the GDT and the Task Register\n");
306 asm volatile ("lgdt %0"::"m"(GDT_sel
));
307 asm volatile ("ltr %w0"::"r"(TASK_SEG
));
308 asm volatile ("mov %0,%%gs"::"a"(SEG_GS
));
312 struct TagItem
*krnNextTagItem(const struct TagItem
**tagListPtr
)
314 if (!(*tagListPtr
)) return 0;
318 switch((*tagListPtr
)->ti_Tag
)
321 if (!((*tagListPtr
) = (struct TagItem
*)(*tagListPtr
)->ti_Data
))
332 (*tagListPtr
) += (*tagListPtr
)->ti_Data
+ 1;
336 return (struct TagItem
*)(*tagListPtr
)++;
344 struct TagItem
*krnFindTagItem(Tag tagValue
, const struct TagItem
*tagList
)
347 const struct TagItem
*tagptr
= tagList
;
349 while((tag
= krnNextTagItem(&tagptr
)))
351 if (tag
->ti_Tag
== tagValue
)
358 IPTR
krnGetTagData(Tag tagValue
, intptr_t defaultVal
, const struct TagItem
*tagList
)
360 struct TagItem
*ti
= 0;
362 if (tagList
&& (ti
= krnFindTagItem(tagValue
, tagList
)))
368 AROS_LH0I(struct TagItem
*, KrnGetBootInfo
,
369 struct KernelBase
*, KernelBase
, 10, Kernel
)