[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v1] Rudimentary Intel Restricted Transactional Memor
From: |
trent . tong |
Subject: |
[Qemu-devel] [PATCH v1] Rudimentary Intel Restricted Transactional Memory Support. |
Date: |
Fri, 6 Feb 2015 19:01:18 -0500 |
Implement a rudimentary support for intel RTM. Xbegin always fails to fallback
code path.
Handle Xbegin, Xend, Xtest, Xabort described in Intel ISA extension manual @
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
Signed-off-by: Xin Tong <address@hidden>
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 3a9b32e..9397665 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -334,7 +334,8 @@ static const char *cpuid_xsave_feature_name[] = {
#define TCG_SVM_FEATURES 0
#define TCG_KVM_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
- CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
+ CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
+ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_RTM)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
@@ -1101,7 +1102,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
.features[FEAT_7_0_EBX] =
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
- CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID,
+ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
+ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_RTM,
.features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT,
.xlevel = 0x8000000A,
@@ -1137,7 +1139,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
- CPUID_7_0_EBX_SMAP,
+ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_RTM,
.features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT,
.xlevel = 0x8000000A,
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 478450c..2879c3a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -625,6 +625,14 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
for syscall instruction */
+/* intel rtm abort reason bit */
+#define INTEL_RTM_XABORT 0
+#define INTEL_RTM_RETRY 1
+#define INTEL_RTM_CONFLICT 2
+#define INTEL_RTM_OVERFLOW 3
+#define INTEL_RTM_BREAKPOINT 4
+#define INTEL_RTM_ABORT_NEST 5
+
/* i386-specific interrupt pending bits. */
#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
diff --git a/target-i386/helper.h b/target-i386/helper.h
index 8eb0145..52a97fe 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -202,6 +202,11 @@ DEF_HELPER_1(enter_mmx, void, env)
DEF_HELPER_1(emms, void, env)
DEF_HELPER_3(movq, void, env, ptr, ptr)
+/* Intel RTM */
+DEF_HELPER_2(xbegin, void, env, i32)
+DEF_HELPER_1(xend, void, env)
+DEF_HELPER_1(xtest, void, env)
+
#define SHIFT 0
#include "ops_sse_header.h"
#define SHIFT 1
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 4aaf1e4..b5690c9 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -600,3 +600,22 @@ void helper_debug(CPUX86State *env)
cs->exception_index = EXCP_DEBUG;
cpu_loop_exit(cs);
}
+
+void helper_xbegin(CPUX86State *env, uint32_t next_eip_addend)
+{
+ /* as a degenerate implementation, always fail xbegin. */
+ env->eip += next_eip_addend;
+ env->regs[R_EAX] = ~(1<<INTEL_RTM_OVERFLOW); /* internal buffer overflow */
+}
+
+void helper_xend(CPUX86State *env)
+{
+ /* only way to get here is to execute a xend without xbegin. GPF. */
+ raise_exception(env, EXCP0D_GPF);
+}
+
+void helper_xtest(CPUX86State *env)
+{
+ /* xbegin always fails to fallback code, set RTM not active. */
+ env->eflags &= ~(1<<6); /* zf */
+}
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 9ebdf4b..064f35e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4433,6 +4433,7 @@ static target_ulong disas_insn(CPUX86State *env,
DisasContext *s,
next_byte:
b = cpu_ldub_code(env, s->pc);
s->pc++;
+
/* Collect prefixes. */
switch (b) {
case 0xf3:
@@ -5364,20 +5365,45 @@ static target_ulong disas_insn(CPUX86State *env,
DisasContext *s,
gen_ldst_modrm(env, s, modrm, ot, reg, 1);
break;
case 0xc6:
- case 0xc7: /* mov Ev, Iv */
+ case 0xc7: /* mov Ev, Iv or xbegin, xabort*/
ot = mo_b_d(b, dflag);
modrm = cpu_ldub_code(env, s->pc++);
mod = (modrm >> 6) & 3;
- if (mod != 3) {
- s->rip_offset = insn_const_size(ot);
- gen_lea_modrm(env, s, modrm);
- }
- val = insn_get(env, s, ot);
- tcg_gen_movi_tl(cpu_T[0], val);
- if (mod != 3) {
- gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
- } else {
- gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
+ op = (modrm >> 3) & 7;
+ switch (op) {
+ case 0: /* mov Ev, Iv */
+ if (mod != 3) {
+ s->rip_offset = insn_const_size(ot);
+ gen_lea_modrm(env, s, modrm);
+ }
+ val = insn_get(env, s, ot);
+ tcg_gen_movi_tl(cpu_T[0], val);
+ if (mod != 3) {
+ gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
+ } else {
+ gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
+ }
+ break;
+ case 7: /* xbegin or xabort */
+ if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RTM) ||
+ (s->prefix & PREFIX_LOCK)) {
+ goto illegal_op;
+ }
+ val = insn_get(env, s, ot);
+ if (b == 0xc6) {
+ /* xbegin always fails to fallback address, the only way to get
+ * here is to execute a xabort without xbegin, which will treat
+ * xabort as a NOP.
+ */
+ break;
+ }
+ if (b == 0xc7) {
+ tcg_gen_movi_i32(cpu_tmp2_i32, val);
+ gen_helper_xbegin(cpu_env, cpu_tmp2_i32);
+ break;
+ }
+ default:
+ goto illegal_op;
}
break;
case 0x8a:
@@ -7349,22 +7375,45 @@ static target_ulong disas_insn(CPUX86State *env,
DisasContext *s,
gen_helper_stgi(cpu_env);
}
break;
- case 5: /* CLGI */
- if (!(s->flags & HF_SVME_MASK) || !s->pe)
- goto illegal_op;
- if (s->cpl != 0) {
- gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
- break;
- } else {
- gen_helper_clgi(cpu_env);
+ case 5: /* XEND or CLGI */
+ if (op == 0x2) {
+ if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_RTM) ||
+ (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ
+ | PREFIX_LOCK | PREFIX_DATA))) {
+ goto illegal_op;
+ }
+ gen_helper_xend(cpu_env);
+ }
+ if (op == 0x3) {
+ if (!(s->flags & HF_SVME_MASK) || !s->pe) {
+ goto illegal_op;
+ }
+ if (s->cpl != 0) {
+ gen_exception(s, EXCP0D_GPF, pc_start -
s->cs_base);
+ break;
+ } else {
+ gen_helper_clgi(cpu_env);
+ }
}
break;
- case 6: /* SKINIT */
- if ((!(s->flags & HF_SVME_MASK) &&
- !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
- !s->pe)
- goto illegal_op;
- gen_helper_skinit(cpu_env);
+ case 6: /* XTEST or SKINIT */
+ if (op == 0x2) {
+ if (!(s->cpuid_7_0_ebx_features &
+ (CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_RTM)) ||
+ (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ
+ | PREFIX_LOCK | PREFIX_DATA))) {
+ goto illegal_op;
+ }
+ gen_helper_xtest(cpu_env);
+ }
+ if (op == 0x3) {
+ if ((!(s->flags & HF_SVME_MASK) &&
+ !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
+ !s->pe) {
+ goto illegal_op;
+ }
+ gen_helper_skinit(cpu_env);
+ }
break;
case 7: /* INVLPGA */
if (!(s->flags & HF_SVME_MASK) || !s->pe)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH v1] Rudimentary Intel Restricted Transactional Memory Support.,
trent . tong <=