target/i386: implement RDPID in TCG
RDPID corresponds to a RDMSR(TSC_AUX); however, it is unprivileged so for user-mode emulation we must provide the value that the kernel places in the MSR. For Linux, it is a combination of the current CPU and the current NUMA node, both of which can be retrieved with getcpu(2). Also try sched_getcpu(), which might be there on the BSDs. If there is no portable way to retrieve the current CPU id from userspace, return 0. RDTSCP is reimplemented as RDTSC + RDPID ECX; the differences in terms of serializability are not relevant to QEMU. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
53b9b4cc9f
commit
6750485bf4
@ -2232,6 +2232,8 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
|
|||||||
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
|
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
|
||||||
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
|
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
|
||||||
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
|
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
|
||||||
|
config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
|
||||||
|
config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
|
||||||
# Note that we need to specify prefix: here to avoid incorrectly
|
# Note that we need to specify prefix: here to avoid incorrectly
|
||||||
# thinking that Windows has posix_memalign()
|
# thinking that Windows has posix_memalign()
|
||||||
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
|
config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
|
||||||
|
@ -661,9 +661,17 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
|||||||
/* missing:
|
/* missing:
|
||||||
CPUID_7_0_EBX_HLE
|
CPUID_7_0_EBX_HLE
|
||||||
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
|
CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM */
|
||||||
|
|
||||||
|
#if defined CONFIG_SOFTMMU || defined CONFIG_LINUX
|
||||||
|
#define TCG_7_0_ECX_RDPID CPUID_7_0_ECX_RDPID
|
||||||
|
#else
|
||||||
|
#define TCG_7_0_ECX_RDPID 0
|
||||||
|
#endif
|
||||||
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
|
#define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | \
|
||||||
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
|
/* CPUID_7_0_ECX_OSPKE is dynamic */ \
|
||||||
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES)
|
CPUID_7_0_ECX_LA57 | CPUID_7_0_ECX_PKS | CPUID_7_0_ECX_VAES | \
|
||||||
|
TCG_7_0_ECX_RDPID)
|
||||||
|
|
||||||
#define TCG_7_0_EDX_FEATURES CPUID_7_0_EDX_FSRM
|
#define TCG_7_0_EDX_FEATURES CPUID_7_0_EDX_FSRM
|
||||||
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
|
#define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \
|
||||||
CPUID_7_1_EAX_FSRC)
|
CPUID_7_1_EAX_FSRC)
|
||||||
|
@ -69,8 +69,8 @@ DEF_HELPER_2(into, void, env, int)
|
|||||||
DEF_HELPER_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
|
DEF_HELPER_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
|
||||||
DEF_HELPER_1(rechecking_single_step, void, env)
|
DEF_HELPER_1(rechecking_single_step, void, env)
|
||||||
DEF_HELPER_1(cpuid, void, env)
|
DEF_HELPER_1(cpuid, void, env)
|
||||||
|
DEF_HELPER_FLAGS_1(rdpid, TCG_CALL_NO_WG, tl, env)
|
||||||
DEF_HELPER_1(rdtsc, void, env)
|
DEF_HELPER_1(rdtsc, void, env)
|
||||||
DEF_HELPER_1(rdtscp, void, env)
|
|
||||||
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
|
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -75,12 +75,6 @@ void helper_rdtsc(CPUX86State *env)
|
|||||||
env->regs[R_EDX] = (uint32_t)(val >> 32);
|
env->regs[R_EDX] = (uint32_t)(val >> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_rdtscp(CPUX86State *env)
|
|
||||||
{
|
|
||||||
helper_rdtsc(env);
|
|
||||||
env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_NORETURN void helper_rdpmc(CPUX86State *env)
|
G_NORETURN void helper_rdpmc(CPUX86State *env)
|
||||||
{
|
{
|
||||||
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
|
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
|
||||||
@ -137,3 +131,18 @@ void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val)
|
|||||||
env->pkru = val;
|
env->pkru = val;
|
||||||
tlb_flush(cs);
|
tlb_flush(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target_ulong HELPER(rdpid)(CPUX86State *env)
|
||||||
|
{
|
||||||
|
#if defined CONFIG_SOFTMMU
|
||||||
|
return env->tsc_aux;
|
||||||
|
#elif defined CONFIG_LINUX && defined CONFIG_GETCPU
|
||||||
|
unsigned cpu, node;
|
||||||
|
getcpu(&cpu, &node);
|
||||||
|
return (node << 12) | (cpu & 0xfff);
|
||||||
|
#elif defined CONFIG_SCHED_GETCPU
|
||||||
|
return sched_getcpu();
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -3924,13 +3924,25 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
|||||||
gen_cmpxchg8b(s, env, modrm);
|
gen_cmpxchg8b(s, env, modrm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* RDSEED */
|
case 7: /* RDSEED, RDPID with f3 prefix */
|
||||||
if (mod != 3 ||
|
if (mod != 3 ||
|
||||||
(s->prefix & (PREFIX_LOCK | PREFIX_REPZ | PREFIX_REPNZ)) ||
|
(s->prefix & (PREFIX_LOCK | PREFIX_REPNZ))) {
|
||||||
!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
|
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
goto do_rdrand;
|
if (s->prefix & PREFIX_REPZ) {
|
||||||
|
if (!(s->cpuid_ext_features & CPUID_7_0_ECX_RDPID)) {
|
||||||
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
gen_helper_rdpid(s->T0, cpu_env);
|
||||||
|
rm = (modrm & 7) | REX_B(s);
|
||||||
|
gen_op_mov_reg_v(s, dflag, rm, s->T0);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RDSEED)) {
|
||||||
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
goto do_rdrand;
|
||||||
|
}
|
||||||
|
|
||||||
case 6: /* RDRAND */
|
case 6: /* RDRAND */
|
||||||
if (mod != 3 ||
|
if (mod != 3 ||
|
||||||
@ -6125,7 +6137,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
|||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
gen_update_eip_cur(s);
|
gen_update_eip_cur(s);
|
||||||
translator_io_start(&s->base);
|
translator_io_start(&s->base);
|
||||||
gen_helper_rdtscp(cpu_env);
|
gen_helper_rdtsc(cpu_env);
|
||||||
|
gen_helper_rdpid(s->T0, cpu_env);
|
||||||
|
gen_op_mov_reg_v(s, dflag, R_ECX, s->T0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user