Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/9/pcboot/realmode0.s – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "mem.h"
2
#include "/sys/src/boot/pc/x16.h"
3
#undef DELAY
4
 
5
#define PADDR(a)	((a) & ~KZERO)
6
#define KADDR(a)	(KZERO|(a))
7
 
8
/*
9
 * Some machine instructions not handled by 8[al].
10
 */
11
#define OP16		BYTE $0x66
12
#define DELAY		BYTE $0xEB; BYTE $0x00	/* JMP .+2 */
13
#define CPUID		BYTE $0x0F; BYTE $0xA2	/* CPUID, argument in AX */
14
#define WRMSR		BYTE $0x0F; BYTE $0x30	/* WRMSR, argument in AX/DX (lo/hi) */
15
#define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */
16
#define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */
17
#define HLT		BYTE $0xF4
18
#define INVLPG	BYTE $0x0F; BYTE $0x01; BYTE $0x39	/* INVLPG (%ecx) */
19
#define WBINVD	BYTE $0x0F; BYTE $0x09
20
 
21
/*
22
 * Macros for calculating offsets within the page directory base
23
 * and page tables. Note that these are assembler-specific hence
24
 * the '<<2'.
25
 */
26
#define PDO(a)		(((((a))>>22) & 0x03FF)<<2)
27
#define PTO(a)		(((((a))>>12) & 0x03FF)<<2)
28
 
29
TEXT m0rgdtptr(SB), $0
30
	WORD	$(NGDT*8-1)
31
	LONG	$(CPU0GDT-KZERO)
32
 
33
TEXT m0gdtptr(SB), $0
34
	WORD	$(NGDT*8-1)
35
	LONG	$CPU0GDT
36
 
37
TEXT m0idtptr(SB), $0
38
	WORD $(256*8-1)
39
	LONG $IDTADDR
40
 
41
/*
42
 * Save registers.
43
 */
44
TEXT saveregs(SB), $0
45
	/* appease 8l */
46
	SUBL $32, SP
47
	POPL AX
48
	POPL AX
49
	POPL AX
50
	POPL AX
51
	POPL AX
52
	POPL AX
53
	POPL AX
54
	POPL AX
55
 
56
	PUSHL	AX
57
	PUSHL	BX
58
	PUSHL	CX
59
	PUSHL	DX
60
	PUSHL	BP
61
	PUSHL	DI
62
	PUSHL	SI
63
	PUSHFL
64
 
65
	XCHGL	32(SP), AX	/* swap return PC and saved flags */
66
	XCHGL	0(SP), AX
67
	XCHGL	32(SP), AX
68
	RET
69
 
70
TEXT restoreregs(SB), $0
71
	/* appease 8l */
72
	PUSHL	AX
73
	PUSHL	AX
74
	PUSHL	AX
75
	PUSHL	AX
76
	PUSHL	AX
77
	PUSHL	AX
78
	PUSHL	AX
79
	PUSHL	AX
80
	ADDL	$32, SP
81
 
82
	XCHGL	32(SP), AX	/* swap return PC and saved flags */
83
	XCHGL	0(SP), AX
84
	XCHGL	32(SP), AX
85
 
86
	POPFL
87
	POPL	SI
88
	POPL	DI
89
	POPL	BP
90
	POPL	DX
91
	POPL	CX
92
	POPL	BX
93
	POPL	AX
94
	RET
95
 
96
/*
97
 * Assumed to be in protected mode at time of call.
98
 * Switch to real mode, execute an interrupt, and
99
 * then switch back to protected mode.  
100
 *
101
 * Assumes:
102
 *	- no device interrupts are going to come in
103
 *	- 0-16MB is identity mapped in page tables
104
 *	- l.s real-mode code is in low memory already but
105
 *	  may need to be copied into the first 64K (if loaded by pbs)
106
 *	- can use code segment rmseg in real mode to get at l.s code
107
 *	- the above Chinese puzzle pretty much forces RMUADDR to be 0x8000 or 0
108
 *	  and rmseg to be 0x800 or 0.
109
 */
110
 
111
TEXT realmodeidtptr(SB), $0
112
	WORD	$(4*256-1)
113
	LONG	$0
114
 
115
TEXT realmode0(SB), $0
116
	CALL	saveregs(SB)
117
 
118
	/* switch to low code address */
119
	LEAL	physcode-KZERO(SB), AX
120
	JMP *AX
121
 
122
TEXT physcode(SB), $0
123
 
124
	/* switch to low stack */
125
	MOVL	SP, AX
126
	MOVL	$RMSTACK, SP
127
	PUSHL	AX
128
 
129
	/* paranoia: make sure modified INT & JMPFAR instr.s are seen below */
130
	BYTE $0x0f; BYTE $0xae; BYTE $0xf8	/* SFENCE */
131
	BYTE $0x0f; BYTE $0xae; BYTE $0xe8	/* LFENCE */
132
	BYTE $0x0f; BYTE $0xae; BYTE $0xf0	/* MFENCE */
133
 
134
	/* change gdt to physical pointer */
135
	MOVL	m0rgdtptr-KZERO(SB), GDTR
136
 
137
	/* load IDT with real-mode version*/
138
	MOVL	realmodeidtptr-KZERO(SB), IDTR
139
 
140
	/* disable paging */
141
	MOVL	CR0, AX
142
	ANDL	$(~PG), AX
143
	MOVL	AX, CR0
144
	/* JMP .+2 to clear prefetch queue*/
145
	BYTE $0xEB; BYTE $0x00
146
 
147
	/* jump to 16-bit code segment */
148
/*	JMPFAR	SELECTOR(KESEG16, SELGDT, 0):$again16bit(SB) /**/
149
	 BYTE	$0xEA
150
	 LONG	$again16bit-KZERO(SB)
151
	 WORD	$SELECTOR(KESEG16, SELGDT, 0)
152
 
153
TEXT again16bit(SB), $0
154
	/*
155
	 * Now in 16-bit compatibility mode.
156
	 * These are 32-bit instructions being interpreted
157
	 * as 16-bit instructions.  I'm being lazy and
158
	 * not using the macros because I know when
159
	 * the 16- and 32-bit instructions look the same
160
	 * or close enough.
161
	 */
162
 
163
	/* disable protected mode and jump to real mode cs */
164
	OPSIZE; MOVL CR0, AX
165
	OPSIZE; XORL BX, BX
166
	OPSIZE; INCL BX
167
	OPSIZE; XORL BX, AX
168
	OPSIZE; MOVL AX, CR0
169
 
170
	/* JMPFAR rmseg:now16real */
171
	 BYTE $0xEA
172
	 WORD	$now16real-KZERO(SB)
173
TEXT rmseg(SB), $0
174
	 WORD	$0
175
 
176
TEXT now16real(SB), $0
177
	/* copy the registers for the bios call */
178
	CLR(rAX)
179
	MTSR(rAX, rSS)			/* 0000 -> rSS */
180
	LWI((RMSTACK-4), rSP)		/* preserve AX pushed in physcode */
181
 
182
	LWI((RMUADDR-KZERO), rBP)
183
 
184
	/* offsets are in Ureg */
185
	LXW(44, xBP, rAX)
186
	MOVW	AX, DS
187
	LXW(40, xBP, rAX)
188
	MOVW	AX, ES
189
 
190
	OPSIZE; LXW(0, xBP, rDI)
191
	OPSIZE; LXW(4, xBP, rSI)
192
	OPSIZE; LXW(16, xBP, rBX)
193
	OPSIZE; LXW(20, xBP, rDX)
194
	OPSIZE; LXW(24, xBP, rCX)
195
	OPSIZE; LXW(28, xBP, rAX)
196
 
197
	CLC
198
 
199
	/* assume that SP and SS persist across INT */
200
 
201
TEXT realmodeintrinst(SB), $0
202
	INT $0x00
203
	CLI			/* who knows what evil the bios got up to */
204
	/* save the registers after the call */
205
 
206
//	CLR(rBP)
207
//	MTSR(rBP, rSS)			/* 0000 -> rSS */
208
//	LWI((RMSTACK-4), rSP)
209
 
210
	OPSIZE; PUSHFL
211
	OPSIZE; PUSHL AX
212
 
213
	LWI((RMUADDR-KZERO), rBP)
214
	OPSIZE; SXW(rDI, 0, xBP)
215
	OPSIZE; SXW(rSI, 4, xBP)
216
	OPSIZE; SXW(rBX, 16, xBP)
217
	OPSIZE; SXW(rDX, 20, xBP)
218
	OPSIZE; SXW(rCX, 24, xBP)
219
	OPSIZE; POPL AX
220
	OPSIZE; SXW(rAX, 28, xBP)
221
 
222
	MOVW	DS, AX
223
	OPSIZE; SXW(rAX, 44, xBP)
224
	MOVW	ES, AX
225
	OPSIZE; SXW(rAX, 40, xBP)
226
 
227
	OPSIZE; POPL AX
228
	OPSIZE; SXW(rAX, 64, xBP)	/* flags */
229
 
230
	/* re-enter protected mode and jump to 32-bit code */
231
	OPSIZE; MOVL $1, AX
232
	OPSIZE; MOVL AX, CR0
233
 
234
/*	JMPFAR	SELECTOR(KESEG, SELGDT, 0):$again32bit(SB) /**/
235
	 OPSIZE
236
	 BYTE $0xEA
237
	 LONG	$again32bit-KZERO(SB)
238
	 WORD	$SELECTOR(KESEG, SELGDT, 0)
239
 
240
TEXT again32bit(SB), $0
241
	MOVW	$SELECTOR(KDSEG, SELGDT, 0),AX
242
	MOVW	AX,DS
243
	MOVW	AX,SS
244
	MOVW	AX,ES
245
	MOVW	AX,FS
246
	MOVW	AX,GS
247
 
248
	/* enable paging and jump to kzero-address code */
249
	MOVL	CR0, AX
250
	ORL	$(PG|0x10000), AX	/* PG|WP */
251
	MOVL	AX, CR0
252
	LEAL	again32kzero(SB), AX
253
	JMP*	AX
254
 
255
TEXT again32kzero(SB), $0
256
	/* breathe a sigh of relief - back in 32-bit protected mode */
257
 
258
	/* switch to old stack */	
259
	PUSHL	AX	/* match popl below for 8l */
260
	MOVL	$(RMSTACK-4), SP
261
	POPL	SP
262
 
263
	/* restore idt */
264
	MOVL	m0idtptr(SB),IDTR
265
 
266
	/* restore gdt */
267
	MOVL	m0gdtptr(SB), GDTR
268
 
269
	CALL	restoreregs(SB)
270
	RET
271
 
272
TEXT realmodeend(SB), $0
273
 
274
/*
275
 * Must be 4-byte aligned & within 8K of the image's start to be seen.
276
 */
277
	NOP
278
	NOP
279
	NOP
280
TEXT _multibootheader(SB), $0			/* CHECK alignment (4) */
281
	LONG	$0x1BADB002			/* magic */
282
	LONG	$0x00010003			/* flags */
283
	LONG	$-(0x1BADB002 + 0x00010003)	/* checksum */
284
	LONG	$_multibootheader-KZERO(SB)	/* header_addr */
285
	LONG	$_start32p-KZERO(SB)		/* load_addr */
286
	LONG	$edata-KZERO(SB)		/* load_end_addr */
287
	LONG	$end-KZERO(SB)			/* bss_end_addr */
288
	LONG	$_start32p-KZERO(SB)		/* entry_addr */
289
	LONG	$0				/* mode_type */
290
	LONG	$0				/* width */
291
	LONG	$0				/* height */
292
	LONG	$0				/* depth */
293
 
294
	LONG	$0				/* +48: saved AX - magic */
295
	LONG	$0				/* +52: saved BX - info* */
296
 
297
/*
298
 * There's no way with 8[al] to make this into local data, hence
299
 * the TEXT definitions. Also, it should be in the same segment as
300
 * the LGDT instruction.
301
 * In real mode only 24-bits of the descriptor are loaded so the
302
 * -KZERO is superfluous for the usual mappings.
303
 * The segments are
304
 *	NULL
305
 *	DATA 32b 4GB PL0
306
 *	EXEC 32b 4GB PL0
307
 *	EXEC 16b 4GB PL0
308
 */
309
TEXT _gdt16r(SB), $0
310
	LONG $0x0000; LONG $0
311
	LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
312
	LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
313
	LONG $0xFFFF; LONG $(SEGG     |(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
314
TEXT _gdtptr16r(SB), $0
315
	WORD	$(4*8)
316
	LONG	$_gdt16r-KZERO(SB)