Re: [PATCH 3/3] target/i386/mshv: support single-stepping

Magnus Kulke <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
On Mon, Jul 27, 2026 at 05:28:07PM +0300, Doru Blânzeanu wrote:
> Single-step by toggling RFLAGS.TF around the vCPU run, as WHPX does.
> TF is set only on the live register, never in env->eflags, so it is not read
> back and re-applied by a later register store.
> The resulting #DB is reported to gdb by mshv_handle_debug() whenever the vCPU
> is single-stepping.
> 
> Signed-off-by: Doru Blânzeanu <[email protected]>
> ---
>  target/i386/mshv/mshv-cpu.c | 50 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 2333d3304a..036b142113 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1974,17 +1974,67 @@ static int handle_debug(CPUState *cpu, hv_message *msg)
>      return 0;
>  }
>  
> +/*
> + * Flip RFLAGS.TF like WHPX. Set it only on the live register, not env->eflags,
> + * so a later store won't put it back.
> + */
> +static int arch_set_single_step(CPUState *cpu, bool enable)
> +{
> +    X86CPU *x86cpu = X86_CPU(cpu);
> +    CPUX86State *env = &x86cpu->env;
> +    hv_register_assoc assoc = { .name = HV_X64_REGISTER_RFLAGS };
> +    uint64_t rflags;
> +    int ret;
> +
> +    if (env->regs_page && env->regs_page->isvalid != 0) {
> +        rflags = env->regs_page->rflags;
> +        rflags = enable ? (rflags | TF_MASK) : (rflags & ~TF_MASK);
> +        env->regs_page->rflags = rflags;
> +        env->regs_page->dirty |= (1u << HV_X64_REGISTER_CLASS_FLAGS);
> +        return 0;
> +    }
> +
> +    ret = mshv_get_generic_regs(cpu, &assoc, 1);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    rflags = assoc.value.reg64;
> +    rflags = enable ? (rflags | TF_MASK) : (rflags & ~TF_MASK);
> +    assoc.value.reg64 = rflags;
> +    return mshv_set_generic_regs(cpu, &assoc, 1);
> +}
> +
>  int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit)
>  {
>      int ret;
>      enum MshvVmExit exit_reason;
>      int cpu_fd = mshv_vcpufd(cpu);
> +    bool single_step;
> +
> +    /* enable single stepping by flipping RFLAGS.TF */
> +    single_step = cpu_single_stepping(cpu);
> +    if (single_step) {
> +        ret = arch_set_single_step(cpu, true);
> +        if (ret < 0) {
> +            error_report("Failed to arm single-step (TF) on vcpu %d: %s",
> +                         cpu->cpu_index, strerror(-ret));
> +            *exit = MshvVmExitShutdown;
> +            return -1;
> +        }
> +    }
>  
>      ret = ioctl(cpu_fd, MSHV_RUN_VP, msg);
>      if (ret < 0) {
>          return MshvVmExitShutdown;
>      }
>  
> +    /* disable single stepping by flipping RFLAGS.TF */
> +    if (single_step && arch_set_single_step(cpu, false) < 0) {
> +        error_report("Failed to clear single-step (TF) on vcpu %d",
> +                     cpu->cpu_index);
> +        return -1;
> +    }
> +
>      switch (msg->header.message_type) {
>      case HVMSG_UNRECOVERABLE_EXCEPTION:
>          return MshvVmExitShutdown;
> -- 
> 2.53.0

Reviewed-by: Magnus Kulke <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.