Browse Source

[librm] Speed up real-to-protected mode transition under KVM

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>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
c64747db50

+ 4
- 1
src/arch/i386/prefix/libprefix.S View File

522
 	subw	$_data16_memsz_pgh, %ax
522
 	subw	$_data16_memsz_pgh, %ax
523
 	pushw	%ax
523
 	pushw	%ax
524
 
524
 
525
-	/* Calculate .text16 segment address */
525
+	/* Calculate .text16 segment address.  Round down to ensure
526
+	 * low bits are zero, to speed up mode transitions under KVM.
527
+	 */
526
 	subw	$_text16_memsz_pgh, %ax
528
 	subw	$_text16_memsz_pgh, %ax
529
+	andb	$~0x03, %al
527
 	pushw	%ax
530
 	pushw	%ax
528
 
531
 
529
 	/* Update FBMS */
532
 	/* Update FBMS */

+ 17
- 2
src/arch/i386/transitions/librm.S View File

200
 	addr32 leal (%eax,%edx), %esi
200
 	addr32 leal (%eax,%edx), %esi
201
 	subl	rm_virt_offset, %esi
201
 	subl	rm_virt_offset, %esi
202
 
202
 
203
+	/* Load protected-mode global descriptor table */
204
+	data32 lgdt gdtr
205
+
206
+	/* Zero segment registers.  This wastes around 12 cycles on
207
+	 * real hardware, but saves a substantial number of emulated
208
+	 * instructions under KVM.
209
+	 */
210
+	xorw	%ax, %ax
211
+	movw	%ax, %ds
212
+	movw	%ax, %es
213
+	movw	%ax, %fs
214
+	movw	%ax, %gs
215
+	movw	%ax, %ss
216
+
203
 	/* Switch to protected mode */
217
 	/* Switch to protected mode */
204
 	cli
218
 	cli
205
-	data32 lgdt gdtr
206
-	data32 lidt idtr
207
 	movl	%cr0, %eax
219
 	movl	%cr0, %eax
208
 	orb	$CR0_PE, %al
220
 	orb	$CR0_PE, %al
209
 	movl	%eax, %cr0
221
 	movl	%eax, %cr0
220
 	movw	%ax, %ss
232
 	movw	%ax, %ss
221
 	movl	pm_esp, %esp
233
 	movl	pm_esp, %esp
222
 
234
 
235
+	/* Load protected-mode interrupt descriptor table */
236
+	lidt	idtr
237
+
223
 	/* Record real-mode %ss:sp (after removal of data) */
238
 	/* Record real-mode %ss:sp (after removal of data) */
224
 	movw	%bp, rm_ss
239
 	movw	%bp, rm_ss
225
 	addl	%ecx, %edx
240
 	addl	%ecx, %edx

+ 1
- 2
src/arch/i386/transitions/librm_mgmt.c View File

26
 struct interrupt_descriptor idt[NUM_INT] __attribute__ (( aligned ( 16 ) ));
26
 struct interrupt_descriptor idt[NUM_INT] __attribute__ (( aligned ( 16 ) ));
27
 
27
 
28
 /** The interrupt descriptor table register */
28
 /** The interrupt descriptor table register */
29
-struct idtr __data16 ( idtr ) = {
29
+struct idtr idtr = {
30
 	.limit = ( sizeof ( idt ) - 1 ),
30
 	.limit = ( sizeof ( idt ) - 1 ),
31
 };
31
 };
32
-#define idtr __use_data16 ( idtr )
33
 
32
 
34
 /**
33
 /**
35
  * Allocate space on the real-mode stack and copy data there from a
34
  * Allocate space on the real-mode stack and copy data there from a

Loading…
Cancel
Save