target/i386: fix TF/RF handling for HLT

HLT uses DISAS_NORETURN because the corresponding helper calls
cpu_loop_exit().  However, while gen_eob() clears HF_RF_MASK and
synthesizes a #DB exception if single-step is active, none of this is
done by HLT.  Note that the single-step trap is generated after the halt
is finished.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2024-05-25 10:47:31 +02:00
parent 3718523d01
commit 6dd7d8c649
2 changed files with 15 additions and 4 deletions

View File

@ -520,7 +520,7 @@ G_NORETURN void helper_hlt(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
do_end_instruction(env);
cs->halted = 1;
cs->exception_index = EXCP_HLT;
cpu_loop_exit(cs);

View File

@ -130,15 +130,26 @@ void x86_cpu_do_interrupt(CPUState *cs)
bool x86_cpu_exec_halt(CPUState *cpu)
{
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
X86CPU *x86_cpu = X86_CPU(cpu);
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
bql_lock();
apic_poll_irq(x86_cpu->apic_state);
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
bql_unlock();
}
return cpu_has_work(cpu);
if (!cpu_has_work(cpu)) {
return false;
}
/* Complete HLT instruction. */
if (env->eflags & TF_MASK) {
env->dr[6] |= DR6_BS;
do_interrupt_all(x86_cpu, EXCP01_DB, 0, 0, env->eip, 0);
}
return true;
}
bool x86_need_replay_interrupt(int interrupt_request)