aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/include/ipxe/cpuid.h3
-rw-r--r--src/arch/x86/transitions/librm.S23
-rw-r--r--src/arch/x86/transitions/librm_mgmt.c16
3 files changed, 36 insertions, 6 deletions
diff --git a/src/arch/x86/include/ipxe/cpuid.h b/src/arch/x86/include/ipxe/cpuid.h
index 0ae572d..b5403bd 100644
--- a/src/arch/x86/include/ipxe/cpuid.h
+++ b/src/arch/x86/include/ipxe/cpuid.h
@@ -42,6 +42,9 @@ struct x86_features {
/** Hypervisor is present */
#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR 0x80000000UL
+/** FXSAVE and FXRSTOR are supported */
+#define CPUID_FEATURES_INTEL_EDX_FXSR 0x01000000UL
+
/** Get largest extended function */
#define CPUID_AMD_MAX_FN 0x80000000UL
diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S
index f2fa8c5..5dacb9b 100644
--- a/src/arch/x86/transitions/librm.S
+++ b/src/arch/x86/transitions/librm.S
@@ -210,9 +210,7 @@ VC_TMP_CR3: .space 4
VC_TMP_CR4: .space 4
VC_TMP_EMER: .space 8
.endif
-#ifdef TIVOLI_VMM_WORKAROUND
VC_TMP_FXSAVE: .space 512
-#endif
VC_TMP_END:
.previous
@@ -350,6 +348,13 @@ init_librm_rmode:
/* Initialise IDT */
virtcall init_idt
+#ifdef TIVOLI_VMM_WORKAROUND
+ /* Check for FXSAVE/FXRSTOR */
+ clc
+ virtcall check_fxsr
+ setnc fxsr_supported
+#endif
+
/* Restore registers */
popl %edi
popl %ebx
@@ -366,6 +371,10 @@ set_seg_base:
roll $16, %eax
ret
+ .section ".data16.fxsr_supported", "awx", @progbits
+fxsr_supported: /* FXSAVE/FXRSTOR instructions supported */
+ .byte 0
+
/****************************************************************************
* real_to_prot (real-mode near call, 32-bit virtual return address)
*
@@ -1007,10 +1016,11 @@ virt_call:
cli
movw %cs:rm_ds, %ds
-#ifdef TIVOLI_VMM_WORKAROUND
/* Preserve FPU, MMX and SSE state in temporary static buffer */
+ testb $0xff, fxsr_supported
+ jz 1f
fxsave ( rm_tmpbuf + VC_TMP_FXSAVE )
-#endif
+1:
/* Preserve GDT and IDT in temporary static buffer */
sidt ( rm_tmpbuf + VC_TMP_IDT )
sgdt ( rm_tmpbuf + VC_TMP_GDT )
@@ -1077,10 +1087,11 @@ vc_rmode:
wrmsr
.endif
-#ifdef TIVOLI_VMM_WORKAROUND
/* Restore FPU, MMX and SSE state from temporary static buffer */
+ testb $0xff, fxsr_supported
+ jz 1f
fxrstor ( rm_tmpbuf + VC_TMP_FXSAVE )
-#endif
+1:
/* Restore registers and flags and return */
popl %eax /* skip %cs and %ss */
popw %ds
diff --git a/src/arch/x86/transitions/librm_mgmt.c b/src/arch/x86/transitions/librm_mgmt.c
index 85cfc8f..da221e8 100644
--- a/src/arch/x86/transitions/librm_mgmt.c
+++ b/src/arch/x86/transitions/librm_mgmt.c
@@ -14,6 +14,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
#include <pic8259.h>
#include <ipxe/shell.h>
+#include <ipxe/cpuid.h>
/*
* This file provides functions for managing librm.
@@ -386,6 +387,21 @@ static void iounmap_pages ( volatile const void *io_addr ) {
io_addr, first, i );
}
+/**
+ * Check for FXSAVE/FXRSTOR instruction support
+ *
+ */
+__asmcall void check_fxsr ( struct i386_all_regs *regs ) {
+ struct x86_features features;
+
+ /* Check for FXSR bit */
+ x86_features ( &features );
+ if ( ! ( features.intel.edx & CPUID_FEATURES_INTEL_EDX_FXSR ) )
+ regs->flags |= CF;
+ DBGC ( &features, "FXSAVE/FXRSTOR is%s supported\n",
+ ( ( regs->flags & CF ) ? " not" : "" ) );
+}
+
PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
PROVIDE_UACCESS_INLINE ( librm, virt_to_user );