diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c index 410320cb6a..dceed2c9f9 100644 --- a/xen/arch/x86/hvm/viridian.c +++ b/xen/arch/x86/hvm/viridian.c @@ -252,7 +252,6 @@ static void initialize_apic_assist(struct vcpu *v) if ( viridian_feature_mask(v->domain) & HVMPV_apic_assist ) { v->arch.hvm_vcpu.viridian.apic_assist.va = va; - v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; return; } @@ -288,12 +287,15 @@ void viridian_start_apic_assist(struct vcpu *v, int vector) if ( !va ) return; + if ( vector < 0x10 ) + return; + /* * If there is already an assist pending then something has gone * wrong and the VM will most likely hang so force a crash now * to make the problem clear. */ - if ( v->arch.hvm_vcpu.viridian.apic_assist.vector >= 0 ) + if ( v->arch.hvm_vcpu.viridian.apic_assist.vector ) domain_crash(v->domain); v->arch.hvm_vcpu.viridian.apic_assist.vector = vector; @@ -306,13 +308,13 @@ int viridian_complete_apic_assist(struct vcpu *v) int vector; if ( !va ) - return -1; + return 0; if ( *va & 1u ) - return -1; /* Interrupt not yet processed by the guest. */ + return 0; /* Interrupt not yet processed by the guest. */ vector = v->arch.hvm_vcpu.viridian.apic_assist.vector; - v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; + v->arch.hvm_vcpu.viridian.apic_assist.vector = 0; return vector; } @@ -325,7 +327,7 @@ void viridian_abort_apic_assist(struct vcpu *v) return; *va &= ~1u; - v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; + v->arch.hvm_vcpu.viridian.apic_assist.vector = 0; } static void update_reference_tsc(struct domain *d, bool_t initialize) @@ -806,7 +808,8 @@ static int viridian_save_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h) for_each_vcpu( d, v ) { struct hvm_viridian_vcpu_context ctxt; - ctxt.apic_assist = v->arch.hvm_vcpu.viridian.apic_assist.msr.raw; + ctxt.apic_assist_msr = v->arch.hvm_vcpu.viridian.apic_assist.msr.raw; + ctxt.apic_assist_vector = v->arch.hvm_vcpu.viridian.apic_assist.vector; if ( hvm_save_entry(VIRIDIAN_VCPU, v->vcpu_id, h, &ctxt) != 0 ) return 1; @@ -829,13 +832,15 @@ static int viridian_load_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h) return -EINVAL; } - if ( hvm_load_entry(VIRIDIAN_VCPU, h, &ctxt) != 0 ) + if ( hvm_load_entry_zeroextend(VIRIDIAN_VCPU, h, &ctxt) != 0 ) return -EINVAL; - v->arch.hvm_vcpu.viridian.apic_assist.msr.raw = ctxt.apic_assist; + v->arch.hvm_vcpu.viridian.apic_assist.msr.raw = ctxt.apic_assist_msr; if ( v->arch.hvm_vcpu.viridian.apic_assist.msr.fields.enabled ) initialize_apic_assist(v); + v->arch.hvm_vcpu.viridian.apic_assist.vector = ctxt.apic_assist_vector; + return 0; } diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index f36eff7d8a..e2f44501b1 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -1189,7 +1189,7 @@ int vlapic_has_pending_irq(struct vcpu *v) * comparing with the IRR. */ vector = viridian_complete_apic_assist(v); - if ( vector != -1 ) + if ( vector ) vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]); isr = vlapic_find_highest_isr(vlapic); diff --git a/xen/include/public/arch-x86/hvm/save.h b/xen/include/public/arch-x86/hvm/save.h index fbd1c6abca..8d73b51f06 100644 --- a/xen/include/public/arch-x86/hvm/save.h +++ b/xen/include/public/arch-x86/hvm/save.h @@ -588,7 +588,9 @@ struct hvm_viridian_domain_context { DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context); struct hvm_viridian_vcpu_context { - uint64_t apic_assist; + uint64_t apic_assist_msr; + uint8_t apic_assist_vector; + uint8_t _pad[7]; }; DECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);