mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86emul: support RDRAND/RDSEED
Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
c4afd683f9
commit
a8fe4ec532
3 files changed
+77
-2
No files matched your search
@@ -14,7 +14,9 @@ $(call cc-option-add,CFLAGS,CC,-Wnested-externs)
|
||||
$(call as-insn-check,CFLAGS,CC,"vmcall",-DHAVE_GAS_VMX)
|
||||
$(call as-insn-check,CFLAGS,CC,"crc32 %eax$$(comma)%eax",-DHAVE_GAS_SSE4_2)
|
||||
$(call as-insn-check,CFLAGS,CC,"invept (%rax)$$(comma)%rax",-DHAVE_GAS_EPT)
|
||||
$(call as-insn-check,CFLAGS,CC,"rdrand %eax",-DHAVE_GAS_RDRAND)
|
||||
$(call as-insn-check,CFLAGS,CC,"rdfsbase %rax",-DHAVE_GAS_FSGSBASE)
|
||||
$(call as-insn-check,CFLAGS,CC,"rdseed %eax",-DHAVE_GAS_RDSEED)
|
||||
$(call as-insn-check,CFLAGS,CC,".equ \"x\"$$(comma)1", \
|
||||
-U__OBJECT_LABEL__ -DHAVE_GAS_QUOTED_SYM \
|
||||
'-D__OBJECT_LABEL__=$(subst $(BASEDIR)/,,$(CURDIR))/$$@')
|
||||
|
||||
@@ -1351,6 +1351,7 @@ static bool vcpu_has(
|
||||
#define vcpu_has_movbe() vcpu_has( 1, ECX, 22, ctxt, ops)
|
||||
#define vcpu_has_popcnt() vcpu_has( 1, ECX, 23, ctxt, ops)
|
||||
#define vcpu_has_avx() vcpu_has( 1, ECX, 28, ctxt, ops)
|
||||
#define vcpu_has_rdrand() vcpu_has( 1, ECX, 30, ctxt, ops)
|
||||
#define vcpu_has_lahf_lm() vcpu_has(0x80000001, ECX, 0, ctxt, ops)
|
||||
#define vcpu_has_cr8_legacy() vcpu_has(0x80000001, ECX, 4, ctxt, ops)
|
||||
#define vcpu_has_lzcnt() vcpu_has(0x80000001, ECX, 5, ctxt, ops)
|
||||
@@ -1361,6 +1362,7 @@ static bool vcpu_has(
|
||||
#define vcpu_has_bmi2() vcpu_has( 7, EBX, 8, ctxt, ops)
|
||||
#define vcpu_has_rtm() vcpu_has( 7, EBX, 11, ctxt, ops)
|
||||
#define vcpu_has_mpx() vcpu_has( 7, EBX, 14, ctxt, ops)
|
||||
#define vcpu_has_rdseed() vcpu_has( 7, EBX, 18, ctxt, ops)
|
||||
#define vcpu_has_adx() vcpu_has( 7, EBX, 19, ctxt, ops)
|
||||
#define vcpu_has_smap() vcpu_has( 7, EBX, 20, ctxt, ops)
|
||||
#define vcpu_has_clflushopt() vcpu_has( 7, EBX, 23, ctxt, ops)
|
||||
@@ -5754,14 +5756,83 @@ x86_emulate(
|
||||
dst.val = src.val;
|
||||
break;
|
||||
|
||||
case X86EMUL_OPC(0x0f, 0xc7): /* Grp9 (cmpxchg8b/cmpxchg16b) */ {
|
||||
case X86EMUL_OPC(0x0f, 0xc7): /* Grp9 */
|
||||
{
|
||||
union {
|
||||
uint32_t u32[2];
|
||||
uint64_t u64[2];
|
||||
} *old, *aux;
|
||||
|
||||
if ( ea.type == OP_REG )
|
||||
{
|
||||
bool __maybe_unused carry;
|
||||
|
||||
switch ( modrm_reg & 7 )
|
||||
{
|
||||
default:
|
||||
goto cannot_emulate;
|
||||
|
||||
#ifdef HAVE_GAS_RDRAND
|
||||
case 6: /* rdrand */
|
||||
generate_exception_if(rep_prefix(), EXC_UD);
|
||||
host_and_vcpu_must_have(rdrand);
|
||||
dst = ea;
|
||||
switch ( op_bytes )
|
||||
{
|
||||
case 2:
|
||||
asm ( "rdrand %w0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
default:
|
||||
# ifdef __x86_64__
|
||||
asm ( "rdrand %k0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
case 8:
|
||||
# endif
|
||||
asm ( "rdrand %0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
}
|
||||
_regs._eflags &= ~EFLAGS_MASK;
|
||||
if ( carry )
|
||||
_regs._eflags |= EFLG_CF;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GAS_RDSEED
|
||||
case 7: /* rdseed */
|
||||
generate_exception_if(rep_prefix(), EXC_UD);
|
||||
host_and_vcpu_must_have(rdseed);
|
||||
dst = ea;
|
||||
switch ( op_bytes )
|
||||
{
|
||||
case 2:
|
||||
asm ( "rdseed %w0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
default:
|
||||
# ifdef __x86_64__
|
||||
asm ( "rdseed %k0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
case 8:
|
||||
# endif
|
||||
asm ( "rdseed %0" ASM_FLAG_OUT(, "; setc %1")
|
||||
: "=r" (dst.val), ASM_FLAG_OUT("=@ccc", "=qm") (carry) );
|
||||
break;
|
||||
}
|
||||
_regs._eflags &= ~EFLAGS_MASK;
|
||||
if ( carry )
|
||||
_regs._eflags |= EFLG_CF;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* cmpxchg8b/cmpxchg16b */
|
||||
generate_exception_if((modrm_reg & 7) != 1, EXC_UD);
|
||||
generate_exception_if(ea.type != OP_MEM, EXC_UD);
|
||||
fail_if(!ops->cmpxchg);
|
||||
if ( rex_prefix & REX_W )
|
||||
{
|
||||
|
||||
@@ -73,6 +73,8 @@
|
||||
#define cpu_has_monitor boot_cpu_has(X86_FEATURE_MONITOR)
|
||||
#define cpu_has_eist boot_cpu_has(X86_FEATURE_EIST)
|
||||
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
|
||||
#define cpu_has_rdrand boot_cpu_has(X86_FEATURE_RDRAND)
|
||||
#define cpu_has_rdseed boot_cpu_has(X86_FEATURE_RDSEED)
|
||||
#define cpu_has_cmp_legacy boot_cpu_has(X86_FEATURE_CMP_LEGACY)
|
||||
#define cpu_has_tbm boot_cpu_has(X86_FEATURE_TBM)
|
||||
#define cpu_has_itsc boot_cpu_has(X86_FEATURE_ITSC)
|
||||
|
||||