Gleb Natapov wrote on 2012-12-11:
> On Tue, Dec 11, 2012 at 12:05:39PM +0000, Zhang, Yang Z wrote:
>> Gleb Natapov wrote on 2012-12-11:
>>> Looks very good overall. Are you testing this with vid disabled with
>>> Linux/Windows guests? Small comments below.
>> Yes. I tested rhel6u3, rhel5u4, winxp and win7. All of them work well
>> with and without vid enabled.
>> 
>>> On Mon, Dec 10, 2012 at 03:20:39PM +0800, Yang Zhang wrote:
>>>> Virtual interrupt delivery avoids KVM to inject vAPIC interrupts
>>>> manually, which is fully taken care of by the hardware. This needs
>>>> some special awareness into existing interrupr injection path:
>>>> 
>>>> - for pending interrupt, instead of direct injection, we may need
>>>>   update architecture specific indicators before resuming to guest. -
>>>>   A pending interrupt, which is masked by ISR, should be also
>>>>   considered in above update action, since hardware will decide when
>>>>   to inject it at right time. Current has_interrupt and get_interrupt
>>>>   only returns a valid vector from injection p.o.v.
>>>> Signed-off-by: Kevin Tian <[email protected]>
>>>> Signed-off-by: Yang Zhang <[email protected]>
>>>> ---
>>>>  arch/ia64/kvm/lapic.h           |    6 ++
>>>>  arch/x86/include/asm/kvm_host.h |    5 ++
> arch/x86/include/asm/vmx.h
>>>>     |   11 ++++ arch/x86/kvm/irq.c              |   76
>>>>  ++++++++++++++++++++++------ arch/x86/kvm/lapic.c            | 99
>>>>  +++++++++++++++++++++++++++++++++--- arch/x86/kvm/lapic.h
> |
>>>>     9 +++ arch/x86/kvm/svm.c              |   25 +++++++++
>>>>  arch/x86/kvm/vmx.c              |  104
>>>>  +++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/x86.c
>>>>   |   18 ++++--- include/linux/kvm_host.h        |    2 +
>>>>  virt/kvm/ioapic.c               |   35 +++++++++++++
> virt/kvm/ioapic.h
>>>>                |    1 + virt/kvm/irq_comm.c             |   18
> +++++++
>>>>  13 files changed, 372 insertions(+), 37 deletions(-)
>>>> diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
>>>> index c5f92a9..cb59eb4 100644
>>>> --- a/arch/ia64/kvm/lapic.h
>>>> +++ b/arch/ia64/kvm/lapic.h
>>>> @@ -27,4 +27,10 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
>>> kvm_lapic_irq *irq);
>>>>  #define kvm_apic_present(x) (true)
>>>>  #define kvm_lapic_enabled(x) (true)
>>>> +static inline void kvm_update_eoi_exitmap(struct kvm *kvm,
>>>> +                                  struct kvm_lapic_irq *irq)
>>>> +{
>>>> +  /* IA64 has no apicv supporting, do nothing here */
>>>> +}
>>>> +
>>>>  #endif
>>>> diff --git a/arch/x86/include/asm/kvm_host.h
>>>> b/arch/x86/include/asm/kvm_host.h index dc87b65..d797ade 100644 ---
>>>> a/arch/x86/include/asm/kvm_host.h +++
>>>> b/arch/x86/include/asm/kvm_host.h @@ -697,6 +697,10 @@ struct
>>>> kvm_x86_ops {
>>>>    void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
>>>>    void (*enable_irq_window)(struct kvm_vcpu *vcpu);
>>>>    void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
>>>> +  int (*has_virtual_interrupt_delivery)(struct kvm_vcpu *vcpu);
>>>> +  void (*update_irq)(struct kvm_vcpu *vcpu, int max_irr);
>>> Lets call it update_apic_irq since this is what is does.
>> Ok.
>> 
>>>> +/*
>>>>   * Read pending interrupt vector and intack.
>>>>   */
>>>>  int kvm_cpu_get_interrupt(struct kvm_vcpu *v) { - struct kvm_pic *s;
>>>>    int vector;
>>>>  
>>>>    if (!irqchip_in_kernel(v->kvm))
>>>>            return v->arch.interrupt.nr;
>>>> -  vector = kvm_get_apic_interrupt(v);     /* APIC */
>>>> -  if (vector == -1) {
>>>> -          if (kvm_apic_accept_pic_intr(v)) {
>>>> -                  s = pic_irqchip(v->kvm);
>>>> -                  s->output = 0;          /* PIC */
>>>> -                  vector = kvm_pic_read_irq(v->kvm);
>>>> -          }
>>>> +  if (kvm_apic_vid_enabled(v))
>>>> +          vector = kvm_cpu_get_extint(v); /* non-APIC */
>>>> +  else {
>>>> +          vector = kvm_get_apic_interrupt(v);     /* APIC */
>>>> +          if (vector == -1)
>>>> +                  vector = kvm_cpu_get_extint(v); /* non-APIC */
>>>>    }
>>> I've send the patch to fix ExtINT handling. Can you review it and rebase on
>>> top of it?
>> Sorry. I missed it.
> http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/102159.
> 
>>> From performance point, I thought this is not friendly. As we known, Extint
> interrupt is used rarely(it may only exist when in virtual wire mode).
> When guest boot up, it is in apic mode. So most of time, interrupts are
> went to apic not pic. And it seems check extint first is unnecessary.
> From my point, if there is no correctness issue, virtualization isn't
> force to follow the hardware's behavior. We try to follow hardware
> behavior as close as possible and when we fail to do so we often regret
> it. Furthermore we do not want to have different behaviour with and
> without vid. kvm_cpu_has_interrupt() can continue checking apic before
> ExtINT since this will not change function return value, but without
> evidence of performance degradation I prefer kvm_cpu_has_interrupt() and
> kvm_cpu_get_interrupt() to have similar logic. kvm_cpu_has_interrupt()
> is called relatively rare (only when KVM_REQ_EVENT is set) and the check
> is very light and can be optimized further.
Ok. We can optimized it further if it really cause problem.
I will rebase the patch based on this. 

>> 
>>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>>> index 3bdaf29..060f36b 100644
>>>> --- a/arch/x86/kvm/x86.c
>>>> +++ b/arch/x86/kvm/x86.c
>>>> @@ -5534,12 +5534,10 @@ static void inject_pending_event(struct
> kvm_vcpu
>>> *vcpu)
>>>>                    vcpu->arch.nmi_injected = true;
>>>>                    kvm_x86_ops->set_nmi(vcpu);
>>>>            }
>>>> -  } else if (kvm_cpu_has_interrupt(vcpu)) { -             if
>>>> (kvm_x86_ops->interrupt_allowed(vcpu)) {
>>>> -                  kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu), 
>>>> -                                           
>>>> false); -                  kvm_x86_ops->set_irq(vcpu); -           } +     
>>>> } else if
>>>> (kvm_cpu_has_injectable_intr(vcpu) &&
>>>> +                  kvm_x86_ops->interrupt_allowed(vcpu)) {
>>>> +          kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu), false);
>>>> +          kvm_x86_ops->set_irq(vcpu);
>>> Please do not change indentation unnecessary. Now this block has
>>> different one from previous. Ok.
>>> 
>>>>    }
>>>>  }
>>>> @@ -5655,6 +5653,8 @@ static int vcpu_enter_guest(struct kvm_vcpu
> *vcpu)
>>>>                    kvm_handle_pmu_event(vcpu);
>>>>            if (kvm_check_request(KVM_REQ_PMI, vcpu))
>>>>                    kvm_deliver_pmi(vcpu);
>>>> +          if (kvm_check_request(KVM_REQ_EOIBITMAP, vcpu))
>>>> +                  kvm_x86_ops->load_eoi_exitmap(vcpu);
>>>>    }
>>>>  
>>>>    if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
>>>> @@ -5663,10 +5663,14 @@ static int vcpu_enter_guest(struct kvm_vcpu
>>> *vcpu)
>>>>            /* enable NMI/IRQ window open exits if needed */
>>>>            if (vcpu->arch.nmi_pending)
>>>>                    kvm_x86_ops->enable_nmi_window(vcpu);
>>>> -          else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
>>>> +          else if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win)
>>>>                    kvm_x86_ops->enable_irq_window(vcpu);
>>>>  
>>>>            if (kvm_lapic_enabled(vcpu)) {
>>>> +                  /* update archtecture specific hints for APIC
>>>> +                   * virtual interrupt delivery */
>>>> +                  kvm_x86_ops->update_irq(vcpu,
>>>> +                                  kvm_lapic_find_highest_irr(vcpu));
>>> Hmm, OK so now we scan IRR even if vid is not enabled. Yeah, I know I
>>> suggested it :). So lets do it similarly to cr8_update callback. If vid is
>>> disabled set kvm_x86_ops->update_irq to NULL. Here do
>>>   if (kvm_x86_ops->update_apic_irq)
>>>      kvm_x86_ops->update_apic_irq(vcpu,
> kvm_lapic_find_highest_irr(vcpu));
>>> Or write small helper function like update_cr8_intercept() below.
>> Ok.
>> 
>>>> diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
>>>> index cfb7e4d..e214ea4 100644
>>>> --- a/virt/kvm/ioapic.c
>>>> +++ b/virt/kvm/ioapic.c
>>>> @@ -115,6 +115,40 @@ static void update_handled_vectors(struct
> kvm_ioapic
>>> *ioapic)
>>>>    smp_wmb();
>>>>  }
>>>> +static void ioapic_update_eoi_exitmap_one(struct kvm_ioapic *ioapic,
>>>> int pin) +{ +      union kvm_ioapic_redirect_entry *e; + + e =
>>>> &ioapic->redirtbl[pin]; + +        /* PIT is a special case: which is edge
>>>> trig but have EOI hook. +   * Always set the eoi exit bitmap for PIT
>>>> interrupt*/
>>> Drop the comment.
>>> 
>>>> +  if (!e->fields.mask &&
>>> Drop this from here. You have it in the caller now.
>> Ok.
>>>> diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
>>>> index 2eb58af..93ecd2a 100644
>>>> --- a/virt/kvm/irq_comm.c
>>>> +++ b/virt/kvm/irq_comm.c
>>>> @@ -178,6 +178,24 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id,
>>> u32 irq, int level)
>>>>    return ret;
>>>>  }
>>>> +bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip,
>>>> unsigned pin) +{ + struct kvm_irq_ack_notifier *kian; +    struct
>>>> hlist_node *n; +   int gsi; + +    rcu_read_lock(); +      gsi =
>>>> rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; +   if (gsi !=
>>>> -1) +              hlist_for_each_entry_rcu(kian, n, 
>>>> &kvm->irq_ack_notifier_list,
>>>> +                                   link) +                        if 
>>>> (kian->gsi == gsi) +                         return true;
>>>> +  rcu_read_unlock(); + +  return false; +} +
>>> Shouldn't you call ioapic_update_eoi_exitmap() in
>>> kvm_(un)register_irq_ack_notifier() too?
>> Right. Will add it in next patch.
>> 
>> Best regards,
>> Yang
>> 
> 
> --
>                       Gleb.


Best regards,
Yang

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to