Bladeren bron

Add infrastructure to support access to .data16 (and .text16) variables

from protected-mode code.

Set up %ds to point to .data16 in prot_to_real, so that code specified
via REAL_EXEC() and friends can access variables in .data16.

Move most real-mode librm variables from .text16 to .data16.
tags/v0.9.3
Michael Brown 18 jaren geleden
bovenliggende
commit
832807726a
2 gewijzigde bestanden met toevoegingen van 125 en 76 verwijderingen
  1. 3
    2
      src/arch/i386/prefix/libprefix.S
  2. 122
    74
      src/arch/i386/transitions/librm.S

+ 3
- 2
src/arch/i386/prefix/libprefix.S Bestand weergeven

@@ -336,6 +336,7 @@ install_prealloc:
336 336
 	call	install_highmem
337 337
 
338 338
 	/* Continue executing in .text16 segment */
339
+	movw	%bx, %ds
339 340
 	pushw	%cs
340 341
 	pushw	$2f
341 342
 	pushw	%ax
@@ -344,11 +345,11 @@ install_prealloc:
344 345
 	.section ".text16", "awx", @progbits
345 346
 1:
346 347
 	/* Set up protected-mode GDT, call relocate(), reset GDT */
347
-	call	init_gdt
348
+	call	init_librm
348 349
 	pushl	$relocate
349 350
 	data32 call	prot_call
350 351
 	addw	$4, %sp
351
-	call	init_gdt
352
+	call	init_librm
352 353
 
353 354
 	/* Return to executing in .prefix section */
354 355
 	lret

+ 122
- 74
src/arch/i386/transitions/librm.S Bestand weergeven

@@ -24,7 +24,7 @@
24 24
 /****************************************************************************
25 25
  * Global descriptor table
26 26
  *
27
- * Call init_gdt to set up the GDT before attempting to use any
27
+ * Call init_librm to set up the GDT before attempting to use any
28 28
  * protected-mode code.
29 29
  *
30 30
  * Define FLATTEN_REAL_MODE if you want to use so-called "flat real
@@ -45,7 +45,7 @@
45 45
 #else
46 46
 #define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
47 47
 #endif
48
-	.section ".text16"
48
+	.section ".data16", "aw", @progbits
49 49
 	.align 16
50 50
 gdt:
51 51
 gdt_limit:		.word gdt_length - 1
@@ -86,56 +86,71 @@ gdt_end:
86 86
 	.equ	gdt_length, gdt_end - gdt
87 87
 
88 88
 /****************************************************************************
89
- * init_gdt (real-mode near call, 16-bit real-mode return address)
89
+ * init_librm (real-mode near call, 16-bit real-mode return address)
90 90
  *
91 91
  * Initialise the GDT ready for transitions to protected mode.
92 92
  *
93
- * Parameters: 
94
- *   %edi : Physical base of protected-mode code
93
+ * Parameters:
94
+ *   %cs : .text16 segment
95
+ *   %ds : .data16 segment
96
+ *   %edi : Physical base of protected-mode code (virt_offset)
95 97
  ****************************************************************************
96 98
  */
97 99
 	.section ".text16"
98 100
 	.code16
99
-	.globl init_gdt
100
-init_gdt:
101
+	.globl init_librm
102
+init_librm:
101 103
 	/* Preserve registers */
102 104
 	pushl	%eax
103
-	pushw	%bx
104
-
105
-	/* Record virt_offset */
106
-	movl	%edi, %cs:virt_offset_rm_copy
105
+	pushl	%ebx
107 106
 
108
-	/* Set virtual_cs and virtual_ds base */
107
+	/* Store _virt_offset and set up virtual_cs and virtual_ds segments */
109 108
 	movl	%edi, %eax
110 109
 	movw	$virtual_cs, %bx
111 110
 	call	set_seg_base
112
-
113
-	/* Set real_cs and real_ds base, and GDT base */
114
-	movw	$real_cs, %bx
111
+	movw	$virtual_ds, %bx
112
+	call	set_seg_base	
113
+	movl	%edi, _virt_offset
114
+
115
+	/* Negate virt_offset */
116
+	negl	%edi
117
+		
118
+	/* Store rm_cs and _text16, set up real_cs segment */
115 119
 	xorl	%eax, %eax
116 120
 	movw	%cs, %ax
121
+	movw	%ax, rm_cs
117 122
 	shll	$4, %eax
123
+	movw	$real_cs, %bx
118 124
 	call	set_seg_base
119
-	addl	$gdt, %eax
120
-	movl	%eax, %cs:gdt_base
125
+	leal	(%eax, %edi), %ebx
126
+	movl	%ebx, _text16
121 127
 
128
+	/* Store rm_ds and _data16, set up real_ds segment and set GDT base */
129
+	xorl	%eax, %eax
130
+	movw	%ds, %ax
131
+	movw	%ax, %cs:rm_ds
132
+	shll	$4, %eax
133
+	movw	$real_ds, %bx
134
+	call	set_seg_base
135
+	leal	(%eax, %edi), %ebx
136
+	movl	%ebx, _data16
137
+	addl	$gdt, %eax
138
+	movl	%eax, gdt_base
139
+		
122 140
 	/* Restore registers */
123
-	popw	%bx
141
+	negl	%edi
142
+	popl	%ebx
124 143
 	popl	%eax
125 144
 	ret
126 145
 
127 146
 	.section ".text16"
128 147
 	.code16
129 148
 set_seg_base:
130
-	pushl	%eax
131
-	movw	%ax, %cs:(0+2)(%bx)
132
-	movw	%ax, %cs:(8+2)(%bx)
133
-	shrl	$16, %eax
134
-	movb	%al, %cs:(0+4)(%bx)
135
-	movb	%al, %cs:(8+4)(%bx)
136
-	movb	%ah, %cs:(0+7)(%bx)
137
-	movb	%ah, %cs:(8+7)(%bx)
138
-	popl	%eax
149
+1:	movw	%ax, 2(%bx)
150
+	rorl	$16, %eax
151
+	movb	%al, 4(%bx)
152
+	movb	%ah, 7(%bx)
153
+	roll	$16, %eax
139 154
 	ret
140 155
 	
141 156
 /****************************************************************************
@@ -157,19 +172,25 @@ set_seg_base:
157 172
 	.section ".text16"
158 173
 	.code16
159 174
 real_to_prot:
160
-	/* Protected-mode return address => %ebx */
161
-	popl	%ebx
162
-
163
-	/* Real-mode %cs => %dx, %ss => %bp */
164
-	movw	%cs, %dx
175
+	/* Make sure we have our data segment available */
176
+	movw	%cs:rm_ds, %ax
177
+	movw	%ax, %ds
178
+	
179
+	/* Add _virt_offset, _text16 and _data16 to stack to be
180
+	 * copied, and also copy the return address.
181
+	 */
182
+	pushl	_virt_offset
183
+	pushl	_text16
184
+	pushl	_data16
185
+	addw	$16, %cx /* %ecx must be less than 64kB anyway */
186
+	
187
+	/* Real-mode %ss:%sp => %bp:%esi */
165 188
 	movw	%ss, %bp
166
-
167
-	/* virt_offset => %edi */
168
-	movl	%cs:virt_offset_rm_copy, %edi
189
+	movzwl	%sp, %esi
169 190
 
170 191
 	/* Switch to protected mode */
171 192
 	cli
172
-	data32 lgdt	%cs:gdt
193
+	data32 lgdt	gdt
173 194
 	movl	%cr0, %eax
174 195
 	orb	$CR0_PE, %al
175 196
 	movl	%eax, %cr0
@@ -184,24 +205,24 @@ real_to_prot:
184 205
 	movw	%ax, %fs
185 206
 	movw	%ax, %gs
186 207
 
187
-	/* Record virt_offset */
188
-	movl	%edi, virt_offset
189
-
190 208
 	/* Move data from RM stack to PM stack and set up PM stack */
191
-	movzwl	%sp, %esi
192 209
 	movl	pm_esp, %esp
193 210
 	subl	%ecx, %esp
194 211
 	movl	%esp, %edi
195 212
 	rep ss movsb
196 213
 	movw	%ax, %ss
197 214
 
198
-	/* Record real-mode %cs and %ss:sp */
199
-	movw	%dx, rm_cs
215
+	/* Record real-mode %ss:sp (after removal of data) */
200 216
 	movw	%bp, rm_ss
201 217
 	movw	%si, rm_sp
202 218
 
219
+	/* Publish virt_offset, text16 and data16 for PM code to use */
220
+	popl	data16
221
+	popl	text16
222
+	popl	virt_offset
223
+
203 224
 	/* Return to virtual address */
204
-	jmp	*%ebx
225
+	ret
205 226
 
206 227
 /****************************************************************************
207 228
  * prot_to_real (protected-mode near call, 32-bit real-mode return address)
@@ -209,9 +230,9 @@ real_to_prot:
209 230
  * Switch from 32-bit protected mode with virtual addresses to 16-bit
210 231
  * real mode.  The protected-mode %esp is stored in pm_esp and the
211 232
  * real-mode %ss:sp is restored from the saved rm_ss and rm_sp.  All
212
- * real-mode data segment registers are set equal to %ss.  Interrupts
213
- * are *not* enabled, since we want to be able to use prot_to_real in
214
- * an ISR.  All other registers may be destroyed.
233
+ * real-mode data segment registers are loaded from the saved rm_ds.
234
+ * Interrupts are *not* enabled, since we want to be able to use
235
+ * prot_to_real in an ISR.  All other registers may be destroyed.
215 236
  *
216 237
  * The return address for this function should be a 32-bit (sic)
217 238
  * real-mode offset within .code16.
@@ -224,15 +245,15 @@ real_to_prot:
224 245
 	.section ".text"
225 246
 	.code32
226 247
 prot_to_real:
227
-	/* Real-mode return address => %ebx */
228
-	popl	%ebx
248
+	/* Add return address to data to be moved to RM stack */
249
+	addl	$4, %ecx
229 250
 	
230 251
 	/* Real-mode %ss:sp => %ebp:edx */
231 252
 	movzwl	rm_ss, %ebp
232 253
 	movzwl	rm_sp, %edx
233 254
 	subl	%ecx, %edx
234 255
 	
235
-	/* Copy data from PM stack to RM stack */
256
+	/* Move data from PM stack to RM stack */
236 257
 	movl	%ebp, %eax
237 258
 	shll	$4, %eax
238 259
 	leal	(%eax,%edx), %edi
@@ -240,12 +261,9 @@ prot_to_real:
240 261
 	movl	%esp, %esi
241 262
 	rep movsb
242 263
 	
243
-	/* Record protected-mode %esp */
264
+	/* Record protected-mode %esp (after removal of data) */
244 265
 	movl	%esi, pm_esp
245 266
 
246
-	/* Real-mode %cs => %di */
247
-	movw	rm_cs, %di
248
-
249 267
 	/* Load real-mode segment limits */
250 268
 	movw	$REAL_DS, %ax
251 269
 	movw	%ax, %ds
@@ -257,27 +275,40 @@ prot_to_real:
257 275
 	.section ".text16"
258 276
 	.code16
259 277
 1:
260
-	/* Set up real-mode ljmp instruction */
261
-	movw	%di, %ds:(p2r_ljmp + 3)
262
-	
263 278
 	/* Switch to real mode */
264 279
 	movl	%cr0, %eax
265 280
 	andb	$0!CR0_PE, %al
266 281
 	movl	%eax, %cr0
282
+	ljmp	*p2r_jump_vector
283
+p2r_jump_target:
267 284
 
268
-p2r_ljmp:
269
-	ljmp	$0, $1f /* Segment is filled in by above code */
270
-1:
271
-	/* Set up real-mode stack and data segments, and stack pointer */
272
-	movw	%bp, %ds
273
-	movw	%bp, %es
274
-	movw	%bp, %fs
275
-	movw	%bp, %gs
285
+	/* Set up real-mode stack */
276 286
 	movw	%bp, %ss
277 287
 	movw	%dx, %sp
288
+	
289
+	/* Set up real-mode data segments */
290
+	movw	%cs:rm_ds, %ax
291
+	movw	%ax, %ds
292
+	movw	%ax, %es
293
+	movw	%ax, %fs
294
+	movw	%ax, %gs
278 295
 
279 296
 	/* Return to real-mode address */
280
-	jmp	*%bx
297
+	data32 ret
298
+
299
+
300
+	/* Real-mode code and data segments.  Assigned by the call to
301
+	 * init_librm.  rm_cs doubles as the segment part of the jump
302
+	 * vector used by prot_to_real.  rm_ds is located in .text16
303
+	 * rather than .data16 because code needs to be able to locate
304
+	 * the data segment.
305
+	 */
306
+	.section ".data16"
307
+p2r_jump_vector:
308
+	.word	p2r_jump_target
309
+rm_cs:	.word 0
310
+	.section ".text16"
311
+rm_ds:	.word 0
281 312
 	
282 313
 /****************************************************************************
283 314
  * prot_call (real-mode near call, 32-bit real-mode return address)
@@ -406,11 +437,12 @@ real_call:
406 437
 	/* Construct call to real-mode function */
407 438
 	movw	%sp, %bp
408 439
 	movw	RC_OFFSET_FUNCTION(%bp), %ax
409
-	movw	%ax, %cs:rc_function
440
+	movw	%ax, rc_function
410 441
 
411 442
 	/* Call real-mode function */
412 443
 	popal
413
-	call	*%cs:rc_function
444
+	call	*RC_OFFSET_FUNCTION(%esp)
445
+	call	*rc_function
414 446
 	pushal
415 447
 
416 448
 	/* Switch to protected mode and move register dump back to PM stack */
@@ -427,7 +459,9 @@ real_call:
427 459
 	popal
428 460
 	ret
429 461
 
430
-	.section ".text16"
462
+
463
+	/* Function vector, used because */
464
+	.section ".data16"
431 465
 rc_function:	.word 0
432 466
 	
433 467
 /****************************************************************************
@@ -464,19 +498,33 @@ rc_function:	.word 0
464 498
  * to us.
465 499
  ****************************************************************************
466 500
  */
467
-
468 501
 	.section ".data"
469 502
 	.globl rm_sp
470 503
 rm_sp:	.word 0
471 504
 	.globl rm_ss
472 505
 rm_ss:	.word 0
473
-	.globl rm_cs
474
-rm_cs:	.word 0
475 506
 	.globl pm_esp
476 507
 pm_esp:	.long _estack
477 508
 
478
-	.section ".text16"
479
-virt_offset_rm_copy:	.long 0
509
+/****************************************************************************
510
+ * Virtual address offsets
511
+ *
512
+ * These are used by the protected-mode code to map between virtual
513
+ * and physical addresses, and to access variables in the .text16 or
514
+ * .data16 segments.
515
+ ****************************************************************************
516
+ */
517
+	/* Internal copies, created by init_librm (which runs in real mode) */
518
+	.section ".data16"
519
+_virt_offset:	.long 0
520
+_text16:	.long 0
521
+_data16:	.long 0
522
+
523
+	/* Externally-visible copies, created by real_to_prot */
480 524
 	.section ".data"
481 525
 	.globl virt_offset
482
-virt_offset:		.long 0	
526
+virt_offset:	.long 0	
527
+	.globl text16
528
+text16:		.long 0
529
+	.globl data16
530
+data16:		.long 0

Laden…
Annuleren
Opslaan