Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1247257 > unrolled thread

Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when vCPU is blocked

Started byDavid Matlack <dmatlack@google.com>
First post2015-10-15 01:50 +0200
Last post2015-10-16 03:50 +0200
Articles 5 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when  vCPU is blocked David Matlack <dmatlack@google.com> - 2015-10-15 01:50 +0200
    RE: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when  vCPU is blocked "Wu, Feng" <feng.wu@intel.com> - 2015-10-15 03:40 +0200
      Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when  vCPU is blocked David Matlack <dmatlack@google.com> - 2015-10-15 19:40 +0200
        Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when  vCPU is blocked Paolo Bonzini <pbonzini@redhat.com> - 2015-10-15 20:20 +0200
          RE: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when  vCPU is blocked "Wu, Feng" <feng.wu@intel.com> - 2015-10-16 03:50 +0200

#1247257 — Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when vCPU is blocked

FromDavid Matlack <dmatlack@google.com>
Date2015-10-15 01:50 +0200
SubjectRe: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when vCPU is blocked
Message-ID<qjDXX-5He-3@gated-at.bofh.it>
Hi Feng.

On Fri, Sep 18, 2015 at 7:29 AM, Feng Wu <feng.wu@intel.com> wrote:
> This patch updates the Posted-Interrupts Descriptor when vCPU
> is blocked.
>
> pre-block:
> - Add the vCPU to the blocked per-CPU list
> - Set 'NV' to POSTED_INTR_WAKEUP_VECTOR
>
> post-block:
> - Remove the vCPU from the per-CPU list

I'm wondering what happens if a posted interrupt arrives at the IOMMU
after pre-block and before post-block.

In pre_block, NV is set to POSTED_INTR_WAKEUP_VECTOR. IIUC, this means
future posted interrupts will not trigger "Posted-Interrupt Processing"
(PIR will not get copied to VIRR). Instead, the IOMMU will do ON := 1,
PIR |= (1 << vector), and send POSTED_INTR_WAKEUP_VECTOR. PIWV calls
wakeup_handler which does kvm_vcpu_kick. kvm_vcpu_kick does a wait-queue
wakeup and possibly a scheduler ipi.

But the VCPU is sitting in kvm_vcpu_block. It spins and/or schedules
(wait queue) until it has a reason to wake up. I couldn't find a code
path from kvm_vcpu_block that lead to checking ON or PIR. How does the
blocked VCPU "receive" the posted interrupt? (And when does Posted-
Interrupt Processing get triggered?)

Thanks!

>
> Signed-off-by: Feng Wu <feng.wu@intel.com>
> ---
> v9:
> - Add description for blocked_vcpu_on_cpu_lock in Documentation/virtual/kvm/locking.txt
> - Check !kvm_arch_has_assigned_device(vcpu->kvm) first, then
>   !irq_remapping_cap(IRQ_POSTING_CAP)
>
> v8:
> - Rename 'pi_pre_block' to 'pre_block'
> - Rename 'pi_post_block' to 'post_block'
> - Change some comments
> - Only add the vCPU to the blocking list when the VM has assigned devices.
>
>  Documentation/virtual/kvm/locking.txt |  12 +++
>  arch/x86/include/asm/kvm_host.h       |  13 +++
>  arch/x86/kvm/vmx.c                    | 153 ++++++++++++++++++++++++++++++++++
>  arch/x86/kvm/x86.c                    |  53 +++++++++---
>  include/linux/kvm_host.h              |   3 +
>  virt/kvm/kvm_main.c                   |   3 +
>  6 files changed, 227 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virtual/kvm/locking.txt
> index d68af4d..19f94a6 100644
> --- a/Documentation/virtual/kvm/locking.txt
> +++ b/Documentation/virtual/kvm/locking.txt
> @@ -166,3 +166,15 @@ Comment:   The srcu read lock must be held while accessing memslots (e.g.
>                 MMIO/PIO address->device structure mapping (kvm->buses).
>                 The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
>                 if it is needed by multiple functions.
> +
> +Name:          blocked_vcpu_on_cpu_lock
> +Type:          spinlock_t
> +Arch:          x86
> +Protects:      blocked_vcpu_on_cpu
> +Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
> +               When VT-d posted-interrupts is supported and the VM has assigned
> +               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
> +               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues
> +               wakeup notification event since external interrupts from the
> +               assigned devices happens, we will find the vCPU on the list to
> +               wakeup.
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 0ddd353..304fbb5 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -552,6 +552,8 @@ struct kvm_vcpu_arch {
>          */
>         bool write_fault_to_shadow_pgtable;
>
> +       bool halted;
> +
>         /* set at EPT violation at this point */
>         unsigned long exit_qualification;
>
> @@ -864,6 +866,17 @@ struct kvm_x86_ops {
>         /* pmu operations of sub-arch */
>         const struct kvm_pmu_ops *pmu_ops;
>
> +       /*
> +        * Architecture specific hooks for vCPU blocking due to
> +        * HLT instruction.
> +        * Returns for .pre_block():
> +        *    - 0 means continue to block the vCPU.
> +        *    - 1 means we cannot block the vCPU since some event
> +        *        happens during this period, such as, 'ON' bit in
> +        *        posted-interrupts descriptor is set.
> +        */
> +       int (*pre_block)(struct kvm_vcpu *vcpu);
> +       void (*post_block)(struct kvm_vcpu *vcpu);
>         int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
>                               uint32_t guest_irq, bool set);
>  };
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 902a67d..9968896 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -879,6 +879,13 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
>  static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
>  static DEFINE_PER_CPU(struct desc_ptr, host_gdt);
>
> +/*
> + * We maintian a per-CPU linked-list of vCPU, so in wakeup_handler() we
> + * can find which vCPU should be waken up.
> + */
> +static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu);
> +static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
> +
>  static unsigned long *vmx_io_bitmap_a;
>  static unsigned long *vmx_io_bitmap_b;
>  static unsigned long *vmx_msr_bitmap_legacy;
> @@ -2985,6 +2992,8 @@ static int hardware_enable(void)
>                 return -EBUSY;
>
>         INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
> +       INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
> +       spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
>
>         /*
>          * Now we can enable the vmclear operation in kdump
> @@ -6121,6 +6130,25 @@ static void update_ple_window_actual_max(void)
>                                             ple_window_grow, INT_MIN);
>  }
>
> +/*
> + * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR.
> + */
> +static void wakeup_handler(void)
> +{
> +       struct kvm_vcpu *vcpu;
> +       int cpu = smp_processor_id();
> +
> +       spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
> +       list_for_each_entry(vcpu, &per_cpu(blocked_vcpu_on_cpu, cpu),
> +                       blocked_vcpu_list) {
> +               struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
> +
> +               if (pi_test_on(pi_desc) == 1)
> +                       kvm_vcpu_kick(vcpu);
> +       }
> +       spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
> +}
> +
>  static __init int hardware_setup(void)
>  {
>         int r = -ENOMEM, i, msr;
> @@ -6305,6 +6333,8 @@ static __init int hardware_setup(void)
>                 kvm_x86_ops->enable_log_dirty_pt_masked = NULL;
>         }
>
> +       kvm_set_posted_intr_wakeup_handler(wakeup_handler);
> +
>         return alloc_kvm_area();
>
>  out8:
> @@ -10430,6 +10460,126 @@ static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
>  }
>
>  /*
> + * This routine does the following things for vCPU which is going
> + * to be blocked if VT-d PI is enabled.
> + * - Store the vCPU to the wakeup list, so when interrupts happen
> + *   we can find the right vCPU to wake up.
> + * - Change the Posted-interrupt descriptor as below:
> + *      'NDST' <-- vcpu->pre_pcpu
> + *      'NV' <-- POSTED_INTR_WAKEUP_VECTOR
> + * - If 'ON' is set during this process, which means at least one
> + *   interrupt is posted for this vCPU, we cannot block it, in
> + *   this case, return 1, otherwise, return 0.
> + *
> + */
> +static int vmx_pre_block(struct kvm_vcpu *vcpu)
> +{
> +       unsigned long flags;
> +       unsigned int dest;
> +       struct pi_desc old, new;
> +       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
> +
> +       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
> +               !irq_remapping_cap(IRQ_POSTING_CAP))
> +               return 0;
> +
> +       vcpu->pre_pcpu = vcpu->cpu;
> +       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
> +                         vcpu->pre_pcpu), flags);
> +       list_add_tail(&vcpu->blocked_vcpu_list,
> +                     &per_cpu(blocked_vcpu_on_cpu,
> +                     vcpu->pre_pcpu));
> +       spin_unlock_irqrestore(&per_cpu(blocked_vcpu_on_cpu_lock,
> +                              vcpu->pre_pcpu), flags);
> +
> +       do {
> +               old.control = new.control = pi_desc->control;
> +
> +               /*
> +                * We should not block the vCPU if
> +                * an interrupt is posted for it.
> +                */
> +               if (pi_test_on(pi_desc) == 1) {
> +                       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
> +                                         vcpu->pre_pcpu), flags);
> +                       list_del(&vcpu->blocked_vcpu_list);
> +                       spin_unlock_irqrestore(
> +                                       &per_cpu(blocked_vcpu_on_cpu_lock,
> +                                       vcpu->pre_pcpu), flags);
> +                       vcpu->pre_pcpu = -1;
> +
> +                       return 1;
> +               }
> +
> +               WARN((pi_desc->sn == 1),
> +                    "Warning: SN field of posted-interrupts "
> +                    "is set before blocking\n");
> +
> +               /*
> +                * Since vCPU can be preempted during this process,
> +                * vcpu->cpu could be different with pre_pcpu, we
> +                * need to set pre_pcpu as the destination of wakeup
> +                * notification event, then we can find the right vCPU
> +                * to wakeup in wakeup handler if interrupts happen
> +                * when the vCPU is in blocked state.
> +                */
> +               dest = cpu_physical_id(vcpu->pre_pcpu);
> +
> +               if (x2apic_enabled())
> +                       new.ndst = dest;
> +               else
> +                       new.ndst = (dest << 8) & 0xFF00;
> +
> +               /* set 'NV' to 'wakeup vector' */
> +               new.nv = POSTED_INTR_WAKEUP_VECTOR;
> +       } while (cmpxchg(&pi_desc->control, old.control,
> +                       new.control) != old.control);
> +
> +       return 0;
> +}
> +
> +static void vmx_post_block(struct kvm_vcpu *vcpu)
> +{
> +       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
> +       struct pi_desc old, new;
> +       unsigned int dest;
> +       unsigned long flags;
> +
> +       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
> +               !irq_remapping_cap(IRQ_POSTING_CAP))
> +               return;
> +
> +       do {
> +               old.control = new.control = pi_desc->control;
> +
> +               dest = cpu_physical_id(vcpu->cpu);
> +
> +               if (x2apic_enabled())
> +                       new.ndst = dest;
> +               else
> +                       new.ndst = (dest << 8) & 0xFF00;
> +
> +               /* Allow posting non-urgent interrupts */
> +               new.sn = 0;
> +
> +               /* set 'NV' to 'notification vector' */
> +               new.nv = POSTED_INTR_VECTOR;
> +       } while (cmpxchg(&pi_desc->control, old.control,
> +                       new.control) != old.control);
> +
> +       if(vcpu->pre_pcpu != -1) {
> +               spin_lock_irqsave(
> +                       &per_cpu(blocked_vcpu_on_cpu_lock,
> +                       vcpu->pre_pcpu), flags);
> +               list_del(&vcpu->blocked_vcpu_list);
> +               spin_unlock_irqrestore(
> +                       &per_cpu(blocked_vcpu_on_cpu_lock,
> +                       vcpu->pre_pcpu), flags);
> +               vcpu->pre_pcpu = -1;
> +       }
> +}
> +
> +/*
>   * vmx_update_pi_irte - set IRTE for Posted-Interrupts
>   *
>   * @kvm: kvm
> @@ -10620,6 +10770,9 @@ static struct kvm_x86_ops vmx_x86_ops = {
>         .flush_log_dirty = vmx_flush_log_dirty,
>         .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked,
>
> +       .pre_block = vmx_pre_block,
> +       .post_block = vmx_post_block,
> +
>         .pmu_ops = &intel_pmu_ops,
>
>         .update_pi_irte = vmx_update_pi_irte,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 58688aa..46f55b2 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5869,7 +5869,12 @@ int kvm_vcpu_halt(struct kvm_vcpu *vcpu)
>  {
>         ++vcpu->stat.halt_exits;
>         if (irqchip_in_kernel(vcpu->kvm)) {
> -               vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
> +               /* Handle posted-interrupt when vCPU is to be halted */
> +               if (!kvm_x86_ops->pre_block ||
> +                               kvm_x86_ops->pre_block(vcpu) == 0) {
> +                       vcpu->arch.halted = true;
> +                       vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
> +               }
>                 return 1;
>         } else {
>                 vcpu->run->exit_reason = KVM_EXIT_HLT;
> @@ -6518,6 +6523,20 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>                         kvm_vcpu_reload_apic_access_page(vcpu);
>         }
>
> +       /*
> +        * KVM_REQ_EVENT is not set when posted interrupts are set by
> +        * VT-d hardware, so we have to update RVI unconditionally.
> +        */
> +       if (kvm_lapic_enabled(vcpu)) {
> +               /*
> +                * Update architecture specific hints for APIC
> +                * virtual interrupt delivery.
> +                */
> +               if (kvm_x86_ops->hwapic_irr_update)
> +                       kvm_x86_ops->hwapic_irr_update(vcpu,
> +                               kvm_lapic_find_highest_irr(vcpu));
> +       }
> +
>         if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
>                 kvm_apic_accept_events(vcpu);
>                 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
> @@ -6534,13 +6553,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>                         kvm_x86_ops->enable_irq_window(vcpu);
>
>                 if (kvm_lapic_enabled(vcpu)) {
> -                       /*
> -                        * Update architecture specific hints for APIC
> -                        * virtual interrupt delivery.
> -                        */
> -                       if (kvm_x86_ops->hwapic_irr_update)
> -                               kvm_x86_ops->hwapic_irr_update(vcpu,
> -                                       kvm_lapic_find_highest_irr(vcpu));
>                         update_cr8_intercept(vcpu);
>                         kvm_lapic_sync_to_vapic(vcpu);
>                 }
> @@ -6711,10 +6723,31 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
>
>         for (;;) {
>                 if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
> -                   !vcpu->arch.apf.halted)
> +                   !vcpu->arch.apf.halted) {
> +                       /*
> +                        * For some cases, we can get here with
> +                        * vcpu->arch.halted being true.
> +                        */
> +                       if (kvm_x86_ops->post_block && vcpu->arch.halted) {
> +                               kvm_x86_ops->post_block(vcpu);
> +                               vcpu->arch.halted = false;
> +                       }
> +
>                         r = vcpu_enter_guest(vcpu);
> -               else
> +               } else {
>                         r = vcpu_block(kvm, vcpu);
> +
> +                       /*
> +                        * post_block() must be called after
> +                        * pre_block() which is called in
> +                        * kvm_vcpu_halt().
> +                        */
> +                       if (kvm_x86_ops->post_block && vcpu->arch.halted) {
> +                               kvm_x86_ops->post_block(vcpu);
> +                               vcpu->arch.halted = false;
> +                       }
> +               }
> +
>                 if (r <= 0)
>                         break;
>
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index feba1fb..bf462e7 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -231,6 +231,9 @@ struct kvm_vcpu {
>         unsigned long requests;
>         unsigned long guest_debug;
>
> +       int pre_pcpu;
> +       struct list_head blocked_vcpu_list;
> +
>         struct mutex mutex;
>         struct kvm_run *run;
>
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 8b8a444..191c7eb 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -220,6 +220,9 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
>         init_waitqueue_head(&vcpu->wq);
>         kvm_async_pf_vcpu_init(vcpu);
>
> +       vcpu->pre_pcpu = -1;
> +       INIT_LIST_HEAD(&vcpu->blocked_vcpu_list);
> +
>         page = alloc_page(GFP_KERNEL | __GFP_ZERO);
>         if (!page) {
>                 r = -ENOMEM;
> --
> 2.1.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1247300

From"Wu, Feng" <feng.wu@intel.com>
Date2015-10-15 03:40 +0200
Message-ID<qjFGq-8dL-25@gated-at.bofh.it>
In reply to#1247257
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogRGF2aWQgTWF0bGFjayBb
bWFpbHRvOmRtYXRsYWNrQGdvb2dsZS5jb21dDQo+IFNlbnQ6IFRodXJzZGF5LCBPY3RvYmVyIDE1
LCAyMDE1IDc6NDEgQU0NCj4gVG86IFd1LCBGZW5nIDxmZW5nLnd1QGludGVsLmNvbT4NCj4gQ2M6
IFBhb2xvIEJvbnppbmkgPHBib256aW5pQHJlZGhhdC5jb20+OyBhbGV4LndpbGxpYW1zb25AcmVk
aGF0LmNvbTsgSm9lcmcNCj4gUm9lZGVsIDxqb3JvQDhieXRlcy5vcmc+OyBNYXJjZWxvIFRvc2F0
dGkgPG10b3NhdHRpQHJlZGhhdC5jb20+Ow0KPiBlcmljLmF1Z2VyQGxpbmFyby5vcmc7IGt2bSBs
aXN0IDxrdm1Admdlci5rZXJuZWwub3JnPjsgaW9tbXVAbGlzdHMubGludXgtDQo+IGZvdW5kYXRp
b24ub3JnOyBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFU
Q0ggdjkgMTcvMThdIEtWTTogVXBkYXRlIFBvc3RlZC1JbnRlcnJ1cHRzIERlc2NyaXB0b3Igd2hl
bg0KPiB2Q1BVIGlzIGJsb2NrZWQNCj4gDQo+IEhpIEZlbmcuDQo+IA0KPiBPbiBGcmksIFNlcCAx
OCwgMjAxNSBhdCA3OjI5IEFNLCBGZW5nIFd1IDxmZW5nLnd1QGludGVsLmNvbT4gd3JvdGU6DQo+
ID4gVGhpcyBwYXRjaCB1cGRhdGVzIHRoZSBQb3N0ZWQtSW50ZXJydXB0cyBEZXNjcmlwdG9yIHdo
ZW4gdkNQVQ0KPiA+IGlzIGJsb2NrZWQuDQo+ID4NCj4gPiBwcmUtYmxvY2s6DQo+ID4gLSBBZGQg
dGhlIHZDUFUgdG8gdGhlIGJsb2NrZWQgcGVyLUNQVSBsaXN0DQo+ID4gLSBTZXQgJ05WJyB0byBQ
T1NURURfSU5UUl9XQUtFVVBfVkVDVE9SDQo+ID4NCj4gPiBwb3N0LWJsb2NrOg0KPiA+IC0gUmVt
b3ZlIHRoZSB2Q1BVIGZyb20gdGhlIHBlci1DUFUgbGlzdA0KPiANCj4gSSdtIHdvbmRlcmluZyB3
aGF0IGhhcHBlbnMgaWYgYSBwb3N0ZWQgaW50ZXJydXB0IGFycml2ZXMgYXQgdGhlIElPTU1VDQo+
IGFmdGVyIHByZS1ibG9jayBhbmQgYmVmb3JlIHBvc3QtYmxvY2suDQo+IA0KPiBJbiBwcmVfYmxv
Y2ssIE5WIGlzIHNldCB0byBQT1NURURfSU5UUl9XQUtFVVBfVkVDVE9SLiBJSVVDLCB0aGlzIG1l
YW5zDQo+IGZ1dHVyZSBwb3N0ZWQgaW50ZXJydXB0cyB3aWxsIG5vdCB0cmlnZ2VyICJQb3N0ZWQt
SW50ZXJydXB0IFByb2Nlc3NpbmciDQo+IChQSVIgd2lsbCBub3QgZ2V0IGNvcGllZCB0byBWSVJS
KS4gSW5zdGVhZCwgdGhlIElPTU1VIHdpbGwgZG8gT04gOj0gMSwNCj4gUElSIHw9ICgxIDw8IHZl
Y3RvciksIGFuZCBzZW5kIFBPU1RFRF9JTlRSX1dBS0VVUF9WRUNUT1IuIFBJV1YgY2FsbHMNCj4g
d2FrZXVwX2hhbmRsZXIgd2hpY2ggZG9lcyBrdm1fdmNwdV9raWNrLiBrdm1fdmNwdV9raWNrIGRv
ZXMgYSB3YWl0LXF1ZXVlDQo+IHdha2V1cCBhbmQgcG9zc2libHkgYSBzY2hlZHVsZXIgaXBpLg0K
PiANCj4gQnV0IHRoZSBWQ1BVIGlzIHNpdHRpbmcgaW4ga3ZtX3ZjcHVfYmxvY2suIEl0IHNwaW5z
IGFuZC9vciBzY2hlZHVsZXMNCj4gKHdhaXQgcXVldWUpIHVudGlsIGl0IGhhcyBhIHJlYXNvbiB0
byB3YWtlIHVwLiBJIGNvdWxkbid0IGZpbmQgYSBjb2RlDQo+IHBhdGggZnJvbSBrdm1fdmNwdV9i
bG9jayB0aGF0IGxlYWQgdG8gY2hlY2tpbmcgT04gb3IgUElSLiBIb3cgZG9lcyB0aGUNCj4gYmxv
Y2tlZCBWQ1BVICJyZWNlaXZlIiB0aGUgcG9zdGVkIGludGVycnVwdD8gKEFuZCB3aGVuIGRvZXMg
UG9zdGVkLQ0KPiBJbnRlcnJ1cHQgUHJvY2Vzc2luZyBnZXQgdHJpZ2dlcmVkPykNCg0KSW4gdGhl
IHByZV9ibG9jaywgaXQgYWxzbyBjaGFuZ2UgdGhlICdORFNUJyBmaWxlZCB0byB0aGUgcENQVSwg
b24gd2hpY2ggdGhlIHZDUFUNCmlzIHB1dCB0byB0aGUgcGVyLUNQVSBsaXN0ICdibG9ja2VkX3Zj
cHVfb25fY3B1Jywgc28gd2hlbiBwb3N0ZWQtaW50ZXJydXB0cw0KY29tZSBpdCwgaXQgd2lsbCBz
ZW50IHRoZSB3YWtldXAgbm90aWZpY2F0aW9uIGV2ZW50IHRvIHRoZSBwQ1BVIGFib3ZlLCB0aGVu
IGluDQp0aGUgd2FrZXVwX2hhbmRsZXIsIGl0IGNhbiBmaW5kIHRoZSB2Q1BVIGZyb20gdGhlIHBl
ci1DUFUgbGlzdCwgaGVuY2UNCmt2bV92Y3B1X2tpY2sgY2FuIHdha2UgdXAgaXQuDQoNClRoYW5r
cywNCkZlbmcNCg0KPiANCj4gVGhhbmtzIQ0KPiANCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IEZl
bmcgV3UgPGZlbmcud3VAaW50ZWwuY29tPg0KPiA+IC0tLQ0KPiA+IHY5Og0KPiA+IC0gQWRkIGRl
c2NyaXB0aW9uIGZvciBibG9ja2VkX3ZjcHVfb25fY3B1X2xvY2sgaW4NCj4gRG9jdW1lbnRhdGlv
bi92aXJ0dWFsL2t2bS9sb2NraW5nLnR4dA0KPiA+IC0gQ2hlY2sgIWt2bV9hcmNoX2hhc19hc3Np
Z25lZF9kZXZpY2UodmNwdS0+a3ZtKSBmaXJzdCwgdGhlbg0KPiA+ICAgIWlycV9yZW1hcHBpbmdf
Y2FwKElSUV9QT1NUSU5HX0NBUCkNCj4gPg0KPiA+IHY4Og0KPiA+IC0gUmVuYW1lICdwaV9wcmVf
YmxvY2snIHRvICdwcmVfYmxvY2snDQo+ID4gLSBSZW5hbWUgJ3BpX3Bvc3RfYmxvY2snIHRvICdw
b3N0X2Jsb2NrJw0KPiA+IC0gQ2hhbmdlIHNvbWUgY29tbWVudHMNCj4gPiAtIE9ubHkgYWRkIHRo
ZSB2Q1BVIHRvIHRoZSBibG9ja2luZyBsaXN0IHdoZW4gdGhlIFZNIGhhcyBhc3NpZ25lZCBkZXZp
Y2VzLg0KPiA+DQo+ID4gIERvY3VtZW50YXRpb24vdmlydHVhbC9rdm0vbG9ja2luZy50eHQgfCAg
MTIgKysrDQo+ID4gIGFyY2gveDg2L2luY2x1ZGUvYXNtL2t2bV9ob3N0LmggICAgICAgfCAgMTMg
KysrDQo+ID4gIGFyY2gveDg2L2t2bS92bXguYyAgICAgICAgICAgICAgICAgICAgfCAxNTMNCj4g
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+ICBhcmNoL3g4Ni9rdm0veDg2
LmMgICAgICAgICAgICAgICAgICAgIHwgIDUzICsrKysrKysrKy0tLQ0KPiA+ICBpbmNsdWRlL2xp
bnV4L2t2bV9ob3N0LmggICAgICAgICAgICAgIHwgICAzICsNCj4gPiAgdmlydC9rdm0va3ZtX21h
aW4uYyAgICAgICAgICAgICAgICAgICB8ICAgMyArDQo+ID4gIDYgZmlsZXMgY2hhbmdlZCwgMjI3
IGluc2VydGlvbnMoKyksIDEwIGRlbGV0aW9ucygtKQ0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL0Rv
Y3VtZW50YXRpb24vdmlydHVhbC9rdm0vbG9ja2luZy50eHQNCj4gYi9Eb2N1bWVudGF0aW9uL3Zp
cnR1YWwva3ZtL2xvY2tpbmcudHh0DQo+ID4gaW5kZXggZDY4YWY0ZC4uMTlmOTRhNiAxMDA2NDQN
Cj4gPiAtLS0gYS9Eb2N1bWVudGF0aW9uL3ZpcnR1YWwva3ZtL2xvY2tpbmcudHh0DQo+ID4gKysr
IGIvRG9jdW1lbnRhdGlvbi92aXJ0dWFsL2t2bS9sb2NraW5nLnR4dA0KPiA+IEBAIC0xNjYsMyAr
MTY2LDE1IEBAIENvbW1lbnQ6ICAgVGhlIHNyY3UgcmVhZCBsb2NrIG11c3QgYmUgaGVsZCB3aGls
ZQ0KPiBhY2Nlc3NpbmcgbWVtc2xvdHMgKGUuZy4NCj4gPiAgICAgICAgICAgICAgICAgTU1JTy9Q
SU8gYWRkcmVzcy0+ZGV2aWNlIHN0cnVjdHVyZSBtYXBwaW5nIChrdm0tPmJ1c2VzKS4NCj4gPiAg
ICAgICAgICAgICAgICAgVGhlIHNyY3UgaW5kZXggY2FuIGJlIHN0b3JlZCBpbiBrdm1fdmNwdS0+
c3JjdV9pZHggcGVyIHZjcHUNCj4gPiAgICAgICAgICAgICAgICAgaWYgaXQgaXMgbmVlZGVkIGJ5
IG11bHRpcGxlIGZ1bmN0aW9ucy4NCj4gPiArDQo+ID4gK05hbWU6ICAgICAgICAgIGJsb2NrZWRf
dmNwdV9vbl9jcHVfbG9jaw0KPiA+ICtUeXBlOiAgICAgICAgICBzcGlubG9ja190DQo+ID4gK0Fy
Y2g6ICAgICAgICAgIHg4Ng0KPiA+ICtQcm90ZWN0czogICAgICBibG9ja2VkX3ZjcHVfb25fY3B1
DQo+ID4gK0NvbW1lbnQ6ICAgICAgIFRoaXMgaXMgYSBwZXItQ1BVIGxvY2sgYW5kIGl0IGlzIHVz
ZWQgZm9yIFZULWQgcG9zdGVkLWludGVycnVwdHMuDQo+ID4gKyAgICAgICAgICAgICAgIFdoZW4g
VlQtZCBwb3N0ZWQtaW50ZXJydXB0cyBpcyBzdXBwb3J0ZWQgYW5kIHRoZSBWTSBoYXMgYXNzaWdu
ZWQNCj4gPiArICAgICAgICAgICAgICAgZGV2aWNlcywgd2UgcHV0IHRoZSBibG9ja2VkIHZDUFUg
b24gdGhlIGxpc3QgYmxvY2tlZF92Y3B1X29uX2NwdQ0KPiA+ICsgICAgICAgICAgICAgICBwcm90
ZWN0ZWQgYnkgYmxvY2tlZF92Y3B1X29uX2NwdV9sb2NrLCB3aGVuIFZULWQgaGFyZHdhcmUNCj4g
aXNzdWVzDQo+ID4gKyAgICAgICAgICAgICAgIHdha2V1cCBub3RpZmljYXRpb24gZXZlbnQgc2lu
Y2UgZXh0ZXJuYWwgaW50ZXJydXB0cyBmcm9tIHRoZQ0KPiA+ICsgICAgICAgICAgICAgICBhc3Np
Z25lZCBkZXZpY2VzIGhhcHBlbnMsIHdlIHdpbGwgZmluZCB0aGUgdkNQVSBvbiB0aGUgbGlzdCB0
bw0KPiA+ICsgICAgICAgICAgICAgICB3YWtldXAuDQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gveDg2
L2luY2x1ZGUvYXNtL2t2bV9ob3N0LmgNCj4gYi9hcmNoL3g4Ni9pbmNsdWRlL2FzbS9rdm1faG9z
dC5oDQo+ID4gaW5kZXggMGRkZDM1My4uMzA0ZmJiNSAxMDA2NDQNCj4gPiAtLS0gYS9hcmNoL3g4
Ni9pbmNsdWRlL2FzbS9rdm1faG9zdC5oDQo+ID4gKysrIGIvYXJjaC94ODYvaW5jbHVkZS9hc20v
a3ZtX2hvc3QuaA0KPiA+IEBAIC01NTIsNiArNTUyLDggQEAgc3RydWN0IGt2bV92Y3B1X2FyY2gg
ew0KPiA+ICAgICAgICAgICovDQo+ID4gICAgICAgICBib29sIHdyaXRlX2ZhdWx0X3RvX3NoYWRv
d19wZ3RhYmxlOw0KPiA+DQo+ID4gKyAgICAgICBib29sIGhhbHRlZDsNCj4gPiArDQo+ID4gICAg
ICAgICAvKiBzZXQgYXQgRVBUIHZpb2xhdGlvbiBhdCB0aGlzIHBvaW50ICovDQo+ID4gICAgICAg
ICB1bnNpZ25lZCBsb25nIGV4aXRfcXVhbGlmaWNhdGlvbjsNCj4gPg0KPiA+IEBAIC04NjQsNiAr
ODY2LDE3IEBAIHN0cnVjdCBrdm1feDg2X29wcyB7DQo+ID4gICAgICAgICAvKiBwbXUgb3BlcmF0
aW9ucyBvZiBzdWItYXJjaCAqLw0KPiA+ICAgICAgICAgY29uc3Qgc3RydWN0IGt2bV9wbXVfb3Bz
ICpwbXVfb3BzOw0KPiA+DQo+ID4gKyAgICAgICAvKg0KPiA+ICsgICAgICAgICogQXJjaGl0ZWN0
dXJlIHNwZWNpZmljIGhvb2tzIGZvciB2Q1BVIGJsb2NraW5nIGR1ZSB0bw0KPiA+ICsgICAgICAg
ICogSExUIGluc3RydWN0aW9uLg0KPiA+ICsgICAgICAgICogUmV0dXJucyBmb3IgLnByZV9ibG9j
aygpOg0KPiA+ICsgICAgICAgICogICAgLSAwIG1lYW5zIGNvbnRpbnVlIHRvIGJsb2NrIHRoZSB2
Q1BVLg0KPiA+ICsgICAgICAgICogICAgLSAxIG1lYW5zIHdlIGNhbm5vdCBibG9jayB0aGUgdkNQ
VSBzaW5jZSBzb21lIGV2ZW50DQo+ID4gKyAgICAgICAgKiAgICAgICAgaGFwcGVucyBkdXJpbmcg
dGhpcyBwZXJpb2QsIHN1Y2ggYXMsICdPTicgYml0IGluDQo+ID4gKyAgICAgICAgKiAgICAgICAg
cG9zdGVkLWludGVycnVwdHMgZGVzY3JpcHRvciBpcyBzZXQuDQo+ID4gKyAgICAgICAgKi8NCj4g
PiArICAgICAgIGludCAoKnByZV9ibG9jaykoc3RydWN0IGt2bV92Y3B1ICp2Y3B1KTsNCj4gPiAr
ICAgICAgIHZvaWQgKCpwb3N0X2Jsb2NrKShzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpOw0KPiA+ICAg
ICAgICAgaW50ICgqdXBkYXRlX3BpX2lydGUpKHN0cnVjdCBrdm0gKmt2bSwgdW5zaWduZWQgaW50
IGhvc3RfaXJxLA0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpbnQzMl90IGd1
ZXN0X2lycSwgYm9vbCBzZXQpOw0KPiA+ICB9Ow0KPiA+IGRpZmYgLS1naXQgYS9hcmNoL3g4Ni9r
dm0vdm14LmMgYi9hcmNoL3g4Ni9rdm0vdm14LmMNCj4gPiBpbmRleCA5MDJhNjdkLi45OTY4ODk2
IDEwMDY0NA0KPiA+IC0tLSBhL2FyY2gveDg2L2t2bS92bXguYw0KPiA+ICsrKyBiL2FyY2gveDg2
L2t2bS92bXguYw0KPiA+IEBAIC04NzksNiArODc5LDEzIEBAIHN0YXRpYyBERUZJTkVfUEVSX0NQ
VShzdHJ1Y3Qgdm1jcyAqLA0KPiBjdXJyZW50X3ZtY3MpOw0KPiA+ICBzdGF0aWMgREVGSU5FX1BF
Ul9DUFUoc3RydWN0IGxpc3RfaGVhZCwgbG9hZGVkX3ZtY3NzX29uX2NwdSk7DQo+ID4gIHN0YXRp
YyBERUZJTkVfUEVSX0NQVShzdHJ1Y3QgZGVzY19wdHIsIGhvc3RfZ2R0KTsNCj4gPg0KPiA+ICsv
Kg0KPiA+ICsgKiBXZSBtYWludGlhbiBhIHBlci1DUFUgbGlua2VkLWxpc3Qgb2YgdkNQVSwgc28g
aW4gd2FrZXVwX2hhbmRsZXIoKSB3ZQ0KPiA+ICsgKiBjYW4gZmluZCB3aGljaCB2Q1BVIHNob3Vs
ZCBiZSB3YWtlbiB1cC4NCj4gPiArICovDQo+ID4gK3N0YXRpYyBERUZJTkVfUEVSX0NQVShzdHJ1
Y3QgbGlzdF9oZWFkLCBibG9ja2VkX3ZjcHVfb25fY3B1KTsNCj4gPiArc3RhdGljIERFRklORV9Q
RVJfQ1BVKHNwaW5sb2NrX3QsIGJsb2NrZWRfdmNwdV9vbl9jcHVfbG9jayk7DQo+ID4gKw0KPiA+
ICBzdGF0aWMgdW5zaWduZWQgbG9uZyAqdm14X2lvX2JpdG1hcF9hOw0KPiA+ICBzdGF0aWMgdW5z
aWduZWQgbG9uZyAqdm14X2lvX2JpdG1hcF9iOw0KPiA+ICBzdGF0aWMgdW5zaWduZWQgbG9uZyAq
dm14X21zcl9iaXRtYXBfbGVnYWN5Ow0KPiA+IEBAIC0yOTg1LDYgKzI5OTIsOCBAQCBzdGF0aWMg
aW50IGhhcmR3YXJlX2VuYWJsZSh2b2lkKQ0KPiA+ICAgICAgICAgICAgICAgICByZXR1cm4gLUVC
VVNZOw0KPiA+DQo+ID4gICAgICAgICBJTklUX0xJU1RfSEVBRCgmcGVyX2NwdShsb2FkZWRfdm1j
c3Nfb25fY3B1LCBjcHUpKTsNCj4gPiArICAgICAgIElOSVRfTElTVF9IRUFEKCZwZXJfY3B1KGJs
b2NrZWRfdmNwdV9vbl9jcHUsIGNwdSkpOw0KPiA+ICsgICAgICAgc3Bpbl9sb2NrX2luaXQoJnBl
cl9jcHUoYmxvY2tlZF92Y3B1X29uX2NwdV9sb2NrLCBjcHUpKTsNCj4gPg0KPiA+ICAgICAgICAg
LyoNCj4gPiAgICAgICAgICAqIE5vdyB3ZSBjYW4gZW5hYmxlIHRoZSB2bWNsZWFyIG9wZXJhdGlv
biBpbiBrZHVtcA0KPiA+IEBAIC02MTIxLDYgKzYxMzAsMjUgQEAgc3RhdGljIHZvaWQgdXBkYXRl
X3BsZV93aW5kb3dfYWN0dWFsX21heCh2b2lkKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgcGxlX3dpbmRvd19ncm93LCBJTlRfTUlOKTsNCj4gPiAgfQ0K
PiA+DQo+ID4gKy8qDQo+ID4gKyAqIEhhbmRsZXIgZm9yIFBPU1RFRF9JTlRFUlJVUFRfV0FLRVVQ
X1ZFQ1RPUi4NCj4gPiArICovDQo+ID4gK3N0YXRpYyB2b2lkIHdha2V1cF9oYW5kbGVyKHZvaWQp
DQo+ID4gK3sNCj4gPiArICAgICAgIHN0cnVjdCBrdm1fdmNwdSAqdmNwdTsNCj4gPiArICAgICAg
IGludCBjcHUgPSBzbXBfcHJvY2Vzc29yX2lkKCk7DQo+ID4gKw0KPiA+ICsgICAgICAgc3Bpbl9s
b2NrKCZwZXJfY3B1KGJsb2NrZWRfdmNwdV9vbl9jcHVfbG9jaywgY3B1KSk7DQo+ID4gKyAgICAg
ICBsaXN0X2Zvcl9lYWNoX2VudHJ5KHZjcHUsICZwZXJfY3B1KGJsb2NrZWRfdmNwdV9vbl9jcHUs
IGNwdSksDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYmxvY2tlZF92Y3B1X2xpc3QpIHsN
Cj4gPiArICAgICAgICAgICAgICAgc3RydWN0IHBpX2Rlc2MgKnBpX2Rlc2MgPSB2Y3B1X3RvX3Bp
X2Rlc2ModmNwdSk7DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBpZiAocGlfdGVzdF9vbihw
aV9kZXNjKSA9PSAxKQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGt2bV92Y3B1X2tpY2so
dmNwdSk7DQo+ID4gKyAgICAgICB9DQo+ID4gKyAgICAgICBzcGluX3VubG9jaygmcGVyX2NwdShi
bG9ja2VkX3ZjcHVfb25fY3B1X2xvY2ssIGNwdSkpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICBzdGF0
aWMgX19pbml0IGludCBoYXJkd2FyZV9zZXR1cCh2b2lkKQ0KPiA+ICB7DQo+ID4gICAgICAgICBp
bnQgciA9IC1FTk9NRU0sIGksIG1zcjsNCj4gPiBAQCAtNjMwNSw2ICs2MzMzLDggQEAgc3RhdGlj
IF9faW5pdCBpbnQgaGFyZHdhcmVfc2V0dXAodm9pZCkNCj4gPiAgICAgICAgICAgICAgICAga3Zt
X3g4Nl9vcHMtPmVuYWJsZV9sb2dfZGlydHlfcHRfbWFza2VkID0gTlVMTDsNCj4gPiAgICAgICAg
IH0NCj4gPg0KPiA+ICsgICAgICAga3ZtX3NldF9wb3N0ZWRfaW50cl93YWtldXBfaGFuZGxlcih3
YWtldXBfaGFuZGxlcik7DQo+ID4gKw0KPiA+ICAgICAgICAgcmV0dXJuIGFsbG9jX2t2bV9hcmVh
KCk7DQo+ID4NCj4gPiAgb3V0ODoNCj4gPiBAQCAtMTA0MzAsNiArMTA0NjAsMTI2IEBAIHN0YXRp
YyB2b2lkDQo+IHZteF9lbmFibGVfbG9nX2RpcnR5X3B0X21hc2tlZChzdHJ1Y3Qga3ZtICprdm0s
DQo+ID4gIH0NCj4gPg0KPiA+ICAvKg0KPiA+ICsgKiBUaGlzIHJvdXRpbmUgZG9lcyB0aGUgZm9s
bG93aW5nIHRoaW5ncyBmb3IgdkNQVSB3aGljaCBpcyBnb2luZw0KPiA+ICsgKiB0byBiZSBibG9j
a2VkIGlmIFZULWQgUEkgaXMgZW5hYmxlZC4NCj4gPiArICogLSBTdG9yZSB0aGUgdkNQVSB0byB0
aGUgd2FrZXVwIGxpc3QsIHNvIHdoZW4gaW50ZXJydXB0cyBoYXBwZW4NCj4gPiArICogICB3ZSBj
YW4gZmluZCB0aGUgcmlnaHQgdkNQVSB0byB3YWtlIHVwLg0KPiA+ICsgKiAtIENoYW5nZSB0aGUg
UG9zdGVkLWludGVycnVwdCBkZXNjcmlwdG9yIGFzIGJlbG93Og0KPiA+ICsgKiAgICAgICdORFNU
JyA8LS0gdmNwdS0+cHJlX3BjcHUNCj4gPiArICogICAgICAnTlYnIDwtLSBQT1NURURfSU5UUl9X
QUtFVVBfVkVDVE9SDQo+ID4gKyAqIC0gSWYgJ09OJyBpcyBzZXQgZHVyaW5nIHRoaXMgcHJvY2Vz
cywgd2hpY2ggbWVhbnMgYXQgbGVhc3Qgb25lDQo+ID4gKyAqICAgaW50ZXJydXB0IGlzIHBvc3Rl
ZCBmb3IgdGhpcyB2Q1BVLCB3ZSBjYW5ub3QgYmxvY2sgaXQsIGluDQo+ID4gKyAqICAgdGhpcyBj
YXNlLCByZXR1cm4gMSwgb3RoZXJ3aXNlLCByZXR1cm4gMC4NCj4gPiArICoNCj4gPiArICovDQo+
ID4gK3N0YXRpYyBpbnQgdm14X3ByZV9ibG9jayhzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpDQo+ID4g
K3sNCj4gPiArICAgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7DQo+ID4gKyAgICAgICB1bnNpZ25l
ZCBpbnQgZGVzdDsNCj4gPiArICAgICAgIHN0cnVjdCBwaV9kZXNjIG9sZCwgbmV3Ow0KPiA+ICsg
ICAgICAgc3RydWN0IHBpX2Rlc2MgKnBpX2Rlc2MgPSB2Y3B1X3RvX3BpX2Rlc2ModmNwdSk7DQo+
ID4gKw0KPiA+ICsgICAgICAgaWYgKCFrdm1fYXJjaF9oYXNfYXNzaWduZWRfZGV2aWNlKHZjcHUt
Pmt2bSkgfHwNCj4gPiArICAgICAgICAgICAgICAgIWlycV9yZW1hcHBpbmdfY2FwKElSUV9QT1NU
SU5HX0NBUCkpDQo+ID4gKyAgICAgICAgICAgICAgIHJldHVybiAwOw0KPiA+ICsNCj4gPiArICAg
ICAgIHZjcHUtPnByZV9wY3B1ID0gdmNwdS0+Y3B1Ow0KPiA+ICsgICAgICAgc3Bpbl9sb2NrX2ly
cXNhdmUoJnBlcl9jcHUoYmxvY2tlZF92Y3B1X29uX2NwdV9sb2NrLA0KPiA+ICsgICAgICAgICAg
ICAgICAgICAgICAgICAgdmNwdS0+cHJlX3BjcHUpLCBmbGFncyk7DQo+ID4gKyAgICAgICBsaXN0
X2FkZF90YWlsKCZ2Y3B1LT5ibG9ja2VkX3ZjcHVfbGlzdCwNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgJnBlcl9jcHUoYmxvY2tlZF92Y3B1X29uX2NwdSwNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgdmNwdS0+cHJlX3BjcHUpKTsNCj4gPiArICAgICAgIHNwaW5fdW5sb2NrX2lycXJlc3Rv
cmUoJnBlcl9jcHUoYmxvY2tlZF92Y3B1X29uX2NwdV9sb2NrLA0KPiA+ICsgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICB2Y3B1LT5wcmVfcGNwdSksIGZsYWdzKTsNCj4gPiArDQo+ID4gKyAg
ICAgICBkbyB7DQo+ID4gKyAgICAgICAgICAgICAgIG9sZC5jb250cm9sID0gbmV3LmNvbnRyb2wg
PSBwaV9kZXNjLT5jb250cm9sOw0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgLyoNCj4gPiAr
ICAgICAgICAgICAgICAgICogV2Ugc2hvdWxkIG5vdCBibG9jayB0aGUgdkNQVSBpZg0KPiA+ICsg
ICAgICAgICAgICAgICAgKiBhbiBpbnRlcnJ1cHQgaXMgcG9zdGVkIGZvciBpdC4NCj4gPiArICAg
ICAgICAgICAgICAgICovDQo+ID4gKyAgICAgICAgICAgICAgIGlmIChwaV90ZXN0X29uKHBpX2Rl
c2MpID09IDEpIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBzcGluX2xvY2tfaXJxc2F2
ZSgmcGVyX2NwdShibG9ja2VkX3ZjcHVfb25fY3B1X2xvY2ssDQo+ID4gKyAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgdmNwdS0+cHJlX3BjcHUpLCBmbGFncyk7DQo+ID4g
KyAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9kZWwoJnZjcHUtPmJsb2NrZWRfdmNwdV9saXN0
KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBzcGluX3VubG9ja19pcnFyZXN0b3JlKA0K
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmcGVyX2NwdShibG9j
a2VkX3ZjcHVfb25fY3B1X2xvY2ssDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHZjcHUtPnByZV9wY3B1KSwgZmxhZ3MpOw0KPiA+ICsgICAgICAgICAgICAgICAg
ICAgICAgIHZjcHUtPnByZV9wY3B1ID0gLTE7DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAgICAg
ICAgICAgIHJldHVybiAxOw0KPiA+ICsgICAgICAgICAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAg
ICAgICAgICAgICBXQVJOKChwaV9kZXNjLT5zbiA9PSAxKSwNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAiV2FybmluZzogU04gZmllbGQgb2YgcG9zdGVkLWludGVycnVwdHMgIg0KPiA+ICsgICAg
ICAgICAgICAgICAgICAgICJpcyBzZXQgYmVmb3JlIGJsb2NraW5nXG4iKTsNCj4gPiArDQo+ID4g
KyAgICAgICAgICAgICAgIC8qDQo+ID4gKyAgICAgICAgICAgICAgICAqIFNpbmNlIHZDUFUgY2Fu
IGJlIHByZWVtcHRlZCBkdXJpbmcgdGhpcyBwcm9jZXNzLA0KPiA+ICsgICAgICAgICAgICAgICAg
KiB2Y3B1LT5jcHUgY291bGQgYmUgZGlmZmVyZW50IHdpdGggcHJlX3BjcHUsIHdlDQo+ID4gKyAg
ICAgICAgICAgICAgICAqIG5lZWQgdG8gc2V0IHByZV9wY3B1IGFzIHRoZSBkZXN0aW5hdGlvbiBv
ZiB3YWtldXANCj4gPiArICAgICAgICAgICAgICAgICogbm90aWZpY2F0aW9uIGV2ZW50LCB0aGVu
IHdlIGNhbiBmaW5kIHRoZSByaWdodCB2Q1BVDQo+ID4gKyAgICAgICAgICAgICAgICAqIHRvIHdh
a2V1cCBpbiB3YWtldXAgaGFuZGxlciBpZiBpbnRlcnJ1cHRzIGhhcHBlbg0KPiA+ICsgICAgICAg
ICAgICAgICAgKiB3aGVuIHRoZSB2Q1BVIGlzIGluIGJsb2NrZWQgc3RhdGUuDQo+ID4gKyAgICAg
ICAgICAgICAgICAqLw0KPiA+ICsgICAgICAgICAgICAgICBkZXN0ID0gY3B1X3BoeXNpY2FsX2lk
KHZjcHUtPnByZV9wY3B1KTsNCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIGlmICh4MmFwaWNf
ZW5hYmxlZCgpKQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIG5ldy5uZHN0ID0gZGVzdDsN
Cj4gPiArICAgICAgICAgICAgICAgZWxzZQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIG5l
dy5uZHN0ID0gKGRlc3QgPDwgOCkgJiAweEZGMDA7DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAg
ICAvKiBzZXQgJ05WJyB0byAnd2FrZXVwIHZlY3RvcicgKi8NCj4gPiArICAgICAgICAgICAgICAg
bmV3Lm52ID0gUE9TVEVEX0lOVFJfV0FLRVVQX1ZFQ1RPUjsNCj4gPiArICAgICAgIH0gd2hpbGUg
KGNtcHhjaGcoJnBpX2Rlc2MtPmNvbnRyb2wsIG9sZC5jb250cm9sLA0KPiA+ICsgICAgICAgICAg
ICAgICAgICAgICAgIG5ldy5jb250cm9sKSAhPSBvbGQuY29udHJvbCk7DQo+ID4gKw0KPiA+ICsg
ICAgICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIHZteF9wb3N0
X2Jsb2NrKHN0cnVjdCBrdm1fdmNwdSAqdmNwdSkNCj4gPiArew0KPiA+ICsgICAgICAgc3RydWN0
IHBpX2Rlc2MgKnBpX2Rlc2MgPSB2Y3B1X3RvX3BpX2Rlc2ModmNwdSk7DQo+ID4gKyAgICAgICBz
dHJ1Y3QgcGlfZGVzYyBvbGQsIG5ldzsNCj4gPiArICAgICAgIHVuc2lnbmVkIGludCBkZXN0Ow0K
PiA+ICsgICAgICAgdW5zaWduZWQgbG9uZyBmbGFnczsNCj4gPiArDQo+ID4gKyAgICAgICBpZiAo
IWt2bV9hcmNoX2hhc19hc3NpZ25lZF9kZXZpY2UodmNwdS0+a3ZtKSB8fA0KPiA+ICsgICAgICAg
ICAgICAgICAhaXJxX3JlbWFwcGluZ19jYXAoSVJRX1BPU1RJTkdfQ0FQKSkNCj4gPiArICAgICAg
ICAgICAgICAgcmV0dXJuOw0KPiA+ICsNCj4gPiArICAgICAgIGRvIHsNCj4gPiArICAgICAgICAg
ICAgICAgb2xkLmNvbnRyb2wgPSBuZXcuY29udHJvbCA9IHBpX2Rlc2MtPmNvbnRyb2w7DQo+ID4g
Kw0KPiA+ICsgICAgICAgICAgICAgICBkZXN0ID0gY3B1X3BoeXNpY2FsX2lkKHZjcHUtPmNwdSk7
DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBpZiAoeDJhcGljX2VuYWJsZWQoKSkNCj4gPiAr
ICAgICAgICAgICAgICAgICAgICAgICBuZXcubmRzdCA9IGRlc3Q7DQo+ID4gKyAgICAgICAgICAg
ICAgIGVsc2UNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBuZXcubmRzdCA9IChkZXN0IDw8
IDgpICYgMHhGRjAwOw0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgLyogQWxsb3cgcG9zdGlu
ZyBub24tdXJnZW50IGludGVycnVwdHMgKi8NCj4gPiArICAgICAgICAgICAgICAgbmV3LnNuID0g
MDsNCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIC8qIHNldCAnTlYnIHRvICdub3RpZmljYXRp
b24gdmVjdG9yJyAqLw0KPiA+ICsgICAgICAgICAgICAgICBuZXcubnYgPSBQT1NURURfSU5UUl9W
RUNUT1I7DQo+ID4gKyAgICAgICB9IHdoaWxlIChjbXB4Y2hnKCZwaV9kZXNjLT5jb250cm9sLCBv
bGQuY29udHJvbCwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBuZXcuY29udHJvbCkgIT0g
b2xkLmNvbnRyb2wpOw0KPiA+ICsNCj4gPiArICAgICAgIGlmKHZjcHUtPnByZV9wY3B1ICE9IC0x
KSB7DQo+ID4gKyAgICAgICAgICAgICAgIHNwaW5fbG9ja19pcnFzYXZlKA0KPiA+ICsgICAgICAg
ICAgICAgICAgICAgICAgICZwZXJfY3B1KGJsb2NrZWRfdmNwdV9vbl9jcHVfbG9jaywNCj4gPiAr
ICAgICAgICAgICAgICAgICAgICAgICB2Y3B1LT5wcmVfcGNwdSksIGZsYWdzKTsNCj4gPiArICAg
ICAgICAgICAgICAgbGlzdF9kZWwoJnZjcHUtPmJsb2NrZWRfdmNwdV9saXN0KTsNCj4gPiArICAg
ICAgICAgICAgICAgc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgICAmcGVyX2NwdShibG9ja2VkX3ZjcHVfb25fY3B1X2xvY2ssDQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgdmNwdS0+cHJlX3BjcHUpLCBmbGFncyk7DQo+ID4gKyAgICAgICAgICAg
ICAgIHZjcHUtPnByZV9wY3B1ID0gLTE7DQo+ID4gKyAgICAgICB9DQo+ID4gK30NCj4gPiArDQo+
ID4gKy8qDQo+ID4gICAqIHZteF91cGRhdGVfcGlfaXJ0ZSAtIHNldCBJUlRFIGZvciBQb3N0ZWQt
SW50ZXJydXB0cw0KPiA+ICAgKg0KPiA+ICAgKiBAa3ZtOiBrdm0NCj4gPiBAQCAtMTA2MjAsNiAr
MTA3NzAsOSBAQCBzdGF0aWMgc3RydWN0IGt2bV94ODZfb3BzIHZteF94ODZfb3BzID0gew0KPiA+
ICAgICAgICAgLmZsdXNoX2xvZ19kaXJ0eSA9IHZteF9mbHVzaF9sb2dfZGlydHksDQo+ID4gICAg
ICAgICAuZW5hYmxlX2xvZ19kaXJ0eV9wdF9tYXNrZWQgPSB2bXhfZW5hYmxlX2xvZ19kaXJ0eV9w
dF9tYXNrZWQsDQo+ID4NCj4gPiArICAgICAgIC5wcmVfYmxvY2sgPSB2bXhfcHJlX2Jsb2NrLA0K
PiA+ICsgICAgICAgLnBvc3RfYmxvY2sgPSB2bXhfcG9zdF9ibG9jaywNCj4gPiArDQo+ID4gICAg
ICAgICAucG11X29wcyA9ICZpbnRlbF9wbXVfb3BzLA0KPiA+DQo+ID4gICAgICAgICAudXBkYXRl
X3BpX2lydGUgPSB2bXhfdXBkYXRlX3BpX2lydGUsDQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gveDg2
L2t2bS94ODYuYyBiL2FyY2gveDg2L2t2bS94ODYuYw0KPiA+IGluZGV4IDU4Njg4YWEuLjQ2ZjU1
YjIgMTAwNjQ0DQo+ID4gLS0tIGEvYXJjaC94ODYva3ZtL3g4Ni5jDQo+ID4gKysrIGIvYXJjaC94
ODYva3ZtL3g4Ni5jDQo+ID4gQEAgLTU4NjksNyArNTg2OSwxMiBAQCBpbnQga3ZtX3ZjcHVfaGFs
dChzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpDQo+ID4gIHsNCj4gPiAgICAgICAgICsrdmNwdS0+c3Rh
dC5oYWx0X2V4aXRzOw0KPiA+ICAgICAgICAgaWYgKGlycWNoaXBfaW5fa2VybmVsKHZjcHUtPmt2
bSkpIHsNCj4gPiAtICAgICAgICAgICAgICAgdmNwdS0+YXJjaC5tcF9zdGF0ZSA9IEtWTV9NUF9T
VEFURV9IQUxURUQ7DQo+ID4gKyAgICAgICAgICAgICAgIC8qIEhhbmRsZSBwb3N0ZWQtaW50ZXJy
dXB0IHdoZW4gdkNQVSBpcyB0byBiZSBoYWx0ZWQgKi8NCj4gPiArICAgICAgICAgICAgICAgaWYg
KCFrdm1feDg2X29wcy0+cHJlX2Jsb2NrIHx8DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICBrdm1feDg2X29wcy0+cHJlX2Jsb2NrKHZjcHUpID09IDApIHsNCj4gPiArICAgICAg
ICAgICAgICAgICAgICAgICB2Y3B1LT5hcmNoLmhhbHRlZCA9IHRydWU7DQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgdmNwdS0+YXJjaC5tcF9zdGF0ZSA9IEtWTV9NUF9TVEFURV9IQUxURUQ7
DQo+ID4gKyAgICAgICAgICAgICAgIH0NCj4gPiAgICAgICAgICAgICAgICAgcmV0dXJuIDE7DQo+
ID4gICAgICAgICB9IGVsc2Ugew0KPiA+ICAgICAgICAgICAgICAgICB2Y3B1LT5ydW4tPmV4aXRf
cmVhc29uID0gS1ZNX0VYSVRfSExUOw0KPiA+IEBAIC02NTE4LDYgKzY1MjMsMjAgQEAgc3RhdGlj
IGludCB2Y3B1X2VudGVyX2d1ZXN0KHN0cnVjdCBrdm1fdmNwdQ0KPiAqdmNwdSkNCj4gPiAgICAg
ICAgICAgICAgICAgICAgICAgICBrdm1fdmNwdV9yZWxvYWRfYXBpY19hY2Nlc3NfcGFnZSh2Y3B1
KTsNCj4gPiAgICAgICAgIH0NCj4gPg0KPiA+ICsgICAgICAgLyoNCj4gPiArICAgICAgICAqIEtW
TV9SRVFfRVZFTlQgaXMgbm90IHNldCB3aGVuIHBvc3RlZCBpbnRlcnJ1cHRzIGFyZSBzZXQgYnkN
Cj4gPiArICAgICAgICAqIFZULWQgaGFyZHdhcmUsIHNvIHdlIGhhdmUgdG8gdXBkYXRlIFJWSSB1
bmNvbmRpdGlvbmFsbHkuDQo+ID4gKyAgICAgICAgKi8NCj4gPiArICAgICAgIGlmIChrdm1fbGFw
aWNfZW5hYmxlZCh2Y3B1KSkgew0KPiA+ICsgICAgICAgICAgICAgICAvKg0KPiA+ICsgICAgICAg
ICAgICAgICAgKiBVcGRhdGUgYXJjaGl0ZWN0dXJlIHNwZWNpZmljIGhpbnRzIGZvciBBUElDDQo+
ID4gKyAgICAgICAgICAgICAgICAqIHZpcnR1YWwgaW50ZXJydXB0IGRlbGl2ZXJ5Lg0KPiA+ICsg
ICAgICAgICAgICAgICAgKi8NCj4gPiArICAgICAgICAgICAgICAgaWYgKGt2bV94ODZfb3BzLT5o
d2FwaWNfaXJyX3VwZGF0ZSkNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBrdm1feDg2X29w
cy0+aHdhcGljX2lycl91cGRhdGUodmNwdSwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIGt2bV9sYXBpY19maW5kX2hpZ2hlc3RfaXJyKHZjcHUpKTsNCj4gPiArICAgICAgIH0N
Cj4gPiArDQo+ID4gICAgICAgICBpZiAoa3ZtX2NoZWNrX3JlcXVlc3QoS1ZNX1JFUV9FVkVOVCwg
dmNwdSkgfHwgcmVxX2ludF93aW4pIHsNCj4gPiAgICAgICAgICAgICAgICAga3ZtX2FwaWNfYWNj
ZXB0X2V2ZW50cyh2Y3B1KTsNCj4gPiAgICAgICAgICAgICAgICAgaWYgKHZjcHUtPmFyY2gubXBf
c3RhdGUgPT0gS1ZNX01QX1NUQVRFX0lOSVRfUkVDRUlWRUQpIHsNCj4gPiBAQCAtNjUzNCwxMyAr
NjU1Myw2IEBAIHN0YXRpYyBpbnQgdmNwdV9lbnRlcl9ndWVzdChzdHJ1Y3Qga3ZtX3ZjcHUNCj4g
KnZjcHUpDQo+ID4gICAgICAgICAgICAgICAgICAgICAgICAga3ZtX3g4Nl9vcHMtPmVuYWJsZV9p
cnFfd2luZG93KHZjcHUpOw0KPiA+DQo+ID4gICAgICAgICAgICAgICAgIGlmIChrdm1fbGFwaWNf
ZW5hYmxlZCh2Y3B1KSkgew0KPiA+IC0gICAgICAgICAgICAgICAgICAgICAgIC8qDQo+ID4gLSAg
ICAgICAgICAgICAgICAgICAgICAgICogVXBkYXRlIGFyY2hpdGVjdHVyZSBzcGVjaWZpYyBoaW50
cyBmb3IgQVBJQw0KPiA+IC0gICAgICAgICAgICAgICAgICAgICAgICAqIHZpcnR1YWwgaW50ZXJy
dXB0IGRlbGl2ZXJ5Lg0KPiA+IC0gICAgICAgICAgICAgICAgICAgICAgICAqLw0KPiA+IC0gICAg
ICAgICAgICAgICAgICAgICAgIGlmIChrdm1feDg2X29wcy0+aHdhcGljX2lycl91cGRhdGUpDQo+
ID4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrdm1feDg2X29wcy0+aHdhcGljX2ly
cl91cGRhdGUodmNwdSwNCj4gPiAtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAga3ZtX2xhcGljX2ZpbmRfaGlnaGVzdF9pcnIodmNwdSkpOw0KPiA+ICAgICAgICAgICAgICAg
ICAgICAgICAgIHVwZGF0ZV9jcjhfaW50ZXJjZXB0KHZjcHUpOw0KPiA+ICAgICAgICAgICAgICAg
ICAgICAgICAgIGt2bV9sYXBpY19zeW5jX3RvX3ZhcGljKHZjcHUpOw0KPiA+ICAgICAgICAgICAg
ICAgICB9DQo+ID4gQEAgLTY3MTEsMTAgKzY3MjMsMzEgQEAgc3RhdGljIGludCB2Y3B1X3J1bihz
dHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpDQo+ID4NCj4gPiAgICAgICAgIGZvciAoOzspIHsNCj4gPiAg
ICAgICAgICAgICAgICAgaWYgKHZjcHUtPmFyY2gubXBfc3RhdGUgPT0gS1ZNX01QX1NUQVRFX1JV
Tk5BQkxFICYmDQo+ID4gLSAgICAgICAgICAgICAgICAgICAhdmNwdS0+YXJjaC5hcGYuaGFsdGVk
KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgIXZjcHUtPmFyY2guYXBmLmhhbHRlZCkgew0KPiA+
ICsgICAgICAgICAgICAgICAgICAgICAgIC8qDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg
ICogRm9yIHNvbWUgY2FzZXMsIHdlIGNhbiBnZXQgaGVyZSB3aXRoDQo+ID4gKyAgICAgICAgICAg
ICAgICAgICAgICAgICogdmNwdS0+YXJjaC5oYWx0ZWQgYmVpbmcgdHJ1ZS4NCj4gPiArICAgICAg
ICAgICAgICAgICAgICAgICAgKi8NCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBpZiAoa3Zt
X3g4Nl9vcHMtPnBvc3RfYmxvY2sgJiYgdmNwdS0+YXJjaC5oYWx0ZWQpIHsNCj4gPiArICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIGt2bV94ODZfb3BzLT5wb3N0X2Jsb2NrKHZjcHUpOw0K
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmNwdS0+YXJjaC5oYWx0ZWQgPSBm
YWxzZTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICAg
ICAgICAgICAgICAgICAgIHIgPSB2Y3B1X2VudGVyX2d1ZXN0KHZjcHUpOw0KPiA+IC0gICAgICAg
ICAgICAgICBlbHNlDQo+ID4gKyAgICAgICAgICAgICAgIH0gZWxzZSB7DQo+ID4gICAgICAgICAg
ICAgICAgICAgICAgICAgciA9IHZjcHVfYmxvY2soa3ZtLCB2Y3B1KTsNCj4gPiArDQo+ID4gKyAg
ICAgICAgICAgICAgICAgICAgICAgLyoNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgKiBw
b3N0X2Jsb2NrKCkgbXVzdCBiZSBjYWxsZWQgYWZ0ZXINCj4gPiArICAgICAgICAgICAgICAgICAg
ICAgICAgKiBwcmVfYmxvY2soKSB3aGljaCBpcyBjYWxsZWQgaW4NCj4gPiArICAgICAgICAgICAg
ICAgICAgICAgICAgKiBrdm1fdmNwdV9oYWx0KCkuDQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgICovDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgaWYgKGt2bV94ODZfb3BzLT5wb3N0
X2Jsb2NrICYmIHZjcHUtPmFyY2guaGFsdGVkKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICBrdm1feDg2X29wcy0+cG9zdF9ibG9jayh2Y3B1KTsNCj4gPiArICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIHZjcHUtPmFyY2guaGFsdGVkID0gZmFsc2U7DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAgICAgICB9DQo+ID4gKw0KPiA+
ICAgICAgICAgICAgICAgICBpZiAociA8PSAwKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAg
IGJyZWFrOw0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgva3ZtX2hvc3QuaCBi
L2luY2x1ZGUvbGludXgva3ZtX2hvc3QuaA0KPiA+IGluZGV4IGZlYmExZmIuLmJmNDYyZTcgMTAw
NjQ0DQo+ID4gLS0tIGEvaW5jbHVkZS9saW51eC9rdm1faG9zdC5oDQo+ID4gKysrIGIvaW5jbHVk
ZS9saW51eC9rdm1faG9zdC5oDQo+ID4gQEAgLTIzMSw2ICsyMzEsOSBAQCBzdHJ1Y3Qga3ZtX3Zj
cHUgew0KPiA+ICAgICAgICAgdW5zaWduZWQgbG9uZyByZXF1ZXN0czsNCj4gPiAgICAgICAgIHVu
c2lnbmVkIGxvbmcgZ3Vlc3RfZGVidWc7DQo+ID4NCj4gPiArICAgICAgIGludCBwcmVfcGNwdTsN
Cj4gPiArICAgICAgIHN0cnVjdCBsaXN0X2hlYWQgYmxvY2tlZF92Y3B1X2xpc3Q7DQo+ID4gKw0K
PiA+ICAgICAgICAgc3RydWN0IG11dGV4IG11dGV4Ow0KPiA+ICAgICAgICAgc3RydWN0IGt2bV9y
dW4gKnJ1bjsNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS92aXJ0L2t2bS9rdm1fbWFpbi5jIGIvdmly
dC9rdm0va3ZtX21haW4uYw0KPiA+IGluZGV4IDhiOGE0NDQuLjE5MWM3ZWIgMTAwNjQ0DQo+ID4g
LS0tIGEvdmlydC9rdm0va3ZtX21haW4uYw0KPiA+ICsrKyBiL3ZpcnQva3ZtL2t2bV9tYWluLmMN
Cj4gPiBAQCAtMjIwLDYgKzIyMCw5IEBAIGludCBrdm1fdmNwdV9pbml0KHN0cnVjdCBrdm1fdmNw
dSAqdmNwdSwgc3RydWN0IGt2bQ0KPiAqa3ZtLCB1bnNpZ25lZCBpZCkNCj4gPiAgICAgICAgIGlu
aXRfd2FpdHF1ZXVlX2hlYWQoJnZjcHUtPndxKTsNCj4gPiAgICAgICAgIGt2bV9hc3luY19wZl92
Y3B1X2luaXQodmNwdSk7DQo+ID4NCj4gPiArICAgICAgIHZjcHUtPnByZV9wY3B1ID0gLTE7DQo+
ID4gKyAgICAgICBJTklUX0xJU1RfSEVBRCgmdmNwdS0+YmxvY2tlZF92Y3B1X2xpc3QpOw0KPiA+
ICsNCj4gPiAgICAgICAgIHBhZ2UgPSBhbGxvY19wYWdlKEdGUF9LRVJORUwgfCBfX0dGUF9aRVJP
KTsNCj4gPiAgICAgICAgIGlmICghcGFnZSkgew0KPiA+ICAgICAgICAgICAgICAgICByID0gLUVO
T01FTTsNCj4gPiAtLQ0KPiA+IDIuMS4wDQo+ID4NCj4gPiAtLQ0KPiA+IFRvIHVuc3Vic2NyaWJl
IGZyb20gdGhpcyBsaXN0OiBzZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBrdm0iIGluDQo+ID4g
dGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiBN
b3JlIG1ham9yZG9tbyBpbmZvIGF0ICBodHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1p
bmZvLmh0bWwNCg==
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1248036

FromDavid Matlack <dmatlack@google.com>
Date2015-10-15 19:40 +0200
Message-ID<qjUFs-4Ty-21@gated-at.bofh.it>
In reply to#1247300
On Wed, Oct 14, 2015 at 6:33 PM, Wu, Feng <feng.wu@intel.com> wrote:
>
>> -----Original Message-----
>> From: David Matlack [mailto:dmatlack@google.com]
>> Sent: Thursday, October 15, 2015 7:41 AM
>> To: Wu, Feng <feng.wu@intel.com>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>; alex.williamson@redhat.com; Joerg
>> Roedel <joro@8bytes.org>; Marcelo Tosatti <mtosatti@redhat.com>;
>> eric.auger@linaro.org; kvm list <kvm@vger.kernel.org>; iommu@lists.linux-
>> foundation.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v9 17/18] KVM: Update Posted-Interrupts Descriptor when
>> vCPU is blocked
>>
>> Hi Feng.
>>
>> On Fri, Sep 18, 2015 at 7:29 AM, Feng Wu <feng.wu@intel.com> wrote:
>> > This patch updates the Posted-Interrupts Descriptor when vCPU
>> > is blocked.
>> >
>> > pre-block:
>> > - Add the vCPU to the blocked per-CPU list
>> > - Set 'NV' to POSTED_INTR_WAKEUP_VECTOR
>> >
>> > post-block:
>> > - Remove the vCPU from the per-CPU list
>>
>> I'm wondering what happens if a posted interrupt arrives at the IOMMU
>> after pre-block and before post-block.
>>
>> In pre_block, NV is set to POSTED_INTR_WAKEUP_VECTOR. IIUC, this means
>> future posted interrupts will not trigger "Posted-Interrupt Processing"
>> (PIR will not get copied to VIRR). Instead, the IOMMU will do ON := 1,
>> PIR |= (1 << vector), and send POSTED_INTR_WAKEUP_VECTOR. PIWV calls
>> wakeup_handler which does kvm_vcpu_kick. kvm_vcpu_kick does a wait-queue
>> wakeup and possibly a scheduler ipi.
>>
>> But the VCPU is sitting in kvm_vcpu_block. It spins and/or schedules
>> (wait queue) until it has a reason to wake up. I couldn't find a code
>> path from kvm_vcpu_block that lead to checking ON or PIR. How does the
>> blocked VCPU "receive" the posted interrupt? (And when does Posted-
>> Interrupt Processing get triggered?)
>
> In the pre_block, it also change the 'NDST' filed to the pCPU, on which the vCPU
> is put to the per-CPU list 'blocked_vcpu_on_cpu', so when posted-interrupts
> come it, it will sent the wakeup notification event to the pCPU above, then in
> the wakeup_handler, it can find the vCPU from the per-CPU list, hence
> kvm_vcpu_kick can wake up it.

Thank you for your response. I was actually confused about something
else. After wakeup_handler->kvm_vcpu_kick causes the vcpu to wake up,
that vcpu calls kvm_vcpu_check_block() to check if there are pending
events, otherwise the vcpu goes back to sleep. I had trouble yesterday
finding the code path from kvm_vcpu_check_block() which checks PIR/ON.

But after spending more time reading the source code this morning I
found that kvm_vcpu_check_block() eventually calls into
vmx_sync_pir_to_irr(), which copies PIR to IRR and clears ON. And then
apic_find_highest_irr() detects the pending posted interrupt.

>
> Thanks,
> Feng
>
>>
>> Thanks!
>>
>> >
>> > Signed-off-by: Feng Wu <feng.wu@intel.com>
>> > ---
>> > v9:
>> > - Add description for blocked_vcpu_on_cpu_lock in
>> Documentation/virtual/kvm/locking.txt
>> > - Check !kvm_arch_has_assigned_device(vcpu->kvm) first, then
>> >   !irq_remapping_cap(IRQ_POSTING_CAP)
>> >
>> > v8:
>> > - Rename 'pi_pre_block' to 'pre_block'
>> > - Rename 'pi_post_block' to 'post_block'
>> > - Change some comments
>> > - Only add the vCPU to the blocking list when the VM has assigned devices.
>> >
>> >  Documentation/virtual/kvm/locking.txt |  12 +++
>> >  arch/x86/include/asm/kvm_host.h       |  13 +++
>> >  arch/x86/kvm/vmx.c                    | 153
>> ++++++++++++++++++++++++++++++++++
>> >  arch/x86/kvm/x86.c                    |  53 +++++++++---
>> >  include/linux/kvm_host.h              |   3 +
>> >  virt/kvm/kvm_main.c                   |   3 +
>> >  6 files changed, 227 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/Documentation/virtual/kvm/locking.txt
>> b/Documentation/virtual/kvm/locking.txt
>> > index d68af4d..19f94a6 100644
>> > --- a/Documentation/virtual/kvm/locking.txt
>> > +++ b/Documentation/virtual/kvm/locking.txt
>> > @@ -166,3 +166,15 @@ Comment:   The srcu read lock must be held while
>> accessing memslots (e.g.
>> >                 MMIO/PIO address->device structure mapping (kvm->buses).
>> >                 The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
>> >                 if it is needed by multiple functions.
>> > +
>> > +Name:          blocked_vcpu_on_cpu_lock
>> > +Type:          spinlock_t
>> > +Arch:          x86
>> > +Protects:      blocked_vcpu_on_cpu
>> > +Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
>> > +               When VT-d posted-interrupts is supported and the VM has assigned
>> > +               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
>> > +               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware
>> issues
>> > +               wakeup notification event since external interrupts from the
>> > +               assigned devices happens, we will find the vCPU on the list to
>> > +               wakeup.
>> > diff --git a/arch/x86/include/asm/kvm_host.h
>> b/arch/x86/include/asm/kvm_host.h
>> > index 0ddd353..304fbb5 100644
>> > --- a/arch/x86/include/asm/kvm_host.h
>> > +++ b/arch/x86/include/asm/kvm_host.h
>> > @@ -552,6 +552,8 @@ struct kvm_vcpu_arch {
>> >          */
>> >         bool write_fault_to_shadow_pgtable;
>> >
>> > +       bool halted;
>> > +
>> >         /* set at EPT violation at this point */
>> >         unsigned long exit_qualification;
>> >
>> > @@ -864,6 +866,17 @@ struct kvm_x86_ops {
>> >         /* pmu operations of sub-arch */
>> >         const struct kvm_pmu_ops *pmu_ops;
>> >
>> > +       /*
>> > +        * Architecture specific hooks for vCPU blocking due to
>> > +        * HLT instruction.
>> > +        * Returns for .pre_block():
>> > +        *    - 0 means continue to block the vCPU.
>> > +        *    - 1 means we cannot block the vCPU since some event
>> > +        *        happens during this period, such as, 'ON' bit in
>> > +        *        posted-interrupts descriptor is set.
>> > +        */
>> > +       int (*pre_block)(struct kvm_vcpu *vcpu);
>> > +       void (*post_block)(struct kvm_vcpu *vcpu);
>> >         int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
>> >                               uint32_t guest_irq, bool set);
>> >  };
>> > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> > index 902a67d..9968896 100644
>> > --- a/arch/x86/kvm/vmx.c
>> > +++ b/arch/x86/kvm/vmx.c
>> > @@ -879,6 +879,13 @@ static DEFINE_PER_CPU(struct vmcs *,
>> current_vmcs);
>> >  static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
>> >  static DEFINE_PER_CPU(struct desc_ptr, host_gdt);
>> >
>> > +/*
>> > + * We maintian a per-CPU linked-list of vCPU, so in wakeup_handler() we
>> > + * can find which vCPU should be waken up.
>> > + */
>> > +static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu);
>> > +static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
>> > +
>> >  static unsigned long *vmx_io_bitmap_a;
>> >  static unsigned long *vmx_io_bitmap_b;
>> >  static unsigned long *vmx_msr_bitmap_legacy;
>> > @@ -2985,6 +2992,8 @@ static int hardware_enable(void)
>> >                 return -EBUSY;
>> >
>> >         INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
>> > +       INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
>> > +       spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
>> >
>> >         /*
>> >          * Now we can enable the vmclear operation in kdump
>> > @@ -6121,6 +6130,25 @@ static void update_ple_window_actual_max(void)
>> >                                             ple_window_grow, INT_MIN);
>> >  }
>> >
>> > +/*
>> > + * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR.
>> > + */
>> > +static void wakeup_handler(void)
>> > +{
>> > +       struct kvm_vcpu *vcpu;
>> > +       int cpu = smp_processor_id();
>> > +
>> > +       spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
>> > +       list_for_each_entry(vcpu, &per_cpu(blocked_vcpu_on_cpu, cpu),
>> > +                       blocked_vcpu_list) {
>> > +               struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
>> > +
>> > +               if (pi_test_on(pi_desc) == 1)
>> > +                       kvm_vcpu_kick(vcpu);
>> > +       }
>> > +       spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
>> > +}
>> > +
>> >  static __init int hardware_setup(void)
>> >  {
>> >         int r = -ENOMEM, i, msr;
>> > @@ -6305,6 +6333,8 @@ static __init int hardware_setup(void)
>> >                 kvm_x86_ops->enable_log_dirty_pt_masked = NULL;
>> >         }
>> >
>> > +       kvm_set_posted_intr_wakeup_handler(wakeup_handler);
>> > +
>> >         return alloc_kvm_area();
>> >
>> >  out8:
>> > @@ -10430,6 +10460,126 @@ static void
>> vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
>> >  }
>> >
>> >  /*
>> > + * This routine does the following things for vCPU which is going
>> > + * to be blocked if VT-d PI is enabled.
>> > + * - Store the vCPU to the wakeup list, so when interrupts happen
>> > + *   we can find the right vCPU to wake up.
>> > + * - Change the Posted-interrupt descriptor as below:
>> > + *      'NDST' <-- vcpu->pre_pcpu
>> > + *      'NV' <-- POSTED_INTR_WAKEUP_VECTOR
>> > + * - If 'ON' is set during this process, which means at least one
>> > + *   interrupt is posted for this vCPU, we cannot block it, in
>> > + *   this case, return 1, otherwise, return 0.
>> > + *
>> > + */
>> > +static int vmx_pre_block(struct kvm_vcpu *vcpu)
>> > +{
>> > +       unsigned long flags;
>> > +       unsigned int dest;
>> > +       struct pi_desc old, new;
>> > +       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
>> > +
>> > +       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
>> > +               !irq_remapping_cap(IRQ_POSTING_CAP))
>> > +               return 0;
>> > +
>> > +       vcpu->pre_pcpu = vcpu->cpu;
>> > +       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                         vcpu->pre_pcpu), flags);
>> > +       list_add_tail(&vcpu->blocked_vcpu_list,
>> > +                     &per_cpu(blocked_vcpu_on_cpu,
>> > +                     vcpu->pre_pcpu));
>> > +       spin_unlock_irqrestore(&per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                              vcpu->pre_pcpu), flags);
>> > +
>> > +       do {
>> > +               old.control = new.control = pi_desc->control;
>> > +
>> > +               /*
>> > +                * We should not block the vCPU if
>> > +                * an interrupt is posted for it.
>> > +                */
>> > +               if (pi_test_on(pi_desc) == 1) {
>> > +                       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                                         vcpu->pre_pcpu), flags);
>> > +                       list_del(&vcpu->blocked_vcpu_list);
>> > +                       spin_unlock_irqrestore(
>> > +                                       &per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                                       vcpu->pre_pcpu), flags);
>> > +                       vcpu->pre_pcpu = -1;
>> > +
>> > +                       return 1;
>> > +               }
>> > +
>> > +               WARN((pi_desc->sn == 1),
>> > +                    "Warning: SN field of posted-interrupts "
>> > +                    "is set before blocking\n");
>> > +
>> > +               /*
>> > +                * Since vCPU can be preempted during this process,
>> > +                * vcpu->cpu could be different with pre_pcpu, we
>> > +                * need to set pre_pcpu as the destination of wakeup
>> > +                * notification event, then we can find the right vCPU
>> > +                * to wakeup in wakeup handler if interrupts happen
>> > +                * when the vCPU is in blocked state.
>> > +                */
>> > +               dest = cpu_physical_id(vcpu->pre_pcpu);
>> > +
>> > +               if (x2apic_enabled())
>> > +                       new.ndst = dest;
>> > +               else
>> > +                       new.ndst = (dest << 8) & 0xFF00;
>> > +
>> > +               /* set 'NV' to 'wakeup vector' */
>> > +               new.nv = POSTED_INTR_WAKEUP_VECTOR;
>> > +       } while (cmpxchg(&pi_desc->control, old.control,
>> > +                       new.control) != old.control);
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static void vmx_post_block(struct kvm_vcpu *vcpu)
>> > +{
>> > +       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
>> > +       struct pi_desc old, new;
>> > +       unsigned int dest;
>> > +       unsigned long flags;
>> > +
>> > +       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
>> > +               !irq_remapping_cap(IRQ_POSTING_CAP))
>> > +               return;
>> > +
>> > +       do {
>> > +               old.control = new.control = pi_desc->control;
>> > +
>> > +               dest = cpu_physical_id(vcpu->cpu);
>> > +
>> > +               if (x2apic_enabled())
>> > +                       new.ndst = dest;
>> > +               else
>> > +                       new.ndst = (dest << 8) & 0xFF00;
>> > +
>> > +               /* Allow posting non-urgent interrupts */
>> > +               new.sn = 0;
>> > +
>> > +               /* set 'NV' to 'notification vector' */
>> > +               new.nv = POSTED_INTR_VECTOR;
>> > +       } while (cmpxchg(&pi_desc->control, old.control,
>> > +                       new.control) != old.control);
>> > +
>> > +       if(vcpu->pre_pcpu != -1) {
>> > +               spin_lock_irqsave(
>> > +                       &per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                       vcpu->pre_pcpu), flags);
>> > +               list_del(&vcpu->blocked_vcpu_list);
>> > +               spin_unlock_irqrestore(
>> > +                       &per_cpu(blocked_vcpu_on_cpu_lock,
>> > +                       vcpu->pre_pcpu), flags);
>> > +               vcpu->pre_pcpu = -1;
>> > +       }
>> > +}
>> > +
>> > +/*
>> >   * vmx_update_pi_irte - set IRTE for Posted-Interrupts
>> >   *
>> >   * @kvm: kvm
>> > @@ -10620,6 +10770,9 @@ static struct kvm_x86_ops vmx_x86_ops = {
>> >         .flush_log_dirty = vmx_flush_log_dirty,
>> >         .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked,
>> >
>> > +       .pre_block = vmx_pre_block,
>> > +       .post_block = vmx_post_block,
>> > +
>> >         .pmu_ops = &intel_pmu_ops,
>> >
>> >         .update_pi_irte = vmx_update_pi_irte,
>> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> > index 58688aa..46f55b2 100644
>> > --- a/arch/x86/kvm/x86.c
>> > +++ b/arch/x86/kvm/x86.c
>> > @@ -5869,7 +5869,12 @@ int kvm_vcpu_halt(struct kvm_vcpu *vcpu)
>> >  {
>> >         ++vcpu->stat.halt_exits;
>> >         if (irqchip_in_kernel(vcpu->kvm)) {
>> > -               vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
>> > +               /* Handle posted-interrupt when vCPU is to be halted */
>> > +               if (!kvm_x86_ops->pre_block ||
>> > +                               kvm_x86_ops->pre_block(vcpu) == 0) {
>> > +                       vcpu->arch.halted = true;
>> > +                       vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
>> > +               }
>> >                 return 1;
>> >         } else {
>> >                 vcpu->run->exit_reason = KVM_EXIT_HLT;
>> > @@ -6518,6 +6523,20 @@ static int vcpu_enter_guest(struct kvm_vcpu
>> *vcpu)
>> >                         kvm_vcpu_reload_apic_access_page(vcpu);
>> >         }
>> >
>> > +       /*
>> > +        * KVM_REQ_EVENT is not set when posted interrupts are set by
>> > +        * VT-d hardware, so we have to update RVI unconditionally.
>> > +        */
>> > +       if (kvm_lapic_enabled(vcpu)) {
>> > +               /*
>> > +                * Update architecture specific hints for APIC
>> > +                * virtual interrupt delivery.
>> > +                */
>> > +               if (kvm_x86_ops->hwapic_irr_update)
>> > +                       kvm_x86_ops->hwapic_irr_update(vcpu,
>> > +                               kvm_lapic_find_highest_irr(vcpu));
>> > +       }
>> > +
>> >         if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
>> >                 kvm_apic_accept_events(vcpu);
>> >                 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
>> > @@ -6534,13 +6553,6 @@ static int vcpu_enter_guest(struct kvm_vcpu
>> *vcpu)
>> >                         kvm_x86_ops->enable_irq_window(vcpu);
>> >
>> >                 if (kvm_lapic_enabled(vcpu)) {
>> > -                       /*
>> > -                        * Update architecture specific hints for APIC
>> > -                        * virtual interrupt delivery.
>> > -                        */
>> > -                       if (kvm_x86_ops->hwapic_irr_update)
>> > -                               kvm_x86_ops->hwapic_irr_update(vcpu,
>> > -                                       kvm_lapic_find_highest_irr(vcpu));
>> >                         update_cr8_intercept(vcpu);
>> >                         kvm_lapic_sync_to_vapic(vcpu);
>> >                 }
>> > @@ -6711,10 +6723,31 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
>> >
>> >         for (;;) {
>> >                 if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
>> > -                   !vcpu->arch.apf.halted)
>> > +                   !vcpu->arch.apf.halted) {
>> > +                       /*
>> > +                        * For some cases, we can get here with
>> > +                        * vcpu->arch.halted being true.
>> > +                        */
>> > +                       if (kvm_x86_ops->post_block && vcpu->arch.halted) {
>> > +                               kvm_x86_ops->post_block(vcpu);
>> > +                               vcpu->arch.halted = false;
>> > +                       }
>> > +
>> >                         r = vcpu_enter_guest(vcpu);
>> > -               else
>> > +               } else {
>> >                         r = vcpu_block(kvm, vcpu);
>> > +
>> > +                       /*
>> > +                        * post_block() must be called after
>> > +                        * pre_block() which is called in
>> > +                        * kvm_vcpu_halt().
>> > +                        */
>> > +                       if (kvm_x86_ops->post_block && vcpu->arch.halted) {
>> > +                               kvm_x86_ops->post_block(vcpu);
>> > +                               vcpu->arch.halted = false;
>> > +                       }
>> > +               }
>> > +
>> >                 if (r <= 0)
>> >                         break;
>> >
>> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
>> > index feba1fb..bf462e7 100644
>> > --- a/include/linux/kvm_host.h
>> > +++ b/include/linux/kvm_host.h
>> > @@ -231,6 +231,9 @@ struct kvm_vcpu {
>> >         unsigned long requests;
>> >         unsigned long guest_debug;
>> >
>> > +       int pre_pcpu;
>> > +       struct list_head blocked_vcpu_list;
>> > +
>> >         struct mutex mutex;
>> >         struct kvm_run *run;
>> >
>> > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> > index 8b8a444..191c7eb 100644
>> > --- a/virt/kvm/kvm_main.c
>> > +++ b/virt/kvm/kvm_main.c
>> > @@ -220,6 +220,9 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm
>> *kvm, unsigned id)
>> >         init_waitqueue_head(&vcpu->wq);
>> >         kvm_async_pf_vcpu_init(vcpu);
>> >
>> > +       vcpu->pre_pcpu = -1;
>> > +       INIT_LIST_HEAD(&vcpu->blocked_vcpu_list);
>> > +
>> >         page = alloc_page(GFP_KERNEL | __GFP_ZERO);
>> >         if (!page) {
>> >                 r = -ENOMEM;
>> > --
>> > 2.1.0
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe kvm" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1248059

FromPaolo Bonzini <pbonzini@redhat.com>
Date2015-10-15 20:20 +0200
Message-ID<qjVib-5Uv-15@gated-at.bofh.it>
In reply to#1248036

On 15/10/2015 19:39, David Matlack wrote:
> But after spending more time reading the source code this morning I
> found that kvm_vcpu_check_block() eventually calls into
> vmx_sync_pir_to_irr(), which copies PIR to IRR and clears ON. And then
> apic_find_highest_irr() detects the pending posted interrupt.

Right.  And related to this, Feng, can you check if this is still
necessary on kvm/queue:

@@ -6518,6 +6523,20 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			kvm_vcpu_reload_apic_access_page(vcpu);
 	}
 
+	/*
+	 * KVM_REQ_EVENT is not set when posted interrupts are set by
+	 * VT-d hardware, so we have to update RVI unconditionally.
+	 */
+	if (kvm_lapic_enabled(vcpu)) {
+		/*
+		 * Update architecture specific hints for APIC
+		 * virtual interrupt delivery.
+		 */
+		if (kvm_x86_ops->hwapic_irr_update)
+			kvm_x86_ops->hwapic_irr_update(vcpu,
+				kvm_lapic_find_highest_irr(vcpu));
+	}
+
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
 		kvm_apic_accept_events(vcpu);
 		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
@@ -6534,13 +6553,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			kvm_x86_ops->enable_irq_window(vcpu);
 
 		if (kvm_lapic_enabled(vcpu)) {
-			/*
-			 * Update architecture specific hints for APIC
-			 * virtual interrupt delivery.
-			 */
-			if (kvm_x86_ops->hwapic_irr_update)
-				kvm_x86_ops->hwapic_irr_update(vcpu,
-					kvm_lapic_find_highest_irr(vcpu));
 			update_cr8_intercept(vcpu);
 			kvm_lapic_sync_to_vapic(vcpu);
 		}


It may be obsolete now that we have the patch from Radim to set KVM_REQ_EVENT
in vmx_sync_pir_to_irr (http://permalink.gmane.org/gmane.linux.kernel/2057138).

Thanks,

Paolo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1248297

From"Wu, Feng" <feng.wu@intel.com>
Date2015-10-16 03:50 +0200
Message-ID<qk2jD-85Q-7@gated-at.bofh.it>
In reply to#1248059
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogUGFvbG8gQm9uemluaSBb
bWFpbHRvOnBhb2xvLmJvbnppbmlAZ21haWwuY29tXSBPbiBCZWhhbGYgT2YgUGFvbG8NCj4gQm9u
emluaQ0KPiBTZW50OiBGcmlkYXksIE9jdG9iZXIgMTYsIDIwMTUgMjoxMyBBTQ0KPiBUbzogRGF2
aWQgTWF0bGFjayA8ZG1hdGxhY2tAZ29vZ2xlLmNvbT47IFd1LCBGZW5nIDxmZW5nLnd1QGludGVs
LmNvbT4NCj4gQ2M6IGFsZXgud2lsbGlhbXNvbkByZWRoYXQuY29tOyBKb2VyZyBSb2VkZWwgPGpv
cm9AOGJ5dGVzLm9yZz47IE1hcmNlbG8NCj4gVG9zYXR0aSA8bXRvc2F0dGlAcmVkaGF0LmNvbT47
IGVyaWMuYXVnZXJAbGluYXJvLm9yZzsga3ZtIGxpc3QNCj4gPGt2bUB2Z2VyLmtlcm5lbC5vcmc+
OyBpb21tdUBsaXN0cy5saW51eC1mb3VuZGF0aW9uLm9yZzsgbGludXgtDQo+IGtlcm5lbEB2Z2Vy
Lmtlcm5lbC5vcmcNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2OSAxNy8xOF0gS1ZNOiBVcGRhdGUg
UG9zdGVkLUludGVycnVwdHMgRGVzY3JpcHRvciB3aGVuDQo+IHZDUFUgaXMgYmxvY2tlZA0KPiAN
Cj4gDQo+IA0KPiBPbiAxNS8xMC8yMDE1IDE5OjM5LCBEYXZpZCBNYXRsYWNrIHdyb3RlOg0KPiA+
IEJ1dCBhZnRlciBzcGVuZGluZyBtb3JlIHRpbWUgcmVhZGluZyB0aGUgc291cmNlIGNvZGUgdGhp
cyBtb3JuaW5nIEkNCj4gPiBmb3VuZCB0aGF0IGt2bV92Y3B1X2NoZWNrX2Jsb2NrKCkgZXZlbnR1
YWxseSBjYWxscyBpbnRvDQo+ID4gdm14X3N5bmNfcGlyX3RvX2lycigpLCB3aGljaCBjb3BpZXMg
UElSIHRvIElSUiBhbmQgY2xlYXJzIE9OLiBBbmQgdGhlbg0KPiA+IGFwaWNfZmluZF9oaWdoZXN0
X2lycigpIGRldGVjdHMgdGhlIHBlbmRpbmcgcG9zdGVkIGludGVycnVwdC4NCj4gDQo+IFJpZ2h0
LiAgQW5kIHJlbGF0ZWQgdG8gdGhpcywgRmVuZywgY2FuIHlvdSBjaGVjayBpZiB0aGlzIGlzIHN0
aWxsDQo+IG5lY2Vzc2FyeSBvbiBrdm0vcXVldWU6DQo+IA0KPiBAQCAtNjUxOCw2ICs2NTIzLDIw
IEBAIHN0YXRpYyBpbnQgdmNwdV9lbnRlcl9ndWVzdChzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpDQo+
ICAJCQlrdm1fdmNwdV9yZWxvYWRfYXBpY19hY2Nlc3NfcGFnZSh2Y3B1KTsNCj4gIAl9DQo+IA0K
PiArCS8qDQo+ICsJICogS1ZNX1JFUV9FVkVOVCBpcyBub3Qgc2V0IHdoZW4gcG9zdGVkIGludGVy
cnVwdHMgYXJlIHNldCBieQ0KPiArCSAqIFZULWQgaGFyZHdhcmUsIHNvIHdlIGhhdmUgdG8gdXBk
YXRlIFJWSSB1bmNvbmRpdGlvbmFsbHkuDQo+ICsJICovDQo+ICsJaWYgKGt2bV9sYXBpY19lbmFi
bGVkKHZjcHUpKSB7DQo+ICsJCS8qDQo+ICsJCSAqIFVwZGF0ZSBhcmNoaXRlY3R1cmUgc3BlY2lm
aWMgaGludHMgZm9yIEFQSUMNCj4gKwkJICogdmlydHVhbCBpbnRlcnJ1cHQgZGVsaXZlcnkuDQo+
ICsJCSAqLw0KPiArCQlpZiAoa3ZtX3g4Nl9vcHMtPmh3YXBpY19pcnJfdXBkYXRlKQ0KPiArCQkJ
a3ZtX3g4Nl9vcHMtPmh3YXBpY19pcnJfdXBkYXRlKHZjcHUsDQo+ICsJCQkJa3ZtX2xhcGljX2Zp
bmRfaGlnaGVzdF9pcnIodmNwdSkpOw0KPiArCX0NCj4gKw0KPiAgCWlmIChrdm1fY2hlY2tfcmVx
dWVzdChLVk1fUkVRX0VWRU5ULCB2Y3B1KSB8fCByZXFfaW50X3dpbikgew0KPiAgCQlrdm1fYXBp
Y19hY2NlcHRfZXZlbnRzKHZjcHUpOw0KPiAgCQlpZiAodmNwdS0+YXJjaC5tcF9zdGF0ZSA9PSBL
Vk1fTVBfU1RBVEVfSU5JVF9SRUNFSVZFRCkgew0KPiBAQCAtNjUzNCwxMyArNjU1Myw2IEBAIHN0
YXRpYyBpbnQgdmNwdV9lbnRlcl9ndWVzdChzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUpDQo+ICAJCQlr
dm1feDg2X29wcy0+ZW5hYmxlX2lycV93aW5kb3codmNwdSk7DQo+IA0KPiAgCQlpZiAoa3ZtX2xh
cGljX2VuYWJsZWQodmNwdSkpIHsNCj4gLQkJCS8qDQo+IC0JCQkgKiBVcGRhdGUgYXJjaGl0ZWN0
dXJlIHNwZWNpZmljIGhpbnRzIGZvciBBUElDDQo+IC0JCQkgKiB2aXJ0dWFsIGludGVycnVwdCBk
ZWxpdmVyeS4NCj4gLQkJCSAqLw0KPiAtCQkJaWYgKGt2bV94ODZfb3BzLT5od2FwaWNfaXJyX3Vw
ZGF0ZSkNCj4gLQkJCQlrdm1feDg2X29wcy0+aHdhcGljX2lycl91cGRhdGUodmNwdSwNCj4gLQkJ
CQkJa3ZtX2xhcGljX2ZpbmRfaGlnaGVzdF9pcnIodmNwdSkpOw0KPiAgCQkJdXBkYXRlX2NyOF9p
bnRlcmNlcHQodmNwdSk7DQo+ICAJCQlrdm1fbGFwaWNfc3luY190b192YXBpYyh2Y3B1KTsNCj4g
IAkJfQ0KPiANCg0KSSB0aGluayB0aGUgYWJvdmUgY29kZSBpcyBuZWVkZWQsIGJlZm9yZSB0aGUg
cGxhY2Ugd2hlcmUgJ0tWTV9SRVFfRVZFTlQnDQpnb3QgY2hlY2tlZCBpbiB2Y3B1X2VudGVyX2d1
ZXN0KCksIFZULWQgaGFyZHdhcmUgY2FuIGlzc3VlIG5vdGlmaWNhdGlvbg0KZXZlbnQgYXQgYW55
IHRpbWUuIENvbnNpZGVyIHRoZSBmb2xsb3dpbmcgc2NlbmFyaW86DQoNCnZjcHVfcnVuKCkNCnsN
CgkuLi4uLi4JDQoJDQoJZm9yKDs7KSB7DQoJCXBvaW50ICMxDQoJCXZjcHVfZW50ZXJfZ3Vlc3Qo
KQ0KCX0JDQoNCglwb2ludCAjMg0KfQ0KDQpGb3IgZXhhbXBsZSwgaWYgd2UgcmVjZWl2ZSBub3Rp
ZmljYXRpb24gZXZlbnRzIGlzc3VlZCBieSBWVC1kIGhhcmR3YXJlIGF0DQpwb2ludCAjMSBhbmQg
cG9pbnQjMiwgdGhlbiBlbnRlciB2Y3B1X2VudGVyX2d1ZXN0KCkgd2l0aCAnS1ZNX1JFUV9FVkVO
VCcNCm5vdCBzZXQsIHRoZSBpbnRlcnJ1cHRzIGNhbm5vdCBiZSBkZWxpdmVyZWQgdG8gZ3Vlc3Qg
ZHVyaW5nIF90aGlzXyBWTS1FbnRyeS4NCg0KVGhlIHBvaW50IGlzIHRoYXQgVlQtZCBoYXJkd2Fy
ZSBjYW4gaXNzdWUgbm90aWZpY2F0aW9uIGV2ZW50IGF0IGFueSB0aW1lLA0KYnV0IGl0IGNhbm5v
dCBzZXQgJ0tWTV9SRVFfRVZFTlQnIGxpa2Ugc29mdHdhcmUgZG9lcy4NCg0KTWF5YmUgb25lIHRo
aW5nIHdlIGNhbiBkbyBpcyBvbmx5IGV4ZWN1dGluZyB0aGUgZm9sbG93aW5nIGNvZGUgd2hlbg0K
dnQtZCBwaSBpcyBlbmFibGVkLA0KDQogKwkvKg0KICsJICogS1ZNX1JFUV9FVkVOVCBpcyBub3Qg
c2V0IHdoZW4gcG9zdGVkIGludGVycnVwdHMgYXJlIHNldCBieQ0KICsJICogVlQtZCBoYXJkd2Fy
ZSwgc28gd2UgaGF2ZSB0byB1cGRhdGUgUlZJIHVuY29uZGl0aW9uYWxseS4NCiArCSAqLw0KICsJ
aWYgKGt2bV9sYXBpY19lbmFibGVkKHZjcHUpKSB7DQogKwkJLyoNCiArCQkgKiBVcGRhdGUgYXJj
aGl0ZWN0dXJlIHNwZWNpZmljIGhpbnRzIGZvciBBUElDDQogKwkJICogdmlydHVhbCBpbnRlcnJ1
cHQgZGVsaXZlcnkuDQogKwkJICovDQogKwkJaWYgKGt2bV94ODZfb3BzLT5od2FwaWNfaXJyX3Vw
ZGF0ZSkNCiArCQkJa3ZtX3g4Nl9vcHMtPmh3YXBpY19pcnJfdXBkYXRlKHZjcHUsDQogKwkJCQlr
dm1fbGFwaWNfZmluZF9oaWdoZXN0X2lycih2Y3B1KSk7DQogKwl9DQogKw0KDQpBbmQgZG8gdGhp
cyBpbnNpZGUgdGhlIEtWTV9SRVFfRVZFTlQgY2hlY2sgd2hlbiBWVC1kIFBJIGlzIG5vdCBlbmFi
bGVkLg0KDQpUaGFua3MsDQpGZW5nDQoNCj4gDQo+IEl0IG1heSBiZSBvYnNvbGV0ZSBub3cgdGhh
dCB3ZSBoYXZlIHRoZSBwYXRjaCBmcm9tIFJhZGltIHRvIHNldA0KPiBLVk1fUkVRX0VWRU5UDQo+
IGluIHZteF9zeW5jX3Bpcl90b19pcnINCj4gKGh0dHA6Ly9wZXJtYWxpbmsuZ21hbmUub3JnL2dt
YW5lLmxpbnV4Lmtlcm5lbC8yMDU3MTM4KS4NCj4gDQo+IFRoYW5rcywNCj4gDQo+IFBhb2xvDQo=
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web