aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-02-18 14:30:27 +0000
committerMichael Brown <mcb30@ipxe.org>2021-02-18 15:38:56 +0000
commit900f1f98d3dbb64803e427318ad61c9d7aa6f9bb (patch)
tree93397baefd0b1391e321dcdfe04afabd1578e89b
parente63b8c3302b1e80e14f3d3628ff279f7316ee208 (diff)
downloadipxe-900f1f98d3dbb64803e427318ad61c9d7aa6f9bb.zip
ipxe-900f1f98d3dbb64803e427318ad61c9d7aa6f9bb.tar.gz
ipxe-900f1f98d3dbb64803e427318ad61c9d7aa6f9bb.tar.bz2
[librm] Test for FXSAVE/FXRSTOR instruction supportfxsr
Assume that preservation of the %xmm registers is unnecessary during installation of iPXE into memory, since this is an operation that by its nature substantially disrupts large portions of the system anyway (such as the E820 memory map). This assumption allows us to utilise the existing CPUID code to check that FXSAVE/FXRSTOR are supported. Test for support during the call to init_librm and store the flag for use during subsequent calls to virt_call. Reduce the scope of TIVOLI_VMM_WORKAROUND to affecting only the call to check_fxsr(), to reduce #ifdef pollution in the remaining code. Debugged-by: Johannes Heimansberg <git@jhe.dedyn.io> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-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 );