mirror of
https://github.com/xcat2/xNBA.git
synced 2025-02-16 18:48:12 +00:00
[librm] Speed up protected-mode calls under KVM
When making a call from real mode to protected mode, we save and restore the global and interrupt descriptor table registers. The restore currently takes place after returning to real mode, which generates two EXCEPTION_NMIs and corresponding VM exits when running under KVM on an Intel CPU. Avoid the VM exits by restoring the descriptor table registers inside prot_to_real, while still running in protected mode. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
c64747db50
commit
bcfaf119a7
@ -253,12 +253,6 @@ r2p_pmode:
|
||||
/* Return to virtual address */
|
||||
ret
|
||||
|
||||
/* Default real-mode interrupt descriptor table */
|
||||
.section ".data", "aw", @progbits
|
||||
rm_idtr:
|
||||
.word 0xffff /* limit */
|
||||
.long 0 /* base */
|
||||
|
||||
/****************************************************************************
|
||||
* prot_to_real (protected-mode near call, 32-bit real-mode return address)
|
||||
*
|
||||
@ -275,12 +269,22 @@ rm_idtr:
|
||||
*
|
||||
* Parameters:
|
||||
* %ecx : number of bytes to move from PM stack to RM stack
|
||||
* %esi : real-mode global and interrupt descriptor table registers
|
||||
*
|
||||
****************************************************************************
|
||||
*/
|
||||
.section ".text", "ax", @progbits
|
||||
.code32
|
||||
prot_to_real:
|
||||
/* Copy real-mode global descriptor table register to RM code segment */
|
||||
movl text16, %edi
|
||||
leal rm_gdtr(%edi), %edi
|
||||
movsw
|
||||
movsl
|
||||
|
||||
/* Load real-mode interrupt descriptor table register */
|
||||
lidt (%esi)
|
||||
|
||||
/* Add return address to data to be moved to RM stack */
|
||||
addl $4, %ecx
|
||||
|
||||
@ -300,9 +304,6 @@ prot_to_real:
|
||||
/* Record protected-mode %esp (after removal of data) */
|
||||
movl %esi, pm_esp
|
||||
|
||||
/* Reset IDTR to the real-mode defaults */
|
||||
lidt rm_idtr
|
||||
|
||||
/* Load real-mode segment limits */
|
||||
movw $REAL_DS, %ax
|
||||
movw %ax, %ds
|
||||
@ -314,6 +315,8 @@ prot_to_real:
|
||||
.section ".text16", "ax", @progbits
|
||||
.code16
|
||||
p2r_rmode:
|
||||
/* Load real-mode GDT */
|
||||
data32 lgdt %cs:rm_gdtr
|
||||
/* Switch to real mode */
|
||||
movl %cr0, %eax
|
||||
andb $0!CR0_PE, %al
|
||||
@ -349,6 +352,12 @@ p2r_ljmp_rm_cs:
|
||||
.globl rm_ds
|
||||
rm_ds: .word 0
|
||||
|
||||
/* Real-mode global and interrupt descriptor table registers */
|
||||
.section ".text16.data", "aw", @progbits
|
||||
rm_gdtr:
|
||||
.word 0 /* Limit */
|
||||
.long 0 /* Base */
|
||||
|
||||
/****************************************************************************
|
||||
* prot_call (real-mode far call, 16-bit real-mode far return address)
|
||||
*
|
||||
@ -384,8 +393,8 @@ rm_ds: .word 0
|
||||
*/
|
||||
|
||||
#define PC_OFFSET_GDT ( 0 )
|
||||
#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 8 /* pad to 8 to keep alignment */ )
|
||||
#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 8 /* pad to 8 to keep alignment */ )
|
||||
#define PC_OFFSET_IDT ( PC_OFFSET_GDT + 6 )
|
||||
#define PC_OFFSET_IX86 ( PC_OFFSET_IDT + 6 )
|
||||
#define PC_OFFSET_RETADDR ( PC_OFFSET_IX86 + SIZEOF_I386_ALL_REGS )
|
||||
#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
|
||||
#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 )
|
||||
@ -403,10 +412,10 @@ prot_call:
|
||||
pushw %ds
|
||||
pushw %ss
|
||||
pushw %cs
|
||||
subw $16, %sp
|
||||
subw $PC_OFFSET_IX86, %sp
|
||||
movw %sp, %bp
|
||||
sidt 8(%bp)
|
||||
sgdt (%bp)
|
||||
sidt PC_OFFSET_IDT(%bp)
|
||||
sgdt PC_OFFSET_GDT(%bp)
|
||||
|
||||
/* For sanity's sake, clear the direction flag as soon as possible */
|
||||
cld
|
||||
@ -426,16 +435,14 @@ pc_pmode:
|
||||
|
||||
/* Switch to real mode and move register dump back to RM stack */
|
||||
movl $PC_OFFSET_END, %ecx
|
||||
movl %esp, %esi
|
||||
pushl $pc_rmode
|
||||
jmp prot_to_real
|
||||
.section ".text16", "ax", @progbits
|
||||
.code16
|
||||
pc_rmode:
|
||||
/* Reload GDT and IDT, restore registers and flags and return */
|
||||
movw %sp, %bp
|
||||
data32 lgdt (%bp)
|
||||
data32 lidt 8(%bp)
|
||||
addw $20, %sp /* also skip %cs and %ss */
|
||||
/* Restore registers and flags and return */
|
||||
addw $( PC_OFFSET_IX86 + 4 /* also skip %cs and %ss */ ), %sp
|
||||
popw %ds
|
||||
popw %es
|
||||
popw %fs
|
||||
@ -489,6 +496,7 @@ real_call:
|
||||
/* Switch to real mode and move register dump to RM stack */
|
||||
movl $( RC_OFFSET_RETADDR + 4 /* function pointer copy */ ), %ecx
|
||||
pushl $rc_rmode
|
||||
movl $rm_default_gdtr_idtr, %esi
|
||||
jmp prot_to_real
|
||||
.section ".text16", "ax", @progbits
|
||||
.code16
|
||||
@ -520,6 +528,14 @@ rc_pmode:
|
||||
.section ".data16", "aw", @progbits
|
||||
rc_function: .word 0, 0
|
||||
|
||||
/* Default real-mode global and interrupt descriptor table registers */
|
||||
.section ".data", "aw", @progbits
|
||||
rm_default_gdtr_idtr:
|
||||
.word 0 /* Global descriptor table limit */
|
||||
.long 0 /* Global descriptor table base */
|
||||
.word 0x03ff /* Interrupt descriptor table limit */
|
||||
.long 0 /* Interrupt descriptor table base */
|
||||
|
||||
/****************************************************************************
|
||||
* flatten_real_mode (real-mode near call)
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user