From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Graf Date: Tue, 06 May 2014 09:12:45 +0000 Subject: Re: [RFC PATCH] KVM: PPC: BOOK3S: HV: THP support for guest Message-Id: <5368A78D.4070509@suse.de> List-Id: References: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> In-Reply-To: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: "Aneesh Kumar K.V" Cc: paulus@samba.org, linuxppc-dev@lists.ozlabs.org, kvm-ppc@vger.kernel.org, kvm@vger.kernel.org On 05/04/2014 07:30 PM, Aneesh Kumar K.V wrote: > Signed-off-by: Aneesh Kumar K.V > --- > arch/powerpc/include/asm/kvm_book3s_64.h | 146 ++++++++++++++++++++++++++----- > arch/powerpc/kvm/book3s_hv.c | 7 ++ > 2 files changed, 130 insertions(+), 23 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h > index 51388befeddb..f03ea8f90576 100644 > --- a/arch/powerpc/include/asm/kvm_book3s_64.h > +++ b/arch/powerpc/include/asm/kvm_book3s_64.h > @@ -77,34 +77,122 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits) > return old = 0; > } > > +static inline int __hpte_actual_psize(unsigned int lp, int psize) > +{ > + int i, shift; > + unsigned int mask; > + > + /* start from 1 ignoring MMU_PAGE_4K */ > + for (i = 1; i < MMU_PAGE_COUNT; i++) { > + > + /* invalid penc */ > + if (mmu_psize_defs[psize].penc[i] = -1) > + continue; > + /* > + * encoding bits per actual page size > + * PTE LP actual page size > + * rrrr rrrz >=8KB > + * rrrr rrzz >KB > + * rrrr rzzz >2KB > + * rrrr zzzz >dKB > + * ....... > + */ > + shift = mmu_psize_defs[i].shift - LP_SHIFT; > + if (shift > LP_BITS) > + shift = LP_BITS; > + mask = (1 << shift) - 1; > + if ((lp & mask) = mmu_psize_defs[psize].penc[i]) > + return i; > + } > + return -1; > +} > + > static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, > unsigned long pte_index) > { > - unsigned long rb, va_low; > + int b_size, a_size; > + unsigned int penc; > + unsigned long rb = 0, va_low, sllp; > + unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); > + > + if (!(v & HPTE_V_LARGE)) { > + /* both base and actual psize is 4k */ > + b_size = MMU_PAGE_4K; > + a_size = MMU_PAGE_4K; > + } else { > + for (b_size = 0; b_size < MMU_PAGE_COUNT; b_size++) { > + > + /* valid entries have a shift value */ > + if (!mmu_psize_defs[b_size].shift) > + continue; > > + a_size = __hpte_actual_psize(lp, b_size); > + if (a_size != -1) > + break; > + } > + } > + /* > + * Ignore the top 14 bits of va > + * v have top two bits covering segment size, hence move > + * by 16 bits, Also clear the lower HPTE_V_AVPN_SHIFT (7) bits. > + * AVA field in v also have the lower 23 bits ignored. > + * For base page size 4K we need 14 .. 65 bits (so need to > + * collect extra 11 bits) > + * For others we need 14..14+i > + */ > + /* This covers 14..54 bits of va*/ > rb = (v & ~0x7fUL) << 16; /* AVA field */ > + /* > + * AVA in v had cleared lower 23 bits. We need to derive > + * that from pteg index > + */ > va_low = pte_index >> 3; > if (v & HPTE_V_SECONDARY) > va_low = ~va_low; > - /* xor vsid from AVA */ > + /* > + * get the vpn bits from va_low using reverse of hashing. > + * In v we have va with 23 bits dropped and then left shifted > + * HPTE_V_AVPN_SHIFT (7) bits. Now to find vsid we need > + * right shift it with (SID_SHIFT - (23 - 7)) > + */ > if (!(v & HPTE_V_1TB_SEG)) > - va_low ^= v >> 12; > + va_low ^= v >> (SID_SHIFT - 16); > else > - va_low ^= v >> 24; > + va_low ^= v >> (SID_SHIFT_1T - 16); > va_low &= 0x7ff; > - if (v & HPTE_V_LARGE) { > - rb |= 1; /* L field */ > - if (cpu_has_feature(CPU_FTR_ARCH_206) && > - (r & 0xff000)) { > - /* non-16MB large page, must be 64k */ > - /* (masks depend on page size) */ > - rb |= 0x1000; /* page encoding in LP field */ > - rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */ > - rb |= ((va_low << 4) & 0xf0); /* AVAL field (P7 doesn't seem to care) */ > - } > - } else { > - /* 4kB page */ > - rb |= (va_low & 0x7ff) << 12; /* remaining 11b of VA */ > + > + switch (b_size) { > + case MMU_PAGE_4K: > + sllp = ((mmu_psize_defs[a_size].sllp & SLB_VSID_L) >> 6) | > + ((mmu_psize_defs[a_size].sllp & SLB_VSID_LP) >> 4); > + rb |= sllp << 5; /* AP field */ > + rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */ > + break; > + default: > + { > + int aval_shift; > + /* > + * remaining 7bits of AVA/LP fields > + * Also contain the rr bits of LP > + */ > + rb |= (va_low & 0x7f) << 16; > + /* > + * Now clear not needed LP bits based on actual psize > + */ > + rb &= ~((1ul << mmu_psize_defs[a_size].shift) - 1); > + /* > + * AVAL field 58..77 - base_page_shift bits of va > + * we have space for 58..64 bits, Missing bits should > + * be zero filled. +1 is to take care of L bit shift > + */ > + aval_shift = 64 - (77 - mmu_psize_defs[b_size].shift) + 1; > + rb |= ((va_low << aval_shift) & 0xfe); > + > + rb |= 1; /* L field */ > + penc = mmu_psize_defs[b_size].penc[a_size]; > + rb |= penc << 12; /* LP field */ > + break; > + } > } > rb |= (v >> 54) & 0x300; /* B field */ > return rb; > @@ -112,14 +200,26 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, > > static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) > { > + int size, a_size; > + /* Look at the 8 bit LP value */ > + unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); > + > /* only handle 4k, 64k and 16M pages for now */ > if (!(h & HPTE_V_LARGE)) > - return 1ul << 12; /* 4k page */ > - if ((l & 0xf000) = 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206)) > - return 1ul << 16; /* 64k page */ > - if ((l & 0xff000) = 0) > - return 1ul << 24; /* 16M page */ > - return 0; /* error */ > + return 1ul << 12; > + else { > + for (size = 0; size < MMU_PAGE_COUNT; size++) { > + /* valid entries have a shift value */ > + if (!mmu_psize_defs[size].shift) > + continue; > + > + a_size = __hpte_actual_psize(lp, size); a_size as psize is probably a slightly confusing namer. Just call it a_psize. So if I understand this patch correctly, it simply introduces logic to handle page sizes other than 4k, 64k, 16M by analyzing the actual page size field in the HPTE. Mind to explain why exactly that enables us to use THP? What exactly is the flow if the pages are not backed by huge pages? What is the flow when they start to get backed by huge pages? > + if (a_size != -1) > + return 1ul << mmu_psize_defs[a_size].shift; > + } > + > + } > + return 0; > } > > static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 8227dba5af0f..a38d3289320a 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -1949,6 +1949,13 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, > * support pte_enc here > */ > (*sps)->enc[0].pte_enc = def->penc[linux_psize]; > + /* > + * Add 16MB MPSS support > + */ > + if (linux_psize != MMU_PAGE_16M) { > + (*sps)->enc[1].page_shift = 24; > + (*sps)->enc[1].pte_enc = def->penc[MMU_PAGE_16M]; > + } So this basically indicates that every segment (except for the 16MB one) can also handle 16MB MPSS page sizes? I suppose you want to remove the comment in kvm_vm_ioctl_get_smmu_info_hv() that says we don't do MPSS here. Can we also ensure that every system we run on can do MPSS? Alex From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4811D140180 for ; Tue, 6 May 2014 19:12:52 +1000 (EST) Message-ID: <5368A78D.4070509@suse.de> Date: Tue, 06 May 2014 11:12:45 +0200 From: Alexander Graf MIME-Version: 1.0 To: "Aneesh Kumar K.V" Subject: Re: [RFC PATCH] KVM: PPC: BOOK3S: HV: THP support for guest References: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> In-Reply-To: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Cc: paulus@samba.org, linuxppc-dev@lists.ozlabs.org, kvm-ppc@vger.kernel.org, kvm@vger.kernel.org List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , On 05/04/2014 07:30 PM, Aneesh Kumar K.V wrote: > Signed-off-by: Aneesh Kumar K.V > --- > arch/powerpc/include/asm/kvm_book3s_64.h | 146 ++++++++++++++++++++++++++----- > arch/powerpc/kvm/book3s_hv.c | 7 ++ > 2 files changed, 130 insertions(+), 23 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h > index 51388befeddb..f03ea8f90576 100644 > --- a/arch/powerpc/include/asm/kvm_book3s_64.h > +++ b/arch/powerpc/include/asm/kvm_book3s_64.h > @@ -77,34 +77,122 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits) > return old == 0; > } > > +static inline int __hpte_actual_psize(unsigned int lp, int psize) > +{ > + int i, shift; > + unsigned int mask; > + > + /* start from 1 ignoring MMU_PAGE_4K */ > + for (i = 1; i < MMU_PAGE_COUNT; i++) { > + > + /* invalid penc */ > + if (mmu_psize_defs[psize].penc[i] == -1) > + continue; > + /* > + * encoding bits per actual page size > + * PTE LP actual page size > + * rrrr rrrz >=8KB > + * rrrr rrzz >=16KB > + * rrrr rzzz >=32KB > + * rrrr zzzz >=64KB > + * ....... > + */ > + shift = mmu_psize_defs[i].shift - LP_SHIFT; > + if (shift > LP_BITS) > + shift = LP_BITS; > + mask = (1 << shift) - 1; > + if ((lp & mask) == mmu_psize_defs[psize].penc[i]) > + return i; > + } > + return -1; > +} > + > static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, > unsigned long pte_index) > { > - unsigned long rb, va_low; > + int b_size, a_size; > + unsigned int penc; > + unsigned long rb = 0, va_low, sllp; > + unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); > + > + if (!(v & HPTE_V_LARGE)) { > + /* both base and actual psize is 4k */ > + b_size = MMU_PAGE_4K; > + a_size = MMU_PAGE_4K; > + } else { > + for (b_size = 0; b_size < MMU_PAGE_COUNT; b_size++) { > + > + /* valid entries have a shift value */ > + if (!mmu_psize_defs[b_size].shift) > + continue; > > + a_size = __hpte_actual_psize(lp, b_size); > + if (a_size != -1) > + break; > + } > + } > + /* > + * Ignore the top 14 bits of va > + * v have top two bits covering segment size, hence move > + * by 16 bits, Also clear the lower HPTE_V_AVPN_SHIFT (7) bits. > + * AVA field in v also have the lower 23 bits ignored. > + * For base page size 4K we need 14 .. 65 bits (so need to > + * collect extra 11 bits) > + * For others we need 14..14+i > + */ > + /* This covers 14..54 bits of va*/ > rb = (v & ~0x7fUL) << 16; /* AVA field */ > + /* > + * AVA in v had cleared lower 23 bits. We need to derive > + * that from pteg index > + */ > va_low = pte_index >> 3; > if (v & HPTE_V_SECONDARY) > va_low = ~va_low; > - /* xor vsid from AVA */ > + /* > + * get the vpn bits from va_low using reverse of hashing. > + * In v we have va with 23 bits dropped and then left shifted > + * HPTE_V_AVPN_SHIFT (7) bits. Now to find vsid we need > + * right shift it with (SID_SHIFT - (23 - 7)) > + */ > if (!(v & HPTE_V_1TB_SEG)) > - va_low ^= v >> 12; > + va_low ^= v >> (SID_SHIFT - 16); > else > - va_low ^= v >> 24; > + va_low ^= v >> (SID_SHIFT_1T - 16); > va_low &= 0x7ff; > - if (v & HPTE_V_LARGE) { > - rb |= 1; /* L field */ > - if (cpu_has_feature(CPU_FTR_ARCH_206) && > - (r & 0xff000)) { > - /* non-16MB large page, must be 64k */ > - /* (masks depend on page size) */ > - rb |= 0x1000; /* page encoding in LP field */ > - rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */ > - rb |= ((va_low << 4) & 0xf0); /* AVAL field (P7 doesn't seem to care) */ > - } > - } else { > - /* 4kB page */ > - rb |= (va_low & 0x7ff) << 12; /* remaining 11b of VA */ > + > + switch (b_size) { > + case MMU_PAGE_4K: > + sllp = ((mmu_psize_defs[a_size].sllp & SLB_VSID_L) >> 6) | > + ((mmu_psize_defs[a_size].sllp & SLB_VSID_LP) >> 4); > + rb |= sllp << 5; /* AP field */ > + rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */ > + break; > + default: > + { > + int aval_shift; > + /* > + * remaining 7bits of AVA/LP fields > + * Also contain the rr bits of LP > + */ > + rb |= (va_low & 0x7f) << 16; > + /* > + * Now clear not needed LP bits based on actual psize > + */ > + rb &= ~((1ul << mmu_psize_defs[a_size].shift) - 1); > + /* > + * AVAL field 58..77 - base_page_shift bits of va > + * we have space for 58..64 bits, Missing bits should > + * be zero filled. +1 is to take care of L bit shift > + */ > + aval_shift = 64 - (77 - mmu_psize_defs[b_size].shift) + 1; > + rb |= ((va_low << aval_shift) & 0xfe); > + > + rb |= 1; /* L field */ > + penc = mmu_psize_defs[b_size].penc[a_size]; > + rb |= penc << 12; /* LP field */ > + break; > + } > } > rb |= (v >> 54) & 0x300; /* B field */ > return rb; > @@ -112,14 +200,26 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, > > static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) > { > + int size, a_size; > + /* Look at the 8 bit LP value */ > + unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1); > + > /* only handle 4k, 64k and 16M pages for now */ > if (!(h & HPTE_V_LARGE)) > - return 1ul << 12; /* 4k page */ > - if ((l & 0xf000) == 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206)) > - return 1ul << 16; /* 64k page */ > - if ((l & 0xff000) == 0) > - return 1ul << 24; /* 16M page */ > - return 0; /* error */ > + return 1ul << 12; > + else { > + for (size = 0; size < MMU_PAGE_COUNT; size++) { > + /* valid entries have a shift value */ > + if (!mmu_psize_defs[size].shift) > + continue; > + > + a_size = __hpte_actual_psize(lp, size); a_size as psize is probably a slightly confusing namer. Just call it a_psize. So if I understand this patch correctly, it simply introduces logic to handle page sizes other than 4k, 64k, 16M by analyzing the actual page size field in the HPTE. Mind to explain why exactly that enables us to use THP? What exactly is the flow if the pages are not backed by huge pages? What is the flow when they start to get backed by huge pages? > + if (a_size != -1) > + return 1ul << mmu_psize_defs[a_size].shift; > + } > + > + } > + return 0; > } > > static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 8227dba5af0f..a38d3289320a 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -1949,6 +1949,13 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, > * support pte_enc here > */ > (*sps)->enc[0].pte_enc = def->penc[linux_psize]; > + /* > + * Add 16MB MPSS support > + */ > + if (linux_psize != MMU_PAGE_16M) { > + (*sps)->enc[1].page_shift = 24; > + (*sps)->enc[1].pte_enc = def->penc[MMU_PAGE_16M]; > + } So this basically indicates that every segment (except for the 16MB one) can also handle 16MB MPSS page sizes? I suppose you want to remove the comment in kvm_vm_ioctl_get_smmu_info_hv() that says we don't do MPSS here. Can we also ensure that every system we run on can do MPSS? Alex From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexander Graf Subject: Re: [RFC PATCH] KVM: PPC: BOOK3S: HV: THP support for guest Date: Tue, 06 May 2014 11:12:45 +0200 Message-ID: <5368A78D.4070509@suse.de> References: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Cc: paulus@samba.org, linuxppc-dev@lists.ozlabs.org, kvm-ppc@vger.kernel.org, kvm@vger.kernel.org To: "Aneesh Kumar K.V" Return-path: In-Reply-To: <1399224616-25142-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+glppe-linuxppc-embedded-2=m.gmane.org@lists.ozlabs.org Sender: "Linuxppc-dev" List-Id: kvm.vger.kernel.org T24gMDUvMDQvMjAxNCAwNzozMCBQTSwgQW5lZXNoIEt1bWFyIEsuViB3cm90ZToKPiBTaWduZWQt b2ZmLWJ5OiBBbmVlc2ggS3VtYXIgSy5WIDxhbmVlc2gua3VtYXJAbGludXgudm5ldC5pYm0uY29t Pgo+IC0tLQo+ICAgYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNtL2t2bV9ib29rM3NfNjQuaCB8IDE0 NiArKysrKysrKysrKysrKysrKysrKysrKysrKy0tLS0tCj4gICBhcmNoL3Bvd2VycGMva3ZtL2Jv b2szc19odi5jICAgICAgICAgICAgIHwgICA3ICsrCj4gICAyIGZpbGVzIGNoYW5nZWQsIDEzMCBp bnNlcnRpb25zKCspLCAyMyBkZWxldGlvbnMoLSkKPgo+IGRpZmYgLS1naXQgYS9hcmNoL3Bvd2Vy cGMvaW5jbHVkZS9hc20va3ZtX2Jvb2szc182NC5oIGIvYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNt L2t2bV9ib29rM3NfNjQuaAo+IGluZGV4IDUxMzg4YmVmZWRkYi4uZjAzZWE4ZjkwNTc2IDEwMDY0 NAo+IC0tLSBhL2FyY2gvcG93ZXJwYy9pbmNsdWRlL2FzbS9rdm1fYm9vazNzXzY0LmgKPiArKysg Yi9hcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20va3ZtX2Jvb2szc182NC5oCj4gQEAgLTc3LDM0ICs3 NywxMjIgQEAgc3RhdGljIGlubGluZSBsb25nIHRyeV9sb2NrX2hwdGUodW5zaWduZWQgbG9uZyAq aHB0ZSwgdW5zaWduZWQgbG9uZyBiaXRzKQo+ICAgCXJldHVybiBvbGQgPT0gMDsKPiAgIH0KPiAg IAo+ICtzdGF0aWMgaW5saW5lIGludCBfX2hwdGVfYWN0dWFsX3BzaXplKHVuc2lnbmVkIGludCBs cCwgaW50IHBzaXplKQo+ICt7Cj4gKwlpbnQgaSwgc2hpZnQ7Cj4gKwl1bnNpZ25lZCBpbnQgbWFz azsKPiArCj4gKwkvKiBzdGFydCBmcm9tIDEgaWdub3JpbmcgTU1VX1BBR0VfNEsgKi8KPiArCWZv ciAoaSA9IDE7IGkgPCBNTVVfUEFHRV9DT1VOVDsgaSsrKSB7Cj4gKwo+ICsJCS8qIGludmFsaWQg cGVuYyAqLwo+ICsJCWlmIChtbXVfcHNpemVfZGVmc1twc2l6ZV0ucGVuY1tpXSA9PSAtMSkKPiAr CQkJY29udGludWU7Cj4gKwkJLyoKPiArCQkgKiBlbmNvZGluZyBiaXRzIHBlciBhY3R1YWwgcGFn ZSBzaXplCj4gKwkJICogICAgICAgIFBURSBMUCAgICAgYWN0dWFsIHBhZ2Ugc2l6ZQo+ICsJCSAq ICAgIHJycnIgcnJyegkJPj04S0IKPiArCQkgKiAgICBycnJyIHJyenoJCT49MTZLQgo+ICsJCSAq ICAgIHJycnIgcnp6egkJPj0zMktCCj4gKwkJICogICAgcnJyciB6enp6CQk+PTY0S0IKPiArCQkg KiAuLi4uLi4uCj4gKwkJICovCj4gKwkJc2hpZnQgPSBtbXVfcHNpemVfZGVmc1tpXS5zaGlmdCAt IExQX1NISUZUOwo+ICsJCWlmIChzaGlmdCA+IExQX0JJVFMpCj4gKwkJCXNoaWZ0ID0gTFBfQklU UzsKPiArCQltYXNrID0gKDEgPDwgc2hpZnQpIC0gMTsKPiArCQlpZiAoKGxwICYgbWFzaykgPT0g bW11X3BzaXplX2RlZnNbcHNpemVdLnBlbmNbaV0pCj4gKwkJCXJldHVybiBpOwo+ICsJfQo+ICsJ cmV0dXJuIC0xOwo+ICt9Cj4gKwo+ICAgc3RhdGljIGlubGluZSB1bnNpZ25lZCBsb25nIGNvbXB1 dGVfdGxiaWVfcmIodW5zaWduZWQgbG9uZyB2LCB1bnNpZ25lZCBsb25nIHIsCj4gICAJCQkJCSAg ICAgdW5zaWduZWQgbG9uZyBwdGVfaW5kZXgpCj4gICB7Cj4gLQl1bnNpZ25lZCBsb25nIHJiLCB2 YV9sb3c7Cj4gKwlpbnQgYl9zaXplLCBhX3NpemU7Cj4gKwl1bnNpZ25lZCBpbnQgcGVuYzsKPiAr CXVuc2lnbmVkIGxvbmcgcmIgPSAwLCB2YV9sb3csIHNsbHA7Cj4gKwl1bnNpZ25lZCBpbnQgbHAg PSAociA+PiBMUF9TSElGVCkgJiAoKDEgPDwgTFBfQklUUykgLSAxKTsKPiArCj4gKwlpZiAoISh2 ICYgSFBURV9WX0xBUkdFKSkgewo+ICsJCS8qIGJvdGggYmFzZSBhbmQgYWN0dWFsIHBzaXplIGlz IDRrICovCj4gKwkJYl9zaXplID0gTU1VX1BBR0VfNEs7Cj4gKwkJYV9zaXplID0gTU1VX1BBR0Vf NEs7Cj4gKwl9IGVsc2Ugewo+ICsJCWZvciAoYl9zaXplID0gMDsgYl9zaXplIDwgTU1VX1BBR0Vf Q09VTlQ7IGJfc2l6ZSsrKSB7Cj4gKwo+ICsJCQkvKiB2YWxpZCBlbnRyaWVzIGhhdmUgYSBzaGlm dCB2YWx1ZSAqLwo+ICsJCQlpZiAoIW1tdV9wc2l6ZV9kZWZzW2Jfc2l6ZV0uc2hpZnQpCj4gKwkJ CQljb250aW51ZTsKPiAgIAo+ICsJCQlhX3NpemUgPSBfX2hwdGVfYWN0dWFsX3BzaXplKGxwLCBi X3NpemUpOwo+ICsJCQlpZiAoYV9zaXplICE9IC0xKQo+ICsJCQkJYnJlYWs7Cj4gKwkJfQo+ICsJ fQo+ICsJLyoKPiArCSAqIElnbm9yZSB0aGUgdG9wIDE0IGJpdHMgb2YgdmEKPiArCSAqIHYgaGF2 ZSB0b3AgdHdvIGJpdHMgY292ZXJpbmcgc2VnbWVudCBzaXplLCBoZW5jZSBtb3ZlCj4gKwkgKiBi eSAxNiBiaXRzLCBBbHNvIGNsZWFyIHRoZSBsb3dlciBIUFRFX1ZfQVZQTl9TSElGVCAoNykgYml0 cy4KPiArCSAqIEFWQSBmaWVsZCBpbiB2IGFsc28gaGF2ZSB0aGUgbG93ZXIgMjMgYml0cyBpZ25v cmVkLgo+ICsJICogRm9yIGJhc2UgcGFnZSBzaXplIDRLIHdlIG5lZWQgMTQgLi4gNjUgYml0cyAo c28gbmVlZCB0bwo+ICsJICogY29sbGVjdCBleHRyYSAxMSBiaXRzKQo+ICsJICogRm9yIG90aGVy cyB3ZSBuZWVkIDE0Li4xNCtpCj4gKwkgKi8KPiArCS8qIFRoaXMgY292ZXJzIDE0Li41NCBiaXRz IG9mIHZhKi8KPiAgIAlyYiA9ICh2ICYgfjB4N2ZVTCkgPDwgMTY7CQkvKiBBVkEgZmllbGQgKi8K PiArCS8qCj4gKwkgKiBBVkEgaW4gdiBoYWQgY2xlYXJlZCBsb3dlciAyMyBiaXRzLiBXZSBuZWVk IHRvIGRlcml2ZQo+ICsJICogdGhhdCBmcm9tIHB0ZWcgaW5kZXgKPiArCSAqLwo+ICAgCXZhX2xv dyA9IHB0ZV9pbmRleCA+PiAzOwo+ICAgCWlmICh2ICYgSFBURV9WX1NFQ09OREFSWSkKPiAgIAkJ dmFfbG93ID0gfnZhX2xvdzsKPiAtCS8qIHhvciB2c2lkIGZyb20gQVZBICovCj4gKwkvKgo+ICsJ ICogZ2V0IHRoZSB2cG4gYml0cyBmcm9tIHZhX2xvdyB1c2luZyByZXZlcnNlIG9mIGhhc2hpbmcu Cj4gKwkgKiBJbiB2IHdlIGhhdmUgdmEgd2l0aCAyMyBiaXRzIGRyb3BwZWQgYW5kIHRoZW4gbGVm dCBzaGlmdGVkCj4gKwkgKiBIUFRFX1ZfQVZQTl9TSElGVCAoNykgYml0cy4gTm93IHRvIGZpbmQg dnNpZCB3ZSBuZWVkCj4gKwkgKiByaWdodCBzaGlmdCBpdCB3aXRoIChTSURfU0hJRlQgLSAoMjMg LSA3KSkKPiArCSAqLwo+ICAgCWlmICghKHYgJiBIUFRFX1ZfMVRCX1NFRykpCj4gLQkJdmFfbG93 IF49IHYgPj4gMTI7Cj4gKwkJdmFfbG93IF49IHYgPj4gKFNJRF9TSElGVCAtIDE2KTsKPiAgIAll bHNlCj4gLQkJdmFfbG93IF49IHYgPj4gMjQ7Cj4gKwkJdmFfbG93IF49IHYgPj4gKFNJRF9TSElG VF8xVCAtIDE2KTsKPiAgIAl2YV9sb3cgJj0gMHg3ZmY7Cj4gLQlpZiAodiAmIEhQVEVfVl9MQVJH RSkgewo+IC0JCXJiIHw9IDE7CQkJLyogTCBmaWVsZCAqLwo+IC0JCWlmIChjcHVfaGFzX2ZlYXR1 cmUoQ1BVX0ZUUl9BUkNIXzIwNikgJiYKPiAtCQkgICAgKHIgJiAweGZmMDAwKSkgewo+IC0JCQkv KiBub24tMTZNQiBsYXJnZSBwYWdlLCBtdXN0IGJlIDY0ayAqLwo+IC0JCQkvKiAobWFza3MgZGVw ZW5kIG9uIHBhZ2Ugc2l6ZSkgKi8KPiAtCQkJcmIgfD0gMHgxMDAwOwkJLyogcGFnZSBlbmNvZGlu ZyBpbiBMUCBmaWVsZCAqLwo+IC0JCQlyYiB8PSAodmFfbG93ICYgMHg3ZikgPDwgMTY7IC8qIDdi IG9mIFZBIGluIEFWQS9MUCBmaWVsZCAqLwo+IC0JCQlyYiB8PSAoKHZhX2xvdyA8PCA0KSAmIDB4 ZjApOwkvKiBBVkFMIGZpZWxkIChQNyBkb2Vzbid0IHNlZW0gdG8gY2FyZSkgKi8KPiAtCQl9Cj4g LQl9IGVsc2Ugewo+IC0JCS8qIDRrQiBwYWdlICovCj4gLQkJcmIgfD0gKHZhX2xvdyAmIDB4N2Zm KSA8PCAxMjsJLyogcmVtYWluaW5nIDExYiBvZiBWQSAqLwo+ICsKPiArCXN3aXRjaCAoYl9zaXpl KSB7Cj4gKwljYXNlIE1NVV9QQUdFXzRLOgo+ICsJCXNsbHAgPSAoKG1tdV9wc2l6ZV9kZWZzW2Ff c2l6ZV0uc2xscCAmIFNMQl9WU0lEX0wpID4+IDYpIHwKPiArCQkJKChtbXVfcHNpemVfZGVmc1th X3NpemVdLnNsbHAgJiBTTEJfVlNJRF9MUCkgPj4gNCk7Cj4gKwkJcmIgfD0gc2xscCA8PCA1Owkv KiAgQVAgZmllbGQgKi8KPiArCQlyYiB8PSAodmFfbG93ICYgMHg3ZmYpIDw8IDEyOwkvKiByZW1h aW5pbmcgMTEgYml0cyBvZiBBVkEgKi8KPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwl7Cj4g KwkJaW50IGF2YWxfc2hpZnQ7Cj4gKwkJLyoKPiArCQkgKiByZW1haW5pbmcgN2JpdHMgb2YgQVZB L0xQIGZpZWxkcwo+ICsJCSAqIEFsc28gY29udGFpbiB0aGUgcnIgYml0cyBvZiBMUAo+ICsJCSAq Lwo+ICsJCXJiIHw9ICh2YV9sb3cgJiAweDdmKSA8PCAxNjsKPiArCQkvKgo+ICsJCSAqIE5vdyBj bGVhciBub3QgbmVlZGVkIExQIGJpdHMgYmFzZWQgb24gYWN0dWFsIHBzaXplCj4gKwkJICovCj4g KwkJcmIgJj0gfigoMXVsIDw8IG1tdV9wc2l6ZV9kZWZzW2Ffc2l6ZV0uc2hpZnQpIC0gMSk7Cj4g KwkJLyoKPiArCQkgKiBBVkFMIGZpZWxkIDU4Li43NyAtIGJhc2VfcGFnZV9zaGlmdCBiaXRzIG9m IHZhCj4gKwkJICogd2UgaGF2ZSBzcGFjZSBmb3IgNTguLjY0IGJpdHMsIE1pc3NpbmcgYml0cyBz aG91bGQKPiArCQkgKiBiZSB6ZXJvIGZpbGxlZC4gKzEgaXMgdG8gdGFrZSBjYXJlIG9mIEwgYml0 IHNoaWZ0Cj4gKwkJICovCj4gKwkJYXZhbF9zaGlmdCA9IDY0IC0gKDc3IC0gbW11X3BzaXplX2Rl ZnNbYl9zaXplXS5zaGlmdCkgKyAxOwo+ICsJCXJiIHw9ICgodmFfbG93IDw8IGF2YWxfc2hpZnQp ICYgMHhmZSk7Cj4gKwo+ICsJCXJiIHw9IDE7CQkvKiBMIGZpZWxkICovCj4gKwkJcGVuYyA9IG1t dV9wc2l6ZV9kZWZzW2Jfc2l6ZV0ucGVuY1thX3NpemVdOwo+ICsJCXJiIHw9IHBlbmMgPDwgMTI7 CS8qIExQIGZpZWxkICovCj4gKwkJYnJlYWs7Cj4gKwl9Cj4gICAJfQo+ICAgCXJiIHw9ICh2ID4+ IDU0KSAmIDB4MzAwOwkJLyogQiBmaWVsZCAqLwo+ICAgCXJldHVybiByYjsKPiBAQCAtMTEyLDE0 ICsyMDAsMjYgQEAgc3RhdGljIGlubGluZSB1bnNpZ25lZCBsb25nIGNvbXB1dGVfdGxiaWVfcmIo dW5zaWduZWQgbG9uZyB2LCB1bnNpZ25lZCBsb25nIHIsCj4gICAKPiAgIHN0YXRpYyBpbmxpbmUg dW5zaWduZWQgbG9uZyBocHRlX3BhZ2Vfc2l6ZSh1bnNpZ25lZCBsb25nIGgsIHVuc2lnbmVkIGxv bmcgbCkKPiAgIHsKPiArCWludCBzaXplLCBhX3NpemU7Cj4gKwkvKiBMb29rIGF0IHRoZSA4IGJp dCBMUCB2YWx1ZSAqLwo+ICsJdW5zaWduZWQgaW50IGxwID0gKGwgPj4gTFBfU0hJRlQpICYgKCgx IDw8IExQX0JJVFMpIC0gMSk7Cj4gKwo+ICAgCS8qIG9ubHkgaGFuZGxlIDRrLCA2NGsgYW5kIDE2 TSBwYWdlcyBmb3Igbm93ICovCj4gICAJaWYgKCEoaCAmIEhQVEVfVl9MQVJHRSkpCj4gLQkJcmV0 dXJuIDF1bCA8PCAxMjsJCS8qIDRrIHBhZ2UgKi8KPiAtCWlmICgobCAmIDB4ZjAwMCkgPT0gMHgx MDAwICYmIGNwdV9oYXNfZmVhdHVyZShDUFVfRlRSX0FSQ0hfMjA2KSkKPiAtCQlyZXR1cm4gMXVs IDw8IDE2OwkJLyogNjRrIHBhZ2UgKi8KPiAtCWlmICgobCAmIDB4ZmYwMDApID09IDApCj4gLQkJ cmV0dXJuIDF1bCA8PCAyNDsJCS8qIDE2TSBwYWdlICovCj4gLQlyZXR1cm4gMDsJCQkJLyogZXJy b3IgKi8KPiArCQlyZXR1cm4gMXVsIDw8IDEyOwo+ICsJZWxzZSB7Cj4gKwkJZm9yIChzaXplID0g MDsgc2l6ZSA8IE1NVV9QQUdFX0NPVU5UOyBzaXplKyspIHsKPiArCQkJLyogdmFsaWQgZW50cmll cyBoYXZlIGEgc2hpZnQgdmFsdWUgKi8KPiArCQkJaWYgKCFtbXVfcHNpemVfZGVmc1tzaXplXS5z aGlmdCkKPiArCQkJCWNvbnRpbnVlOwo+ICsKPiArCQkJYV9zaXplID0gX19ocHRlX2FjdHVhbF9w c2l6ZShscCwgc2l6ZSk7CgphX3NpemUgYXMgcHNpemUgaXMgcHJvYmFibHkgYSBzbGlnaHRseSBj b25mdXNpbmcgbmFtZXIuIEp1c3QgY2FsbCBpdCAKYV9wc2l6ZS4KClNvIGlmIEkgdW5kZXJzdGFu ZCB0aGlzIHBhdGNoIGNvcnJlY3RseSwgaXQgc2ltcGx5IGludHJvZHVjZXMgbG9naWMgdG8gCmhh bmRsZSBwYWdlIHNpemVzIG90aGVyIHRoYW4gNGssIDY0aywgMTZNIGJ5IGFuYWx5emluZyB0aGUg YWN0dWFsIHBhZ2UgCnNpemUgZmllbGQgaW4gdGhlIEhQVEUuIE1pbmQgdG8gZXhwbGFpbiB3aHkg ZXhhY3RseSB0aGF0IGVuYWJsZXMgdXMgdG8gCnVzZSBUSFA/CgpXaGF0IGV4YWN0bHkgaXMgdGhl IGZsb3cgaWYgdGhlIHBhZ2VzIGFyZSBub3QgYmFja2VkIGJ5IGh1Z2UgcGFnZXM/IFdoYXQgCmlz IHRoZSBmbG93IHdoZW4gdGhleSBzdGFydCB0byBnZXQgYmFja2VkIGJ5IGh1Z2UgcGFnZXM/Cgo+ ICsJCQlpZiAoYV9zaXplICE9IC0xKQo+ICsJCQkJcmV0dXJuIDF1bCA8PCBtbXVfcHNpemVfZGVm c1thX3NpemVdLnNoaWZ0Owo+ICsJCX0KPiArCj4gKwl9Cj4gKwlyZXR1cm4gMDsKPiAgIH0KPiAg IAo+ICAgc3RhdGljIGlubGluZSB1bnNpZ25lZCBsb25nIGhwdGVfcnBuKHVuc2lnbmVkIGxvbmcg cHRlbCwgdW5zaWduZWQgbG9uZyBwc2l6ZSkKPiBkaWZmIC0tZ2l0IGEvYXJjaC9wb3dlcnBjL2t2 bS9ib29rM3NfaHYuYyBiL2FyY2gvcG93ZXJwYy9rdm0vYm9vazNzX2h2LmMKPiBpbmRleCA4MjI3 ZGJhNWFmMGYuLmEzOGQzMjg5MzIwYSAxMDA2NDQKPiAtLS0gYS9hcmNoL3Bvd2VycGMva3ZtL2Jv b2szc19odi5jCj4gKysrIGIvYXJjaC9wb3dlcnBjL2t2bS9ib29rM3NfaHYuYwo+IEBAIC0xOTQ5 LDYgKzE5NDksMTMgQEAgc3RhdGljIHZvaWQga3ZtcHBjX2FkZF9zZWdfcGFnZV9zaXplKHN0cnVj dCBrdm1fcHBjX29uZV9zZWdfcGFnZV9zaXplICoqc3BzLAo+ICAgCSAqIHN1cHBvcnQgcHRlX2Vu YyBoZXJlCj4gICAJICovCj4gICAJKCpzcHMpLT5lbmNbMF0ucHRlX2VuYyA9IGRlZi0+cGVuY1ts aW51eF9wc2l6ZV07Cj4gKwkvKgo+ICsJICogQWRkIDE2TUIgTVBTUyBzdXBwb3J0Cj4gKwkgKi8K PiArCWlmIChsaW51eF9wc2l6ZSAhPSBNTVVfUEFHRV8xNk0pIHsKPiArCQkoKnNwcyktPmVuY1sx XS5wYWdlX3NoaWZ0ID0gMjQ7Cj4gKwkJKCpzcHMpLT5lbmNbMV0ucHRlX2VuYyA9IGRlZi0+cGVu Y1tNTVVfUEFHRV8xNk1dOwo+ICsJfQoKU28gdGhpcyBiYXNpY2FsbHkgaW5kaWNhdGVzIHRoYXQg ZXZlcnkgc2VnbWVudCAoZXhjZXB0IGZvciB0aGUgMTZNQiBvbmUpIApjYW4gYWxzbyBoYW5kbGUg MTZNQiBNUFNTIHBhZ2Ugc2l6ZXM/IEkgc3VwcG9zZSB5b3Ugd2FudCB0byByZW1vdmUgdGhlIApj b21tZW50IGluIGt2bV92bV9pb2N0bF9nZXRfc21tdV9pbmZvX2h2KCkgdGhhdCBzYXlzIHdlIGRv bid0IGRvIE1QU1MgaGVyZS4KCkNhbiB3ZSBhbHNvIGVuc3VyZSB0aGF0IGV2ZXJ5IHN5c3RlbSB3 ZSBydW4gb24gY2FuIGRvIE1QU1M/CgoKQWxleAoKX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KTGludXhwcGMtZGV2IG1haWxpbmcgbGlzdApMaW51eHBwYy1k ZXZAbGlzdHMub3psYWJzLm9yZwpodHRwczovL2xpc3RzLm96bGFicy5vcmcvbGlzdGluZm8vbGlu dXhwcGMtZGV2