2 |
- |
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 |
#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
|
|
|
15 |
BYTE $0x01; BYTE $0x16; \
|
|
|
16 |
WORD $gdtptr
|
|
|
17 |
#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \
|
|
|
18 |
WORD $o; WORD $s; \
|
|
|
19 |
NOP; NOP; NOP
|
|
|
20 |
#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \
|
|
|
21 |
BYTE $0xEA; LONG $o; WORD $s
|
|
|
22 |
|
|
|
23 |
#define DELAY BYTE $0xEB; /* JMP .+2 */ \
|
|
|
24 |
BYTE $0x00
|
|
|
25 |
#define INVD BYTE $0x0F; BYTE $0x08
|
|
|
26 |
#define WBINVD BYTE $0x0F; BYTE $0x09
|
|
|
27 |
|
|
|
28 |
/*
|
|
|
29 |
* Macros for calculating offsets within the page directory base
|
|
|
30 |
* and page tables. Note that these are assembler-specific hence
|
|
|
31 |
* the '<<2'.
|
|
|
32 |
*/
|
|
|
33 |
#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
|
|
|
34 |
#define PTO(a) (((((a))>>12) & 0x03FF)<<2)
|
|
|
35 |
|
|
|
36 |
TEXT apbootstrap(SB), $0
|
|
|
37 |
FARJUMP16(0, _apbootstrap(SB))
|
|
|
38 |
TEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */
|
|
|
39 |
LONG $0
|
|
|
40 |
TEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */
|
|
|
41 |
LONG $0
|
|
|
42 |
TEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */
|
|
|
43 |
LONG $0
|
|
|
44 |
TEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */
|
|
|
45 |
MOVW CS, AX
|
|
|
46 |
MOVW AX, DS /* initialise DS */
|
|
|
47 |
|
|
|
48 |
LGDT(gdtptr(SB)) /* load a basic gdt */
|
|
|
49 |
|
|
|
50 |
MOVL CR0, AX
|
|
|
51 |
ORL $1, AX
|
|
|
52 |
MOVL AX, CR0 /* turn on protected mode */
|
|
|
53 |
DELAY /* JMP .+2 */
|
|
|
54 |
|
|
|
55 |
BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */
|
|
|
56 |
MOVW AX, DS
|
|
|
57 |
MOVW AX, ES
|
|
|
58 |
MOVW AX, FS
|
|
|
59 |
MOVW AX, GS
|
|
|
60 |
MOVW AX, SS
|
|
|
61 |
|
|
|
62 |
FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB))
|
|
|
63 |
|
|
|
64 |
/*
|
|
|
65 |
* For Pentiums and higher, the code that enables paging must come from
|
|
|
66 |
* pages that are identity mapped.
|
|
|
67 |
* To this end double map KZERO at virtual 0 and undo the mapping once virtual
|
|
|
68 |
* nirvana has been obtained.
|
|
|
69 |
*/
|
|
|
70 |
TEXT _ap32(SB), $0
|
|
|
71 |
MOVL _appdb-KZERO(SB), CX /* physical address of PDB */
|
|
|
72 |
MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
|
|
|
73 |
MOVL DX, (PDO(0))(CX)
|
|
|
74 |
MOVL CX, CR3 /* load and flush the mmu */
|
|
|
75 |
|
|
|
76 |
MOVL CR0, DX
|
|
|
77 |
ORL $0x80010000, DX /* PG|WP */
|
|
|
78 |
ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
|
|
|
79 |
|
|
|
80 |
MOVL $_appg(SB), AX
|
|
|
81 |
MOVL DX, CR0 /* turn on paging */
|
|
|
82 |
JMP* AX
|
|
|
83 |
|
|
|
84 |
TEXT _appg(SB), $0
|
|
|
85 |
MOVL CX, AX /* physical address of PDB */
|
|
|
86 |
ORL $KZERO, AX
|
|
|
87 |
MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */
|
|
|
88 |
MOVL CX, CR3 /* load and flush the mmu */
|
|
|
89 |
|
|
|
90 |
MOVL $(MACHADDR+MACHSIZE-4), SP
|
|
|
91 |
|
|
|
92 |
MOVL $0, AX
|
|
|
93 |
PUSHL AX
|
|
|
94 |
POPFL
|
|
|
95 |
|
|
|
96 |
MOVL _apapic(SB), AX
|
|
|
97 |
MOVL AX, (SP)
|
|
|
98 |
MOVL _apvector(SB), AX
|
|
|
99 |
CALL* AX
|
|
|
100 |
_aphalt:
|
|
|
101 |
HLT
|
|
|
102 |
JMP _aphalt
|
|
|
103 |
|
|
|
104 |
TEXT gdt(SB), $0
|
|
|
105 |
LONG $0x0000; LONG $0
|
|
|
106 |
LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
|
|
|
107 |
LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
|
|
|
108 |
TEXT gdtptr(SB), $0
|
|
|
109 |
WORD $(3*8-1)
|
|
|
110 |
LONG $gdt-KZERO(SB)
|