2 |
- |
1 |
#include "mem.h"
|
|
|
2 |
|
|
|
3 |
#define KB 1024
|
|
|
4 |
#define MB (1024*1024)
|
|
|
5 |
|
|
|
6 |
/*
|
|
|
7 |
* Some machine instructions not handled by 8[al].
|
|
|
8 |
*/
|
|
|
9 |
#define DELAY BYTE $0xEB; BYTE $0x00 /* JMP .+2 */
|
|
|
10 |
#define FARJUMP(s, o) BYTE $0xEA; /* far jump to ptr32:16 */\
|
|
|
11 |
LONG $o; WORD $s
|
|
|
12 |
|
|
|
13 |
#define NOP BYTE $0x90
|
|
|
14 |
#define HLT BYTE $0xF4
|
|
|
15 |
|
|
|
16 |
/*
|
|
|
17 |
* Macro for calculating offset within the page directory base.
|
|
|
18 |
* Note that this is assembler-specific hence the '<<2'.
|
|
|
19 |
*/
|
|
|
20 |
#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
|
|
|
21 |
|
|
|
22 |
/*
|
|
|
23 |
* May enter here either from the 16-bit real-mode startup or
|
|
|
24 |
* from other 32-bit protected mode code. For the latter case must
|
|
|
25 |
* make sure the GDT is set as it would be by the 16-bit code:
|
|
|
26 |
* disable interrupts;
|
|
|
27 |
* load the GDT with the table in _gdt32p;
|
|
|
28 |
* load all the data segments
|
|
|
29 |
* load the code segment via a far jump.
|
|
|
30 |
*/
|
|
|
31 |
TEXT _start32p(SB), $0
|
|
|
32 |
/* if distance to _start32p32 changes, update the offset after 0xEB. */
|
|
|
33 |
// jmp .+32 (_start32p32).
|
|
|
34 |
BYTE $0xEB; BYTE $(2+3*2*4+2+4)
|
|
|
35 |
NOP; NOP
|
|
|
36 |
|
|
|
37 |
TEXT _gdt32p(SB), $0
|
|
|
38 |
LONG $0x0000; LONG $0
|
|
|
39 |
LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
|
|
|
40 |
LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
|
|
|
41 |
|
|
|
42 |
TEXT _gdtptr32p(SB), $0
|
|
|
43 |
WORD $(3*8)
|
|
|
44 |
LONG $_gdt32p-KZERO(SB)
|
|
|
45 |
|
|
|
46 |
_start32p32:
|
|
|
47 |
CLI
|
|
|
48 |
|
|
|
49 |
MOVL AX, _multibootheader+(48-KZERO)(SB)
|
|
|
50 |
MOVL BX, _multibootheader+(52-KZERO)(SB)
|
|
|
51 |
|
|
|
52 |
MOVL $_gdtptr32p-KZERO(SB), AX
|
|
|
53 |
MOVL (AX), GDTR
|
|
|
54 |
|
|
|
55 |
MOVL $KDSEL, AX
|
|
|
56 |
MOVW AX, DS
|
|
|
57 |
MOVW AX, ES
|
|
|
58 |
MOVW AX, FS
|
|
|
59 |
MOVW AX, GS
|
|
|
60 |
MOVW AX, SS
|
|
|
61 |
|
|
|
62 |
DELAY
|
|
|
63 |
FARJUMP(KESEL, _start32pg-KZERO(SB))
|
|
|
64 |
|
|
|
65 |
/*
|
|
|
66 |
* Make the basic page tables for processor 0. Eight pages are needed for
|
|
|
67 |
* the basic set:
|
|
|
68 |
* a page directory, 5 pages pf page tables for mapping the first 20MB of
|
|
|
69 |
* physical memory, a single physical and virtual page for the Mach structure,
|
|
|
70 |
* and a page to be used later for the GDT.
|
|
|
71 |
*
|
|
|
72 |
* The remaining PTEs will be allocated later when memory is sized.
|
|
|
73 |
* Could clear BSS here too when clearing the space for the tables,
|
|
|
74 |
* but that would violate the separation of church and state.
|
|
|
75 |
* The first aligned page after end[] was used for passing BIOS parameters
|
|
|
76 |
* by the real-mode startup, now it's BIOSTABLES.
|
|
|
77 |
*/
|
|
|
78 |
TEXT _start32pg(SB), $0 /* CHECK alignment (16) */
|
|
|
79 |
DELAY
|
|
|
80 |
|
|
|
81 |
MOVL $end-KZERO(SB), DX /* clear pages for the tables etc. */
|
|
|
82 |
/* start must be page aligned, skip boot params page */
|
|
|
83 |
ADDL $(2*BY2PG-1), DX
|
|
|
84 |
ANDL $~(BY2PG-1), DX
|
|
|
85 |
|
|
|
86 |
/*
|
|
|
87 |
* zero mach page & gdt in low memory
|
|
|
88 |
*/
|
|
|
89 |
MOVL $(CPU0MACH-KZERO), DI
|
|
|
90 |
XORL AX, AX
|
|
|
91 |
MOVL $(2*BY2PG), CX /* mach (phys & virt) & gdt */
|
|
|
92 |
SHRL $2, CX
|
|
|
93 |
CLD
|
|
|
94 |
REP; STOSL /* zero mach & gdt pages */
|
|
|
95 |
|
|
|
96 |
/*
|
|
|
97 |
* zero pdb and pte for low memory
|
|
|
98 |
*/
|
|
|
99 |
MOVL DX, DI /* first page after end & boot params */
|
|
|
100 |
XORL AX, AX
|
|
|
101 |
MOVL $((1+LOWPTEPAGES)*BY2PG), CX /* pdb, n pte */
|
|
|
102 |
SHRL $2, CX
|
|
|
103 |
CLD
|
|
|
104 |
REP; STOSL /* zero pdb & pte pages */
|
|
|
105 |
|
|
|
106 |
/*
|
|
|
107 |
* populate pdb for low memory (20MB)
|
|
|
108 |
*/
|
|
|
109 |
MOVL DX, AX /* bootstrap processor PDB (page 0) */
|
|
|
110 |
MOVL DX, DI /* save it for later */
|
|
|
111 |
MOVL $(PTEWRITE|PTEVALID), BX/* page permissions */
|
|
|
112 |
|
|
|
113 |
ADDL $BY2PG, DX /* -> PA of first page of page table (page 1) */
|
|
|
114 |
ADDL $PDO(KZERO), AX /* page directory offset for KZERO */
|
|
|
115 |
MOVL DX, (AX) /* PTE's for KZERO */
|
|
|
116 |
ORL BX, (AX)
|
|
|
117 |
|
|
|
118 |
/* should be LOWPTEPAGES-1 repetitions of this fragment */
|
|
|
119 |
ADDL $BY2PG, DX /* -> PA of second page of page table (page 2) */
|
|
|
120 |
ADDL $4, AX /* page dir. offset for KZERO+4MB */
|
|
|
121 |
MOVL DX, (AX) /* PTE's for KZERO */
|
|
|
122 |
ORL BX, (AX)
|
|
|
123 |
|
|
|
124 |
ADDL $BY2PG, DX /* -> PA of third page of page table (page 3) */
|
|
|
125 |
ADDL $4, AX /* page dir. offset for KZERO+8MB */
|
|
|
126 |
MOVL DX, (AX) /* PTE's for KZERO */
|
|
|
127 |
ORL BX, (AX)
|
|
|
128 |
|
|
|
129 |
ADDL $BY2PG, DX /* -> PA of fourth page of page table (page 4) */
|
|
|
130 |
ADDL $4, AX /* page dir. offset for KZERO+12MB */
|
|
|
131 |
MOVL DX, (AX) /* PTE's for KZERO */
|
|
|
132 |
ORL BX, (AX)
|
|
|
133 |
|
|
|
134 |
ADDL $BY2PG, DX /* -> PA of fifth page of page table (page 5) */
|
|
|
135 |
ADDL $4, AX /* page dir. offset for KZERO+16MB */
|
|
|
136 |
MOVL DX, (AX) /* PTE's for KZERO */
|
|
|
137 |
ORL BX, (AX)
|
|
|
138 |
|
|
|
139 |
/*
|
|
|
140 |
* populate page tables for low memory
|
|
|
141 |
*/
|
|
|
142 |
MOVL DI, AX
|
|
|
143 |
ADDL $BY2PG, AX /* PA of first page of page table */
|
|
|
144 |
MOVL $(MemMin/BY2PG), CX
|
|
|
145 |
_setpte:
|
|
|
146 |
MOVL BX, (AX)
|
|
|
147 |
ADDL $(1<<PGSHIFT), BX
|
|
|
148 |
ADDL $4, AX
|
|
|
149 |
LOOP _setpte
|
|
|
150 |
|
|
|
151 |
/*
|
|
|
152 |
* map the Mach page
|
|
|
153 |
*/
|
|
|
154 |
MOVL DI, AX
|
|
|
155 |
ADDL $BY2PG, AX /* PA of first page of page table */
|
|
|
156 |
MOVL $(CPU0MACH-KZERO), DX /* -> PA of Mach structure */
|
|
|
157 |
MOVL $CPU0MACH, BX /* VA of Mach structure */
|
|
|
158 |
SHRL $10, BX /* create offset into PTEs */
|
|
|
159 |
ANDL $(0x3FF<<2), BX
|
|
|
160 |
|
|
|
161 |
ADDL BX, AX /* PTE offset for Mach structure */
|
|
|
162 |
MOVL DX, (AX) /* create PTE for Mach */
|
|
|
163 |
MOVL $(PTEWRITE|PTEVALID), BX/* page permissions */
|
|
|
164 |
ORL BX, (AX)
|
|
|
165 |
|
|
|
166 |
/*
|
|
|
167 |
* Now ready to use the new map. Initialise CR0 (assume the BIOS gets
|
|
|
168 |
* it mostly correct for this processor type w.r.t. caches and FPU).
|
|
|
169 |
* It is necessary on some processors to follow mode switching
|
|
|
170 |
* with a JMP instruction to clear the prefetch queues.
|
|
|
171 |
* The instruction to switch modes and the following jump instruction
|
|
|
172 |
* should be identity-mapped; to this end double map KZERO at
|
|
|
173 |
* virtual 0 and undo the mapping once virtual nirvana has been attained.
|
|
|
174 |
* If paging is already on, don't load CR3 before setting CR0, in which
|
|
|
175 |
* case most of this is a NOP and the 2nd load of CR3 actually does
|
|
|
176 |
* the business.
|
|
|
177 |
*/
|
|
|
178 |
MOVL DI, CX /* load address of PDB */
|
|
|
179 |
/* double-map first 20 MB, since we are running at 7 or 9 MB */
|
|
|
180 |
/* should be LOWPTEPAGES repetitions */
|
|
|
181 |
MOVL PDO(KZERO)(CX), DX /* double-map KZERO at 0 */
|
|
|
182 |
MOVL DX, PDO(0)(CX)
|
|
|
183 |
MOVL PDO(KZERO+4*MB)(CX), DX
|
|
|
184 |
MOVL DX, PDO(4*MB)(CX)
|
|
|
185 |
MOVL PDO(KZERO+8*MB)(CX), DX
|
|
|
186 |
MOVL DX, PDO(8*MB)(CX)
|
|
|
187 |
MOVL PDO(KZERO+12*MB)(CX), DX
|
|
|
188 |
MOVL DX, PDO(12*MB)(CX)
|
|
|
189 |
MOVL PDO(KZERO+16*MB)(CX), DX
|
|
|
190 |
MOVL DX, PDO(16*MB)(CX)
|
|
|
191 |
|
|
|
192 |
MOVL CR0, DX
|
|
|
193 |
MOVL DX, AX
|
|
|
194 |
ANDL $PG, AX /* check paging not already on */
|
|
|
195 |
JNE _nocr3load
|
|
|
196 |
MOVL CX, CR3 /* paging off, safe to load cr3 */
|
|
|
197 |
_nocr3load:
|
|
|
198 |
ORL $(PG|0x10000), DX /* PG|WP */
|
|
|
199 |
ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
|
|
|
200 |
|
|
|
201 |
MOVL $_startpg(SB), AX
|
|
|
202 |
TESTL $KZERO, AX /* want to run protected or virtual? */
|
|
|
203 |
JEQ _to32v /* protected */
|
|
|
204 |
MOVL DX, CR0 /* turn on paging */
|
|
|
205 |
JMP* AX /* headfirst into the new world */
|
|
|
206 |
|
|
|
207 |
TEXT _startpg(SB), $0
|
|
|
208 |
// MOVL $0, PDO(0)(CX) /* undo double-map of KZERO at 0 */
|
|
|
209 |
MOVL CX, CR3 /* load and flush the mmu */
|
|
|
210 |
_to32v:
|
|
|
211 |
MOVL $_start32v(SB), AX
|
|
|
212 |
JMP* AX /* into the dorkness */
|