qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] Rudimentary Intel Restricted Transactional Memor


From: trent . tong
Subject: [Qemu-devel] [PATCH v2] Rudimentary Intel Restricted Transactional Memory Support.
Date: Fri, 6 Feb 2015 19:12:40 -0500

From: Xin Tong <address@hidden>

A better looking patch generated by git format-patch.

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>

---
 target-i386/cpu.c         |  8 ++--
 target-i386/cpu.h         |  8 ++++
 target-i386/helper.h      |  5 +++
 target-i386/misc_helper.c | 19 +++++++++
 target-i386/translate.c   | 99 +++++++++++++++++++++++++++++++++++------------
 5 files changed, 111 insertions(+), 28 deletions(-)

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)
--
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]