x86: smp_boot no longer uses smp_call_*
[akaros.git] / kern / arch / x86 / smp_entry32.S
1 #include <arch/mmu.h>
2 #include <ros/memlayout.h>
3 #include <arch/trap.h>
4
5 #define RELOC(x) ((x) - KERNBASE)
6 #define CPUID_PSE_SUPPORT       0x00000008
7
8 .globl                  smp_entry
9 smp_entry:              .code16
10         cli
11         cld
12         lock incw       smp_semaphore - smp_entry + 0x1000  # announce our presence
13 spin_start:                                             # grab lock in real mode
14         movw    $1, %ax
15         xchgw   %ax, smp_boot_lock - smp_entry + 0x1000
16         test    %ax, %ax
17         jne             spin_start
18
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         # Note that this GDT is straight through, with no KERNBASE translation
28         lgdt    gdtdesc - smp_entry + 0x1000
29
30         # Turn on protected mode
31         movl    %cr0, %eax
32         orl             $CR0_PE, %eax
33         movl    %eax, %cr0
34         ljmp    $GD_KT, $(protcseg - smp_entry + 0x1000)
35         
36 protcseg:       .code32
37         # Set up the protected-mode data segment registers
38         movw    $GD_KD, %ax             # Kernel segment selector
39         movw    %ax, %ds                # -> DS: Data Segment
40         movw    %ax, %es                # -> ES: Extra Segment
41         movw    %ax, %ss                # -> SS: Stack Segment
42         movw    %ax, %fs                # -> FS
43         movw    %ax, %gs                # -> GS
44
45         # Turn on Paging
46         movl    RELOC(boot_cr3), %eax
47         movl    %eax, %cr3
48         # Enable PSE, if available
49         movl    $1, %eax
50         cpuid
51         test    $CPUID_PSE_SUPPORT, %edx
52         jz              past_pse
53         movl    %cr4, %eax
54         orl             $CR4_PSE, %eax
55         movl    %eax, %cr4
56 past_pse:
57         # Turn on PGE, no matter what.  Ghetto, but we panic if it's not supported.
58         movl    %cr4, %eax
59         orl             $CR4_PGE, %eax
60         movl    %eax, %cr4
61         movl    %cr0, %eax      
62         # These cr0 flags are the same as in pmap.c.  Keep them in sync
63         orl             $(CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_MP), %eax  
64         andl    $(~(CR0_TS|CR0_EM|CR0_CD|CR0_NW)), %eax  
65         movl    %eax, %cr0
66
67         # Reload Segments, using the same gdt_pd as Core 0
68         lgdt    gdt_pd
69         movw    $GD_KD, %ax             # Kernel segment selector
70         movw    %ax, %ds                # -> DS: Data Segment
71         movw    %ax, %es                # -> ES: Extra Segment
72         movw    %ax, %ss                # -> SS: Stack Segment
73         movw    $GD_UD|3, %ax   # User segment selector, with RPL=3
74         movw    %ax, %fs                # -> FS
75         movw    %ax, %gs                # -> GS
76         ljmp    $GD_KT, $here   # jumping to original location of trampoline!
77 here:
78         xorl    %eax, %eax
79         lldt    %ax
80         incl    num_cpus
81         movl    (smp_stack_top), %esp
82         movl    $0, %ebp                # so backtrace works
83         call    smp_main
84         movl    %eax, %esp              # use our new stack, value returned from smp_main
85         # note the next two lines are using the direct mapping from smp_boot()
86         movw    $0, smp_boot_lock - smp_entry + 0x1000  # release lock
87         lock decw       smp_semaphore - smp_entry + 0x1000  # show we are done
88         sti                     # so we can get the IPI
89         hlt                     # wait for the IPI to run smp_pcu_init()
90         call    smp_final_core_init
91         call    smp_idle                # idle loop, will have interrupts turned on
92         # smp_idle should never return
93 spin:
94         jmp spin
95
96         # Below here is just data, stored with the code text
97         .p2align        2                                               # force 4 byte alignment
98 gdt:
99         SEG_NULL                                                        # null seg
100         SEG(STA_X|STA_R, 0, 0xffffffff)         # code seg
101         SEG(STA_W, 0, 0xffffffff)                       # data seg
102 gdtdesc:
103         .word   gdtdesc - gdt - 1                       # sizeof(gdt) - 1
104         .long   gdt - smp_entry + 0x1000        # address gdt
105         .p2align        2                                               # force 4 byte alignment
106 .globl                  smp_boot_lock
107 smp_boot_lock:                                                  # this lock word will be only used from
108         .word   0                                                       # its spot in the trampoline (0x1000)
109 .globl                  smp_semaphore
110 smp_semaphore:                                                  # poor man's polling semaphore
111         .word   0                                                       
112 .globl                  smp_entry_end
113 smp_entry_end: