mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Do as was decided in Lisbon. Reportedly Xen hasn't been working very well on those processors anyway. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-By: Oleksii Kurochko <oleksii.kurochko@gmail.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com>
269 lines
6.2 KiB
C
269 lines
6.2 KiB
C
#include "x86-emulate.h"
|
|
|
|
#include <errno.h>
|
|
#include <sys/mman.h>
|
|
|
|
/* See gcc bug 100680, but here don't bother making this version dependent. */
|
|
#define gcc11_wrap(x) ({ \
|
|
unsigned long x_; \
|
|
__asm__ ( "" : "=g" (x_) : "0" (x) ); \
|
|
(typeof(x))x_; \
|
|
})
|
|
|
|
#define cpu_has_amd_erratum(nr) 0
|
|
#define cpu_has_mpx false
|
|
#define read_bndcfgu() 0
|
|
#define xstate_set_init(what)
|
|
|
|
/* For generic assembly code: use macros to define operation/operand sizes. */
|
|
#ifdef __i386__
|
|
# define __OS "l" /* Operation Suffix */
|
|
# define __OP "e" /* Operand Prefix */
|
|
#else
|
|
# define __OS "q" /* Operation Suffix */
|
|
# define __OP "r" /* Operand Prefix */
|
|
#endif
|
|
|
|
uint32_t mxcsr_mask = 0x0000ffbf;
|
|
struct cpu_policy cp;
|
|
|
|
static char fpu_save_area[0x4000] __attribute__((__aligned__((64))));
|
|
static bool use_xsave;
|
|
|
|
/*
|
|
* Re-use the area above also as scratch space for the emulator itself.
|
|
* (When debugging the emulator, care needs to be taken when inserting
|
|
* printf() or alike function calls into regions using this.)
|
|
*/
|
|
struct x86_fxsr *get_fpu_save_area(void)
|
|
{
|
|
return (void *)fpu_save_area;
|
|
}
|
|
|
|
void emul_save_fpu_state(void)
|
|
{
|
|
if ( use_xsave )
|
|
asm volatile ( "xsave %[ptr]"
|
|
: [ptr] "=m" (fpu_save_area)
|
|
: "a" (~0ul), "d" (~0ul) );
|
|
else
|
|
asm volatile ( "fxsave %0" : "=m" (fpu_save_area) );
|
|
}
|
|
|
|
void emul_restore_fpu_state(void)
|
|
{
|
|
/* Older gcc can't deal with "m" array inputs; make them outputs instead. */
|
|
if ( use_xsave )
|
|
asm volatile ( "xrstor %[ptr]"
|
|
: [ptr] "+m" (fpu_save_area)
|
|
: "a" (~0ul), "d" (~0ul) );
|
|
else
|
|
asm volatile ( "fxrstor %0" : "+m" (fpu_save_area) );
|
|
}
|
|
|
|
bool emul_test_init(void)
|
|
{
|
|
union {
|
|
char x[464];
|
|
struct {
|
|
uint32_t other[6];
|
|
uint32_t mxcsr;
|
|
uint32_t mxcsr_mask;
|
|
/* ... */
|
|
};
|
|
} *fxs = (void *)fpu_save_area;
|
|
|
|
unsigned long sp;
|
|
|
|
x86_cpu_policy_fill_native(&cp);
|
|
|
|
/*
|
|
* The emulator doesn't use these instructions, so can always emulate
|
|
* them.
|
|
*/
|
|
cp.basic.movbe = true;
|
|
cp.feat.invpcid = true;
|
|
cp.feat.adx = true;
|
|
cp.feat.rdpid = true;
|
|
cp.feat.wrmsrns = true;
|
|
cp.extd.clzero = true;
|
|
|
|
if ( cpu_has_xsave )
|
|
{
|
|
unsigned int tmp, ebx;
|
|
|
|
asm ( "cpuid"
|
|
: "=a" (tmp), "=b" (ebx), "=c" (tmp), "=d" (tmp)
|
|
: "a" (0xd), "c" (0) );
|
|
|
|
/*
|
|
* Sanity check that fpu_save_area[] is large enough. This assertion
|
|
* will trip eventually, at which point fpu_save_area[] needs to get
|
|
* larger.
|
|
*/
|
|
assert(ebx < sizeof(fpu_save_area));
|
|
|
|
/* Use xsave if available... */
|
|
use_xsave = true;
|
|
}
|
|
else
|
|
/* But use fxsave if xsave isn't available. */
|
|
assert(cpu_has_fxsr);
|
|
|
|
/* Reuse the save state buffer to find mcxsr_mask. */
|
|
asm ( "fxsave %0" : "=m" (*fxs) );
|
|
if ( fxs->mxcsr_mask )
|
|
mxcsr_mask = fxs->mxcsr_mask;
|
|
|
|
/*
|
|
* Mark the entire stack executable so that the stub executions
|
|
* don't fault
|
|
*/
|
|
#ifdef __x86_64__
|
|
asm ("movq %%rsp, %0" : "=g" (sp));
|
|
#else
|
|
asm ("movl %%esp, %0" : "=g" (sp));
|
|
#endif
|
|
|
|
return mprotect((void *)(sp & -0x1000L) - (MMAP_SZ - 0x1000),
|
|
MMAP_SZ, PROT_READ|PROT_WRITE|PROT_EXEC) == 0;
|
|
}
|
|
|
|
int emul_test_cpuid(
|
|
uint32_t leaf,
|
|
uint32_t subleaf,
|
|
struct cpuid_leaf *res,
|
|
struct x86_emulate_ctxt *ctxt)
|
|
{
|
|
asm ("cpuid"
|
|
: "=a" (res->a), "=b" (res->b), "=c" (res->c), "=d" (res->d)
|
|
: "a" (leaf), "c" (subleaf));
|
|
|
|
/*
|
|
* The emulator doesn't itself use MOVBE, so we can always run the
|
|
* respective tests.
|
|
*/
|
|
if ( leaf == 1 )
|
|
res->c |= 1U << 22;
|
|
|
|
/*
|
|
* The emulator doesn't itself use ADCX/ADOX/RDPID nor the S/G prefetch
|
|
* insns, so we can always run the respective tests.
|
|
*/
|
|
if ( leaf == 7 && subleaf == 0 )
|
|
{
|
|
res->b |= (1U << 10) | (1U << 19);
|
|
if ( res->b & (1U << 16) )
|
|
res->b |= 1U << 26;
|
|
res->c |= 1U << 22;
|
|
}
|
|
|
|
/*
|
|
* The emulator doesn't itself use CLZERO, so we can always run the
|
|
* respective test(s).
|
|
*/
|
|
if ( leaf == 0x80000008 )
|
|
res->b |= 1U << 0;
|
|
|
|
return X86EMUL_OKAY;
|
|
}
|
|
|
|
int emul_test_read_cr(
|
|
unsigned int reg,
|
|
unsigned long *val,
|
|
struct x86_emulate_ctxt *ctxt)
|
|
{
|
|
/* Fake just enough state for the emulator's _get_fpu() to be happy. */
|
|
switch ( reg )
|
|
{
|
|
case 0:
|
|
*val = 0x00000001; /* PE */
|
|
return X86EMUL_OKAY;
|
|
|
|
case 4:
|
|
*val = X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT | X86_CR4_PKE |
|
|
(cpu_has_xsave ? X86_CR4_OSXSAVE : 0);
|
|
return X86EMUL_OKAY;
|
|
}
|
|
|
|
return X86EMUL_UNHANDLEABLE;
|
|
}
|
|
|
|
int emul_test_read_xcr(
|
|
unsigned int reg,
|
|
uint64_t *val,
|
|
struct x86_emulate_ctxt *ctxt)
|
|
{
|
|
uint32_t lo, hi;
|
|
|
|
ASSERT(cpu_has_xsave);
|
|
|
|
switch ( reg )
|
|
{
|
|
case 0:
|
|
break;
|
|
|
|
case 1:
|
|
if ( cpu_has_xgetbv1 )
|
|
break;
|
|
/* fall through */
|
|
default:
|
|
x86_emul_hw_exception(13 /* #GP */, 0, ctxt);
|
|
return X86EMUL_EXCEPTION;
|
|
}
|
|
|
|
asm ( "xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg) );
|
|
*val = lo | ((uint64_t)hi << 32);
|
|
|
|
return X86EMUL_OKAY;
|
|
}
|
|
|
|
int emul_test_get_fpu(
|
|
enum x86_emulate_fpu_type type,
|
|
struct x86_emulate_ctxt *ctxt)
|
|
{
|
|
switch ( type )
|
|
{
|
|
case X86EMUL_FPU_fpu:
|
|
break;
|
|
case X86EMUL_FPU_mmx:
|
|
if ( cpu_has_mmx )
|
|
break;
|
|
case X86EMUL_FPU_xmm:
|
|
if ( cpu_has_sse )
|
|
break;
|
|
case X86EMUL_FPU_ymm:
|
|
if ( cpu_has_avx )
|
|
break;
|
|
case X86EMUL_FPU_opmask:
|
|
case X86EMUL_FPU_zmm:
|
|
if ( cpu_has_avx512f )
|
|
break;
|
|
default:
|
|
return X86EMUL_UNHANDLEABLE;
|
|
}
|
|
return X86EMUL_OKAY;
|
|
}
|
|
|
|
void emul_test_put_fpu(
|
|
struct x86_emulate_ctxt *ctxt,
|
|
enum x86_emulate_fpu_type backout,
|
|
const struct x86_emul_fpu_aux *aux)
|
|
{
|
|
/* TBD */
|
|
}
|
|
|
|
static uint32_t pkru;
|
|
|
|
unsigned int rdpkru(void)
|
|
{
|
|
return pkru;
|
|
}
|
|
|
|
void wrpkru(unsigned int val)
|
|
{
|
|
pkru = val;
|
|
}
|
|
|
|
#include "x86_emulate/x86_emulate.c"
|