]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[librm] Speed up real-to-protected mode transition under KVM
authorMichael Brown <mcb30@ipxe.org>
Fri, 2 May 2014 12:18:55 +0000 (13:18 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 2 May 2014 14:23:21 +0000 (15:23 +0100)
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>
src/arch/i386/prefix/libprefix.S
src/arch/i386/transitions/librm.S
src/arch/i386/transitions/librm_mgmt.c

index 197a86bc8e8a9b8215878a20c469ea84dba960c6..3aee415f5a1ed2f04eeab685961b732b0e459626 100644 (file)
@@ -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 */
index 0d8110ac1ab48c6a8d051acd2eb916300e34f584..eaf520b3e9a91399dfdcf12c8293e41537f3c203 100644 (file)
@@ -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
@@ -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
index dee14357221586a07fe8f49abf4df633bc56701a..f90d49b02af41fddba5f30e34840756fb44369cd 100644 (file)
@@ -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