138786Sdfr/**
238786Sdfr * \file
338786Sdfr * \brief Bootstrap the bootloader.
438786Sdfr */
538786Sdfr
638786Sdfr/*
738786Sdfr * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
838786Sdfr * All rights reserved.
938786Sdfr *
1038786Sdfr * This file is distributed under the terms in the attached LICENSE file.
1138786Sdfr * If you do not find this file, copies can be found by writing to:
1238786Sdfr * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
1338786Sdfr */
1438786Sdfr
1538786Sdfr#include <multiboot.h>
1638786Sdfr
1738786Sdfr#define STACK_SIZE  4096
1838786Sdfr
1938786Sdfr#define MSR_IA32_EFER   0xc0000080      ///< Extended features enables
2038786Sdfr#define PAGING_ENABLE 31
2138786Sdfr#define LONG_MODE_CS 0x0008
2238786Sdfr#define PAE     0x20
2338786Sdfr#define LME     8
2438786Sdfr
2538786Sdfr/* The flags for the Multiboot header */
2638786Sdfr#define MB_FLAGS (MULTIBOOT_HEADER_FLAG_MODS_PGALIGNED | MULTIBOOT_HEADER_FLAG_NEED_MEMINFO)
2738786Sdfr
2838786Sdfr.code32
2950476Speter.text
3038786Sdfr.globl  start, halt
31231244Sgjb
3238786Sdfr/* Multiboot header, 4-byte aligned */
3379538Sru    .align  4
3438786Sdfr    .long   MULTIBOOT_HEADER_MAGIC               /* magic */
3538786Sdfr    .long   MB_FLAGS                             /* flags */
3638786Sdfr    .long   -(MULTIBOOT_HEADER_MAGIC + MB_FLAGS) /* checksum */
3738786Sdfr
3884306Srustart:
3984306Sru    /* Initialize the stack pointer */
4038786Sdfr    movl    $(stack + STACK_SIZE), %esp
4138786Sdfr
4238786Sdfr    /* Reset EFLAGS */
43139772Skeramida    pushl   $0
44139772Skeramida    popf
45139772Skeramida
4669052Sru    /* Enter main -- this should never return */
4769052Sru    push    %ebp
4869052Sru    mov %esp, %ebp
4957695Ssheldonh    push    %ebx        /* Pointer to multiboot info struct */
5057695Ssheldonh    push    %eax        /* Multiboot magic value */
5157695Ssheldonh    call    startup
5247984Sn_hibma
53121379Shmp    // Load 64-bit GDT
54121379Shmp    mov $gdt_ptr, %esi
55121379Shmp    lgdt    (%esi)
56121379Shmp
5792566Sru    // enable page address extension
5892566Sru    mov %cr4,%eax
5992566Sru    or $PAE,%eax
6047984Sn_hibma    mov %eax,%cr4
6138786Sdfr
6247984Sn_hibma    // set PML4 pointer to cr3
6347984Sn_hibma    mov $boot_pml4, %eax
6457695Ssheldonh    mov %eax,%cr3
6557695Ssheldonh
6647984Sn_hibma    // enable long-mode by setting EFER.LME
6747984Sn_hibma    mov $MSR_IA32_EFER,%ecx
6857695Ssheldonh    rdmsr
69128104Simp    bts $LME,%eax
70128104Simp    wrmsr
71128104Simp
72128104Simp    // enable paging
73128104Simp    mov %cr0,%eax
7457695Ssheldonh    bts $PAGING_ENABLE,%eax
75128104Simp    mov %eax,%cr0
76128104Simp
77133526Simp    // Setup multiboot registers
78133526Simp    mov     eax, %eax
7938786Sdfr    mov     multiboot_info, %ebx
8047984Sn_hibma    mov kernel_entry, %ecx
81131530Sru
82131530Sru    // jmp to long-mode to the linear address corresponding the
8347984Sn_hibma    // real mode segment REAL_MODE_SEGMENT
84108260Sru    //  jmp LONG_MODE_CS:start_64
85131530Sru    .byte 0xea
86176966Simp    .long start_64
87176966Simp    .word LONG_MODE_CS
88176966Simp
89176966Simp/* start the 64bit long-mode code here */
90176966Simp.code64
91176966Simpstart_64:
92176966Simp
93176966Simp    // initialize bootup stack for the 64bit long mode
94211397Sjoel    lea (start_64_stack)(%rip), %rsp
95176966Simp    // Jump to kernel image entry
96176966Simp    jmp *%rcx
97176966Simp
98176966Simp/* Halt -- this should never be reached */
99233648Seadlerhalt:
100176966Simp    hlt
101176966Simp    jmp halt
102176966Simp
103176966Simp/* Stack for 64bit mode */
104176966Simp    .comm   stack, STACK_SIZE
105176966Simp    .align 16
106176966Simp    .fill STACK_SIZE,1,0
107176966Simpstart_64_stack:
108176966Simp
109176966Simp/* Global descriptor table */
110176966Simp.align 16
111176966Simpgdt:
112176966Simp    .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
113176966Simp    .byte 0xff,0xff,0x00,0x00,0x00,0x9a,0xaf,0x00 // 64bit code segment, D _cleared_ => "16bit"
114176966Simp    .byte 0xff,0xff,0x00,0x00,0x00,0x92,0xcf,0x00 // data
115176966Simp    .byte 0xff,0xff,0x00,0x00,0x00,0x9a,0xcf,0x00 // 32bit code segment for protected-mode
116176966Simp    .byte 0xff,0xff,0x00,0x80,0x0b,0x92,0xff,0x00 // screen
117210669Sjoel    .byte 0xff,0xff,0x00,0x60,0x00,0x9a,0xcf,0x00 // segment at linear address 0x6000
118176966Simp    .byte 0xff,0xff,0x00,0x00,0x00,0x92,0xaf,0x00 // stack segment in 64bit mode
119176966Simp
120176966Simpgdt_ptr:
121176966Simp    .word gdt_ptr - gdt
122233648Seadler    .long gdt
123233648Seadler    .long 0
124176966Simp