[PATCH v1 2/2] x86/viridian: Implement synthetic timer direct mode
Ross Lagerwall <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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