|
@@ -253,12 +253,6 @@ r2p_pmode:
|
253
|
253
|
/* Return to virtual address */
|
254
|
254
|
ret
|
255
|
255
|
|
256
|
|
- /* Default real-mode interrupt descriptor table */
|
257
|
|
- .section ".data", "aw", @progbits
|
258
|
|
-rm_idtr:
|
259
|
|
- .word 0xffff /* limit */
|
260
|
|
- .long 0 /* base */
|
261
|
|
-
|
262
|
256
|
/****************************************************************************
|
263
|
257
|
* prot_to_real (protected-mode near call, 32-bit real-mode return address)
|
264
|
258
|
*
|
|
@@ -275,12 +269,22 @@ rm_idtr:
|
275
|
269
|
*
|
276
|
270
|
* Parameters:
|
277
|
271
|
* %ecx : number of bytes to move from PM stack to RM stack
|
|
272
|
+ * %esi : real-mode global and interrupt descriptor table registers
|
278
|
273
|
*
|
279
|
274
|
****************************************************************************
|
280
|
275
|
*/
|
281
|
276
|
.section ".text", "ax", @progbits
|
282
|
277
|
.code32
|
283
|
278
|
prot_to_real:
|
|
279
|
+ /* Copy real-mode global descriptor table register to RM code segment */
|
|
280
|
+ movl text16, %edi
|
|
281
|
+ leal rm_gdtr(%edi), %edi
|
|
282
|
+ movsw
|
|
283
|
+ movsl
|
|
284
|
+
|
|
285
|
+ /* Load real-mode interrupt descriptor table register */
|
|
286
|
+ lidt (%esi)
|
|
287
|
+
|
284
|
288
|
/* Add return address to data to be moved to RM stack */
|
285
|
289
|
addl $4, %ecx
|
286
|
290
|
|
|
@@ -300,9 +304,6 @@ prot_to_real:
|
300
|
304
|
/* Record protected-mode %esp (after removal of data) */
|
301
|
305
|
movl %esi, pm_esp
|
302
|
306
|
|
303
|
|
- /* Reset IDTR to the real-mode defaults */
|
304
|
|
- lidt rm_idtr
|
305
|
|
-
|
306
|
307
|
/* Load real-mode segment limits */
|
307
|
308
|
movw $REAL_DS, %ax
|
308
|
309
|
movw %ax, %ds
|
|
@@ -314,6 +315,8 @@ prot_to_real:
|
314
|
315
|
.section ".text16", "ax", @progbits
|
315
|
316
|
.code16
|
316
|
317
|
p2r_rmode:
|
|
318
|
+ /* Load real-mode GDT */
|
|
319
|
+ data32 lgdt %cs:rm_gdtr
|
317
|
320
|
/* Switch to real mode */
|
318
|
321
|
movl %cr0, %eax
|
319
|
322
|
andb $0!CR0_PE, %al
|
|
@@ -349,6 +352,12 @@ p2r_ljmp_rm_cs:
|
349
|
352
|
.globl rm_ds
|
350
|
353
|
rm_ds: .word 0
|
351
|
354
|
|
|
355
|
+ /* Real-mode global and interrupt descriptor table registers */
|
|
356
|
+ .section ".text16.data", "aw", @progbits
|
|
357
|
+rm_gdtr:
|
|
358
|
+ .word 0 /* Limit */
|
|
359
|
+ .long 0 /* Base */
|
|
360
|
+
|
352
|
361
|
/****************************************************************************
|
353
|
362
|
* prot_call (real-mode far call, 16-bit real-mode far return address)
|
354
|
363
|
*
|
|
@@ -384,8 +393,8 @@ rm_ds: .word 0
|
384
|
393
|
*/
|
385
|
394
|
|
386
|
395
|
#define PC_OFFSET_GDT ( 0 )
|
387
|
|
-#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 8 /* pad to 8 to keep alignment */ )
|
388
|
|
-#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 8 /* pad to 8 to keep alignment */ )
|
|
396
|
+#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 6 )
|
|
397
|
+#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 6 )
|
389
|
398
|
#define PC_OFFSET_RETADDR ( PC_OFFSET_IX86 + SIZEOF_I386_ALL_REGS )
|
390
|
399
|
#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
|
391
|
400
|
#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 )
|
|
@@ -403,10 +412,10 @@ prot_call:
|
403
|
412
|
pushw %ds
|
404
|
413
|
pushw %ss
|
405
|
414
|
pushw %cs
|
406
|
|
- subw $16, %sp
|
|
415
|
+ subw $PC_OFFSET_IX86, %sp
|
407
|
416
|
movw %sp, %bp
|
408
|
|
- sidt 8(%bp)
|
409
|
|
- sgdt (%bp)
|
|
417
|
+ sidt PC_OFFSET_IDT(%bp)
|
|
418
|
+ sgdt PC_OFFSET_GDT(%bp)
|
410
|
419
|
|
411
|
420
|
/* For sanity's sake, clear the direction flag as soon as possible */
|
412
|
421
|
cld
|
|
@@ -426,16 +435,14 @@ pc_pmode:
|
426
|
435
|
|
427
|
436
|
/* Switch to real mode and move register dump back to RM stack */
|
428
|
437
|
movl $PC_OFFSET_END, %ecx
|
|
438
|
+ movl %esp, %esi
|
429
|
439
|
pushl $pc_rmode
|
430
|
440
|
jmp prot_to_real
|
431
|
441
|
.section ".text16", "ax", @progbits
|
432
|
442
|
.code16
|
433
|
443
|
pc_rmode:
|
434
|
|
- /* Reload GDT and IDT, restore registers and flags and return */
|
435
|
|
- movw %sp, %bp
|
436
|
|
- data32 lgdt (%bp)
|
437
|
|
- data32 lidt 8(%bp)
|
438
|
|
- addw $20, %sp /* also skip %cs and %ss */
|
|
444
|
+ /* Restore registers and flags and return */
|
|
445
|
+ addw $( PC_OFFSET_IX86 + 4 /* also skip %cs and %ss */ ), %sp
|
439
|
446
|
popw %ds
|
440
|
447
|
popw %es
|
441
|
448
|
popw %fs
|
|
@@ -489,6 +496,7 @@ real_call:
|
489
|
496
|
/* Switch to real mode and move register dump to RM stack */
|
490
|
497
|
movl $( RC_OFFSET_RETADDR + 4 /* function pointer copy */ ), %ecx
|
491
|
498
|
pushl $rc_rmode
|
|
499
|
+ movl $rm_default_gdtr_idtr, %esi
|
492
|
500
|
jmp prot_to_real
|
493
|
501
|
.section ".text16", "ax", @progbits
|
494
|
502
|
.code16
|
|
@@ -520,6 +528,14 @@ rc_pmode:
|
520
|
528
|
.section ".data16", "aw", @progbits
|
521
|
529
|
rc_function: .word 0, 0
|
522
|
530
|
|
|
531
|
+ /* Default real-mode global and interrupt descriptor table registers */
|
|
532
|
+ .section ".data", "aw", @progbits
|
|
533
|
+rm_default_gdtr_idtr:
|
|
534
|
+ .word 0 /* Global descriptor table limit */
|
|
535
|
+ .long 0 /* Global descriptor table base */
|
|
536
|
+ .word 0x03ff /* Interrupt descriptor table limit */
|
|
537
|
+ .long 0 /* Interrupt descriptor table base */
|
|
538
|
+
|
523
|
539
|
/****************************************************************************
|
524
|
540
|
* flatten_real_mode (real-mode near call)
|
525
|
541
|
*
|