[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 2/3] x86/viridian: Implement synthetic timer direct mode



On Fri, Sep 04, 2026 at 03:15:15PM +0100, Ross Lagerwall wrote:
> In direct mode, the timer asserts an interrupt on expiration rather than
> using a SynIC message. It is useful to implement this since Windows 11's
> Hyper-V can only use synthetic timers in direct mode.
> 
> Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
> ---
> 
> In v2:
> 
> * Handle migration from older Xen by introducing a new Viridian flag.
> * Added more sanity checks during MSR write and vCPU context load.
> 
>  xen/arch/x86/hvm/viridian/time.c     | 46 ++++++++++++++++++++++++----
>  xen/arch/x86/hvm/viridian/viridian.c |  3 ++
>  xen/include/public/hvm/params.h      |  7 ++++-
>  3 files changed, 49 insertions(+), 7 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/viridian/time.c 
> b/xen/arch/x86/hvm/viridian/time.c
> index 082528dc9416..4c8352612b19 100644
> --- a/xen/arch/x86/hvm/viridian/time.c
> +++ b/xen/arch/x86/hvm/viridian/time.c
> @@ -223,6 +223,14 @@ static void start_stimer(struct viridian_stimer *vs)
>      set_timer(&vs->timer, timeout + NOW());
>  }
>  
> +static void stimer_deliver_direct(struct vcpu *v, const struct 
> viridian_stimer *vs)
> +{
> +    struct vlapic *vlapic = vcpu_vlapic(v);
> +
> +    if ( vlapic_enabled(vlapic) )
> +        vlapic_set_irq(vlapic, vs->config.apic_vector, 0);
> +}
> +
>  static void poll_stimer(struct vcpu *v, unsigned int stimerx)
>  {
>      struct viridian_vcpu *vv = v->arch.hvm.viridian;
> @@ -242,9 +250,11 @@ static void poll_stimer(struct vcpu *v, unsigned int 
> stimerx)
>      if ( !test_bit(stimerx, &vv->stimer_pending) )
>          return;
>  
> -    if ( !viridian_synic_deliver_timer_msg(v, vs->config.sintx,
> -                                           stimerx, vs->expiration,
> -                                           time_ref_count(v->domain)) )
> +    if ( vs->config.direct_mode )
> +        stimer_deliver_direct(v, vs);
> +    else if ( !viridian_synic_deliver_timer_msg(v, vs->config.sintx,
> +                                                stimerx, vs->expiration,
> +                                                time_ref_count(v->domain)) )
>          return;
>  
>      clear_bit(stimerx, &vv->stimer_pending);
> @@ -361,6 +371,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, 
> uint64_t val)
>      case HV_X64_MSR_STIMER2_CONFIG:
>      case HV_X64_MSR_STIMER3_CONFIG:
>      {
> +        union hv_stimer_config new;
>          unsigned int stimerx = (idx - HV_X64_MSR_STIMER0_CONFIG) / 2;
>          struct viridian_stimer *vs =
>              &array_access_nospec(vv->stimer, stimerx);
> @@ -368,11 +379,18 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, 
> uint64_t val)
>          if ( !(viridian_feature_mask(d) & HVMPV_stimer) )
>              return X86EMUL_EXCEPTION;
>  
> +        new.as_uint64 = val;
> +        if ( new.direct_mode &&
> +             !(viridian_feature_mask(d) & HVMPV_stimer_direct) )
> +            return X86EMUL_EXCEPTION;

Do we know whether native HyperV also injects a #GP in case of setting
reserved bits on the register?

To keep the previous behavior, should Xen silently ignore the setting
when not supported, like it did in the past?

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.