Added: new boot.S, serial out for Xeon Phi
[barrelfish] / kernel / arch / k1om / init.c
1 /**
2  * \file
3  * \brief x86-64 architecture initialization.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <kernel.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <paging_kernel_arch.h>
19 #include <elf/elf.h>
20 #include <init.h>
21 #include <irq.h>
22 #include <x86.h>
23 #include <serial.h>
24 #include <kernel_multiboot.h>
25 #include <syscall.h>
26 #include <getopt/getopt.h>
27 #include <exec.h>
28 #include <kputchar.h>
29 #include <arch/x86/conio.h>
30 #include <arch/x86/pic.h>
31 #include <arch/x86/apic.h>
32 #include <arch/x86/mcheck.h>
33 #include <arch/x86/perfmon.h>
34 #include <arch/x86/rtc.h>
35 #include <target/x86/barrelfish_kpi/coredata_target.h>
36 #include <arch/x86/timing.h>
37 #include <arch/x86/startup_x86.h>
38 #include <arch/x86/ipi_notify.h>
39 #include <barrelfish_kpi/cpu_arch.h>
40 #include <target/k1om/barrelfish_kpi/cpu_target.h>
41 #include <linux_host.h>
42
43 #include <dev/xapic_dev.h> // XXX
44 #include <dev/ia32_dev.h>
45 #include <dev/amd64_dev.h>
46
47 /**
48  * Used to store the address of global struct passed during boot across kernel
49  * relocations.
50  */
51 static uint64_t addr_global;
52
53 /**
54  * \brief Kernel stack.
55  *
56  * This is the one and only kernel stack for a kernel instance.
57  */
58 uintptr_t x86_64_kernel_stack[X86_64_KERNEL_STACK_SIZE / sizeof(uintptr_t)];
59
60 /**
61  * \brief Global Task State Segment (TSS).
62  *
63  * This is the global, static and only Task State Segment (TSS). It is used
64  * for interrupt and exception handling (stack setup) while in user-space.
65  */
66 static struct task_state_segment tss __attribute__ ((aligned (4)));
67
68 /**
69  * \brief Global Descriptor Table (GDT) for processor this kernel is running on.
70  *
71  * This descriptor table is completely static, as segments are basically
72  * turned off in 64-bit mode. They map flat-mode code and stack segments for
73  * both kernel- and user-space and the only Task State Segment (TSS).
74  */
75 union segment_descriptor gdt[] __attribute__ ((aligned (4))) = { [NULL_SEL] = {  // Null segment
76         .raw = 0 }, [KCODE_SEL] = {   // Kernel code segment
77         .d = {
78             .lo_limit = 0xffff,
79             .lo_base = 0,
80             .type = 0xa,
81             .system_desc = 1,
82             .privilege_level = SEL_KPL,
83             .present = 1,
84             .hi_limit = 0xf,
85             .available = 0,
86             .long_mode = 1,
87             .operation_size = 0,
88             .granularity = 1,
89             .hi_base = 0 } }, [KSTACK_SEL] = {  // Kernel stack segment
90         .d = {
91             .lo_limit = 0xffff,
92             .lo_base = 0,
93             .type = 2,
94             .system_desc = 1,
95             .privilege_level = SEL_KPL,
96             .present = 1,
97             .hi_limit = 0xf,
98             .available = 0,
99             .long_mode = 1,
100             .operation_size = 0,
101             .granularity = 1,
102             .hi_base = 0 } }, [USTACK_SEL] = {  // User stack segment
103         .d = {
104             .lo_limit = 0xffff,
105             .lo_base = 0,
106             .type = 2,
107             .system_desc = 1,
108             .privilege_level = SEL_UPL,
109             .present = 1,
110             .hi_limit = 0xf,
111             .available = 0,
112             .long_mode = 1,
113             .operation_size = 0,
114             .granularity = 1,
115             .hi_base = 0 } }, [UCODE_SEL] = {  // User code segment
116         .d = {
117             .lo_limit = 0xffff,
118             .lo_base = 0,
119             .type = 0xa,
120             .system_desc = 1,
121             .privilege_level = SEL_UPL,
122             .present = 1,
123             .hi_limit = 0xf,
124             .available = 0,
125             .long_mode = 1,
126             .operation_size = 0,
127             .granularity = 1,
128             .hi_base = 0 } }, [TSS_LO_SEL] = {  // Global Task State Segment (TSS), lower 8 bytes
129         .sys_lo = {
130             .lo_limit = sizeof(tss) & 0xffff,
131             .type = SDT_SYSTSS,
132             .privilege_level = SEL_KPL,
133             .present = 1,
134             .hi_limit = (sizeof(tss) >> 16) & 0xf,
135             .available = 0,
136             .granularity = 0, } }, [TSS_HI_SEL] = {  // Global Task State Segment (TSS), upper 8 bytes
137         .sys_hi = { .base = 0 } }, [LDT_LO_SEL] = {  // Local descriptor table (LDT), lower 8 bytes
138         .sys_lo = { .lo_limit = 0,  // # 4k pages (since granularity = 1)
139             .lo_base = 0,  // changed by context switch path when doing lldt
140             .type = 2,  // LDT
141             .privilege_level = SEL_UPL,
142             .present = 1,
143             .hi_limit = 0,
144             .available = 0,
145             .granularity = 1,
146             .hi_base = 0 } }, [LDT_HI_SEL ] = {  // Local descriptor table (LDT), upper 8 bytes
147         .sys_hi = { .base = 0  // changed by context switch path when doing lldt
148                 } }, };
149
150 union segment_descriptor *ldt_descriptor = &gdt[LDT_LO_SEL];
151
152 /**
153  * Bootup PML4, used to map both low (identity-mapped) memory and relocated
154  * memory at the same time.
155  */
156 static union x86_64_pdir_entry boot_pml4[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE)));
157
158 /**
159  * Bootup low-map PDPT and hi-map PDPT.
160  */
161 static union x86_64_pdir_entry
162         boot_pdpt[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE))),
163         boot_pdpt_hi[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE)));
164
165 /**
166  * Bootup low-map PDIR, hi-map PDIR, and 1GB PDIR.
167  */
168 static union x86_64_ptable_entry
169         boot_pdir[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE))),
170         boot_pdir_hi[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE))),
171         boot_pdir_1GB[PTABLE_SIZE] __attribute__ ((aligned(BASE_PAGE_SIZE)));
172
173 /**
174  * This flag is set to true once the IDT is initialized and exceptions can be
175  * caught.
176  */
177 bool idt_initialized = false;
178
179 /**
180  * \brief Setup bootup page table.
181  *
182  * This function sets up the page table needed to boot the kernel
183  * proper.  The table identity maps the first 1 GByte of physical
184  * memory in order to have access to various data structures and the
185  * first MByte containing bootloader-passed data structures. It also
186  * identity maps the local copy of the kernel in low memory and
187  * aliases it in kernel address space.
188  *
189  * \param base  Start address of kernel image in physical address space.
190  * \param size  Size of kernel image.
191  */
192 static void
193 paging_init(lpaddr_t base,
194             size_t size)
195 {
196     lvaddr_t vbase = local_phys_to_mem(base);
197
198     // Align base to kernel page size
199     if (base & X86_64_MEM_PAGE_MASK) {
200         size += base & X86_64_MEM_PAGE_MASK;
201         base -= base & X86_64_MEM_PAGE_MASK;
202     }
203
204     // Align vbase to kernel page size
205     if (vbase & X86_64_MEM_PAGE_MASK) {
206         vbase -= vbase & X86_64_MEM_PAGE_MASK;
207     }
208
209     // Align size to kernel page size
210     if (size & X86_64_MEM_PAGE_MASK) {
211         size += X86_64_MEM_PAGE_SIZE - (size & X86_64_MEM_PAGE_MASK);
212     }
213
214     // XXX: Cannot currently map more than one table of pages
215     assert(size <= X86_64_MEM_PAGE_SIZE * X86_64_PTABLE_SIZE);
216     /*     assert(size <= MEM_PAGE_SIZE); */
217
218     for (size_t i = 0; i < size; i += X86_64_MEM_PAGE_SIZE, base +=
219     X86_64_MEM_PAGE_SIZE, vbase += X86_64_MEM_PAGE_SIZE) {
220         // No kernel image above 4 GByte
221         assert(base < ((lpaddr_t )4 << 30));
222
223         // Identity-map the kernel's physical region, so we don't lose ground
224         paging_x86_64_map_table(&boot_pml4[X86_64_PML4_BASE(base)],
225                                 (lpaddr_t) boot_pdpt);
226         paging_x86_64_map_table(&boot_pdpt[X86_64_PDPT_BASE(base)],
227                                 (lpaddr_t) boot_pdir);
228         paging_x86_64_map_large(
229                 &boot_pdir[X86_64_PDIR_BASE(base)], base,
230                 PTABLE_PRESENT | PTABLE_READ_WRITE | PTABLE_USER_SUPERVISOR);
231
232         // Alias the same region at MEMORY_OFFSET
233         paging_x86_64_map_table(&boot_pml4[X86_64_PML4_BASE(vbase)],
234                                 (lpaddr_t) boot_pdpt_hi);
235         paging_x86_64_map_table(&boot_pdpt_hi[X86_64_PDPT_BASE(vbase)],
236                                 (lpaddr_t) boot_pdir_hi);
237         paging_x86_64_map_large(
238                 &boot_pdir_hi[X86_64_PDIR_BASE(vbase)], base,
239                 PTABLE_PRESENT | PTABLE_READ_WRITE | PTABLE_USER_SUPERVISOR);
240     }
241
242     // Identity-map the first 1G of physical memory for bootloader data
243     paging_x86_64_map_table(&boot_pml4[0], (lpaddr_t) boot_pdpt);
244     paging_x86_64_map_table(&boot_pdpt[0], (lpaddr_t) boot_pdir_1GB);
245     for (int i = 0; i < X86_64_PTABLE_SIZE; i++) {
246         paging_x86_64_map_large(
247                 &boot_pdir_1GB[X86_64_PDIR_BASE(X86_64_MEM_PAGE_SIZE * i)],
248                 X86_64_MEM_PAGE_SIZE * i,
249                 PTABLE_PRESENT | PTABLE_READ_WRITE | PTABLE_USER_SUPERVISOR);
250     }
251
252     // Activate new page tables
253     paging_x86_64_context_switch((lpaddr_t) boot_pml4);
254 }
255
256 /**
257  * \brief Setup default GDT.
258  *
259  * Loads the GDT register with the default GDT and reloads CS and SS
260  * to point to the new entries. Resets all other segment registers to null.
261  * Finally, completes setup of GDT to include TSS base address mapping and
262  * loads TSS into task register.
263  */
264 static void
265 gdt_reset(void)
266 {
267     lvaddr_t ptss = (lvaddr_t) &tss;
268     struct region_descriptor region = { .rd_limit = sizeof(gdt), .rd_base =
269             (uint64_t) &gdt };
270
271     // Load default GDT
272     __asm volatile("lgdt %[region]" :: [region] "m" (region));
273
274     // Reload segments
275     __asm volatile("mov %[null], %%ds      \n\t"
276             "mov %[null], %%es      \n\t"
277             "mov %[ss], %%ss        \n\t"
278             "mov %[null], %%gs      \n\t"
279             "mov %[null], %%fs      \n\t"
280             "pushq %[cs]            \n\t"          // new CS
281             "lea 1f(%%rip), %%rax   \n\t"// jumps to after lret
282             "pushq %%rax            \n\t"// new IP
283             "lretq                  \n\t"// fake return
284             "1:                     \n\t"// we'll continue here
285             : /* No Output */
286             :
287             [null] "r" (0),
288             [ss] "r" (GSEL(KSTACK_SEL, SEL_KPL)),
289             [cs] "i" (GSEL(KCODE_SEL, SEL_KPL))
290             : "rax"
291     );
292
293     // Complete setup of TSS descriptor (by inserting base address of TSS)
294     gdt[TSS_LO_SEL].sys_lo.lo_base = ptss & 0xffffff;
295     gdt[TSS_LO_SEL].sys_lo.hi_base = (ptss >> 24) & 0xff;
296     gdt[TSS_HI_SEL].sys_hi.base = ptss >> 32;
297
298     // Complete setup of TSS
299     tss.rsp[0] = (lvaddr_t) &x86_64_kernel_stack[X86_64_KERNEL_STACK_SIZE
300             / sizeof(uintptr_t)];
301
302     // Load task state register
303     __asm volatile("ltr %%ax" :: "a" (GSEL(TSS_LO_SEL, SEL_KPL)));
304 }
305
306 /**
307  * \brief Relocates the active stack.
308  *
309  * This function relocates the stack, by adding 'offset' to the stack
310  * pointer.
311  *
312  * \param offset        Offset to add to the stack pointer.
313  */
314 static inline void __attribute__ ((always_inline))
315 relocate_stack(lvaddr_t offset)
316 {
317     __asm volatile("add %[stack], %%rsp\n\t"
318             : /* No output */
319             : [stack] "er" (offset)
320             : "rsp"
321     );
322 }
323
324 /**
325  * \brief Enable SYSCALL/SYSRET fast system calls.
326  *
327  * This function enables the SYSCALL/SYSRET pair of fast system calls in
328  * long mode. Also sets the IA32_STAR and IA32_FMASK MSRs to point to the
329  * user-space base selector and RFLAGS mask for SYSCALL/SYSRET fast system
330  * calls.
331  */
332 static inline void
333 enable_fast_syscalls(void)
334 {
335     // Segment selector bases for both kernel- and user-space for fast
336     // system calls
337     ia32_star_t star = ia32_star_rd(NULL);
338     star = ia32_star_call_insert(star, GSEL(KCODE_SEL, SEL_KPL));
339     star = ia32_star_ret_insert(star, GSEL(KSTACK_SEL, SEL_UPL));
340     ia32_star_wr(NULL, star);
341
342     // Set ia32_lstar MSR to point to kernel-space system call multiplexer
343     ia32_lstar_wr(NULL, (lvaddr_t) syscall_entry);
344
345     // Set IA32_FMASK MSR for our OSes EFLAGS mask
346     // We mask out everything (including interrupts).
347     ia32_fmask_v_wrf(NULL, ~(RFLAGS_ALWAYS1));
348
349     // Enable fast system calls
350     ia32_efer_sce_wrf(NULL, 1);
351 }
352
353 static inline void
354 enable_tlb_flush_filter(void)
355 {
356     uint32_t eax, ebx, ecx, edx;
357
358     // Must read "AuthenticAMD"
359     cpuid(0, &eax, &ebx, &ecx, &edx);
360     if (ebx != 0x68747541 || ecx != 0x444d4163 || edx != 0x69746e65) {
361         return;
362     }
363
364     // Is at least family 0fh?
365     cpuid(1, &eax, &ebx, &ecx, &edx);
366     if (((eax >> 8) & 0xf) != 0xf) {
367         return;
368     }
369
370     debug(SUBSYS_STARTUP, "Enabling TLB flush filter\n");
371     ia32_amd_hwcr_ffdis_wrf(NULL, 1);
372 }
373
374 static inline void
375 enable_monitor_mwait(void)
376 {
377     uint32_t eax, ebx, ecx, edx;
378
379     cpuid(1, &eax, &ebx, &ecx, &edx);
380
381     if (ecx & (1 << 3)) {
382         cpuid(5, &eax, &ebx, &ecx, &edx);
383         debug(SUBSYS_STARTUP, "MONITOR/MWAIT supported: "
384               "min size %u bytes, max %u bytes. %s %s\n",
385               eax, ebx, (ecx & 2) ? "IBE" : "", (ecx & 1) ? "EMX" : "");
386     }
387 }
388
389 /**
390  * \brief Continue kernel initialization in kernel address space.
391  *
392  * This function resets paging to map out low memory and map in physical
393  * address space, relocating all remaining data structures. It resets the
394  * Global Descriptor Table for flat mode and to exclude legacy segments from
395  * boot initialization code. It sets up the IDT for exception and interrupt
396  * handling, initializes the local APIC and enables interrupts. After that it
397  * calls kernel_startup(), which should not return (if it does, this function
398  * halts the kernel).
399  */
400 static void __attribute__ ((noreturn, noinline))
401 text_init(void)
402 {
403     // Reset global and locks to point to the memory in the pristine image
404     global = (struct global*) addr_global;
405
406     /*
407      * Reset paging once more to use relocated data structures and map in
408      * whole of kernel and available physical memory. Map out low memory.
409      */
410     paging_x86_64_reset();
411
412     // Relocate global to "memory"
413     global = (struct global*) local_phys_to_mem((lpaddr_t) global);
414
415     // Relocate glbl_core_data to "memory"
416     glbl_core_data = (struct x86_core_data *) local_phys_to_mem(
417             (lpaddr_t) glbl_core_data);
418
419     /*
420      * Use new physical address space for video memory -- no calls to functions
421      * that end up calling a conio.c function may be called between
422      * paging_reset() and conio_relocate_vidmem()!
423      */
424     conio_relocate_vidmem(local_phys_to_mem(VIDEO_MEM));
425
426     // Re-map physical memory
427     /* XXX: Currently we are statically mapping a fixed amount of
428      memory.  We should not map in more memory than the machine
429      actually has.  Or else if the kernel tries to access addresses
430      not backed by real memory, it will experience weird faults
431      instead of a simpler pagefault.
432
433      Ideally, we should use the ACPI information to figure out which
434      memory to map in. Look at ticket #218 for more
435      information. -Akhi
436      */
437     if (paging_x86_64_map_memory(0, X86_64_PADDR_SPACE_LIMIT) != 0) {
438         panic("error while mapping physical memory!");
439     }
440
441     /*
442      * Also reset the global descriptor table (GDT), so we get
443      * segmentation again and can catch interrupts/exceptions (the IDT
444      * needs the GDT).
445      */
446     gdt_reset();
447
448     // Arch-independent early startup
449     kernel_startup_early();
450
451     // XXX: re-init the serial driver, in case the port changed after parsing args
452     serial_console_init();
453
454     // Setup IDT
455     setup_default_idt();
456     idt_initialized = true;
457
458     // Enable machine check reporting
459     mcheck_init();
460
461     // Initialize local APIC
462     apic_init();
463
464     // do not remove/change this printf: needed by regression harness
465     printf("Barrelfish CPU driver starting on x86_64 apic_id %u\n", apic_id);
466
467     if (apic_is_bsp()) {
468         // Initialize classic (8259A) PIC
469         pic_init();
470     }
471
472     // Initialize real-time clock
473     rtc_init();
474
475     // Initialize local APIC timer
476     if (kernel_ticks_enabled) {
477         timing_calibrate();
478         bool periodic = true;
479 #ifdef CONFIG_ONESHOT_TIMER
480         // we probably need a global variable like kernel_ticks_enabled
481         periodic = false;
482 #endif
483         apic_timer_init(false, periodic);
484         timing_apic_timer_set_ms(kernel_timeslice);
485     } else {
486         printk(LOG_WARN, "APIC timer disabled: NO timeslicing\n");
487         apic_mask_timer();
488     }
489
490     // Initialize IPI notification mechanism
491     ipi_notify_init();
492
493     // Enable SYSCALL/SYSRET fast system calls
494     enable_fast_syscalls();
495
496     // Enable "no execute" page-level protection bit
497     ia32_efer_nxe_wrf(NULL, 1);
498
499     // Enable FPU and MMX
500     enable_fpu();
501
502     // Enable user-mode RDPMC opcode
503     amd64_cr4_pce_wrf(NULL, 1);
504
505     // AMD64: Check if TLB flush filter is enabled
506     enable_tlb_flush_filter();
507
508     // Enable global pages
509     amd64_cr4_pge_wrf(NULL, 1);
510
511     // Check/Enable MONITOR/MWAIT opcodes
512     enable_monitor_mwait();
513
514     // Call main kernel startup function -- this should never return
515     kernel_startup();
516
517     halt();
518     // Returning here will crash! -- low pages not mapped anymore!
519 }
520
521
522
523 /**
524  * \brief Architecture-specific initialization function.
525  *
526  * This function is called by the bootup code in boot.S to initialize
527  * architecture-specific stuff. It is expected to call the kernel main
528  * loop. This function never returns.
529  *
530  * The kernel expects one of two magic values in 'magic' that determine how it
531  * has been booted. If 'magic' is #MULTIBOOT_INFO_MAGIC the kernel has been
532  * booted by a (Multiboot-compliant) bootloader and this is the first image on
533  * the boot CPU. It will relocate itself to a default position. If 'magic' is
534  * #KERNEL_BOOT_MAGIC it has been booted by another image of itself and is
535  * running on an (so-called) application CPU.
536  *
537  * This function sets up new page tables to alias the kernel
538  * at #MEMORY_OFFSET. It also does any relocations necessary to the
539  * "position-independent" code to make it run at the new location (e.g.
540  * relocating the GOT). After all relocations, it calls text_init() of
541  * the relocated image, which destroys the lower alias and may never return.
542  *
543  * For bsp kernels, the void pointer is of type multiboot_info, for application
544  * CPUs, it is of type global. Global carries a pointer to multiboot_info.
545  * Global also contains pointers to memory that is shared between kernels.
546  *
547  * \param magic         Boot magic value
548  * \param pointer       Pointer to Multiboot Info or to Global structure
549  */
550 void
551 arch_init(uint64_t magic,
552           void *pointer)
553 {
554     // Sanitize the screen
555     //conio_cls();
556     serial_console_init();
557
558     notify_host();
559
560     /* we do not have multiboot */
561
562     void __attribute__ ((noreturn))
563     (*reloc_text_init)(void) =
564     (void *)local_phys_to_mem((lpaddr_t)text_init);
565
566
567     struct Elf64_Shdr *rela, *symtab;
568     struct multiboot_info *mb = NULL;
569
570     /*
571      * If this is the boot image, make Multiboot information structure globally
572      * known. Otherwise the passed value should equal the original structure.
573      * If magic value does not match what we expect, we cannot proceed safely.
574      */
575     switch (magic) {
576     case MULTIBOOT_INFO_MAGIC:
577         mb = (struct multiboot_info *) pointer;
578
579         // Construct the global structure and store its address to retrive it
580         // across relocation
581         memset(&global->locks, 0, sizeof(global->locks));
582         addr_global = (uint64_t) global;
583         break;
584
585     case KERNEL_BOOT_MAGIC:
586         global = (struct global*) pointer;
587         // Store the address of global to retrive it across relocation
588         addr_global = (uint64_t) global;
589         break;
590
591     default:
592         addr_global = (uint64_t) global;
593         break;
594     }
595
596
597     /* determine page-aligned physical address past end of multiboot */
598     lvaddr_t dest = (lvaddr_t) &_start_kernel;
599     if (dest & (BASE_PAGE_SIZE - 1)) {
600         dest &= ~(BASE_PAGE_SIZE - 1);
601         dest += BASE_PAGE_SIZE;
602     }
603
604     printf("Welcome to Barrelfish\n");
605
606     // XXX: print kernel address for debugging with gdb
607 //    printf("Kernel starting at address 0x%"PRIxLVADDR"\n", local_phys_to_mem(dest));
608
609     printf("Hi there!\n");
610
611     struct x86_coredata_elf *elf;
612     uint32_t multiboot_flags;
613     if (mb != NULL) { /* Multiboot info was passed */
614         multiboot_flags = mb->flags;
615         elf = (struct x86_coredata_elf *) &mb->syms.elf;
616
617         // We need the ELF section header table for relocation
618         if (!(multiboot_flags & MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS)) {
619             panic("Multiboot information structure does not include ELF section"
620                   "header information -- Relocation impossible!");
621         }
622
623         // Determine where free RAM starts
624         glbl_core_data->start_free_ram = ROUND_UP(
625                 max(multiboot_end_addr(mb), (uintptr_t)&_end_kernel),
626                 BASE_PAGE_SIZE);
627
628         glbl_core_data->mods_addr = mb->mods_addr;
629         glbl_core_data->mods_count = mb->mods_count;
630         glbl_core_data->cmdline = mb->cmdline;
631         glbl_core_data->mmap_length = mb->mmap_length;
632         glbl_core_data->mmap_addr = mb->mmap_addr;
633     } else { /* No multiboot info, use the core_data struct */
634
635         printf("No multiboot \n");
636
637         struct x86_core_data *core_data = (struct x86_core_data*) (dest
638                 - BASE_PAGE_SIZE);
639         multiboot_flags = core_data->multiboot_flags;
640         elf = &core_data->elf;
641         glbl_core_data = core_data;
642         core_data->cmdline = (lpaddr_t) &core_data->kernel_cmdline;
643         my_core_id = core_data->dst_core_id;
644
645         if (core_data->module_end > 4ul * (1ul << 20)) {
646             panic("The cpu module is outside the initial 4MB mapping."
647                   " Either move the module or increase initial mapping.");
648         }
649     }
650     printf("Continuing... \n");
651
652
653     if (!elf) {
654         printf("ELF is null.Continuing... \n");
655         while(1)
656             ;
657     }
658
659     printf("Elf non null.. go ahead\n");
660
661     printf("testing....\n");
662     printf("1+2=%d\n", 1+2);
663
664     // We're only able to process Elf64_Rela entries
665     if (elf->size != sizeof(struct Elf64_Shdr)) {
666         printf("ELF section header entry size mismatch!\n");
667         while(1)
668             ;
669         panic("ELF section header entry size mismatch!");
670     }
671
672     printf("Continuing... 2\n");
673
674     // Find relocation section
675     rela = elf64_find_section_header_type((struct Elf64_Shdr *) (lpaddr_t) elf->addr,
676                                           elf->num, SHT_RELA);
677     if (rela == NULL) {
678         panic("Kernel image does not include relocation section!");
679     }
680
681     printf("Continuing... 3\n");
682
683     // Find symbol table section
684     symtab = elf64_find_section_header_type(
685             (struct Elf64_Shdr *) (lpaddr_t) elf->addr, elf->num, SHT_DYNSYM);
686     if (symtab == NULL) {
687         panic("Kernel image does not include symbol table!");
688     }
689
690     printf("Continuing... 4\n");
691
692     // Alias kernel on top of memory, keep low memory
693     paging_init((lpaddr_t) &_start_kernel, SIZE_KERNEL_IMAGE);
694
695     // Relocate kernel image for top of memory
696     elf64_relocate(
697             X86_64_MEMORY_OFFSET + (lvaddr_t) &_start_kernel,
698             (lvaddr_t) &_start_kernel,
699             (struct Elf64_Rela *) (rela->sh_addr - X86_64_START_KERNEL_PHYS
700                     + &_start_kernel),
701             rela->sh_size,
702             (struct Elf64_Sym *) (symtab->sh_addr - X86_64_START_KERNEL_PHYS
703                     + &_start_kernel),
704             symtab->sh_size,
705             X86_64_START_KERNEL_PHYS,
706             &_start_kernel);
707
708     /*** Aliased kernel available now -- low memory still mapped ***/
709
710     // Relocate stack to aliased location
711     relocate_stack(X86_64_MEMORY_OFFSET);
712
713     printf("Before reloc_text_init()\n");
714
715     while(1)
716         ;
717
718     // Call aliased text_init() function and continue initialization
719     reloc_text_init();
720 }