summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target-i386/helper.h1
-rw-r--r--target-i386/misc_helper.c22
-rw-r--r--target-i386/translate.c5
3 files changed, 25 insertions, 3 deletions
diff --git a/target-i386/helper.h b/target-i386/helper.h
index d6974dfd6b..3775abeba7 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -58,6 +58,7 @@ DEF_HELPER_2(sysret, void, env, int)
 DEF_HELPER_2(hlt, void, env, int)
 DEF_HELPER_2(monitor, void, env, tl)
 DEF_HELPER_2(mwait, void, env, int)
+DEF_HELPER_2(pause, void, env, int)
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_1(reset_rf, void, env)
 DEF_HELPER_3(raise_interrupt, void, env, int, int)
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 93933fd162..b6307ca386 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -566,6 +566,15 @@ void helper_rdmsr(CPUX86State *env)
 }
 #endif
 
+static void do_pause(X86CPU *cpu)
+{
+    CPUX86State *env = &cpu->env;
+
+    /* Just let another CPU run.  */
+    env->exception_index = EXCP_INTERRUPT;
+    cpu_loop_exit(env);
+}
+
 static void do_hlt(X86CPU *cpu)
 {
     CPUState *cs = CPU(cpu);
@@ -611,13 +620,22 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
     cs = CPU(cpu);
     /* XXX: not complete but not completely erroneous */
     if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
-        /* more than one CPU: do not sleep because another CPU may
-           wake this one */
+        do_pause(cpu);
     } else {
         do_hlt(cpu);
     }
 }
 
+void helper_pause(CPUX86State *env, int next_eip_addend)
+{
+    X86CPU *cpu = x86_env_get_cpu(env);
+
+    cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
+    env->eip += next_eip_addend;
+
+    do_pause(cpu);
+}
+
 void helper_debug(CPUX86State *env)
 {
     env->exception_index = EXCP_DEBUG;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index eb0ea93dbb..ecf16b389b 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7224,7 +7224,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto do_xchg_reg_eax;
         }
         if (prefixes & PREFIX_REPZ) {
-            gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
+            gen_update_cc_op(s);
+            gen_jmp_im(pc_start - s->cs_base);
+            gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
+            s->is_jmp = DISAS_TB_JUMP;
         }
         break;
     case 0x9b: /* fwait */