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

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


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
  • Date: Fri, 4 Sep 2026 15:15:15 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=QpE4bVBGUwH9EvsjPyq1mD2BzEXMSLIFuK5hnOBmzlQ=; b=L4UpoAMrtQFstWtHJlUyZ0L5hmcCjZ/yguXEa7Do8+mEY+GJUyBBvl2NsWY6+AFxe0UfstjoCsEuU9ItXswK+vE3mc6O5OayEvBzfi9YgnxA+CTe1rttGJBqwSzE85MfZtrKxlU2xTk3rFwBZX2C84TrtqsagB4prAkrUmuzB+BeFO6wBUTRU5K6hyOaymZ/tD3d4h8jq0azu+6gi2yGWV/Nel8/vu0AqRsv6oRGIdDMV9jtnOkArTohLjK3UW28f8jWKkxOhLkG9FCfD36MbSPlPnq9gxKxrDRvzRcCEDGLhCTfdJ5Kp8dWmezD752pKXyeOCEuxkQh/f5TXkYT3w==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=EHP6iTHLSpa/GUYjC8ITUSgVZVEaBFcEWHjtqCh+oLluXuZ30sBxcyDA+UR17d9wZ9lQJziTNxMKOddo7lPcHYn33QcPGpWb+xp39u4PheYKlNsD5u1rFous72L0I5sw40iG8eq3Q1bVICJHY4vcJm8eV3P6l83PQP6rGQObxliOxS1pT/Z8UCuEkaS4hNfQ6GjcZr2MFZduqX1aZuJSZiuM/7GignXmSaslHhAtf4c0zUD9m4wOfzmx/t/OEDlk2pJNny1dncpGb/k6cyGIvaDiPtR1PS0x8OJMc8JcWfvkSUEA9TSctsxcwnCv9cAG/fmmMYDgI9z6U9YnruqGuw==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>, Paul Durrant <paul@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Julien Grall <julien@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>
  • Delivery-date: Fri, 04 Sep 2026 14:15:41 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

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;
+
         stop_stimer(vs);
 
         vs->config.as_uint64 = val;
 
-        if ( !vs->config.sintx || !vs->count )
+        if ( (vs->config.direct_mode &&
+              (vs->config.sintx || vs->config.apic_vector < 0x10)) ||
+             (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
             vs->config.enable = 0;
 
         if ( vs->config.enable )
@@ -583,8 +601,24 @@ 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 &&
+             !(viridian_feature_mask(v->domain) & HVMPV_stimer_direct) )
+        {
+            /*
+             * Old Xen didn't support direct mode but it could still be enabled
+             * in the MSR. Disable it now to avoid unexpected behaviour.
+             */
+            vs->config.direct_mode = 0;
+        }
+
+        if ( (vs->config.direct_mode &&
+              (vs->config.sintx || vs->config.apic_vector < 0x10)) ||
+             (!vs->config.direct_mode && !vs->config.sintx) || !vs->count )
+            /*
+             * Disable if sanity checking direct mode / sintx / APIC vector
+             * fails, or if the count is zero.
+             */
             vs->config.enable = 0;
     }
 }
diff --git a/xen/arch/x86/hvm/viridian/viridian.c 
b/xen/arch/x86/hvm/viridian/viridian.c
index 90e749ceb581..90be5842b995 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_direct )
+            res->d |= CPUID3D_STIMER_DIRECT_MODE;
 
         break;
     }
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 99c40b4287f1..4db5142970c2 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -159,6 +159,10 @@
 #define _HVMPV_cpu_hotplug 12
 #define HVMPV_cpu_hotplug (1 << _HVMPV_cpu_hotplug)
 
+/* Enable STIMER direct mode */
+#define _HVMPV_stimer_direct 13
+#define HVMPV_stimer_direct (1 << _HVMPV_stimer_direct)
+
 #define HVMPV_feature_mask \
         (HVMPV_base_freq | \
          HVMPV_no_freq | \
@@ -172,7 +176,8 @@
          HVMPV_hcall_ipi | \
          HVMPV_ex_processor_masks | \
          HVMPV_no_vp_limit | \
-         HVMPV_cpu_hotplug)
+         HVMPV_cpu_hotplug | \
+         HVMPV_stimer_direct)
 
 #endif
 
-- 
2.53.0




 


Rackspace

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