Browse Source

[librm] Use genuine real mode to accelerate operation in virtual machines

We currently use flat real mode wherever real mode is required.  This
guarantees that we will not surprise some unsuspecting external caller
which has carefully set up flat real mode by suddenly reducing the
segment limits to 64kB.

However, operating in flat real mode imposes a severe performance
penalty in some virtualisation environments, since some CPUs cannot
fully virtualise flat real mode and so the hypervisor must fall back
to emulation.  In particular, operating under KVM on a pre-Westmere
Intel CPU will be at least an order of magnitude slower, to the point
that there is a visible teletype effect when printing anything to the
BIOS console.  (Older versions of KVM used to cheat and ignore the
"flat" part of flat real mode, which masked the problem.)

Switch (back) to using genuine real mode with 64kB segment limits
instead of flat real mode.  Hopefully this won't break anything.

Add an explicit switch to flat real mode before returning to the BIOS
from the ROM prefix, since we know that a PMM BIOS will call the ROM
initialisation point (and potentially the BEV) in flat real mode.

As noted in previous commit messages, it is not possible to restore
the real-mode segment limits after a transition to protected mode,
since there is no way to know which protected-mode segment descriptor
was originally used to initialise the limit portion of the segment
register.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
6d4deeeb6c
2 changed files with 38 additions and 5 deletions
  1. 3
    0
      src/arch/i386/prefix/romprefix.S
  2. 35
    5
      src/arch/i386/transitions/librm.S

+ 3
- 0
src/arch/i386/prefix/romprefix.S View File

754
 	call	prot_call
754
 	call	prot_call
755
 	popl	%eax /* discard */
755
 	popl	%eax /* discard */
756
 
756
 
757
+	/* Set up flat real mode for return to BIOS */
758
+	call	flatten_real_mode
759
+
757
 	/* Uninstall iPXE */
760
 	/* Uninstall iPXE */
758
 	call	uninstall
761
 	call	uninstall
759
 
762
 

+ 35
- 5
src/arch/i386/transitions/librm.S View File

66
 	.byte	0, 0x93, 0xcf, 0	
66
 	.byte	0, 0x93, 0xcf, 0	
67
 
67
 
68
 	.org	gdt + REAL_CS, 0
68
 	.org	gdt + REAL_CS, 0
69
-real_cs: 	/* 16 bit flat real mode code segment */
69
+real_cs: 	/* 16 bit real mode code segment */
70
 	.word	0xffff, 0
70
 	.word	0xffff, 0
71
-	.byte	0, 0x9b, 0x8f, 0
71
+	.byte	0, 0x9b, 0x00, 0
72
 
72
 
73
 	.org	gdt + REAL_DS	
73
 	.org	gdt + REAL_DS	
74
-real_ds:	/* 16 bit flat real mode data segment */
74
+real_ds:	/* 16 bit real mode data segment */
75
 	.word	0xffff, 0
75
 	.word	0xffff, 0
76
-	.byte	0, 0x93, 0x8f, 0
77
-	
76
+	.byte	0, 0x93, 0x00, 0
77
+
78
 gdt_end:
78
 gdt_end:
79
 	.equ	gdt_length, gdt_end - gdt
79
 	.equ	gdt_length, gdt_end - gdt
80
 
80
 
506
 	.section ".data16", "aw", @progbits
506
 	.section ".data16", "aw", @progbits
507
 rc_function:	.word 0, 0
507
 rc_function:	.word 0, 0
508
 
508
 
509
+/****************************************************************************
510
+ * flatten_real_mode (real-mode near call)
511
+ *
512
+ * Switch to flat real mode
513
+ *
514
+ ****************************************************************************
515
+ */
516
+	.section ".text16", "ax", @progbits
517
+	.code16
518
+	.globl flatten_real_mode
519
+flatten_real_mode:
520
+	/* Modify GDT to use flat real mode */
521
+	movb	$0x8f, real_cs + 6
522
+	movb	$0x8f, real_ds + 6
523
+	/* Call dummy protected-mode function */
524
+	pushl	$flatten_dummy
525
+	pushw	%cs
526
+	call	prot_call
527
+	addw	$4, %sp
528
+	/* Restore GDT */
529
+	movb	$0x00, real_cs + 6
530
+	movb	$0x00, real_ds + 6
531
+	/* Return */
532
+	ret
533
+
534
+	.section ".text", "ax", @progbits
535
+	.code32
536
+flatten_dummy:
537
+	ret
538
+
509
 /****************************************************************************
539
 /****************************************************************************
510
  * Stored real-mode and protected-mode stack pointers
540
  * Stored real-mode and protected-mode stack pointers
511
  *
541
  *

Loading…
Cancel
Save