All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/2] Viridian changes for Hyper-V as a guest
@ 2026-08-28 13:11 Ross Lagerwall
  2026-08-28 13:11 ` [PATCH v1 1/2] x86/viridian: Workaround Hyper-V GP fault writing to MSR Ross Lagerwall
  2026-08-28 13:11 ` [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode Ross Lagerwall
  0 siblings, 2 replies; 5+ messages in thread
From: Ross Lagerwall @ 2026-08-28 13:11 UTC (permalink / raw)
  To: xen-devel
  Cc: Ross Lagerwall, Paul Durrant, Jan Beulich, Andrew Cooper,
	Roger Pau Monné, Teddy Astie

Hi,

Here are two changes to get the existing Virdian enlightenments working
when running a Windows 11 guest with Hyper-V enabled

Hyper-V also depends on some unimplemented MSRs to boot, but that will
be addressed in a separate series.

Thanks,
Ross


Ross Lagerwall (2):
  x86/viridian: Workaround Hyper-V GP fault writing to MSR
  x86/viridian: Implement synthetic timer direct mode

 xen/arch/x86/hvm/viridian/synic.c    |  3 +++
 xen/arch/x86/hvm/viridian/time.c     | 25 +++++++++++++++++++------
 xen/arch/x86/hvm/viridian/viridian.c |  3 +++
 3 files changed, 25 insertions(+), 6 deletions(-)

-- 
2.53.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v1 1/2] x86/viridian: Workaround Hyper-V GP fault writing to MSR
  2026-08-28 13:11 [PATCH v1 0/2] Viridian changes for Hyper-V as a guest Ross Lagerwall
@ 2026-08-28 13:11 ` Ross Lagerwall
  2026-08-28 13:11 ` [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode Ross Lagerwall
  1 sibling, 0 replies; 5+ messages in thread
From: Ross Lagerwall @ 2026-08-28 13:11 UTC (permalink / raw)
  To: xen-devel
  Cc: Ross Lagerwall, Paul Durrant, Jan Beulich, Andrew Cooper,
	Roger Pau Monné, Teddy Astie

The Viridian spec requires the vector to be >= 0x10 when writing to the
SINTx MSR, otherwise it should #GP fault.
The spec-defined initial value is 0x0000000000010000, i.e. the vector is
0. On startup, for some reason Windows 11 Hyper-V tries to set the MSR to
the spec-defined initial value and since the vector is 0, it GP faults.
To workaround this, treat the write as a no-op if the value is
unchanged.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 xen/arch/x86/hvm/viridian/synic.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/xen/arch/x86/hvm/viridian/synic.c b/xen/arch/x86/hvm/viridian/synic.c
index e6cba7548f1b..37ddff201a6b 100644
--- a/xen/arch/x86/hvm/viridian/synic.c
+++ b/xen/arch/x86/hvm/viridian/synic.c
@@ -157,6 +157,9 @@ int viridian_synic_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
         if ( !(viridian_feature_mask(d) & HVMPV_synic) )
             return X86EMUL_EXCEPTION;
 
+        if ( val == vs->as_uint64 )
+            break;
+
         /* Vectors must be in the range 0x10-0xff inclusive */
         new.as_uint64 = val;
         if ( new.vector < 0x10 )
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode
  2026-08-28 13:11 [PATCH v1 0/2] Viridian changes for Hyper-V as a guest Ross Lagerwall
  2026-08-28 13:11 ` [PATCH v1 1/2] x86/viridian: Workaround Hyper-V GP fault writing to MSR Ross Lagerwall
@ 2026-08-28 13:11 ` Ross Lagerwall
  2026-08-28 14:11   ` Tu Dinh
  1 sibling, 1 reply; 5+ messages in thread
From: Ross Lagerwall @ 2026-08-28 13:11 UTC (permalink / raw)
  To: xen-devel
  Cc: Ross Lagerwall, Paul Durrant, Jan Beulich, Andrew Cooper,
	Roger Pau Monné, Teddy Astie

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@citrix.com>
---

Should this use a new Viridian feature bit or is it OK to use the
existing stimer bit?

 xen/arch/x86/hvm/viridian/time.c     | 25 +++++++++++++++++++------
 xen/arch/x86/hvm/viridian/viridian.c |  3 +++
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/hvm/viridian/time.c b/xen/arch/x86/hvm/viridian/time.c
index 082528dc9416..2b0ac3eac963 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, struct viridian_stimer *vs)
+{
+    struct vlapic *vlapic = vcpu_vlapic(v);
+
+    if ( vlapic_enabled(vlapic) )
+        vlapic_set_irq(vcpu_vlapic(v), 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);
@@ -372,7 +382,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
 
         vs->config.as_uint64 = val;
 
-        if ( !vs->config.sintx || !vs->count )
+        if ( (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
             vs->config.enable = 0;
 
         if ( vs->config.enable )
@@ -583,8 +593,11 @@ void viridian_time_load_vcpu_ctxt(
 
         vs->config.as_uint64 = ctxt->stimer_config_msr[i];
         vs->count = ctxt->stimer_count_msr[i];
-        if ( !vs->config.sintx || !vs->count )
-            /* Reject enabling with a zero sintx or count fields. */
+        if ( (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
+            /*
+             * Reject enabling with a zero sintx (if not using direct mode) or
+             * zero count field.
+             */
             vs->config.enable = 0;
     }
 }
diff --git a/xen/arch/x86/hvm/viridian/viridian.c b/xen/arch/x86/hvm/viridian/viridian.c
index 90e749ceb581..99192e8d077d 100644
--- a/xen/arch/x86/hvm/viridian/viridian.c
+++ b/xen/arch/x86/hvm/viridian/viridian.c
@@ -78,6 +78,7 @@ typedef union _HV_CRASH_CTL_REG_CONTENTS
 #define CPUID3D_CPU_DYNAMIC_PARTITIONING (1 << 3)
 #define CPUID3D_CRASH_MSRS (1 << 10)
 #define CPUID3D_SINT_POLLING (1 << 17)
+#define CPUID3D_STIMER_DIRECT_MODE (1 << 19)
 
 /* Viridian CPUID leaf 4: Implementation Recommendations. */
 #define CPUID4A_HCALL_REMOTE_TLB_FLUSH (1 << 2)
@@ -185,6 +186,8 @@ void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
             res->d |= CPUID3D_CRASH_MSRS;
         if ( viridian_feature_mask(d) & HVMPV_synic )
             res->d |= CPUID3D_SINT_POLLING;
+        if ( viridian_feature_mask(d) & HVMPV_stimer )
+            res->d |= CPUID3D_STIMER_DIRECT_MODE;
 
         break;
     }
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode
  2026-08-28 13:11 ` [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode Ross Lagerwall
@ 2026-08-28 14:11   ` Tu Dinh
  2026-08-28 14:17     ` Ross Lagerwall
  0 siblings, 1 reply; 5+ messages in thread
From: Tu Dinh @ 2026-08-28 14:11 UTC (permalink / raw)
  To: Ross Lagerwall, xen-devel
  Cc: Paul Durrant, Jan Beulich, Andrew Cooper, Roger Pau Monné,
	Teddy Astie

[-- Attachment #1: Type: text/plain, Size: 4345 bytes --]

On 28/08/2026 15:14, 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.

Hello, is this new behavior compared to Server 2025? What happens if 
direct mode is not available, does it fall back to disabling stimer?

> 
> Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
> ---
> 
> Should this use a new Viridian feature bit or is it OK to use the
> existing stimer bit?
> 
>   xen/arch/x86/hvm/viridian/time.c     | 25 +++++++++++++++++++------
>   xen/arch/x86/hvm/viridian/viridian.c |  3 +++
>   2 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/viridian/time.c b/xen/arch/x86/hvm/viridian/time.c
> index 082528dc9416..2b0ac3eac963 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, struct viridian_stimer *vs)
> +{
> +    struct vlapic *vlapic = vcpu_vlapic(v);
> +
> +    if ( vlapic_enabled(vlapic) )
> +        vlapic_set_irq(vcpu_vlapic(v), 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);
> @@ -372,7 +382,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
>   
>           vs->config.as_uint64 = val;
>   
> -        if ( !vs->config.sintx || !vs->count )
> +        if ( (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
>               vs->config.enable = 0;
>   
>           if ( vs->config.enable )
> @@ -583,8 +593,11 @@ void viridian_time_load_vcpu_ctxt(
>   
>           vs->config.as_uint64 = ctxt->stimer_config_msr[i];
>           vs->count = ctxt->stimer_count_msr[i];
> -        if ( !vs->config.sintx || !vs->count )
> -            /* Reject enabling with a zero sintx or count fields. */
> +        if ( (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
> +            /*
> +             * Reject enabling with a zero sintx (if not using direct mode) or
> +             * zero count field.
> +             */
>               vs->config.enable = 0;
>       }
>   }
> diff --git a/xen/arch/x86/hvm/viridian/viridian.c b/xen/arch/x86/hvm/viridian/viridian.c
> index 90e749ceb581..99192e8d077d 100644
> --- a/xen/arch/x86/hvm/viridian/viridian.c
> +++ b/xen/arch/x86/hvm/viridian/viridian.c
> @@ -78,6 +78,7 @@ typedef union _HV_CRASH_CTL_REG_CONTENTS
>   #define CPUID3D_CPU_DYNAMIC_PARTITIONING (1 << 3)
>   #define CPUID3D_CRASH_MSRS (1 << 10)
>   #define CPUID3D_SINT_POLLING (1 << 17)
> +#define CPUID3D_STIMER_DIRECT_MODE (1 << 19)
>   
>   /* Viridian CPUID leaf 4: Implementation Recommendations. */
>   #define CPUID4A_HCALL_REMOTE_TLB_FLUSH (1 << 2)
> @@ -185,6 +186,8 @@ void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf,
>               res->d |= CPUID3D_CRASH_MSRS;
>           if ( viridian_feature_mask(d) & HVMPV_synic )
>               res->d |= CPUID3D_SINT_POLLING;
> +        if ( viridian_feature_mask(d) & HVMPV_stimer )
> +            res->d |= CPUID3D_STIMER_DIRECT_MODE;
>   
>           break;
>       }



--
Ngoc Tu Dinh | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode
  2026-08-28 14:11   ` Tu Dinh
@ 2026-08-28 14:17     ` Ross Lagerwall
  0 siblings, 0 replies; 5+ messages in thread
From: Ross Lagerwall @ 2026-08-28 14:17 UTC (permalink / raw)
  To: Tu Dinh, xen-devel
  Cc: Paul Durrant, Jan Beulich, Andrew Cooper, Roger Pau Monné,
	Teddy Astie

On 8/28/26 3:11 PM, Tu Dinh wrote:
> On 28/08/2026 15:14, 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.
> 
> Hello, is this new behavior compared to Server 2025? What happens if
> direct mode is not available, does it fall back to disabling stimer?

No, it's not new behaviour. According to Linux commit 8644f771e07c it
has been this way since 2016. If direct mode is not available, the VM
still works but without using synthetic timers.

Ross


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-28 14:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 13:11 [PATCH v1 0/2] Viridian changes for Hyper-V as a guest Ross Lagerwall
2026-08-28 13:11 ` [PATCH v1 1/2] x86/viridian: Workaround Hyper-V GP fault writing to MSR Ross Lagerwall
2026-08-28 13:11 ` [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode Ross Lagerwall
2026-08-28 14:11   ` Tu Dinh
2026-08-28 14:17     ` Ross Lagerwall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.