summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/prefix/libprefix.S5
-rw-r--r--src/arch/i386/transitions/librm.S19
-rw-r--r--src/arch/i386/transitions/librm_mgmt.c3
3 files changed, 22 insertions, 5 deletions
diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S
index 197a86bc8..3aee415f5 100644
--- a/src/arch/i386/prefix/libprefix.S
+++ b/src/arch/i386/prefix/libprefix.S
@@ -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 */
diff --git a/src/arch/i386/transitions/librm.S b/src/arch/i386/transitions/librm.S
index 0d8110ac1..eaf520b3e 100644
--- a/src/arch/i386/transitions/librm.S
+++ b/src/arch/i386/transitions/librm.S
@@ -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
diff --git a/src/arch/i386/transitions/librm_mgmt.c b/src/arch/i386/transitions/librm_mgmt.c
index dee143572..f90d49b02 100644
--- a/src/arch/i386/transitions/librm_mgmt.c
+++ b/src/arch/i386/transitions/librm_mgmt.c
@@ -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