Skip to content

Commit

Permalink
[librm] Speed up real-to-protected mode transition under KVM
Browse files Browse the repository at this point in the history
Ensure that all segment registers have zero in the low two bits before
transitioning to protected mode.  This allows the CPU state to
immediately be deemed to be "valid", and eliminates the need for any
further emulated instructions.

Load the protected-mode interrupt descriptor table after switching to
protected mode, since this avoids triggering an EXCEPTION_NMI and
corresponding VM exit.

This reduces the time taken by real_to_prot under KVM by around 50%.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed May 2, 2014
1 parent 5a08b63 commit c64747d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 5 deletions.
5 changes: 4 additions & 1 deletion src/arch/i386/prefix/libprefix.S
Expand Up @@ -522,8 +522,11 @@ alloc_basemem:
subw $_data16_memsz_pgh, %ax
pushw %ax

/* Calculate .text16 segment address */
/* Calculate .text16 segment address. Round down to ensure
* low bits are zero, to speed up mode transitions under KVM.
*/
subw $_text16_memsz_pgh, %ax
andb $~0x03, %al
pushw %ax

/* Update FBMS */
Expand Down
19 changes: 17 additions & 2 deletions src/arch/i386/transitions/librm.S
Expand Up @@ -200,10 +200,22 @@ real_to_prot:
addr32 leal (%eax,%edx), %esi
subl rm_virt_offset, %esi

/* Load protected-mode global descriptor table */
data32 lgdt gdtr

/* Zero segment registers. This wastes around 12 cycles on
* real hardware, but saves a substantial number of emulated
* instructions under KVM.
*/
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss

/* Switch to protected mode */
cli
data32 lgdt gdtr
data32 lidt idtr
movl %cr0, %eax
orb $CR0_PE, %al
movl %eax, %cr0
Expand All @@ -220,6 +232,9 @@ r2p_pmode:
movw %ax, %ss
movl pm_esp, %esp

/* Load protected-mode interrupt descriptor table */
lidt idtr

/* Record real-mode %ss:sp (after removal of data) */
movw %bp, rm_ss
addl %ecx, %edx
Expand Down
3 changes: 1 addition & 2 deletions src/arch/i386/transitions/librm_mgmt.c
Expand Up @@ -26,10 +26,9 @@ static struct interrupt_vector intr_vec[ IRQ_MAX + 1 ];
struct interrupt_descriptor idt[NUM_INT] __attribute__ (( aligned ( 16 ) ));

/** The interrupt descriptor table register */
struct idtr __data16 ( idtr ) = {
struct idtr idtr = {
.limit = ( sizeof ( idt ) - 1 ),
};
#define idtr __use_data16 ( idtr )

/**
* Allocate space on the real-mode stack and copy data there from a
Expand Down

0 comments on commit c64747d

Please sign in to comment.