From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28D51C47094 for ; Thu, 10 Jun 2021 11:54:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0CE85613E7 for ; Thu, 10 Jun 2021 11:54:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230212AbhFJL4C (ORCPT ); Thu, 10 Jun 2021 07:56:02 -0400 Received: from m43-7.mailgun.net ([69.72.43.7]:28672 "EHLO m43-7.mailgun.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230113AbhFJL4B (ORCPT ); Thu, 10 Jun 2021 07:56:01 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1623326046; h=Message-ID: References: In-Reply-To: Subject: Cc: To: From: Date: Content-Transfer-Encoding: Content-Type: MIME-Version: Sender; bh=DYoWVGF66T3kPghm81L8ucvdZSLOiQtMZDyvXXzEyjY=; b=b6/26dKs7WAJaDolvPH1G+J4y0eA5akQeuHfvyV1NpDJMUoCERiuryPQJhRvREcvq/x55r/J 7vUgF0Ipw3bL4pxGJFes4jyU8BhuAzvYpTHr7PfNAyXb7J08hHhplPQot6aMumL+vaP3J+fv ddHGVG9OQuXzXhNlUUZiqRUo+2o= X-Mailgun-Sending-Ip: 69.72.43.7 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n03.prod.us-east-1.postgun.com with SMTP id 60c1fd5be27c0cc77f930467 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Thu, 10 Jun 2021 11:54:03 GMT Sender: saiprakash.ranjan=codeaurora.org@mg.codeaurora.org Received: by smtp.codeaurora.org (Postfix, from userid 1001) id D4904C4338A; Thu, 10 Jun 2021 11:54:02 +0000 (UTC) Received: from mail.codeaurora.org (localhost.localdomain [127.0.0.1]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: saiprakash.ranjan) by smtp.codeaurora.org (Postfix) with ESMTPSA id 6DDDDC433F1; Thu, 10 Jun 2021 11:54:01 +0000 (UTC) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Date: Thu, 10 Jun 2021 17:24:01 +0530 From: Sai Prakash Ranjan To: Robin Murphy Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, Will Deacon , linux-arm-kernel@lists.infradead.org, Thierry Reding , Krishna Reddy Subject: Re: [PATCH] iommu/io-pgtable-arm: Optimize partial walk flush for large scatter-gather list In-Reply-To: <266f190e-99ae-9175-cf13-7a77730af389@arm.com> References: <20210609145315.25750-1-saiprakash.ranjan@codeaurora.org> <35bfd245-45e2-8083-b620-330d6dbd7bd7@arm.com> <12067ffb8243b220cf03e83aaac3e823@codeaurora.org> <266f190e-99ae-9175-cf13-7a77730af389@arm.com> Message-ID: X-Sender: saiprakash.ranjan@codeaurora.org User-Agent: Roundcube Webmail/1.3.9 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Hi Robin, On 2021-06-10 17:03, Robin Murphy wrote: > On 2021-06-10 10:36, Sai Prakash Ranjan wrote: >> Hi Robin, >> >> On 2021-06-10 14:38, Robin Murphy wrote: >>> On 2021-06-10 06:24, Sai Prakash Ranjan wrote: >>>> Hi Robin, >>>> >>>> On 2021-06-10 00:14, Robin Murphy wrote: >>>>> On 2021-06-09 15:53, Sai Prakash Ranjan wrote: >>>>>> Currently for iommu_unmap() of large scatter-gather list with page >>>>>> size >>>>>> elements, the majority of time is spent in flushing of partial >>>>>> walks in >>>>>> __arm_lpae_unmap() which is a VA based TLB invalidation (TLBIVA >>>>>> for >>>>>> arm-smmu). >>>>>> >>>>>> For example: to unmap a 32MB scatter-gather list with page size >>>>>> elements >>>>>> (8192 entries), there are 16->2MB buffer unmaps based on the >>>>>> pgsize (2MB >>>>>> for 4K granule) and each of 2MB will further result in 512 TLBIVAs >>>>>> (2MB/4K) >>>>>> resulting in a total of 8192 TLBIVAs (512*16) for 16->2MB causing >>>>>> a huge >>>>>> overhead. >>>>>> >>>>>> So instead use io_pgtable_tlb_flush_all() to invalidate the entire >>>>>> context >>>>>> if size (pgsize) is greater than the granule size (4K, 16K, 64K). >>>>>> For this >>>>>> example of 32MB scatter-gather list unmap, this results in just 16 >>>>>> ASID >>>>>> based TLB invalidations or tlb_flush_all() callback (TLBIASID in >>>>>> case of >>>>>> arm-smmu) as opposed to 8192 TLBIVAs thereby increasing the >>>>>> performance of >>>>>> unmaps drastically. >>>>>> >>>>>> Condition (size > granule size) is chosen for >>>>>> io_pgtable_tlb_flush_all() >>>>>> because for any granule with supported pgsizes, we will have at >>>>>> least 512 >>>>>> TLB invalidations for which tlb_flush_all() is already >>>>>> recommended. For >>>>>> example, take 4K granule with 2MB pgsize, this will result in 512 >>>>>> TLBIVA >>>>>> in partial walk flush. >>>>>> >>>>>> Test on QTI SM8150 SoC for 10 iterations of iommu_{map_sg}/unmap: >>>>>> (average over 10 iterations) >>>>>> >>>>>> Before this optimization: >>>>>> >>>>>>      size        iommu_map_sg      iommu_unmap >>>>>>        4K            2.067 us         1.854 us >>>>>>       64K            9.598 us         8.802 us >>>>>>        1M          148.890 us       130.718 us >>>>>>        2M          305.864 us        67.291 us >>>>>>       12M         1793.604 us       390.838 us >>>>>>       16M         2386.848 us       518.187 us >>>>>>       24M         3563.296 us       775.989 us >>>>>>       32M         4747.171 us      1033.364 us >>>>>> >>>>>> After this optimization: >>>>>> >>>>>>      size        iommu_map_sg      iommu_unmap >>>>>>        4K            1.723 us         1.765 us >>>>>>       64K            9.880 us         8.869 us >>>>>>        1M          155.364 us       135.223 us >>>>>>        2M          303.906 us         5.385 us >>>>>>       12M         1786.557 us        21.250 us >>>>>>       16M         2391.890 us        27.437 us >>>>>>       24M         3570.895 us        39.937 us >>>>>>       32M         4755.234 us        51.797 us >>>>>> >>>>>> This is further reduced once the map/unmap_pages() support gets in >>>>>> which >>>>>> will result in just 1 tlb_flush_all() as opposed to 16 >>>>>> tlb_flush_all(). >>>>>> >>>>>> Signed-off-by: Sai Prakash Ranjan >>>>>> >>>>>> --- >>>>>>   drivers/iommu/io-pgtable-arm.c | 7 +++++-- >>>>>>   1 file changed, 5 insertions(+), 2 deletions(-) >>>>>> >>>>>> diff --git a/drivers/iommu/io-pgtable-arm.c >>>>>> b/drivers/iommu/io-pgtable-arm.c >>>>>> index 87def58e79b5..c3cb9add3179 100644 >>>>>> --- a/drivers/iommu/io-pgtable-arm.c >>>>>> +++ b/drivers/iommu/io-pgtable-arm.c >>>>>> @@ -589,8 +589,11 @@ static size_t __arm_lpae_unmap(struct >>>>>> arm_lpae_io_pgtable *data, >>>>>>             if (!iopte_leaf(pte, lvl, iop->fmt)) { >>>>>>               /* Also flush any partial walks */ >>>>>> -            io_pgtable_tlb_flush_walk(iop, iova, size, >>>>>> -                          ARM_LPAE_GRANULE(data)); >>>>>> +            if (size > ARM_LPAE_GRANULE(data)) >>>>>> +                io_pgtable_tlb_flush_all(iop); >>>>>> +            else >>>>> >>>>> Erm, when will the above condition ever not be true? ;) >>>>> >>>> >>>> Ah right, silly me :) >>>> >>>>> Taking a step back, though, what about the impact to drivers other >>>>> than SMMUv2? >>>> >>>> Other drivers would be msm_iommu.c, qcom_iommu.c which does the same >>>> thing as arm-smmu-v2 (page based invalidations), then there is >>>> ipmmu-vmsa.c >>>> which does tlb_flush_all() for flush walk. >>>> >>>>> In particular I'm thinking of SMMUv3.2 where the whole >>>>> range can be invalidated by VA in a single command anyway, so the >>>>> additional penalties of TLBIALL are undesirable. >>>>> >>>> >>>> Right, so I am thinking we can have a new generic quirk >>>> IO_PGTABLE_QUIRK_RANGE_INV >>>> to choose between range based invalidations(tlb_flush_walk) and >>>> tlb_flush_all(). >>>> In this case of arm-smmu-v3.2, we can tie up ARM_SMMU_FEAT_RANGE_INV >>>> with this quirk >>>> and have something like below, thoughts? >>>> >>>> if (iop->cfg.quirks & IO_PGTABLE_QUIRK_RANGE_INV) >>>>          io_pgtable_tlb_flush_walk(iop, iova, size, >>>>                                    ARM_LPAE_GRANULE(data)); >>>> else >>>>          io_pgtable_tlb_flush_all(iop); >>> >>> The design here has always been that io-pgtable says *what* needs >>> invalidating, and we left it up to the drivers to decide exactly >>> *how*. Even though things have evolved a bit I don't think that has >>> fundamentally changed - tlb_flush_walk is now only used in this one >>> place (technically I suppose it could be renamed tlb_flush_table but >>> it's not worth the churn), so drivers can implement their own >>> preferred table-invalidating behaviour even more easily than choosing >>> whether to bounce a quirk through the common code or not. Consider >>> what you've already seen for the Renesas IPMMU, or SMMUv1 stage 2... >>> >> >> Thanks for the explanation, makes sense. If I am not mistaken, I see >> that >> you are suggesting to move this logic based on size and granule-size >> to >> arm-smmu-v2 driver and one more thing below.. > > Simpler than that - following on from my original comment above, > tlb_flush_walk already knows it's invalidating at least one full level > of table so there's nothing it even needs to check. Adding a > size-based heuristic to arm_smmu_inv_range_* for leaf invalidations > would be a separate concern (note that changing the non-leaf behaviour > might allow cleaning up the "reg" indirection there too). Right, sorry I didn't mean to mention the size check as it was obvious from your first reply, but rather just calling impl->tlb_inv() in arm_smmu_tlb_inv_walk_s1(). > >>> I'm instinctively a little twitchy about making this a blanket >>> optimisation for SMMUv2 since I still remember the palaver with our >>> display and MMU-500 integrations, where it had to implement the dodgy >>> "prefetch" register to trigger translations before scanning out a >>> frame since it couldn't ever afford a TLB miss, thus TLBIALL when >>> freeing an old buffer would be a dangerous hammer to swing. However >>> IIRC it also had to ensure everything was mapped as 2MB blocks to >>> guarantee fitting everything in the TLBs in the first place, so I >>> guess it would still work out OK due to never realistically unmapping >>> a whole table at once anyway. >>> >> >> You are also hinting to not do this for all SMMUv2 implementations and >> make >> it QCOM specific? > > No, I'm really just wary that the performance implication is more > complex than a simple unmap latency benefit, possibly even for QCOM. > Consider the access latency, power and memory bandwidth hit from all > the additional pagetable walks incurred by other ongoing traffic > fighting against those 16 successive TLBIASIDs. Whether it's an > overall win really depends on the specific workload and system > conditions as much as the SMMU implementation. No, the unmap latency is not just in some test case written, the issue is very real and we have workloads where camera is reporting frame drops because of this unmap latency in the order of 100s of milliseconds. And hardware team recommends using ASID based invalidations for anything larger than 128 TLB entries. So yes, we have taken note of impacts here before going this way and hence feel more inclined to make this qcom specific if required. > Thinking some more, I > wonder if the Tegra folks might have an opinion to add here, given > that their multiple-SMMU solution was seemingly about trying to get > enough TLB and pagetable walk bandwidth in the first place? > Sure but I do not see how that will help with the unmap latency? Thanks, Sai -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5BC7FC47094 for ; Thu, 10 Jun 2021 11:54:31 +0000 (UTC) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C595F613FE for ; Thu, 10 Jun 2021 11:54:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C595F613FE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=iommu-bounces@lists.linux-foundation.org Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 897AF401FE; Thu, 10 Jun 2021 11:54:30 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CMnRDfWNJYiJ; Thu, 10 Jun 2021 11:54:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTPS id 3D26D4000B; Thu, 10 Jun 2021 11:54:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E53FAC000D; Thu, 10 Jun 2021 11:54:28 +0000 (UTC) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id C86C5C000B for ; Thu, 10 Jun 2021 11:54:27 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with UTF8SMTP id ACFC5405EB for ; Thu, 10 Jun 2021 11:54:27 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp4.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=mg.codeaurora.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with UTF8SMTP id nz3a5oV5uHwh for ; Thu, 10 Jun 2021 11:54:26 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 Received: from so254-9.mailgun.net (so254-9.mailgun.net [198.61.254.9]) by smtp4.osuosl.org (Postfix) with UTF8SMTPS id 27C8E405E8 for ; Thu, 10 Jun 2021 11:54:23 +0000 (UTC) DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1623326066; h=Message-ID: References: In-Reply-To: Subject: Cc: To: From: Date: Content-Transfer-Encoding: Content-Type: MIME-Version: Sender; bh=DYoWVGF66T3kPghm81L8ucvdZSLOiQtMZDyvXXzEyjY=; b=SPy9+U00Rh5S4+s8Z6t/2aAxdw4VvsbRn5z0666v8s+nSbP2K2/+QV/KRZEz5tFv33SnUi9K 6t2t19TsAzTRXzlNRMbArasdbX6BsopYbRoLlgAMpD+HqYjXKyEKRkDkrs2It8sU9FPsxGwh OdL817myK7+4HW7BD2S2+JvBSec= X-Mailgun-Sending-Ip: 198.61.254.9 X-Mailgun-Sid: WyI3NDkwMCIsICJpb21tdUBsaXN0cy5saW51eC1mb3VuZGF0aW9uLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n07.prod.us-east-1.postgun.com with SMTP id 60c1fd5be27c0cc77f9304b0 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Thu, 10 Jun 2021 11:54:03 GMT Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 06B4CC4360C; Thu, 10 Jun 2021 11:54:03 +0000 (UTC) Received: from mail.codeaurora.org (localhost.localdomain [127.0.0.1]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: saiprakash.ranjan) by smtp.codeaurora.org (Postfix) with ESMTPSA id 6DDDDC433F1; Thu, 10 Jun 2021 11:54:01 +0000 (UTC) MIME-Version: 1.0 Date: Thu, 10 Jun 2021 17:24:01 +0530 From: Sai Prakash Ranjan To: Robin Murphy Subject: Re: [PATCH] iommu/io-pgtable-arm: Optimize partial walk flush for large scatter-gather list In-Reply-To: <266f190e-99ae-9175-cf13-7a77730af389@arm.com> References: <20210609145315.25750-1-saiprakash.ranjan@codeaurora.org> <35bfd245-45e2-8083-b620-330d6dbd7bd7@arm.com> <12067ffb8243b220cf03e83aaac3e823@codeaurora.org> <266f190e-99ae-9175-cf13-7a77730af389@arm.com> Message-ID: X-Sender: saiprakash.ranjan@codeaurora.org User-Agent: Roundcube Webmail/1.3.9 Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, Thierry Reding , Will Deacon , linux-arm-kernel@lists.infradead.org X-BeenThere: iommu@lists.linux-foundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Development issues for Linux IOMMU support List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Errors-To: iommu-bounces@lists.linux-foundation.org Sender: "iommu" SGkgUm9iaW4sCgpPbiAyMDIxLTA2LTEwIDE3OjAzLCBSb2JpbiBNdXJwaHkgd3JvdGU6Cj4gT24g MjAyMS0wNi0xMCAxMDozNiwgU2FpIFByYWthc2ggUmFuamFuIHdyb3RlOgo+PiBIaSBSb2JpbiwK Pj4gCj4+IE9uIDIwMjEtMDYtMTAgMTQ6MzgsIFJvYmluIE11cnBoeSB3cm90ZToKPj4+IE9uIDIw MjEtMDYtMTAgMDY6MjQsIFNhaSBQcmFrYXNoIFJhbmphbiB3cm90ZToKPj4+PiBIaSBSb2JpbiwK Pj4+PiAKPj4+PiBPbiAyMDIxLTA2LTEwIDAwOjE0LCBSb2JpbiBNdXJwaHkgd3JvdGU6Cj4+Pj4+ IE9uIDIwMjEtMDYtMDkgMTU6NTMsIFNhaSBQcmFrYXNoIFJhbmphbiB3cm90ZToKPj4+Pj4+IEN1 cnJlbnRseSBmb3IgaW9tbXVfdW5tYXAoKSBvZiBsYXJnZSBzY2F0dGVyLWdhdGhlciBsaXN0IHdp dGggcGFnZSAKPj4+Pj4+IHNpemUKPj4+Pj4+IGVsZW1lbnRzLCB0aGUgbWFqb3JpdHkgb2YgdGlt ZSBpcyBzcGVudCBpbiBmbHVzaGluZyBvZiBwYXJ0aWFsIAo+Pj4+Pj4gd2Fsa3MgaW4KPj4+Pj4+ IF9fYXJtX2xwYWVfdW5tYXAoKSB3aGljaCBpcyBhIFZBIGJhc2VkIFRMQiBpbnZhbGlkYXRpb24g KFRMQklWQSAKPj4+Pj4+IGZvcgo+Pj4+Pj4gYXJtLXNtbXUpLgo+Pj4+Pj4gCj4+Pj4+PiBGb3Ig ZXhhbXBsZTogdG8gdW5tYXAgYSAzMk1CIHNjYXR0ZXItZ2F0aGVyIGxpc3Qgd2l0aCBwYWdlIHNp emUgCj4+Pj4+PiBlbGVtZW50cwo+Pj4+Pj4gKDgxOTIgZW50cmllcyksIHRoZXJlIGFyZSAxNi0+ Mk1CIGJ1ZmZlciB1bm1hcHMgYmFzZWQgb24gdGhlIAo+Pj4+Pj4gcGdzaXplICgyTUIKPj4+Pj4+ IGZvciA0SyBncmFudWxlKSBhbmQgZWFjaCBvZiAyTUIgd2lsbCBmdXJ0aGVyIHJlc3VsdCBpbiA1 MTIgVExCSVZBcyAKPj4+Pj4+ICgyTUIvNEspCj4+Pj4+PiByZXN1bHRpbmcgaW4gYSB0b3RhbCBv ZiA4MTkyIFRMQklWQXMgKDUxMioxNikgZm9yIDE2LT4yTUIgY2F1c2luZyAKPj4+Pj4+IGEgaHVn ZQo+Pj4+Pj4gb3ZlcmhlYWQuCj4+Pj4+PiAKPj4+Pj4+IFNvIGluc3RlYWQgdXNlIGlvX3BndGFi bGVfdGxiX2ZsdXNoX2FsbCgpIHRvIGludmFsaWRhdGUgdGhlIGVudGlyZSAKPj4+Pj4+IGNvbnRl eHQKPj4+Pj4+IGlmIHNpemUgKHBnc2l6ZSkgaXMgZ3JlYXRlciB0aGFuIHRoZSBncmFudWxlIHNp emUgKDRLLCAxNkssIDY0SykuIAo+Pj4+Pj4gRm9yIHRoaXMKPj4+Pj4+IGV4YW1wbGUgb2YgMzJN QiBzY2F0dGVyLWdhdGhlciBsaXN0IHVubWFwLCB0aGlzIHJlc3VsdHMgaW4ganVzdCAxNiAKPj4+ Pj4+IEFTSUQKPj4+Pj4+IGJhc2VkIFRMQiBpbnZhbGlkYXRpb25zIG9yIHRsYl9mbHVzaF9hbGwo KSBjYWxsYmFjayAoVExCSUFTSUQgaW4gCj4+Pj4+PiBjYXNlIG9mCj4+Pj4+PiBhcm0tc21tdSkg YXMgb3Bwb3NlZCB0byA4MTkyIFRMQklWQXMgdGhlcmVieSBpbmNyZWFzaW5nIHRoZSAKPj4+Pj4+ IHBlcmZvcm1hbmNlIG9mCj4+Pj4+PiB1bm1hcHMgZHJhc3RpY2FsbHkuCj4+Pj4+PiAKPj4+Pj4+ IENvbmRpdGlvbiAoc2l6ZSA+IGdyYW51bGUgc2l6ZSkgaXMgY2hvc2VuIGZvciAKPj4+Pj4+IGlv X3BndGFibGVfdGxiX2ZsdXNoX2FsbCgpCj4+Pj4+PiBiZWNhdXNlIGZvciBhbnkgZ3JhbnVsZSB3 aXRoIHN1cHBvcnRlZCBwZ3NpemVzLCB3ZSB3aWxsIGhhdmUgYXQgCj4+Pj4+PiBsZWFzdCA1MTIK Pj4+Pj4+IFRMQiBpbnZhbGlkYXRpb25zIGZvciB3aGljaCB0bGJfZmx1c2hfYWxsKCkgaXMgYWxy ZWFkeSAKPj4+Pj4+IHJlY29tbWVuZGVkLiBGb3IKPj4+Pj4+IGV4YW1wbGUsIHRha2UgNEsgZ3Jh bnVsZSB3aXRoIDJNQiBwZ3NpemUsIHRoaXMgd2lsbCByZXN1bHQgaW4gNTEyIAo+Pj4+Pj4gVExC SVZBCj4+Pj4+PiBpbiBwYXJ0aWFsIHdhbGsgZmx1c2guCj4+Pj4+PiAKPj4+Pj4+IFRlc3Qgb24g UVRJIFNNODE1MCBTb0MgZm9yIDEwIGl0ZXJhdGlvbnMgb2YgaW9tbXVfe21hcF9zZ30vdW5tYXA6 Cj4+Pj4+PiAoYXZlcmFnZSBvdmVyIDEwIGl0ZXJhdGlvbnMpCj4+Pj4+PiAKPj4+Pj4+IEJlZm9y ZSB0aGlzIG9wdGltaXphdGlvbjoKPj4+Pj4+IAo+Pj4+Pj4gwqDCoMKgwqAgc2l6ZcKgwqDCoMKg wqDCoMKgIGlvbW11X21hcF9zZ8KgwqDCoMKgwqAgaW9tbXVfdW5tYXAKPj4+Pj4+IMKgwqDCoMKg wqDCoCA0S8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgMi4wNjcgdXPCoMKgwqDCoMKgwqDCoMKgIDEu ODU0IHVzCj4+Pj4+PiDCoMKgwqDCoMKgIDY0S8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgOS41OTgg dXPCoMKgwqDCoMKgwqDCoMKgIDguODAyIHVzCj4+Pj4+PiDCoMKgwqDCoMKgwqAgMU3CoMKgwqDC oMKgwqDCoMKgwqAgMTQ4Ljg5MCB1c8KgwqDCoMKgwqDCoCAxMzAuNzE4IHVzCj4+Pj4+PiDCoMKg wqDCoMKgwqAgMk3CoMKgwqDCoMKgwqDCoMKgwqAgMzA1Ljg2NCB1c8KgwqDCoMKgwqDCoMKgIDY3 LjI5MSB1cwo+Pj4+Pj4gwqDCoMKgwqDCoCAxMk3CoMKgwqDCoMKgwqDCoMKgIDE3OTMuNjA0IHVz wqDCoMKgwqDCoMKgIDM5MC44MzggdXMKPj4+Pj4+IMKgwqDCoMKgwqAgMTZNwqDCoMKgwqDCoMKg wqDCoCAyMzg2Ljg0OCB1c8KgwqDCoMKgwqDCoCA1MTguMTg3IHVzCj4+Pj4+PiDCoMKgwqDCoMKg IDI0TcKgwqDCoMKgwqDCoMKgwqAgMzU2My4yOTYgdXPCoMKgwqDCoMKgwqAgNzc1Ljk4OSB1cwo+ Pj4+Pj4gwqDCoMKgwqDCoCAzMk3CoMKgwqDCoMKgwqDCoMKgIDQ3NDcuMTcxIHVzwqDCoMKgwqDC oCAxMDMzLjM2NCB1cwo+Pj4+Pj4gCj4+Pj4+PiBBZnRlciB0aGlzIG9wdGltaXphdGlvbjoKPj4+ Pj4+IAo+Pj4+Pj4gwqDCoMKgwqAgc2l6ZcKgwqDCoMKgwqDCoMKgIGlvbW11X21hcF9zZ8KgwqDC oMKgwqAgaW9tbXVfdW5tYXAKPj4+Pj4+IMKgwqDCoMKgwqDCoCA0S8KgwqDCoMKgwqDCoMKgwqDC oMKgwqAgMS43MjMgdXPCoMKgwqDCoMKgwqDCoMKgIDEuNzY1IHVzCj4+Pj4+PiDCoMKgwqDCoMKg IDY0S8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgOS44ODAgdXPCoMKgwqDCoMKgwqDCoMKgIDguODY5 IHVzCj4+Pj4+PiDCoMKgwqDCoMKgwqAgMU3CoMKgwqDCoMKgwqDCoMKgwqAgMTU1LjM2NCB1c8Kg wqDCoMKgwqDCoCAxMzUuMjIzIHVzCj4+Pj4+PiDCoMKgwqDCoMKgwqAgMk3CoMKgwqDCoMKgwqDC oMKgwqAgMzAzLjkwNiB1c8KgwqDCoMKgwqDCoMKgwqAgNS4zODUgdXMKPj4+Pj4+IMKgwqDCoMKg wqAgMTJNwqDCoMKgwqDCoMKgwqDCoCAxNzg2LjU1NyB1c8KgwqDCoMKgwqDCoMKgIDIxLjI1MCB1 cwo+Pj4+Pj4gwqDCoMKgwqDCoCAxNk3CoMKgwqDCoMKgwqDCoMKgIDIzOTEuODkwIHVzwqDCoMKg wqDCoMKgwqAgMjcuNDM3IHVzCj4+Pj4+PiDCoMKgwqDCoMKgIDI0TcKgwqDCoMKgwqDCoMKgwqAg MzU3MC44OTUgdXPCoMKgwqDCoMKgwqDCoCAzOS45MzcgdXMKPj4+Pj4+IMKgwqDCoMKgwqAgMzJN wqDCoMKgwqDCoMKgwqDCoCA0NzU1LjIzNCB1c8KgwqDCoMKgwqDCoMKgIDUxLjc5NyB1cwo+Pj4+ Pj4gCj4+Pj4+PiBUaGlzIGlzIGZ1cnRoZXIgcmVkdWNlZCBvbmNlIHRoZSBtYXAvdW5tYXBfcGFn ZXMoKSBzdXBwb3J0IGdldHMgaW4gCj4+Pj4+PiB3aGljaAo+Pj4+Pj4gd2lsbCByZXN1bHQgaW4g anVzdCAxIHRsYl9mbHVzaF9hbGwoKSBhcyBvcHBvc2VkIHRvIDE2IAo+Pj4+Pj4gdGxiX2ZsdXNo X2FsbCgpLgo+Pj4+Pj4gCj4+Pj4+PiBTaWduZWQtb2ZmLWJ5OiBTYWkgUHJha2FzaCBSYW5qYW4g Cj4+Pj4+PiA8c2FpcHJha2FzaC5yYW5qYW5AY29kZWF1cm9yYS5vcmc+Cj4+Pj4+PiAtLS0KPj4+ Pj4+IMKgIGRyaXZlcnMvaW9tbXUvaW8tcGd0YWJsZS1hcm0uYyB8IDcgKysrKystLQo+Pj4+Pj4g wqAgMSBmaWxlIGNoYW5nZWQsIDUgaW5zZXJ0aW9ucygrKSwgMiBkZWxldGlvbnMoLSkKPj4+Pj4+ IAo+Pj4+Pj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaW9tbXUvaW8tcGd0YWJsZS1hcm0uYyAKPj4+ Pj4+IGIvZHJpdmVycy9pb21tdS9pby1wZ3RhYmxlLWFybS5jCj4+Pj4+PiBpbmRleCA4N2RlZjU4 ZTc5YjUuLmMzY2I5YWRkMzE3OSAxMDA2NDQKPj4+Pj4+IC0tLSBhL2RyaXZlcnMvaW9tbXUvaW8t cGd0YWJsZS1hcm0uYwo+Pj4+Pj4gKysrIGIvZHJpdmVycy9pb21tdS9pby1wZ3RhYmxlLWFybS5j Cj4+Pj4+PiBAQCAtNTg5LDggKzU4OSwxMSBAQCBzdGF0aWMgc2l6ZV90IF9fYXJtX2xwYWVfdW5t YXAoc3RydWN0IAo+Pj4+Pj4gYXJtX2xwYWVfaW9fcGd0YWJsZSAqZGF0YSwKPj4+Pj4+IMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAgaWYgKCFpb3B0ZV9sZWFmKHB0ZSwgbHZsLCBpb3AtPmZtdCkpIHsK Pj4+Pj4+IMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC8qIEFsc28gZmx1c2ggYW55IHBhcnRp YWwgd2Fsa3MgKi8KPj4+Pj4+IC3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGlvX3BndGFibGVfdGxi X2ZsdXNoX3dhbGsoaW9wLCBpb3ZhLCBzaXplLAo+Pj4+Pj4gLcKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEFSTV9MUEFFX0dSQU5VTEUoZGF0YSkpOwo+ Pj4+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgaWYgKHNpemUgPiBBUk1fTFBBRV9HUkFOVUxF KGRhdGEpKQo+Pj4+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpb19wZ3RhYmxl X3RsYl9mbHVzaF9hbGwoaW9wKTsKPj4+Pj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGVsc2UK Pj4+Pj4gCj4+Pj4+IEVybSwgd2hlbiB3aWxsIHRoZSBhYm92ZSBjb25kaXRpb24gZXZlciBub3Qg YmUgdHJ1ZT8gOykKPj4+Pj4gCj4+Pj4gCj4+Pj4gQWggcmlnaHQsIHNpbGx5IG1lIDopCj4+Pj4g Cj4+Pj4+IFRha2luZyBhIHN0ZXAgYmFjaywgdGhvdWdoLCB3aGF0IGFib3V0IHRoZSBpbXBhY3Qg dG8gZHJpdmVycyBvdGhlcgo+Pj4+PiB0aGFuIFNNTVV2Mj8KPj4+PiAKPj4+PiBPdGhlciBkcml2 ZXJzIHdvdWxkIGJlIG1zbV9pb21tdS5jLCBxY29tX2lvbW11LmMgd2hpY2ggZG9lcyB0aGUgc2Ft ZQo+Pj4+IHRoaW5nIGFzIGFybS1zbW11LXYyIChwYWdlIGJhc2VkIGludmFsaWRhdGlvbnMpLCB0 aGVuIHRoZXJlIGlzIAo+Pj4+IGlwbW11LXZtc2EuYwo+Pj4+IHdoaWNoIGRvZXMgdGxiX2ZsdXNo X2FsbCgpIGZvciBmbHVzaCB3YWxrLgo+Pj4+IAo+Pj4+PiBJbiBwYXJ0aWN1bGFyIEknbSB0aGlu a2luZyBvZiBTTU1VdjMuMiB3aGVyZSB0aGUgd2hvbGUKPj4+Pj4gcmFuZ2UgY2FuIGJlIGludmFs aWRhdGVkIGJ5IFZBIGluIGEgc2luZ2xlIGNvbW1hbmQgYW55d2F5LCBzbyB0aGUKPj4+Pj4gYWRk aXRpb25hbCBwZW5hbHRpZXMgb2YgVExCSUFMTCBhcmUgdW5kZXNpcmFibGUuCj4+Pj4+IAo+Pj4+ IAo+Pj4+IFJpZ2h0LCBzbyBJIGFtIHRoaW5raW5nIHdlIGNhbiBoYXZlIGEgbmV3IGdlbmVyaWMg cXVpcmsgCj4+Pj4gSU9fUEdUQUJMRV9RVUlSS19SQU5HRV9JTlYKPj4+PiB0byBjaG9vc2UgYmV0 d2VlbiByYW5nZSBiYXNlZCBpbnZhbGlkYXRpb25zKHRsYl9mbHVzaF93YWxrKSBhbmQgCj4+Pj4g dGxiX2ZsdXNoX2FsbCgpLgo+Pj4+IEluIHRoaXMgY2FzZSBvZiBhcm0tc21tdS12My4yLCB3ZSBj YW4gdGllIHVwIEFSTV9TTU1VX0ZFQVRfUkFOR0VfSU5WIAo+Pj4+IHdpdGggdGhpcyBxdWlyawo+ Pj4+IGFuZCBoYXZlIHNvbWV0aGluZyBsaWtlIGJlbG93LCB0aG91Z2h0cz8KPj4+PiAKPj4+PiBp ZiAoaW9wLT5jZmcucXVpcmtzICYgSU9fUEdUQUJMRV9RVUlSS19SQU5HRV9JTlYpCj4+Pj4gwqDC oMKgwqDCoMKgwqDCoCBpb19wZ3RhYmxlX3RsYl9mbHVzaF93YWxrKGlvcCwgaW92YSwgc2l6ZSwK Pj4+PiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoCBBUk1fTFBBRV9HUkFOVUxFKGRhdGEpKTsKPj4+PiBlbHNlCj4+Pj4g wqDCoMKgwqDCoMKgwqDCoCBpb19wZ3RhYmxlX3RsYl9mbHVzaF9hbGwoaW9wKTsKPj4+IAo+Pj4g VGhlIGRlc2lnbiBoZXJlIGhhcyBhbHdheXMgYmVlbiB0aGF0IGlvLXBndGFibGUgc2F5cyAqd2hh dCogbmVlZHMKPj4+IGludmFsaWRhdGluZywgYW5kIHdlIGxlZnQgaXQgdXAgdG8gdGhlIGRyaXZl cnMgdG8gZGVjaWRlIGV4YWN0bHkKPj4+ICpob3cqLiBFdmVuIHRob3VnaCB0aGluZ3MgaGF2ZSBl dm9sdmVkIGEgYml0IEkgZG9uJ3QgdGhpbmsgdGhhdCBoYXMKPj4+IGZ1bmRhbWVudGFsbHkgY2hh bmdlZCAtIHRsYl9mbHVzaF93YWxrIGlzIG5vdyBvbmx5IHVzZWQgaW4gdGhpcyBvbmUKPj4+IHBs YWNlICh0ZWNobmljYWxseSBJIHN1cHBvc2UgaXQgY291bGQgYmUgcmVuYW1lZCB0bGJfZmx1c2hf dGFibGUgYnV0Cj4+PiBpdCdzIG5vdCB3b3J0aCB0aGUgY2h1cm4pLCBzbyBkcml2ZXJzIGNhbiBp bXBsZW1lbnQgdGhlaXIgb3duCj4+PiBwcmVmZXJyZWQgdGFibGUtaW52YWxpZGF0aW5nIGJlaGF2 aW91ciBldmVuIG1vcmUgZWFzaWx5IHRoYW4gY2hvb3NpbmcKPj4+IHdoZXRoZXIgdG8gYm91bmNl IGEgcXVpcmsgdGhyb3VnaCB0aGUgY29tbW9uIGNvZGUgb3Igbm90LiBDb25zaWRlcgo+Pj4gd2hh dCB5b3UndmUgYWxyZWFkeSBzZWVuIGZvciB0aGUgUmVuZXNhcyBJUE1NVSwgb3IgU01NVXYxIHN0 YWdlIDIuLi4KPj4+IAo+PiAKPj4gVGhhbmtzIGZvciB0aGUgZXhwbGFuYXRpb24sIG1ha2VzIHNl bnNlLiBJZiBJIGFtIG5vdCBtaXN0YWtlbiwgSSBzZWUgCj4+IHRoYXQKPj4geW91IGFyZSBzdWdn ZXN0aW5nIHRvIG1vdmUgdGhpcyBsb2dpYyBiYXNlZCBvbiBzaXplIGFuZCBncmFudWxlLXNpemUg Cj4+IHRvCj4+IGFybS1zbW11LXYyIGRyaXZlciBhbmQgb25lIG1vcmUgdGhpbmcgYmVsb3cuLgo+ IAo+IFNpbXBsZXIgdGhhbiB0aGF0IC0gZm9sbG93aW5nIG9uIGZyb20gbXkgb3JpZ2luYWwgY29t bWVudCBhYm92ZSwKPiB0bGJfZmx1c2hfd2FsayBhbHJlYWR5IGtub3dzIGl0J3MgaW52YWxpZGF0 aW5nIGF0IGxlYXN0IG9uZSBmdWxsIGxldmVsCj4gb2YgdGFibGUgc28gdGhlcmUncyBub3RoaW5n IGl0IGV2ZW4gbmVlZHMgdG8gY2hlY2suIEFkZGluZyBhCj4gc2l6ZS1iYXNlZCBoZXVyaXN0aWMg dG8gYXJtX3NtbXVfaW52X3JhbmdlXyogZm9yIGxlYWYgaW52YWxpZGF0aW9ucwo+IHdvdWxkIGJl IGEgc2VwYXJhdGUgY29uY2VybiAobm90ZSB0aGF0IGNoYW5naW5nIHRoZSBub24tbGVhZiBiZWhh dmlvdXIKPiBtaWdodCBhbGxvdyBjbGVhbmluZyB1cCB0aGUgInJlZyIgaW5kaXJlY3Rpb24gdGhl cmUgdG9vKS4KClJpZ2h0LCBzb3JyeSBJIGRpZG4ndCBtZWFuIHRvIG1lbnRpb24gdGhlIHNpemUg Y2hlY2sgYXMgaXQgd2FzIG9idmlvdXMKZnJvbSB5b3VyIGZpcnN0IHJlcGx5LCBidXQgcmF0aGVy IGp1c3QgY2FsbGluZyBpbXBsLT50bGJfaW52KCkgaW4KYXJtX3NtbXVfdGxiX2ludl93YWxrX3Mx KCkuCgo+IAo+Pj4gSSdtIGluc3RpbmN0aXZlbHkgYSBsaXR0bGUgdHdpdGNoeSBhYm91dCBtYWtp bmcgdGhpcyBhIGJsYW5rZXQKPj4+IG9wdGltaXNhdGlvbiBmb3IgU01NVXYyIHNpbmNlIEkgc3Rp bGwgcmVtZW1iZXIgdGhlIHBhbGF2ZXIgd2l0aCBvdXIKPj4+IGRpc3BsYXkgYW5kIE1NVS01MDAg aW50ZWdyYXRpb25zLCB3aGVyZSBpdCBoYWQgdG8gaW1wbGVtZW50IHRoZSBkb2RneQo+Pj4gInBy ZWZldGNoIiByZWdpc3RlciB0byB0cmlnZ2VyIHRyYW5zbGF0aW9ucyBiZWZvcmUgc2Nhbm5pbmcg b3V0IGEKPj4+IGZyYW1lIHNpbmNlIGl0IGNvdWxkbid0IGV2ZXIgYWZmb3JkIGEgVExCIG1pc3Ms IHRodXMgVExCSUFMTCB3aGVuCj4+PiBmcmVlaW5nIGFuIG9sZCBidWZmZXIgd291bGQgYmUgYSBk YW5nZXJvdXMgaGFtbWVyIHRvIHN3aW5nLiBIb3dldmVyCj4+PiBJSVJDIGl0IGFsc28gaGFkIHRv IGVuc3VyZSBldmVyeXRoaW5nIHdhcyBtYXBwZWQgYXMgMk1CIGJsb2NrcyB0bwo+Pj4gZ3VhcmFu dGVlIGZpdHRpbmcgZXZlcnl0aGluZyBpbiB0aGUgVExCcyBpbiB0aGUgZmlyc3QgcGxhY2UsIHNv IEkKPj4+IGd1ZXNzIGl0IHdvdWxkIHN0aWxsIHdvcmsgb3V0IE9LIGR1ZSB0byBuZXZlciByZWFs aXN0aWNhbGx5IHVubWFwcGluZwo+Pj4gYSB3aG9sZSB0YWJsZSBhdCBvbmNlIGFueXdheS4KPj4+ IAo+PiAKPj4gWW91IGFyZSBhbHNvIGhpbnRpbmcgdG8gbm90IGRvIHRoaXMgZm9yIGFsbCBTTU1V djIgaW1wbGVtZW50YXRpb25zIGFuZCAKPj4gbWFrZQo+PiBpdCBRQ09NIHNwZWNpZmljPwo+IAo+ IE5vLCBJJ20gcmVhbGx5IGp1c3Qgd2FyeSB0aGF0IHRoZSBwZXJmb3JtYW5jZSBpbXBsaWNhdGlv biBpcyBtb3JlCj4gY29tcGxleCB0aGFuIGEgc2ltcGxlIHVubWFwIGxhdGVuY3kgYmVuZWZpdCwg cG9zc2libHkgZXZlbiBmb3IgUUNPTS4KPiBDb25zaWRlciB0aGUgYWNjZXNzIGxhdGVuY3ksIHBv d2VyIGFuZCBtZW1vcnkgYmFuZHdpZHRoIGhpdCBmcm9tIGFsbAo+IHRoZSBhZGRpdGlvbmFsIHBh Z2V0YWJsZSB3YWxrcyBpbmN1cnJlZCBieSBvdGhlciBvbmdvaW5nIHRyYWZmaWMKPiBmaWdodGlu ZyBhZ2FpbnN0IHRob3NlIDE2IHN1Y2Nlc3NpdmUgVExCSUFTSURzLiBXaGV0aGVyIGl0J3MgYW4K PiBvdmVyYWxsIHdpbiByZWFsbHkgZGVwZW5kcyBvbiB0aGUgc3BlY2lmaWMgd29ya2xvYWQgYW5k IHN5c3RlbQo+IGNvbmRpdGlvbnMgYXMgbXVjaCBhcyB0aGUgU01NVSBpbXBsZW1lbnRhdGlvbi4K Ck5vLCB0aGUgdW5tYXAgbGF0ZW5jeSBpcyBub3QganVzdCBpbiBzb21lIHRlc3QgY2FzZSB3cml0 dGVuLCB0aGUgaXNzdWUKaXMgdmVyeSByZWFsIGFuZCB3ZSBoYXZlIHdvcmtsb2FkcyB3aGVyZSBj YW1lcmEgaXMgcmVwb3J0aW5nIGZyYW1lIGRyb3BzCmJlY2F1c2Ugb2YgdGhpcyB1bm1hcCBsYXRl bmN5IGluIHRoZSBvcmRlciBvZiAxMDBzIG9mIG1pbGxpc2Vjb25kcy4KQW5kIGhhcmR3YXJlIHRl YW0gcmVjb21tZW5kcyB1c2luZyBBU0lEIGJhc2VkIGludmFsaWRhdGlvbnMgZm9yIGFueXRoaW5n CmxhcmdlciB0aGFuIDEyOCBUTEIgZW50cmllcy4gU28geWVzLCB3ZSBoYXZlIHRha2VuIG5vdGUg b2YgaW1wYWN0cyBoZXJlCmJlZm9yZSBnb2luZyB0aGlzIHdheSBhbmQgaGVuY2UgZmVlbCBtb3Jl IGluY2xpbmVkIHRvIG1ha2UgdGhpcyBxY29tCnNwZWNpZmljIGlmIHJlcXVpcmVkLgoKPiBUaGlu a2luZyBzb21lIG1vcmUsIEkKPiB3b25kZXIgaWYgdGhlIFRlZ3JhIGZvbGtzIG1pZ2h0IGhhdmUg YW4gb3BpbmlvbiB0byBhZGQgaGVyZSwgZ2l2ZW4KPiB0aGF0IHRoZWlyIG11bHRpcGxlLVNNTVUg c29sdXRpb24gd2FzIHNlZW1pbmdseSBhYm91dCB0cnlpbmcgdG8gZ2V0Cj4gZW5vdWdoIFRMQiBh bmQgcGFnZXRhYmxlIHdhbGsgYmFuZHdpZHRoIGluIHRoZSBmaXJzdCBwbGFjZT8KPiAKClN1cmUg YnV0IEkgZG8gbm90IHNlZSBob3cgdGhhdCB3aWxsIGhlbHAgd2l0aCB0aGUgdW5tYXAgbGF0ZW5j eT8KClRoYW5rcywKU2FpCgotLSAKUVVBTENPTU0gSU5ESUEsIG9uIGJlaGFsZiBvZiBRdWFsY29t bSBJbm5vdmF0aW9uIENlbnRlciwgSW5jLiBpcyBhIAptZW1iZXIKb2YgQ29kZSBBdXJvcmEgRm9y dW0sIGhvc3RlZCBieSBUaGUgTGludXggRm91bmRhdGlvbgpfX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fXwppb21tdSBtYWlsaW5nIGxpc3QKaW9tbXVAbGlzdHMu bGludXgtZm91bmRhdGlvbi5vcmcKaHR0cHM6Ly9saXN0cy5saW51eGZvdW5kYXRpb24ub3JnL21h aWxtYW4vbGlzdGluZm8vaW9tbXU=