On 12/14/20 8:39 AM, David Woodhouse wrote: > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index df44d9e50adc..e627139cf8cd 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -8896,7 +8896,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > kvm_x86_ops.msr_filter_changed(vcpu); > } > > - if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) { > + if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win || > + kvm_xen_has_interrupt(vcpu)) { > ++vcpu->stat.req_event; > kvm_apic_accept_events(vcpu); > if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { > diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c > index 17cbb4462b7e..4bc9da9fcfb8 100644 > --- a/arch/x86/kvm/xen.c > +++ b/arch/x86/kvm/xen.c > @@ -176,6 +176,45 @@ void kvm_xen_setup_runstate_page(struct kvm_vcpu *v) > kvm_xen_update_runstate(v, RUNSTATE_running, steal_time); > } > > +int kvm_xen_has_interrupt(struct kvm_vcpu *v) > +{ > + u8 rc = 0; > + > + /* > + * If the global upcall vector (HVMIRQ_callback_vector) is set and > + * the vCPU's evtchn_upcall_pending flag is set, the IRQ is pending. > + */ > + if (v->arch.xen.vcpu_info_set && v->kvm->arch.xen.upcall_vector) { > + struct gfn_to_hva_cache *ghc = &v->arch.xen.vcpu_info_cache; > + struct kvm_memslots *slots = kvm_memslots(v->kvm); > + unsigned int offset = offsetof(struct vcpu_info, evtchn_upcall_pending); > + To have less nesting, wouldn't it be better to invert the logic? say: u8 rc = 0; struct gfn_to_hva_cache *ghc struct kvm_memslots *slots; unsigned int offset; if (!v->arch.xen.vcpu_info_set || !v->kvm->arch.xen.upcall_vector) return 0; BUILD_BUG_ON(...) ghc = &v->arch.xen.vcpu_info_cache; slots = kvm_memslots(v->kvm); offset = offsetof(struct vcpu_info, evtchn_upcall_pending); But I think there's a flaw here. That is handling the case where you don't have a vcpu_info registered, and only shared info. The vcpu_info is then placed elsewhere, i.e. another offset out of shared_info -- which is *I think* the case for PVHVM Windows guests. Perhaps introducing a helper which adds xen_vcpu_info() and returns you the hva (picking the right cache) similar to the RFC patch. Albeit that was with page pinning, but borrowing an older version I had with hva_to_gfn_cache incantation would probably look like: if (v->arch.xen.vcpu_info_set) { ghc = &v->arch.xen.vcpu_info_cache; } else { ghc = &v->arch.xen.vcpu_info_cache; offset += offsetof(struct shared_info, vcpu_info); offset += (v - kvm_get_vcpu_by_id(0)) * sizeof(struct vcpu_info); } if (likely(slots->generation == ghc->generation && !kvm_is_error_hva(ghc->hva) && ghc->memslot)) { /* Fast path */ __get_user(rc, (u8 __user *)ghc->hva + offset); } else { /* Slow path */ kvm_read_guest_offset_cached(v->kvm, ghc, &rc, offset, sizeof(rc)); } ? Joao