---
 i386/i386/msr.h  |   3 ++
 x86_64/boothdr.S | 105 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/i386/i386/msr.h b/i386/i386/msr.h
index 8f09b80b..42b01062 100644
--- a/i386/i386/msr.h
+++ b/i386/i386/msr.h
@@ -26,6 +26,9 @@
 #define MSR_REG_FMASK 0xC0000084
 #define MSR_REG_FSBASE 0xC0000100
 #define MSR_REG_GSBASE 0xC0000101
+#ifdef __x86_64__
+#define MSR_REG_KGSBASE 0xC0000102
+#endif
 
 #define MSR_EFER_SCE  0x00000001
 
diff --git a/x86_64/boothdr.S b/x86_64/boothdr.S
index 0ab9bd55..abccec9a 100644
--- a/x86_64/boothdr.S
+++ b/x86_64/boothdr.S
@@ -20,7 +20,10 @@
 
 #include <i386/i386asm.h>
 #include <i386/i386/proc_reg.h>
+#include <i386/i386/gdt.h>
+#include <i386/i386/msr.h>
 #include <i386/i386/seg.h>
+#include <i386/apic.h>
        /*
         * This section will be put first into .boot.  See also x86_64/ldscript.
         */
@@ -48,6 +51,17 @@ boot_hdr:
        .global _start
 _start:
 boot_entry:
+       /* Enable local apic in xAPIC mode */
+       xorl    %eax, %eax
+       xorl    %edx, %edx
+       movl    $APIC_MSR, %ecx
+       rdmsr
+       orl     $APIC_MSR_ENABLE, %eax
+       orl     $APIC_MSR_BSP, %eax
+       andl    $(~APIC_MSR_X2APIC), %eax
+       movl    $APIC_MSR, %ecx
+       wrmsr
+
        /*
         * Prepare minimal page mapping to jump to 64 bit and to C code.
         * The first 4GB is identity mapped, and the first 2GB are re-mapped
@@ -133,7 +147,7 @@ switch64:
        mov     %cr4,%eax
        or      $CR4_PAE,%eax
        mov     %eax,%cr4
-       mov     $0xC0000080,%ecx  // select EFER register
+       mov     $MSR_REG_EFER,%ecx
        rdmsr
        or      $(1 << 8),%eax  // long mode enable bit
        wrmsr
@@ -144,7 +158,9 @@ switch64:
        or      $CR0_WP,%eax
        mov     %eax,%cr0
 
-       lgdt    gdt64pointer
+       /* Load gdt */
+       lgdt    gdt64descr
+       /* Load segment registers */
        movw    $0,%ax
        movw    %ax,%fs
        movw    %ax,%gs
@@ -158,13 +174,53 @@ switch64:
 
 boot_entry64:
        /* Switch to our own interrupt stack.  */
-       movq    $solid_intstack+INTSTACK_SIZE-16, %rax
-       andq    $(~15),%rax
-       movq    %rax,%rsp
+       movq    $solid_intstack+INTSTACK_SIZE-16, %rsp
+       andq    $(~0xf),%rsp
+
+       /* Set GS base address */
+       movq    $percpu_array, %rdx
+       movl    %edx, %eax
+       shrq    $32, %rdx
+       movl    $MSR_REG_GSBASE, %ecx
+       wrmsr
+
+       /* Reload gdt in long mode takes 2 args */
+       movw    gdt64descr, %di
+       movq    gdt64descr+2, %rsi
+       lgdt    gdt64descr
+
+       movw    $PERCPU_DS,%ax
+       movw    %ax,%gs
+
+       /* instead of ljmp */
+       movq    $fixup64, %rcx
+       pushq   $8
+       pushq   %rcx
+       /* far return to below - performs actual reload of gdt */
+       retfq
+
+fixup64:
+       /* Set GS base address again, it may have been wiped */
+       movq    $percpu_array, %rdx
+       movl    %edx, %eax
+       shrq    $32, %rdx
+       movl    $MSR_REG_GSBASE, %ecx
+       wrmsr
+
+       /* Set KernelGS base address */
+       movq    $percpu_array, %rdx
+       movl    %edx, %eax
+       shrq    $32, %rdx
+       movl    $MSR_REG_KGSBASE, %ecx
+       wrmsr
+
+       /* Reset stack */
+       andq    $(~0xf),%rsp
 
        /* Reset EFLAGS to a known state.  */
        pushq   $0
        popf
+
        /* save multiboot info for later */
        movq    %rbx,%r8
 
@@ -196,16 +252,47 @@ iplt_done:
        .section .boot.data
        .align 4096
 #define  SEG_ACCESS_OFS 40
-#define  SEG_GRANULARITY_OFS 52
+#define  SEG_FLAGS_OFS 52
 gdt64:
        .quad   0
 gdt64code:
-        .quad  (ACC_P << SEG_ACCESS_OFS) | (ACC_CODE_R << SEG_ACCESS_OFS) | 
(SZ_64 << SEG_GRANULARITY_OFS)
+        .quad  ((ACC_A | ACC_P | ACC_CODE_R) << SEG_ACCESS_OFS) | (SZ_64 << 
SEG_FLAGS_OFS)
 gdt64data:
-        .quad  (ACC_P << SEG_ACCESS_OFS) | (ACC_DATA_W << SEG_ACCESS_OFS)
+        .quad  ((ACC_A | ACC_P | ACC_DATA_W) << SEG_ACCESS_OFS) | (SZ_64 << 
SEG_FLAGS_OFS)
+
+       /* LDT = 0x18 */
+       .quad   0
+
+       /* TSS = 0x20 */
+       .quad   0
+
+       /* USER_LDT = 0x28 */
+       .quad   0
+
+       /* USER_TSS = 0x30 */
+       .quad   0
+
+       /* LINEAR = 0x38 */
+       .quad   0
+
+       /* FPREGS = 0x40 */
+       .quad   0
+
+       /* USER_GDT = 0x48 and 0x50 */
+       .quad   0
+       .quad   0
+
+       /* USER_TSS64 = 0x58 */
+       .quad   0
+
+       /* USER_TSS64 = 0x60 */
+       .quad   0
+
+       /* boot GS = 0x68 */
+        .quad  ((ACC_A | ACC_P | ACC_DATA_W) << SEG_ACCESS_OFS) | (SZ_64 << 
SEG_FLAGS_OFS)
 gdt64end:
        .skip   (4096 - (gdt64end - gdt64))
-gdt64pointer:
+gdt64descr:
        .word   gdt64end - gdt64 - 1
        .quad   gdt64
 
-- 
2.45.2



Reply via email to