BXE: min->MIN, plus an spatch
[akaros.git] / kern / arch / x86 / smp_entry64.S
1 #include <arch/mmu.h>
2 #include <ros/memlayout.h>
3 #include <arch/trap.h>
4 #include <arch/x86.h>
5
6 #define RELOC(x) ((x) - KERNBASE)
7 #define CPUID_PSE_SUPPORT       0x00000008
8
9 .globl                  smp_entry
10 smp_entry:              .code16
11         cli
12         cld
13         lock incw       smp_semaphore - smp_entry + 0x1000  # announce our presence
14 spin_start:                                             # grab lock in real mode
15         movw    $1, %ax
16         xchgw   %ax, smp_boot_lock - smp_entry + 0x1000
17         test    %ax, %ax
18         jne             spin_start
19         # Set up rudimentary segmentation
20         xorw    %ax, %ax                        # Segment number zero
21         movw    %ax, %ds                        # -> Data Segment
22         movw    %ax, %es                        # -> Extra Segment
23         movw    %ax, %ss                        # -> Stack Segment
24         # Would like to patch all of these 0x1000's at trampoline relocation time
25         # There's three of them, so we could patch the trampoline code when we load,
26         # once we're sure the entry code will not change anymore
27         lgdt    gdtdesc - smp_entry + 0x1000
28         # Turn on protected mode
29         movl    %cr0, %eax
30         orl             $CR0_PE, %eax
31         movl    %eax, %cr0
32         ljmp    $GD_KT, $(protcseg - smp_entry + 0x1000)
33 .code32
34 protcseg:
35         # Set up the protected-mode data segment registers
36         movw    $GD_KD, %ax             # Kernel segment selector
37         movw    %ax, %ds                # -> DS: Data Segment
38         movw    %ax, %es                # -> ES: Extra Segment
39         movw    %ax, %ss                # -> SS: Stack Segment
40         movw    %ax, %fs                # -> FS
41         movw    %ax, %gs                # -> GS
42         # Turn on Paging.  We're using the symbol from entry64, which we'll have no
43         # problem linking against (compared to boot_cr3).  this assumes we use the
44         # boot stuff at least through smp_boot.
45         movl    $boot_pml4, %eax
46         movl    %eax, %cr3
47         # turn on paging option in cr4.  note we assume PSE support.  if we didn't
48         # have it, then our jumbo page mappings are going to fail.  we also want
49         # global pages (for performance).  PAE is the basics needed for long paging
50         movl    %cr4, %eax
51         orl             $(CR4_PSE | CR4_PGE | CR4_PAE), %eax
52         movl    %eax, %cr4
53         # Turn on the IA32E enabled bit.
54         # rd/wrmsr use ecx for the addr, and eax as the in/out register.
55         movl    $IA32_EFER_MSR, %ecx
56         rdmsr
57         orl             $IA32_EFER_IA32E_EN, %eax
58         wrmsr
59         # Setup cr0.  PE and PG are critical for now.  The others are similar to
60         # what we want in general (-AM with 64 bit, it's useless).
61         movl    %cr0, %eax
62         orl             $(CR0_PE | CR0_PG | CR0_WP | CR0_NE | CR0_MP), %eax  
63         andl    $(~(CR0_AM | CR0_TS | CR0_EM | CR0_CD | CR0_NW)), %eax  
64         movl    %eax, %cr0
65         # load the 64bit GDT and jump to long mode (symbol from entry64)
66         lgdt    gdt64desc
67         # Want to jump to the label long_mode, but we need to relocate to code
68         # reachable by 32 bit code: on our trampoline page.
69         ljmp    $0x08, $(long_mode - smp_entry + 0x1000)
70 .code64
71 long_mode:
72         # Note: we are still running code on the trampoline
73         # zero the data segments.  Not sure if this is legit or not.
74         xor             %rax, %rax
75         mov             %ax, %ds
76         mov             %ax, %es
77         mov             %ax, %ss
78         mov             %ax, %fs
79         mov             %ax, %gs
80         lldt    %ax
81         incl    num_cpus                # uint32_t
82         movq    (smp_stack_top), %rsp
83         movq    $0, %rbp                # so backtrace works
84         # We're on the trampoline, but want to be in the real location of the smp
85         # code (somewhere above KERN_LOAD_ADDR).  This allows us to easily unmap
86         # the boot up memory, which the trampoline is part of.
87         movabs  $(non_trampoline), %rax
88         call    *%rax
89 non_trampoline:
90         call    smp_main
91         movq    %rax, %rsp              # use our new stack, value returned from smp_main
92         # note the next two lines are using the direct mapping from smp_boot().
93         # Remember, the stuff at 0x1000 is a *copy* of the code and data at
94         # KERN_LOAD_ADDR.
95         movw    $0, smp_boot_lock - smp_entry + 0x1000  # release lock
96         lock decw       smp_semaphore - smp_entry + 0x1000  # show we are done
97         sti                     # so we can get the IPI
98         hlt                     # wait for the IPI to run smp_pcu_init()
99         call    smp_final_core_init
100         call    smp_idle                # idle loop, will have interrupts turned on
101         # smp_idle should never return
102 spin:
103         jmp spin
104
105         # Below here is just data, stored with the code text
106         .p2align        2                                               # force 4 byte alignment
107 gdt:
108         SEG_NULL                                                        # null seg
109         SEG(STA_X|STA_R, 0, 0xffffffff)         # code seg
110         SEG(STA_W, 0, 0xffffffff)                       # data seg
111 gdtdesc:
112         .word   gdtdesc - gdt - 1                       # sizeof(gdt) - 1
113         .long   gdt - smp_entry + 0x1000        # address gdt
114         .p2align        2                                               # force 4 byte alignment
115 .globl                  smp_boot_lock
116 smp_boot_lock:                                                  # this lock word will be only used from
117         .word   0                                                       # its spot in the trampoline (0x1000)
118 .globl                  smp_semaphore
119 smp_semaphore:                                                  # poor man's polling semaphore
120         .word   0                                                       
121 .globl                  smp_entry_end
122 smp_entry_end: