Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / head64.c
1 #include <lwk/init.h>
2 #include <lwk/kernel.h>
3 #include <lwk/string.h>
4 #include <lwk/screen_info.h>
5 #include <lwk/params.h>
6 #include <lwk/smp.h>
7 #include <lwk/cpuinfo.h>
8 #include <arch/bootsetup.h>
9 #include <arch/sections.h>
10 #include <arch/pda.h>
11 #include <arch/processor.h>
12 #include <arch/desc.h>
13 #include <arch/proto.h>
14 #include <arch/page.h>
15 #include <arch/pgtable.h>
16 #include <arch/tlbflush.h>
17
18 /**
19  * Data passed to the kernel by the bootloader.
20  *
21  * NOTE: This is marked as __initdata so it goes away after the
22  *       kernel bootstrap process is complete.
23  */
24 char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
25
26 /**
27  * Interrupt Descriptor Table (IDT) descriptor.
28  *
29  * This descriptor contains the length of the IDT table and a
30  * pointer to the table.  The lidt instruction (load IDT) requires
31  * this format.
32  */
33 struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
34
35 /**
36  * Array of pointers to each CPU's per-processor data area.
37  * The array is indexed by CPU ID.
38  */
39 struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
40
41 /**
42  * Array of per-processor data area structures, one per CPU.
43  * The array is indexed by CPU ID.
44  */
45 struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
46
47 /**
48  * This unmaps virtual addresses [0,512GB) by clearing the first entry in the
49  * PGD/PML4T. After this executes, accesses to virtual addresses [0,512GB) will
50  * cause a page fault.
51  */
52 static void __init
53 zap_identity_mappings(void)
54 {
55         pgd_t *pgd = pgd_offset_k(0UL);
56         pgd_clear(pgd);
57         __flush_tlb();
58 }
59
60 /**
61  * Determines the address of the kernel boot command line.
62  */
63 static char * __init
64 find_command_line(void)
65 {
66         unsigned long new_data;
67
68         new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER);
69         if (!new_data) {
70                 if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
71                         return NULL;
72                 }
73                 new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
74         }
75         return __va(new_data);
76 }
77
78 /**
79  * This is the initial C entry point to the kernel.
80  * NOTE: The order of operations is usually important.  Be careful.
81  */
82 void __init
83 x86_64_start_kernel(char * real_mode_data)
84 {
85         int i;
86
87         /*
88          * Zero the "Block Started by Symbol" section...
89          * you know, the one that holds uninitialized data.
90          */
91         memset(__bss_start, 0,
92                (unsigned long) __bss_stop - (unsigned long) __bss_start);
93
94         /*
95          * Make NULL pointer dereferences segfault.
96          */
97         zap_identity_mappings();
98
99         /*
100          * Setup the initial interrupt descriptor table (IDT).
101          * This will be eventually be populated with the real handlers.
102          */
103         for (i = 0; i < 256; i++)
104                 set_intr_gate(i, early_idt_handler);
105         asm volatile("lidt %0" :: "m" (idt_descr));
106
107         /*
108          * Early per-processor data area (PDA) initialization.
109          */
110         for (i = 0; i < NR_CPUS; i++)
111                 cpu_pda(i) = &boot_cpu_pda[i];
112         pda_init(0, &bootstrap_task_union.task_info);
113
114         /*
115          * Make a copy data passed by the bootloader.
116          * real_mode_data will get clobbered eventually when the memory
117          * subsystem is initialized.
118          */
119         memcpy(x86_boot_params, __va(real_mode_data), sizeof(x86_boot_params));
120         memcpy(lwk_command_line, find_command_line(), sizeof(lwk_command_line));
121         
122         /*
123          * Tell the VGA driver the starting line number... this avoids
124          * overwriting BIOS and bootloader messages. 
125          */
126         param_set_by_name_int("vga.row", SCREEN_INFO.orig_y);
127
128         /* 
129          * Okay... we've done the bare essentials. Call into the 
130          * platform-independent bootstrap function. This will in turn
131          * call back into architecture dependent code to do things like
132          * initialize interrupts and boot CPUs. 
133          */
134         start_kernel();
135 }
136