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