]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/apbootstrap.s
pc, pc64: properly track dependencies for mem.h on autogenerated apbootstrap.h and...
[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 _apbootstrap(SB), 1, $-4 
46         MOVW    CS, AX
47         MOVW    AX, DS                          /* initialise DS */
48
49         rLGDT(_gdtptr32p<>-KZERO(SB))           /* load a basic gdt */
50
51         MOVL    CR0, AX
52         ORL     $1, AX
53         MOVL    AX, CR0                         /* turn on protected mode */
54         DELAY                                   /* JMP .+2 */
55
56         rFARJMP16(SELECTOR(3, SELGDT, 0), _ap32-KZERO(SB))
57
58 /*
59  * Enable and activate Long Mode. From the manual:
60  *      make sure Page Size Extentions are off, and Page Global
61  *      Extensions and Physical Address Extensions are on in CR4;
62  *      set Long Mode Enable in the Extended Feature Enable MSR;
63  *      set Paging Enable in CR0;
64  *      make an inter-segment jump to the Long Mode code.
65  * It's all in 32-bit mode until the jump is made.
66  */
67 MODE $32
68
69 TEXT _ap32(SB), 1, $-4
70         MOVW    $SELECTOR(2, SELGDT, 0), AX
71         MOVW    AX, DS
72         MOVW    AX, ES
73         MOVW    AX, FS
74         MOVW    AX, GS
75         MOVW    AX, SS
76
77         MOVL    _appml4-KZERO(SB), AX   /* physical address of PML4 */
78         MOVL    AX, CR3                 /* load the mmu */
79         DELAY
80
81         MOVL    CR4, AX
82         ANDL    $~0x00000010, AX                /* Page Size */
83         ORL     $0x000000A0, AX                 /* Page Global, Phys. Address */
84         MOVL    AX, CR4
85
86         MOVL    $0xc0000080, CX                 /* Extended Feature Enable */
87         RDMSR
88         ORL     $0x00000100, AX                 /* Long Mode Enable */
89         WRMSR
90
91         MOVL    CR0, DX
92         ANDL    $~0x6000000a, DX
93         ORL     $0x80010000, DX                 /* Paging Enable, Write Protect */
94         MOVL    DX, CR0
95
96         pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _ap64-KZERO(SB))
97
98 /*
99  * Long mode. Welcome to 2003.
100  * Jump out of the identity map space;
101  * load a proper long mode GDT;
102  * initialise the stack and call the
103  * C startup code in m->splpc.
104  */
105 MODE $64
106
107 TEXT _ap64(SB), 1, $-4
108         MOVQ    $_gdtptr64v<>(SB), AX
109         MOVL    (AX), GDTR
110
111         XORQ    AX, AX
112         MOVW    AX, DS                          /* not used in long mode */
113         MOVW    AX, ES                          /* not used in long mode */
114         MOVW    AX, FS
115         MOVW    AX, GS
116         MOVW    AX, SS                          /* not used in long mode */
117
118         MOVW    AX, LDTR
119
120         MOVQ    _apmach(SB), SP
121
122         MOVQ    AX, RUSER                       /* up = 0; */
123         MOVQ    SP, RMACH                       /* m = apmach */
124
125         ADDQ    $MACHSIZE, SP
126
127         PUSHQ   AX                              /* clear flags */
128         POPFQ
129
130         MOVQ    _apvector(SB), AX
131         MOVQ    _apapic(SB), RARG
132         PUSHQ   RARG
133
134         CALL    *AX
135
136 _halt:
137         HLT
138         JMP _halt
139         
140 TEXT _gdt<>(SB), 1, $-4
141         /* null descriptor */
142         LONG    $0
143         LONG    $0
144
145         /* (KESEG) 64 bit long mode exec segment */
146         LONG    $(0xFFFF)
147         LONG    $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
148
149         /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
150         LONG    $(0xFFFF)
151         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
152
153         /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
154         LONG    $(0xFFFF)
155         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
156
157
158 TEXT _gdtptr32p<>(SB), 1, $-4
159         WORD    $(4*8-1)
160         LONG    $_gdt<>-KZERO(SB)
161
162 TEXT _gdtptr64p<>(SB), 1, $-4
163         WORD    $(4*8-1)
164         QUAD    $_gdt<>-KZERO(SB)
165
166 TEXT _gdtptr64v<>(SB), 1, $-4
167         WORD    $(4*8-1)
168         QUAD    $_gdt<>(SB)