added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / x86_64-pc / kernel / kernel_init.c
blob33cb51a975be9b1804bc7a9cfd9ff9da5481058f
1 #define DEBUG 1
2 #include <aros/debug.h>
3 #include <asm/cpu.h>
4 #include <asm/io.h>
5 #include <asm/segments.h>
6 #include <inttypes.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>
15 #include <stdio.h>
17 #include "kernel_intern.h"
18 #include "../bootstrap/multiboot.h"
19 #include LC_LIBDEFS_FILE
21 /* Pre-exec init */
23 asm(".section .aros.init,\"ax\"\n\t"
24 ".globl start64\n\t"
25 ".type start64,@function\n"
26 "start64: movq tmp_stack_end(%rip),%rsp\n\t"
27 "movq %rdi,%rbx\n\t"
28 "call __clear_bss\n\t"
29 "movq %rbx,%rdi\n\t"
30 "movq stack_end(%rip), %rsp\n\t"
31 "movq target_address(%rip), %rsi\n\t"
32 "jmp *%rsi\n\t"
33 ".string \"Native/CORE v3 (" __DATE__ ")\""
34 "\n\t.text\n\t"
37 void __clear_bss(struct TagItem *msg)
39 struct KernelBSS *bss;
40 bss = krnGetTagData(KRN_KernelBss, 0, msg);
42 if (bss)
44 while (bss->addr)
46 bzero(bss->addr, bss->len);
47 bss++;
52 /* Post exec init */
54 static int Kernel_Init(LIBBASETYPEPTR LIBBASE)
56 int i;
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]);
65 switch(i)
67 case 0x20 ... 0x2f:
68 LIBBASE->kb_Intr[i].lh_Type = KBL_XTPIC;
69 break;
70 case 0xfe:
71 LIBBASE->kb_Intr[i].lh_Type = KBL_APIC;
72 break;
73 default:
74 LIBBASE->kb_Intr[i].lh_Type = KBL_INTERNAL;
75 break;
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));
86 /*
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);
135 if (tag)
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);
144 if (tag)
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);
153 if (tag)
155 if (tag->ti_Data != (IPTR)&vbectrl) {
156 bcopy(tag->ti_Data, &vbectrl, sizeof(vbectrl));
157 tag->ti_Data = (IPTR)&vbectrl;
161 BootMsg = msg;
163 /* Set TSS, GDT, LDT and MMU up */
164 core_SetupGDT();
165 core_SetupIDT();
166 core_SetupMMU();
168 core_ProtKernelArea(addr, len, 1, 0, 1);
170 /* Lock page 0! */
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)));
209 static struct {
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)));
222 const struct
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;
231 void core_SetupGDT()
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;
241 GDT.super_cs.g=1;
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;
247 GDT.super_ds.g=1;
248 GDT.super_ds.d=1;
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;
258 GDT.user_cs.g=1;
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;
267 GDT.user_cs32.g=1;
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;
274 GDT.user_ds.g=1;
275 GDT.user_ds.d=1;
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;
296 GDT.gs.g=1;
297 GDT.gs.d=1;
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;
316 while(1)
318 switch((*tagListPtr)->ti_Tag)
320 case TAG_MORE:
321 if (!((*tagListPtr) = (struct TagItem *)(*tagListPtr)->ti_Data))
322 return NULL;
323 continue;
324 case TAG_IGNORE:
325 break;
327 case TAG_END:
328 (*tagListPtr) = 0;
329 return NULL;
331 case TAG_SKIP:
332 (*tagListPtr) += (*tagListPtr)->ti_Data + 1;
333 continue;
335 default:
336 return (struct TagItem *)(*tagListPtr)++;
340 (*tagListPtr)++;
344 struct TagItem *krnFindTagItem(Tag tagValue, const struct TagItem *tagList)
346 struct TagItem *tag;
347 const struct TagItem *tagptr = tagList;
349 while((tag = krnNextTagItem(&tagptr)))
351 if (tag->ti_Tag == tagValue)
352 return tag;
355 return 0;
358 IPTR krnGetTagData(Tag tagValue, intptr_t defaultVal, const struct TagItem *tagList)
360 struct TagItem *ti = 0;
362 if (tagList && (ti = krnFindTagItem(tagValue, tagList)))
363 return ti->ti_Data;
365 return defaultVal;
368 AROS_LH0I(struct TagItem *, KrnGetBootInfo,
369 struct KernelBase *, KernelBase, 10, Kernel)
371 AROS_LIBFUNC_INIT
373 return BootMsg;
375 AROS_LIBFUNC_EXIT