Browse Source

Preserve the whole of %esp across prot_call(). We have to split this

between the low half stored in the static variable rm_sp, and the high
half stored on the prot_call() stack, because:

  Just using the stack would screw up when a prot_call()ed routine
  executes a real_call(); it would have no way to find the current top of
  the RM stack.

  Extending rm_sp to rm_esp would not be safe, because the guarantee that
  rm_sp must return to the correct value by the time an external
  real-mode call returns applies only to %sp, not to %esp.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
fdb983d473
1 changed files with 14 additions and 7 deletions
  1. 14
    7
      src/arch/i386/transitions/librm.S

+ 14
- 7
src/arch/i386/transitions/librm.S View File

@@ -229,10 +229,11 @@ real_to_prot:
229 229
  *
230 230
  * Switch from 32-bit protected mode with virtual addresses to 16-bit
231 231
  * real mode.  The protected-mode %esp is stored in pm_esp and the
232
- * real-mode %ss:sp is restored from the saved rm_ss and rm_sp.  All
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.
232
+ * real-mode %ss:sp is restored from the saved rm_ss and rm_sp.  The
233
+ * high word of the real-mode %esp is set to zero.  All real-mode data
234
+ * segment registers are loaded from the saved rm_ds.  Interrupts are
235
+ * *not* enabled, since we want to be able to use prot_to_real in an
236
+ * ISR.  All other registers may be destroyed.
236 237
  *
237 238
  * The return address for this function should be a 32-bit (sic)
238 239
  * real-mode offset within .code16.
@@ -284,7 +285,7 @@ p2r_jump_target:
284 285
 
285 286
 	/* Set up real-mode stack */
286 287
 	movw	%bp, %ss
287
-	movw	%dx, %sp
288
+	movl	%edx, %esp
288 289
 	
289 290
 	/* Set up real-mode data segments */
290 291
 	movw	%cs:rm_ds, %ax
@@ -321,7 +322,7 @@ rm_ds:	.word 0
321 322
  *
322 323
  * All registers will be preserved across prot_call(), unless the C
323 324
  * function explicitly overwrites values in ix86.  Interrupt status
324
- * will also be preserved.  Gate A20 will be enabled.
325
+ * and GDT will also be preserved.  Gate A20 will be enabled.
325 326
  *
326 327
  * Parameters:
327 328
  *   function : virtual address of protected-mode function to call
@@ -384,7 +385,9 @@ prot_call:
384 385
 	.section ".text16"
385 386
 	.code16
386 387
 1:	
387
-	/* Reload GDT, restore registers and flags and return */
388
+	/* Reload GDT, restore registers and flags and return.  Note
389
+	 * that %esp is restored manually, since popal discards it.
390
+	 */
388 391
 	movw	%sp, %bp
389 392
 	lgdt	(%bp)
390 393
 	addw	$12, %sp /* also skip %cs and %ss */
@@ -393,6 +396,10 @@ prot_call:
393 396
 	popw	%fs
394 397
 	popw	%gs
395 398
 	popal
399
+	movl	-20(%esp), %esp /* -20(%sp) is not a valid 80386 expression.
400
+				 * -20(%esp) is safe because prot_to_real
401
+				 * zeroes the high word of %esp, and interrupts
402
+				 * are still disabled at this point. */
396 403
 	popfl
397 404
 	data32 ret
398 405
 

Loading…
Cancel
Save