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;
13 #define NOP BYTE $0x90 /* NOP */
15 #define pFARJMP32(s, o) BYTE $0xea; /* far jmp ptr32:16 */ \
17 #define rFARJMP16(s, o) BYTE $0xea; /* far jump ptr16:16 */ \
19 #define rFARJMP32(s, o) BYTE $0x66; /* far jump ptr32:16 */ \
22 #define rLGDT(gdtptr) BYTE $0x0f; /* LGDT */ \
23 BYTE $0x01; BYTE $0x16; \
26 #define rMOVAX(i) BYTE $0xb8; /* i -> AX */ \
29 #define DELAY BYTE $0xEB; /* JMP .+2 */ \
34 TEXT apbootstrap(SB), 1, $-4
35 rFARJMP16(0, _apbootstrap-KZERO(SB))
37 TEXT _apvector(SB), 1, $-4 /* address APBOOTSTRAP+0x08 */
39 TEXT _appml4(SB), 1, $-4 /* address APBOOTSTRAP+0x10 */
41 TEXT _apapic(SB), 1, $-4 /* address APBOOTSTRAP+0x18 */
43 TEXT _apmach(SB), 1, $-4 /* address APBOOTSTRAP+0x20 */
45 TEXT _apbootstrap(SB), 1, $-4
47 MOVW AX, DS /* initialise DS */
49 rLGDT(_gdtptr32p<>-KZERO(SB)) /* load a basic gdt */
53 MOVL AX, CR0 /* turn on protected mode */
56 rFARJMP16(SELECTOR(3, SELGDT, 0), _ap32-KZERO(SB))
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.
69 TEXT _ap32(SB), 1, $-4
70 MOVW $SELECTOR(2, SELGDT, 0), AX
77 MOVL _appml4-KZERO(SB), AX /* physical address of PML4 */
78 MOVL AX, CR3 /* load the mmu */
82 ANDL $~0x00000010, AX /* Page Size */
83 ORL $0x000000A0, AX /* Page Global, Phys. Address */
86 MOVL $0xc0000080, CX /* Extended Feature Enable */
88 ORL $0x00000100, AX /* Long Mode Enable */
93 ORL $0x80010000, DX /* Paging Enable, Write Protect */
96 pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _ap64-KZERO(SB))
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.
107 TEXT _ap64(SB), 1, $-4
108 MOVQ $_gdtptr64v<>(SB), AX
112 MOVW AX, DS /* not used in long mode */
113 MOVW AX, ES /* not used in long mode */
116 MOVW AX, SS /* not used in long mode */
122 MOVQ AX, RUSER /* up = 0; */
123 MOVQ SP, RMACH /* m = apmach */
127 PUSHQ AX /* clear flags */
130 MOVQ _apvector(SB), AX
131 MOVQ _apapic(SB), RARG
140 TEXT _gdt<>(SB), 1, $-4
141 /* null descriptor */
145 /* (KESEG) 64 bit long mode exec segment */
147 LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
149 /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
151 LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
153 /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
155 LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
158 TEXT _gdtptr32p<>(SB), 1, $-4
160 LONG $_gdt<>-KZERO(SB)
162 TEXT _gdtptr64p<>(SB), 1, $-4
164 QUAD $_gdt<>-KZERO(SB)
166 TEXT _gdtptr64v<>(SB), 1, $-4