Skip to content

Commit

Permalink
[librm] Use genuine real mode to accelerate operation in virtual mach…
Browse files Browse the repository at this point in the history
…ines

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>
  • Loading branch information
mcb30 committed Apr 28, 2014
1 parent b2c7b6a commit 6d4deee
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/arch/i386/prefix/romprefix.S
Expand Up @@ -754,6 +754,9 @@ exec: /* Set %ds = %cs */
call prot_call
popl %eax /* discard */

/* Set up flat real mode for return to BIOS */
call flatten_real_mode

/* Uninstall iPXE */
call uninstall

Expand Down
40 changes: 35 additions & 5 deletions src/arch/i386/transitions/librm.S
Expand Up @@ -66,15 +66,15 @@ physical_ds: /* 32 bit protected mode data segment, physical addresses */
.byte 0, 0x93, 0xcf, 0

.org gdt + REAL_CS, 0
real_cs: /* 16 bit flat real mode code segment */
real_cs: /* 16 bit real mode code segment */
.word 0xffff, 0
.byte 0, 0x9b, 0x8f, 0
.byte 0, 0x9b, 0x00, 0

.org gdt + REAL_DS
real_ds: /* 16 bit flat real mode data segment */
real_ds: /* 16 bit real mode data segment */
.word 0xffff, 0
.byte 0, 0x93, 0x8f, 0
.byte 0, 0x93, 0x00, 0

gdt_end:
.equ gdt_length, gdt_end - gdt

Expand Down Expand Up @@ -506,6 +506,36 @@ real_call:
.section ".data16", "aw", @progbits
rc_function: .word 0, 0

/****************************************************************************
* flatten_real_mode (real-mode near call)
*
* Switch to flat real mode
*
****************************************************************************
*/
.section ".text16", "ax", @progbits
.code16
.globl flatten_real_mode
flatten_real_mode:
/* Modify GDT to use flat real mode */
movb $0x8f, real_cs + 6
movb $0x8f, real_ds + 6
/* Call dummy protected-mode function */
pushl $flatten_dummy
pushw %cs
call prot_call
addw $4, %sp
/* Restore GDT */
movb $0x00, real_cs + 6
movb $0x00, real_ds + 6
/* Return */
ret

.section ".text", "ax", @progbits
.code32
flatten_dummy:
ret

/****************************************************************************
* Stored real-mode and protected-mode stack pointers
*
Expand Down

0 comments on commit 6d4deee

Please sign in to comment.