@@ -39,6 +39,7 @@ void x86_cpu_do_interrupt(CPUState *cpu);
#ifndef CONFIG_USER_ONLY
void x86_cpu_poll_during_halt(CPUState *cpu);
bool x86_cpu_exec_halt(CPUState *cpu);
+void x86_cpu_leaving_halt(CPUState *cpu);
bool x86_need_replay_interrupt(int interrupt_request);
bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
#endif
@@ -140,22 +140,31 @@ void x86_cpu_poll_during_halt(CPUState *cpu)
}
}
-bool x86_cpu_exec_halt(CPUState *cpu)
+void x86_cpu_leaving_halt(CPUState *cpu)
{
X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
-
- x86_cpu_poll_during_halt(cpu);
-
- if (!cpu_has_work(cpu)) {
- return false;
- }
+ CPUX86State *env = cpu_env(cpu);
/* Complete HLT instruction. */
if (env->eflags & TF_MASK) {
env->dr[6] |= DR6_BS;
+ /*
+ * do_interrupt_all() is the normal TCG exception-delivery path
+ * and runs in the same vCPU thread context, so #DB delivery does
+ * not require BQL protection here.
+ */
do_interrupt_all(x86_cpu, EXCP01_DB, 0, 0, env->eip, 0);
}
+}
+
+bool x86_cpu_exec_halt(CPUState *cpu)
+{
+ if (!cpu_has_work(cpu)) {
+ return false;
+ }
+
+ x86_cpu_leaving_halt(cpu);
+
return true;
}