1/**
2 * \file
3 * \brief X-Loader for the Intel Xeon Phi
4 */
5
6/*
7 * Copyright (c) 2014 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, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15 /*
16  * Parts of this code comes from the Linux distribution shipped with the
17  * MPSS 3.2 for the Xeon Phi.
18  */
19
20#include <../kernel/include/target/k1om/offsets_target.h>
21
22/* Boot Magic */
23#define K1OM_BOOT_MAGIC               0xB001B001
24
25/* The long mode code segment */
26#define LONG_MODE_CS                  0x0010
27
28/* the boot stack size (16 kb)*/
29#define BOOT_STACK_SIZE               0x4000
30
31/* X86 Registers */
32#define MSR_EFER                      0xc0000080
33#define X86_EFER_LONG_MODE_ENABLE     8
34#define X86_CR0_PROTECTION_ENABLE     0x00000001
35#define X86_CR0_PAGING_ENABLE         0x80000000
36#define X86_CR4_PADDREXT_ENABLE       0x00000020
37
38/*
39 * scratch field in struct boot_params supplied by the bootloader
40 * this is used for a mini stack to determine the load address
41 */
42#define BP_SCRATCH                     484
43
44
45#define ENTRY(name) \
46  .globl name; \
47  .align 4,0x90; \
48  name:
49
50#ifndef ENDPROC
51#define ENDPROC(name) \
52  .type name, @function; \
53  .size name, .-name
54#endif
55
56
57/*
58 * ===========================================================================
59 * Begin of 32 bit entry code
60 * ===========================================================================
61 */
62
63          .section  ".head.text","ax"
64          .code32
65ENTRY(startup_32)
66
67          /* clear direction and interrupts */
68          cld
69          cli
70
71          leal      (BP_SCRATCH+4)(%esi), %esp
72          call      1f
731:        popl      %ebp
74          subl      $1b, %ebp
75          movl      %ebp, %ebx
76
77		  leal      prepare_long_mode(%ebx), %eax
78		  jmp		*%eax
79ENDPROC(startup_32)
80
81          /* Prepare for the long mode */
82.section  ".head32.text","ax"
83
84ENTRY(prepare_long_mode)
85          /* Load new GDT with the 64bit segments using 32bit descriptor */
86          leal      gdt(%ebx), %eax
87          movl      %eax, gdt+2(%ebx)
88          lgdt      gdt(%ebx)
89
90          /* Enable physical address extension */
91          mov       %cr4,%eax
92          orl       $X86_CR4_PADDREXT_ENABLE,%eax
93          mov       %eax,%cr4
94
95         /* Building the boot page tables for long mode */
96
97          /* Initialize Page tables to 0 */
98          leal      pgtable(%ebx), %edi
99          xorl      %eax, %eax
100          movl      $((4096*6)/4), %ecx
101          rep       stosl
102
103          /* Build Level 4 */
104          leal      pgtable + 0(%ebx), %edi
105          leal      0x1007 (%edi), %eax
106          movl      %eax, 0(%edi)
107
108          /* Build Level 3 */
109          leal      pgtable + 0x1000(%ebx), %edi
110          leal      0x1007(%edi), %eax
111          movl      $4, %ecx
1121:        movl      %eax, 0x00(%edi)
113          addl      $0x00001000, %eax
114          addl      $8, %edi
115          decl      %ecx
116          jnz       1b
117
118          /* Build Level 2 */
119          leal      pgtable + 0x2000(%ebx), %edi
120          movl      $0x00000183, %eax
121          movl      $2048, %ecx
1221:        movl      %eax, 0(%edi)
123          addl      $0x00200000, %eax
124          addl      $8, %edi
125          decl      %ecx
126          jnz       1b
127
128          /* Adding mappings for the "serial out" */
129
130          /* Build Level 3 */
131          leal      pgtable + 0x1000(%ebx), %edi
132          leal      0x5007(%edi), %eax
133          addl      $256, %edi                    //31st entry
134          movl      %eax, 0x00(%edi)
135
136          /* Build Level 2 */
137          leal      pgtable + 0x6000(%ebx), %edi
138          movl      $0x00000183, %eax
139          movl      $512, %ecx
1401:        movl      %eax, 0(%edi)
141          addl      $0x00200000, %eax
142          addl      $8, %edi
143          decl      %ecx
144          jnz       1b
145
146          /* Build Level 2 - high part*/
147          leal    pgtable + 0x6000(%ebx), %edi
148          addl    $4, %edi
149          movl    $512, %ecx
1501:        movl    $0x8, 0(%edi)
151          addl    $8, %edi
152          decl    %ecx
153          jnz     1b
154
155          /* Enable the boot page tables */
156          leal      pgtable(%ebx), %eax
157          movl      %eax, %cr3
158
159          /* Enable the long mode */
160          movl      $MSR_EFER, %ecx
161          rdmsr
162          btsl      $X86_EFER_LONG_MODE_ENABLE, %eax
163          wrmsr
164
165            /* prepare the long mode jump */
166          pushl     $LONG_MODE_CS
167          leal      startup_64(%ebx), %eax
168          pushl     %eax
169
170          /* Activate protected mode and paging*/
171          movl        %cr0, %eax
172          orl      $(X86_CR0_PAGING_ENABLE | X86_CR0_PROTECTION_ENABLE), %eax
173          movl      %eax, %cr0
174
175          /* Jump from 32bit compatibility mode into 64bit mode. */
176          lret
177
178ENDPROC(prepare_long_mode)
179
180/*
181 * ===========================================================================
182 * Begin of 64 bit code
183 * ===========================================================================
184 */
185 	.section  ".head64.text","ax"
186          .code64
187ENTRY(startup_64)
188
189          /* Setup data segments. */
190          xorl      %eax, %eax
191          movl      %eax, %ds
192          movl      %eax, %es
193          movl      %eax, %ss
194          movl      %eax, %fs
195          movl      %eax, %gs
196          lldt      %ax
197          movl      $0x20, %eax
198          ltr       %ax
199
200          /* a little "printf" to show that we are running */
201          movabsq $0x08007DAB5C, %r14
202          movl    $0x0A58553E, (%r14)
203          movabsq $0x08007DAB40, %r14
204          movl    $2054847098, (%r14)
205
206
207          /* Set up the stack */
208          leaq      boot_stack_end(%rbx), %rsp
209
210
211          /* Reset EFLAGS */
212          pushq     $0
213          popf
214
215          /*
216           * store the boot param struct pointer and the magic value
217           * Note: %rsi holds already a pointer to the boot params
218           */
219          movq      $K1OM_BOOT_MAGIC, %rdi
220          call      loader
221
222           /* jump to the kernel entry point */
223          movq      $K1OM_BOOT_MAGIC, %rax
224          movq      multiboot_info, %rbx
225          movq      kernel_entry, %rcx
226          jmp       *%rcx
227
228          .data
229          .align 16
230gdt:
231          .word     gdt_end - gdt
232          .long     gdt
233          .word     0
234          .quad     0x0000000000000000  /* NULL descriptor */
235          .quad     0x00af9a000000ffff  /* __KERNEL_CS */
236          .quad     0x00cf92000000ffff  /* __KERNEL_DS */
237          .quad     0x0080890000000000  /* TS descriptor */
238          .quad     0x0000000000000000    /* TS continued */
239gdt_end:
240
241          .align 16
242boot_stack:
243          .fill BOOT_STACK_SIZE, 1, 0
244boot_stack_end:
245
246          .section ".pgtable","a",@nobits
247          .align 4096
248pgtable:
249          .fill 7*4096, 1, 0
250
251
252