]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/apbootstrap.s
merge
[plan9front.git] / sys / src / 9 / pc64 / apbootstrap.s
1 /*
2  * Start an Application Processor. This must be placed on a 4KB boundary
3  * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However,
4  * due to some shortcuts below it's restricted further to within the 1st
5  * 64KB. The AP starts in real-mode, with
6  *   CS selector set to the startup memory address/16;
7  *   CS base set to startup memory address;
8  *   CS limit set to 64KB;
9  *   CPL and IP set to 0.
10  */
11 #include "mem.h"
12
13 #define NOP             BYTE $0x90              /* NOP */
14
15 #define pFARJMP32(s, o) BYTE $0xea;             /* far jmp ptr32:16 */  \
16                         LONG $o; WORD $s
17 #define rFARJMP16(s, o) BYTE $0xea;             /* far jump ptr16:16 */ \
18                         WORD $o; WORD $s;
19 #define rFARJMP32(s, o) BYTE $0x66;             /* far jump ptr32:16 */ \
20                         pFARJMP32(s, o)
21
22 #define rLGDT(gdtptr)   BYTE $0x0f;             /* LGDT */              \
23                         BYTE $0x01; BYTE $0x16;                         \
24                         WORD $gdtptr
25
26 #define rMOVAX(i)       BYTE $0xb8;             /* i -> AX */           \
27                         WORD $i;
28
29 #define DELAY           BYTE $0xEB;             /* JMP .+2 */                   \
30                         BYTE $0x00
31
32 MODE $16
33
34 TEXT apbootstrap(SB), 1, $-4 
35         rFARJMP16(0, _apbootstrap-KZERO(SB))
36         NOP; NOP; NOP;
37 TEXT _apvector(SB), 1, $-4                      /* address APBOOTSTRAP+0x08 */
38         QUAD $0
39 TEXT _appml4(SB), 1, $-4                        /* address APBOOTSTRAP+0x10 */
40         QUAD $0
41 TEXT _apapic(SB), 1, $-4                        /* address APBOOTSTRAP+0x18 */
42         QUAD $0
43 TEXT _apmach(SB), 1, $-4                        /* address APBOOTSTRAP+0x20 */
44         QUAD $0
45 TEXT _apefer(SB), 1, $-4
46         QUAD $0x100                             /* Long Mode Enable */
47
48 TEXT _apbootstrap(SB), 1, $-4 
49         MOVW    CS, AX
50         MOVW    AX, DS                          /* initialise DS */
51
52         rLGDT(_gdtptr32p<>-KZERO(SB))           /* load a basic gdt */
53
54         MOVL    CR0, AX
55         ORL     $1, AX
56         MOVL    AX, CR0                         /* turn on protected mode */
57         DELAY                                   /* JMP .+2 */
58
59         rFARJMP16(SELECTOR(3, SELGDT, 0), _ap32-KZERO(SB))
60
61 /*
62  * Enable and activate Long Mode. From the manual:
63  *      make sure Page Size Extentions are off, and Page Global
64  *      Extensions and Physical Address Extensions are on in CR4;
65  *      set Long Mode Enable in the Extended Feature Enable MSR;
66  *      set Paging Enable in CR0;
67  *      make an inter-segment jump to the Long Mode code.
68  * It's all in 32-bit mode until the jump is made.
69  */
70 MODE $32
71
72 TEXT _ap32(SB), 1, $-4
73         MOVW    $SELECTOR(2, SELGDT, 0), AX
74         MOVW    AX, DS
75         MOVW    AX, ES
76         MOVW    AX, FS
77         MOVW    AX, GS
78         MOVW    AX, SS
79
80         MOVL    _appml4-KZERO(SB), AX   /* physical address of PML4 */
81         MOVL    AX, CR3                 /* load the mmu */
82         DELAY
83
84         MOVL    CR4, AX
85         ANDL    $~0x00000010, AX                /* Page Size */
86         ORL     $0x000000A0, AX                 /* Page Global, Phys. Address */
87         MOVL    AX, CR4
88
89         MOVL    $0xc0000080, CX                 /* Extended Feature Enable */
90         RDMSR
91         ORL     _apefer-KZERO(SB), AX
92         WRMSR
93
94         MOVL    CR0, DX
95         ANDL    $~0x6000000a, DX
96         ORL     $0x80010000, DX                 /* Paging Enable, Write Protect */
97         MOVL    DX, CR0
98
99         pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _ap64-KZERO(SB))
100
101 /*
102  * Long mode. Welcome to 2003.
103  * Jump out of the identity map space;
104  * load a proper long mode GDT;
105  * initialise the stack and call the
106  * C startup code in m->splpc.
107  */
108 MODE $64
109
110 TEXT _ap64(SB), 1, $-4
111         MOVQ    $_gdtptr64v<>(SB), AX
112         MOVL    (AX), GDTR
113
114         XORQ    AX, AX
115         MOVW    AX, DS                          /* not used in long mode */
116         MOVW    AX, ES                          /* not used in long mode */
117         MOVW    AX, FS
118         MOVW    AX, GS
119         MOVW    AX, SS                          /* not used in long mode */
120
121         MOVW    AX, LDTR
122
123         MOVQ    _apmach(SB), SP
124
125         MOVQ    AX, RUSER                       /* up = 0; */
126         MOVQ    SP, RMACH                       /* m = apmach */
127
128         ADDQ    $MACHSIZE, SP
129
130         PUSHQ   AX                              /* clear flags */
131         POPFQ
132
133         MOVQ    _apvector(SB), AX
134         MOVQ    _apapic(SB), RARG
135         PUSHQ   RARG
136
137         CALL    *AX
138
139 _halt:
140         HLT
141         JMP _halt
142         
143 TEXT _gdt<>(SB), 1, $-4
144         /* null descriptor */
145         LONG    $0
146         LONG    $0
147
148         /* (KESEG) 64 bit long mode exec segment */
149         LONG    $(0xFFFF)
150         LONG    $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
151
152         /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
153         LONG    $(0xFFFF)
154         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
155
156         /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
157         LONG    $(0xFFFF)
158         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
159
160
161 TEXT _gdtptr32p<>(SB), 1, $-4
162         WORD    $(4*8-1)
163         LONG    $_gdt<>-KZERO(SB)
164
165 TEXT _gdtptr64p<>(SB), 1, $-4
166         WORD    $(4*8-1)
167         QUAD    $_gdt<>-KZERO(SB)
168
169 TEXT _gdtptr64v<>(SB), 1, $-4
170         WORD    $(4*8-1)
171         QUAD    $_gdt<>(SB)