|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode
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>
---
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |