aboutsummaryrefslogtreecommitdiff
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 d6974df..3775abe 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 93933fd..b6307ca 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 eb0ea93..ecf16b3 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 */