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=-5.2 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=no 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 4FD96C388F7 for ; Tue, 10 Nov 2020 16:07:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E8FD20797 for ; Tue, 10 Nov 2020 16:07:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730479AbgKJQHQ (ORCPT ); Tue, 10 Nov 2020 11:07:16 -0500 Received: from foss.arm.com ([217.140.110.172]:58154 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729909AbgKJQHQ (ORCPT ); Tue, 10 Nov 2020 11:07:16 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 04AC91396; Tue, 10 Nov 2020 08:07:15 -0800 (PST) Received: from arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3C5383F718; Tue, 10 Nov 2020 08:07:13 -0800 (PST) Date: Tue, 10 Nov 2020 16:07:09 +0000 From: Dave Martin To: Li Qiang Cc: alexandre.torgue@st.com, catalin.marinas@arm.com, gaoguijin@huawei.com, colordev.jiang@huawei.com, luchunhua@huawei.com, linux-crypto@vger.kernel.org, mcoquelin.stm32@gmail.com, liliang889@huawei.com, will@kernel.org, davem@davemloft.net, linux-arm-kernel@lists.infradead.org, herbert@gondor.apana.org.au Subject: Re: [PATCH 0/1] arm64: Accelerate Adler32 using arm64 SVE instructions. Message-ID: <20201110160708.GL6882@arm.com> References: <20201103121506.1533-1-liqiang64@huawei.com> <20201105165301.GH6882@arm.com> <20201110104629.GJ6882@arm.com> <89a9bdcc-b96e-2f2d-6c52-ca44e0e3472c@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <89a9bdcc-b96e-2f2d-6c52-ca44e0e3472c@huawei.com> User-Agent: Mutt/1.5.23 (2014-03-12) Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org On Tue, Nov 10, 2020 at 09:20:46PM +0800, Li Qiang wrote: > > > 在 2020/11/10 18:46, Dave Martin 写道: > > On Mon, Nov 09, 2020 at 11:43:35AM +0800, Li Qiang wrote: > >> Hi Dave, > >> > >> I carefully read the ideas you provided and the sample code you gave me.:) > >> > >> 在 2020/11/6 0:53, Dave Martin 写道: > >>> On Tue, Nov 03, 2020 at 08:15:05PM +0800, l00374334 wrote: > >>>> From: liqiang > >>>> > >>>> Dear all, > >>>> > >>>> Thank you for taking the precious time to read this email! > >>>> > >>>> Let me introduce the implementation ideas of my code here. > >>>> > >>>> In the process of using the compression library libz, I found that the adler32 > >>>> checksum always occupies a higher hot spot, so I paid attention to this algorithm. > >>>> After getting in touch with the SVE instruction set of armv8, I realized that > >>>> SVE can effectively accelerate adler32, so I made some attempts and got correct > >>>> and better performance results. I very much hope that this modification can be > >>>> applied to the kernel. > >>>> > >>>> Below is my analysis process: > >>>> > >>>> Adler32 algorithm > >>>> ================= > >>>> > >>>> Reference: https://en.wikipedia.org/wiki/Adler-32 > >>>> > >>>> Assume that the buf of the Adler32 checksum to be calculated is D and the length is n: > >>>> > >>>> A = 1 + D1 + D2 + ... + Dn (mod 65521) > >>>> > >>>> B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521) > >>>> = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n (mod 65521) > >>>> > >>>> Adler-32(D) = B × 65536 + A > >>>> > >>>> In C, an inefficient but straightforward implementation is: > >>>> > >>>> const uint32_t MOD_ADLER = 65521; > >>>> > >>>> uint32_t adler32(unsigned char *data, size_t len) > >>>> { > >>>> uint32_t a = 1, b = 0; > >>>> size_t index; > >>>> > >>>> // Process each byte of the data in order > >>>> for (index = 0; index < len; ++index) > >>>> { > >>>> a = (a + data[index]) % MOD_ADLER; > >>>> b = (b + a) % MOD_ADLER; > >>>> } > >>>> > >>>> return (b << 16) | a; > >>>> } > >>>> > >>>> SVE vector method > >>>> ================= > >>>> > >>>> Step 1. Determine the block size: > >>>> Use addvl instruction to get SVE bit width. > >>>> Assuming the SVE bit width is x here. > >>>> > >>>> Step 2. Start to calculate the first block: > >>>> The calculation formula is: > >>>> A1 = 1 + D1 + D2 + ... + Dx (mod 65521) > >>>> B1 = x*D1 + (x-1)*D2 + ... + Dx + x (mod 65521) > >>>> > >>>> Step 3. Calculate the follow block: > >>>> The calculation formula of A2 is very simple, just add up: > >>>> A2 = A1 + Dx+1 + Dx+2 + ... + D2x (mod 65521) > >>>> > >>>> The calculation formula of B2 is more complicated, because > >>>> the result is related to the length of buf. When calculating > >>>> the B1 block, it is actually assumed that the length is the > >>>> block length x. Now when calculating B2, the length is expanded > >>>> to 2x, so B2 becomes: > >>>> B2 = 2x*D1 + (2x-1)*D2 + ... + (x+1)*Dx + x*D(x+1) + ... + D2x + 2x > >>>> = x*D1 + x*D1 + x*D2 + (x-1)*D2 + ... + x*Dx + Dx + x*1 + x + [x*D(x+1) + (x-1)*D(x+2) + ... + D2x] > >>>> ^^^^ ~~~~ ^^^^ ~~~~~~~~ ^^^^ ~~ ^^^ ~ +++++++++++++++++++++++++++++++++++++ > >>>> Through the above polynomial transformation: > >>>> Symbol "^" represents the ; > >>>> Symbol "~" represents the ; > >>>> Symbol "+" represents the next block. > >>>> > >>>> So we can get the method of calculating the next block from > >>>> the previous block(Assume that the first byte number of the > >>>> new block starts from 1): > >>>> An+1 = An + D1 + D2 + ... + Dx (mod 65521) > >>>> Bn+1 = Bn + x*An + x*D1 + (x-1)*D2 + ... + Dx (mod 65521) > >>> > >>> Putting aside people's concerns for the moment, I think this may be > >>> formulated in a slightly more convenient way: > >>> > >>> If > >>> X0, X1, ... are the data bytes > >>> An is 1 + Sum [i=0 .. n-1] Xi > >>> Bn is n + Sum [i=0 .. n-1] (n-i)Xi > >>> = Sum [i=1 .. n] Ai > >> > >> Yes, this can be calculated from the original expression. > >> > >>> > >>> (i.e., An, Bn are the accumulations for the first n bytes here, not the > >>> first n blocks) > >>> > >>> then > >>> > >>> A[n+v] - An = Sum[i=n .. n+v-1] Xi > >>> > >>> B[n+v] - Bn = v + (Sum [i=0 .. n+v-1] (n+v-i) Xi) > >>> - Sum [i=0 .. n-1] (n-i)Xi > >>> > >>> = v + (Sum [i=n .. n+v-1] (n+v-i) Xi) > >>> + (Sum [i=0 .. n-1] (n+v-i) Xi) > >>> - Sum [i=0 .. n-1] (n-i)Xi > >>> > >>> = v + (Sum [i=n .. n+v-1] (n+v-i) Xi) > >>> + Sum [i=0 .. n-1] ((n+v-i) - (n-i)) Xi > >>> > >>> = v + (Sum [i=n .. n+v-1] (n+v-i) Xi) > >>> + vSum [i=0 .. n-1] Xi > >>> > >>> = v + v(An - 1) + Sum [i=n .. n+v-1] (n+v-i) Xi > >>> > >>> = vAn + Sum [i=n .. n+v-1] (n+v-i) Xi > >>> > >>> = vAn + vSum [i=n .. n+v-1] Xi > >>> + Sum [i=n .. n+v-1] (n-i) Xi > >>> > >>> = vAn + vSum [i=n .. n+v-1] Xi > >>> + Sum [i=n .. n+v-1] (n-i) Xi > >>> > >>> = vA[n+v] + Sum [i=n .. n+v-1] (n-i) Xi > >>> > >>> Let j = i - n; then: > >>> > >>> B[n+v] - Bn = vA[n+v] - Sum [j=0 .. v-1] j X[j+n] > >>> > >>> Which gives us a multiplier j that increases with the X[] index. > >> > >> My original approach is to multiply the byte sequence with the **decreasing** > >> sequence. I think the increasing sequence here is more friendly to the trailing > >> bytes of the loop.:-) > >> > >>> > >>> > >>> I think this gives a core loop along the following lines. I don't know > >>> whether this is correct, or whether it works -- but feel free to take > >>> ideas from it if it helps. > >>> > >>> Accumulators are 32 bits. This provides for a fair number of iterations > >>> without overflow, but large input data will still require splitting into > >>> chunks, with modulo reduction steps in between. There are rather a lot > >>> of serial dependencies in the core loop, but since the operations > >>> involved are relatively cheap, this is probably not a significant issue > >>> in practice: the load-to-use dependency is probably the bigger concern. > >>> Pipelined loop unrolling could address these if necessary. > >>> > >>> The horizontal reductions (UADDV) still probably don't need to be done > >>> until after the last chunk. > >>> > >>> > >>> Beware: I wasn't careful with the initial values for Bn / An, so some > >>> additional adjustments might be needed... > >>> > >>> --8<-- > >>> > >>> ptrue pP.s > >>> ptrue pA.s > >>> > >>> mov zA.s, #0 // accumulator for An > >>> mov zB.s, #0 // accumulator for Bn > >>> index zJ.s, #0, #1 // zJ.s = [0, 1, .. V-1] > >>> > >>> mov zV.s, #0 > >>> incw zV.s // zV.s = [V, V, .. V] > >> > >> When I actually tested this code, I found that the byte length of the > >> test must be equal to the vector length divided by 4 (that is, an integer > >> multiple of the number of words in the SVE) and the result is correct. > >> > >> And I think one of the reasons is that the value stored in zV.s needs to be > >> changed in the last cycle. It should be changed to the actual number of > >> bytes remaining in the last cycle. :) > > > > Ah yes, you're quite right about this. In my derivation above, v will > > need to be smaller than the vector length when processing the final, > > partial block (if any). > > > >> > >>> > >>> // where V is number of elements per block > >>> // = the number of 32-bit elements that fit in a Z-register > >>> > >>> add xLimit, xX, xLen > >>> b start > >>> > >>> loop: > >>> ld1b zX.s, pP/z, [xX] > >>> incw xX > >> > >> In order to verify my conjecture, I added a bit of code to here, which is to > >> subtract the corresponding value from zV in the last loop. But it is correct > >> only when the number of bytes is less than one cycle. Test cases that exceed > >> one complete cycle will also fail. > >> > >> So I guess before calculating the last cycle, zA should be summed first, > >> because before the end of the cycle, zA and zB are scattered in the elements > >> of the vector, if the last cycle calculates zB, only part of zA is summed > >> ( Because pP/m does not count inactive elements), it should be incomplete. > >> > >> This is just my guess and has not yet been verified.:) > > > > I think zA shouldn't be wrong, since that only accumulates active > > elements anyway. I think it's the bogus zV multiplier involved in the > > update to zB that is the problem. > > > >>> > >>> add zA.s, pP/m, zA.s, zX.s // zA.s += zX.s > >>> > >>> msb zX.s, pP/m, zJ.s, zB.s // zX.s := zB.s - zX.s * zJ.s > >>> > >>> movprfx zB, zA > >>> mad zB.s, pP/m, zV.s, zX.s // zB.s := zX.s + zA.s * V > > I found the bug I encountered earlier, that is, the calculation of zB here > needs to use pA with all elements activated. The reason is the same as my > previous guess, because all elements of zA should be involved when calculating zB. > Because the original calculation formula is like this. > > For example: > In the last loop: > left byte is: 3 | 4 | \0 | > zA.s is: 100 | 200 | 100 | 200 (sum = 600) > pP.s is: 1 | 1 | 0 | 0 (Only activate the first 2 channels) > > At this time, if the calculation of zB only takes the first 2 active elements, the data > is incomplete, because according to the description of the original algorithm, zB is always > based on the sum of all the accumulated bytes. Yes, you're quite right here: zX is partial: only the elements pP are valid; but all elements of zA and zB are always valid. I was focusing too much on the handling of the partial input block. > > Here we can simply change the prediction register used in the two sentences related to > zB to the one that is all true (it is pA in our code), like this: > msb zX.s, pA/m, zJ.s, zB.s // zX.s := zB.s - zX.s * zJ.s Are you sure about this? In a final partial block, the trailing elements of zX.s beyond pP will be leftover junk from the last iteration. This might require a bit more thought in order to get the final block handling correct. > movprfx zB, zA > mad zB.s, pA/m, zV.s, zX.s // zB.s := zX.s + zA.s * V > > >>> start: > >>> whilelo pP.s, xX, xLimit > >>> b.first loop > > > > There are a few options, I guess. > > > > One way is to use CNTP inside the loop to get the number of active > > elements, instead of just setting zV in advance. This approach may add > > a slight overhead, but it is worth experimenting with it. If the > > overhead is neglibible, then this approach has the example of being > > simple to understand. > > > > Alternatively, you could do an adjustment after the loop ends to > > subtract the appropriate amounts from zB. Unfortunately, pP has already > > been overwritten by the time the loop ends. If could be backed up into > > another P-register before overwriting it: this should be pretty low- > > overhead. > > > > A final option would be to change the b.first to a b.last, so that the > > loop ends after the final full block. Then copy-paste the loop body to > > execute once more, but using CNTP to get the element count to multiply > > by, as described above. This makes the code a bit larger, but it > > probably the best-performance option. You may be able to rotate the > > loop so that it breaks out after updating zA (which IIUC doesn't need to > > be done in a special way for the partial block). This would mean you > > only have to specialise the zB update code. > > Regarding the last loop, I tried to wrap another layer before and after the > core loop, and I have verified its correctness. > My code is at the end of this email. > > > > >>> > >>> // Collect the partial sums together: > >>> > >>> uaddv d0, pA, z0.s > >>> uaddv d1, pA, z1.s > >>> > >>> // Finally, add 1 to d0, and xLen to d1, and do modulo reduction. > >>> > >>> -->8-- > >>> > >>> [...] > >>> > >>> Cheers > >>> ---Dave > >>> . > >>> > >> > >> The code you sent me provides a correct way to deal with trailing bytes, > >> I need to spend some more time to debug the problem encountered above. > >> Thank you! > >> > >> Cheers.^_^ > > > > I was cheekily leaving the testing and debugging for you to do :) > > > > Part of my reason for interest in this is that if we enable SVE in the > > kernel, it would be good to have some clean examples for people to > > follow -- even if not this algo. SVE is a bit different to use > > compared with fixed-length vector ISAs, so worked examples are always > > useful. > Yes it is necessary. > > > > > Cheers > > ---Dave > > . > > > > This is the main part of my newly modified code: > --8<-- > ptrue p0.s > ptrue p1.s > > mov zA.s, #0 > mov zB.s, #0 > index zJ.s, #0, #1 > mov zV.s, #0 > incw zV.s > > add xLimit, x1, x2 > b start //Enter the core loop first > > trailloop: // Last cycle entrance > cntp x6, p1, p0.s // Get active element count of last cycle > cpy zV.s, p1/m, w6 // Set zV to the actual value. Note that you can also write "mov" here, but I'm not sure which alias is preferred. > loop: // Core loop entrance > ld1b zX.s, p0/z, [x1] > incw x1 > > add zA.s, p0/m, zA.s, zX.s // The calculation of zA still needs to use p0 > msb zX.s, p1/m, zJ.s, zB.s // Change p register here > movprfx zB, zA > mad zB.s, p1/m, zV.s, zX.s // Change p register here As discussed above, are you sure this is correct now? > start: > whilelo p0.s, x1, xLimit > b.last loop // The condition for the core loop to continue is that b.last is true > b.first trailloop // If b.last is false and b.first is true, it means the last cycle > > uaddv d0, p1, zA.s > uaddv d1, p1, zB.s > > mov x12, v0.2d[0] > mov x13, v1.2d[0] The "2" here seems not to be required by the syntax, although it's harmless. > add x10, x10, x12 > add x11, x11, x13 > add x11, x11, x2 If x10 and x11 are used as accmulators by the caller, I guess this works. > > mod65521 10, 14, 12 > mod65521 11, 14, 12 > lsl x11, x11, #16 > orr x0, x10, x11 > ret > -->8-- > > After this modification, The test results are correct when the data length is less than about 8 Kbyte, > part A will still be correct after 8K, and an overflow error will occur in part B. This is because A > only accumulates all the bytes, and the accumulative acceleration of B expands faster, because the > accumulative formula of B is: > B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521) > = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n (mod 65521) > > If we take the average value of Dx to 128 and n to 8192: > B = (1 + 2 + ... + 8129) * 128 + 8192 > = 4,295,499,776 (32bit overflow) > > So I think the 32-bit accumulator is still not enough for part B here. :) > > -- > Best regards, > Li Qiang That makes sense. I hadn't tried to calculate the actual bound. It may be worth trying this with 64-bit accumulators. This will probably slow things down, but it depends on the relative computation / memory throughput exhibited by the hardware. I think the code can't be bulletproof without breaking the input into chunks anyway, though. Cheers ---Dave 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=-5.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=no 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 85225C5517A for ; Tue, 10 Nov 2020 16:08:51 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 01A012076E for ; Tue, 10 Nov 2020 16:08:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="EJHwyb4I" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 01A012076E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References:Message-ID: Subject:To:From:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=DOBoB95hX1XcxG1YGhUcC/0XPL6SXG5pY5X7YePq2M0=; b=EJHwyb4IrQKFM7rwxX7xq05rr 8FGEpdeSMCawoGj3zCcABIGRYpDFoNPI44FeZTLakfNUaDlGb/esnjCfTVLU7VjUZ0R4s6LURGYmG XDFn369AExZEBqku8bQPWaJU0sCUwlIbNcDh60PSgxM0Uxn5QUnBhSgyVQNMHld4mta+ym5dXjCjH edZeElC/ZkQjKzanE6LI9L6kq42Bv99vhnGNs5SZkh5uyaqH4BRTBNJqBeLnNfb9RjQP5+hIYcLNM cu2MeTdmkL64l75QvjlHlS1nKbO5R2g8fpU/UdJnlm2BHgZV1i0D8j/9hasurfvGpnQcmX4ng2XgC i5sDqUw2g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kcWB0-0003I3-HF; Tue, 10 Nov 2020 16:07:22 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kcWAu-0003Gi-Rv for linux-arm-kernel@lists.infradead.org; Tue, 10 Nov 2020 16:07:19 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 04AC91396; Tue, 10 Nov 2020 08:07:15 -0800 (PST) Received: from arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3C5383F718; Tue, 10 Nov 2020 08:07:13 -0800 (PST) Date: Tue, 10 Nov 2020 16:07:09 +0000 From: Dave Martin To: Li Qiang Subject: Re: [PATCH 0/1] arm64: Accelerate Adler32 using arm64 SVE instructions. Message-ID: <20201110160708.GL6882@arm.com> References: <20201103121506.1533-1-liqiang64@huawei.com> <20201105165301.GH6882@arm.com> <20201110104629.GJ6882@arm.com> <89a9bdcc-b96e-2f2d-6c52-ca44e0e3472c@huawei.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <89a9bdcc-b96e-2f2d-6c52-ca44e0e3472c@huawei.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201110_110717_070939_C1B4802A X-CRM114-Status: GOOD ( 66.44 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: alexandre.torgue@st.com, catalin.marinas@arm.com, gaoguijin@huawei.com, colordev.jiang@huawei.com, luchunhua@huawei.com, linux-crypto@vger.kernel.org, mcoquelin.stm32@gmail.com, liliang889@huawei.com, will@kernel.org, davem@davemloft.net, linux-arm-kernel@lists.infradead.org, herbert@gondor.apana.org.au Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gVHVlLCBOb3YgMTAsIDIwMjAgYXQgMDk6MjA6NDZQTSArMDgwMCwgTGkgUWlhbmcgd3JvdGU6 Cj4gCj4gCj4g5ZyoIDIwMjAvMTEvMTAgMTg6NDYsIERhdmUgTWFydGluIOWGmemBkzoKPiA+IE9u IE1vbiwgTm92IDA5LCAyMDIwIGF0IDExOjQzOjM1QU0gKzA4MDAsIExpIFFpYW5nIHdyb3RlOgo+ ID4+IEhpIERhdmUsCj4gPj4KPiA+PiBJIGNhcmVmdWxseSByZWFkIHRoZSBpZGVhcyB5b3UgcHJv dmlkZWQgYW5kIHRoZSBzYW1wbGUgY29kZSB5b3UgZ2F2ZSBtZS46KQo+ID4+Cj4gPj4g5ZyoIDIw MjAvMTEvNiAwOjUzLCBEYXZlIE1hcnRpbiDlhpnpgZM6Cj4gPj4+IE9uIFR1ZSwgTm92IDAzLCAy MDIwIGF0IDA4OjE1OjA1UE0gKzA4MDAsIGwwMDM3NDMzNCB3cm90ZToKPiA+Pj4+IEZyb206IGxp cWlhbmcgPGxpcWlhbmc2NEBodWF3ZWkuY29tPgo+ID4+Pj4KPiA+Pj4+IERlYXIgYWxsLAo+ID4+ Pj4KPiA+Pj4+IFRoYW5rIHlvdSBmb3IgdGFraW5nIHRoZSBwcmVjaW91cyB0aW1lIHRvIHJlYWQg dGhpcyBlbWFpbCEKPiA+Pj4+Cj4gPj4+PiBMZXQgbWUgaW50cm9kdWNlIHRoZSBpbXBsZW1lbnRh dGlvbiBpZGVhcyBvZiBteSBjb2RlIGhlcmUuCj4gPj4+Pgo+ID4+Pj4gSW4gdGhlIHByb2Nlc3Mg b2YgdXNpbmcgdGhlIGNvbXByZXNzaW9uIGxpYnJhcnkgbGlieiwgSSBmb3VuZCB0aGF0IHRoZSBh ZGxlcjMyCj4gPj4+PiBjaGVja3N1bSBhbHdheXMgb2NjdXBpZXMgYSBoaWdoZXIgaG90IHNwb3Qs IHNvIEkgcGFpZCBhdHRlbnRpb24gdG8gdGhpcyBhbGdvcml0aG0uCj4gPj4+PiBBZnRlciBnZXR0 aW5nIGluIHRvdWNoIHdpdGggdGhlIFNWRSBpbnN0cnVjdGlvbiBzZXQgb2YgYXJtdjgsIEkgcmVh bGl6ZWQgdGhhdAo+ID4+Pj4gU1ZFIGNhbiBlZmZlY3RpdmVseSBhY2NlbGVyYXRlIGFkbGVyMzIs IHNvIEkgbWFkZSBzb21lIGF0dGVtcHRzIGFuZCBnb3QgY29ycmVjdAo+ID4+Pj4gYW5kIGJldHRl ciBwZXJmb3JtYW5jZSByZXN1bHRzLiBJIHZlcnkgbXVjaCBob3BlIHRoYXQgdGhpcyBtb2RpZmlj YXRpb24gY2FuIGJlCj4gPj4+PiBhcHBsaWVkIHRvIHRoZSBrZXJuZWwuCj4gPj4+Pgo+ID4+Pj4g QmVsb3cgaXMgbXkgYW5hbHlzaXMgcHJvY2VzczoKPiA+Pj4+Cj4gPj4+PiBBZGxlcjMyIGFsZ29y aXRobQo+ID4+Pj4gPT09PT09PT09PT09PT09PT0KPiA+Pj4+Cj4gPj4+PiBSZWZlcmVuY2U6IGh0 dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FkbGVyLTMyCj4gPj4+Pgo+ID4+Pj4gQXNzdW1l IHRoYXQgdGhlIGJ1ZiBvZiB0aGUgQWRsZXIzMiBjaGVja3N1bSB0byBiZSBjYWxjdWxhdGVkIGlz IEQgYW5kIHRoZSBsZW5ndGggaXMgbjoKPiA+Pj4+Cj4gPj4+PiAgICAgICAgIEEgPSAxICsgRDEg KyBEMiArIC4uLiArIERuIChtb2QgNjU1MjEpCj4gPj4+Pgo+ID4+Pj4gICAgICAgICBCID0gKDEg KyBEMSkgKyAoMSArIEQxICsgRDIpICsgLi4uICsgKDEgKyBEMSArIEQyICsgLi4uICsgRG4pICht b2QgNjU1MjEpCj4gPj4+PiAgICAgICAgICAgPSBuw5dEMSArIChu4oiSMSnDl0QyICsgKG7iiJIy KcOXRDMgKyAuLi4gKyBEbiArIG4gKG1vZCA2NTUyMSkKPiA+Pj4+Cj4gPj4+PiAgICAgICAgIEFk bGVyLTMyKEQpID0gQiDDlyA2NTUzNiArIEEKPiA+Pj4+Cj4gPj4+PiBJbiBDLCBhbiBpbmVmZmlj aWVudCBidXQgc3RyYWlnaHRmb3J3YXJkIGltcGxlbWVudGF0aW9uIGlzOgo+ID4+Pj4KPiA+Pj4+ ICAgICAgICAgY29uc3QgdWludDMyX3QgTU9EX0FETEVSID0gNjU1MjE7Cj4gPj4+Pgo+ID4+Pj4g ICAgICAgICB1aW50MzJfdCBhZGxlcjMyKHVuc2lnbmVkIGNoYXIgKmRhdGEsIHNpemVfdCBsZW4p Cj4gPj4+PiAgICAgICAgIHsKPiA+Pj4+ICAgICAgICAgICAgICAgICB1aW50MzJfdCBhID0gMSwg YiA9IDA7Cj4gPj4+PiAgICAgICAgICAgICAgICAgc2l6ZV90IGluZGV4Owo+ID4+Pj4KPiA+Pj4+ ICAgICAgICAgICAgICAgICAvLyBQcm9jZXNzIGVhY2ggYnl0ZSBvZiB0aGUgZGF0YSBpbiBvcmRl cgo+ID4+Pj4gICAgICAgICAgICAgICAgIGZvciAoaW5kZXggPSAwOyBpbmRleCA8IGxlbjsgKytp bmRleCkKPiA+Pj4+ICAgICAgICAgICAgICAgICB7Cj4gPj4+PiAgICAgICAgICAgICAgICAgICAg ICAgICBhID0gKGEgKyBkYXRhW2luZGV4XSkgJSBNT0RfQURMRVI7Cj4gPj4+PiAgICAgICAgICAg ICAgICAgICAgICAgICBiID0gKGIgKyBhKSAlIE1PRF9BRExFUjsKPiA+Pj4+ICAgICAgICAgICAg ICAgICB9Cj4gPj4+Pgo+ID4+Pj4gICAgICAgICAgICAgICAgIHJldHVybiAoYiA8PCAxNikgfCBh Owo+ID4+Pj4gICAgICAgICB9Cj4gPj4+Pgo+ID4+Pj4gU1ZFIHZlY3RvciBtZXRob2QKPiA+Pj4+ ID09PT09PT09PT09PT09PT09Cj4gPj4+Pgo+ID4+Pj4gU3RlcCAxLiBEZXRlcm1pbmUgdGhlIGJs b2NrIHNpemU6Cj4gPj4+PiAgICAgICAgIFVzZSBhZGR2bCBpbnN0cnVjdGlvbiB0byBnZXQgU1ZF IGJpdCB3aWR0aC4KPiA+Pj4+ICAgICAgICAgQXNzdW1pbmcgdGhlIFNWRSBiaXQgd2lkdGggaXMg eCBoZXJlLgo+ID4+Pj4KPiA+Pj4+IFN0ZXAgMi4gU3RhcnQgdG8gY2FsY3VsYXRlIHRoZSBmaXJz dCBibG9jazoKPiA+Pj4+ICAgICAgICAgVGhlIGNhbGN1bGF0aW9uIGZvcm11bGEgaXM6Cj4gPj4+ PiAgICAgICAgICAgICAgICAgQTEgPSAxICsgRDEgKyBEMiArIC4uLiArIER4IChtb2QgNjU1MjEp Cj4gPj4+PiAgICAgICAgICAgICAgICAgQjEgPSB4KkQxICsgKHgtMSkqRDIgKyAuLi4gKyBEeCAr IHggKG1vZCA2NTUyMSkKPiA+Pj4+Cj4gPj4+PiBTdGVwIDMuIENhbGN1bGF0ZSB0aGUgZm9sbG93 IGJsb2NrOgo+ID4+Pj4gICAgICAgICBUaGUgY2FsY3VsYXRpb24gZm9ybXVsYSBvZiBBMiBpcyB2 ZXJ5IHNpbXBsZSwganVzdCBhZGQgdXA6Cj4gPj4+PiAgICAgICAgICAgICAgICAgQTIgPSBBMSAr IER4KzEgKyBEeCsyICsgLi4uICsgRDJ4IChtb2QgNjU1MjEpCj4gPj4+Pgo+ID4+Pj4gICAgICAg ICBUaGUgY2FsY3VsYXRpb24gZm9ybXVsYSBvZiBCMiBpcyBtb3JlIGNvbXBsaWNhdGVkLCBiZWNh dXNlCj4gPj4+PiAgICAgICAgIHRoZSByZXN1bHQgaXMgcmVsYXRlZCB0byB0aGUgbGVuZ3RoIG9m IGJ1Zi4gV2hlbiBjYWxjdWxhdGluZwo+ID4+Pj4gICAgICAgICB0aGUgQjEgYmxvY2ssIGl0IGlz IGFjdHVhbGx5IGFzc3VtZWQgdGhhdCB0aGUgbGVuZ3RoIGlzIHRoZQo+ID4+Pj4gICAgICAgICBi bG9jayBsZW5ndGggeC4gTm93IHdoZW4gY2FsY3VsYXRpbmcgQjIsIHRoZSBsZW5ndGggaXMgZXhw YW5kZWQKPiA+Pj4+ICAgICAgICAgdG8gMngsIHNvIEIyIGJlY29tZXM6Cj4gPj4+PiAgICAgICAg ICAgICAgICAgQjIgPSAyeCpEMSArICgyeC0xKSpEMiAgICAgICAgICAgICArIC4uLiArICh4KzEp KkR4ICsgeCpEKHgrMSkgKyAuLi4gKyBEMnggKyAyeAo+ID4+Pj4gICAgICAgICAgICAgICAgICAg ID0geCpEMSArIHgqRDEgKyB4KkQyICsgKHgtMSkqRDIgKyAuLi4gKyB4KkR4ICsgRHggKyB4KjEg KyB4ICsgW3gqRCh4KzEpICsgKHgtMSkqRCh4KzIpICsgLi4uICsgRDJ4XQo+ID4+Pj4gICAgICAg ICAgICAgICAgICAgICAgXl5eXiAgIH5+fn4gICBeXl5eICAgfn5+fn5+fn4gICAgICAgICBeXl5e ICAgfn4gICBeXl4gICB+ICAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ ID4+Pj4gICAgICAgICBUaHJvdWdoIHRoZSBhYm92ZSBwb2x5bm9taWFsIHRyYW5zZm9ybWF0aW9u Ogo+ID4+Pj4gICAgICAgICAgICAgICAgIFN5bWJvbCAiXiIgcmVwcmVzZW50cyB0aGUgPHggKiBB MT47Cj4gPj4+PiAgICAgICAgICAgICAgICAgU3ltYm9sICJ+IiByZXByZXNlbnRzIHRoZSA8QjE+ Owo+ID4+Pj4gICAgICAgICAgICAgICAgIFN5bWJvbCAiKyIgcmVwcmVzZW50cyB0aGUgbmV4dCBi bG9jay4KPiA+Pj4+Cj4gPj4+PiAgICAgICAgIFNvIHdlIGNhbiBnZXQgdGhlIG1ldGhvZCBvZiBj YWxjdWxhdGluZyB0aGUgbmV4dCBibG9jayBmcm9tCj4gPj4+PiAgICAgICAgIHRoZSBwcmV2aW91 cyBibG9jayhBc3N1bWUgdGhhdCB0aGUgZmlyc3QgYnl0ZSBudW1iZXIgb2YgdGhlCj4gPj4+PiAg ICAgICAgIG5ldyBibG9jayBzdGFydHMgZnJvbSAxKToKPiA+Pj4+ICAgICAgICAgICAgICAgICBB bisxID0gQW4gKyBEMSArIEQyICsgLi4uICsgRHggKG1vZCA2NTUyMSkKPiA+Pj4+ICAgICAgICAg ICAgICAgICBCbisxID0gQm4gKyB4KkFuICsgeCpEMSArICh4LTEpKkQyICsgLi4uICsgRHggKG1v ZCA2NTUyMSkKPiA+Pj4KPiA+Pj4gUHV0dGluZyBhc2lkZSBwZW9wbGUncyBjb25jZXJucyBmb3Ig dGhlIG1vbWVudCwgSSB0aGluayB0aGlzIG1heSBiZQo+ID4+PiBmb3JtdWxhdGVkIGluIGEgc2xp Z2h0bHkgbW9yZSBjb252ZW5pZW50IHdheToKPiA+Pj4KPiA+Pj4gSWYKPiA+Pj4gCVgwLCBYMSwg Li4uIGFyZSB0aGUgZGF0YSBieXRlcwo+ID4+PiAJQW4gaXMgMSArIFN1bSBbaT0wIC4uIG4tMV0g WGkKPiA+Pj4gCUJuIGlzIG4gKyBTdW0gW2k9MCAuLiBuLTFdIChuLWkpWGkKPiA+Pj4gCQk9IFN1 bSBbaT0xIC4uIG5dIEFpCj4gPj4KPiA+PiBZZXMsIHRoaXMgY2FuIGJlIGNhbGN1bGF0ZWQgZnJv bSB0aGUgb3JpZ2luYWwgZXhwcmVzc2lvbi4KPiA+Pgo+ID4+Pgo+ID4+PiAoaS5lLiwgQW4sIEJu IGFyZSB0aGUgYWNjdW11bGF0aW9ucyBmb3IgdGhlIGZpcnN0IG4gYnl0ZXMgaGVyZSwgbm90IHRo ZQo+ID4+PiBmaXJzdCBuIGJsb2NrcykKPiA+Pj4KPiA+Pj4gdGhlbgo+ID4+Pgo+ID4+PiAJQVtu K3ZdIC0gQW4gPSBTdW1baT1uIC4uIG4rdi0xXSBYaQo+ID4+Pgo+ID4+PiAJQltuK3ZdIC0gQm4g PSB2ICsgKFN1bSBbaT0wIC4uIG4rdi0xXSAobit2LWkpIFhpKQo+ID4+PiAJCQktIFN1bSBbaT0w IC4uIG4tMV0gKG4taSlYaQo+ID4+Pgo+ID4+PiAJCT0gdiArIChTdW0gW2k9biAuLiBuK3YtMV0g KG4rdi1pKSBYaSkKPiA+Pj4gCQkJKyAoU3VtIFtpPTAgLi4gbi0xXSAobit2LWkpIFhpKQo+ID4+ PiAJCQktIFN1bSBbaT0wIC4uIG4tMV0gKG4taSlYaQo+ID4+Pgo+ID4+PiAJCT0gdiArIChTdW0g W2k9biAuLiBuK3YtMV0gKG4rdi1pKSBYaSkKPiA+Pj4gCQkJKyBTdW0gW2k9MCAuLiBuLTFdICgo bit2LWkpIC0gKG4taSkpIFhpCj4gPj4+Cj4gPj4+IAkJPSB2ICsgKFN1bSBbaT1uIC4uIG4rdi0x XSAobit2LWkpIFhpKQo+ID4+PiAJCQkrIHZTdW0gW2k9MCAuLiBuLTFdIFhpCj4gPj4+Cj4gPj4+ IAkJPSB2ICsgdihBbiAtIDEpICsgU3VtIFtpPW4gLi4gbit2LTFdIChuK3YtaSkgWGkKPiA+Pj4K PiA+Pj4gCQk9IHZBbiArIFN1bSBbaT1uIC4uIG4rdi0xXSAobit2LWkpIFhpCj4gPj4+Cj4gPj4+ IAkJPSB2QW4gKyB2U3VtIFtpPW4gLi4gbit2LTFdIFhpCj4gPj4+IAkJCSsgU3VtIFtpPW4gLi4g bit2LTFdIChuLWkpIFhpCj4gPj4+Cj4gPj4+IAkJPSB2QW4gKyB2U3VtIFtpPW4gLi4gbit2LTFd IFhpCj4gPj4+IAkJCSsgU3VtIFtpPW4gLi4gbit2LTFdIChuLWkpIFhpCj4gPj4+Cj4gPj4+IAkJ PSB2QVtuK3ZdICsgU3VtIFtpPW4gLi4gbit2LTFdIChuLWkpIFhpCj4gPj4+Cj4gPj4+IExldCBq ID0gaSAtIG47IHRoZW46Cj4gPj4+Cj4gPj4+IAlCW24rdl0gLSBCbiA9IHZBW24rdl0gLSBTdW0g W2o9MCAuLiB2LTFdIGogWFtqK25dCj4gPj4+Cj4gPj4+IFdoaWNoIGdpdmVzIHVzIGEgbXVsdGlw bGllciBqIHRoYXQgaW5jcmVhc2VzIHdpdGggdGhlIFhbXSBpbmRleC4KPiA+Pgo+ID4+IE15IG9y aWdpbmFsIGFwcHJvYWNoIGlzIHRvIG11bHRpcGx5IHRoZSBieXRlIHNlcXVlbmNlIHdpdGggdGhl ICoqZGVjcmVhc2luZyoqCj4gPj4gc2VxdWVuY2UuIEkgdGhpbmsgdGhlIGluY3JlYXNpbmcgc2Vx dWVuY2UgaGVyZSBpcyBtb3JlIGZyaWVuZGx5IHRvIHRoZSB0cmFpbGluZwo+ID4+IGJ5dGVzIG9m IHRoZSBsb29wLjotKQo+ID4+Cj4gPj4+Cj4gPj4+Cj4gPj4+IEkgdGhpbmsgdGhpcyBnaXZlcyBh IGNvcmUgbG9vcCBhbG9uZyB0aGUgZm9sbG93aW5nIGxpbmVzLiAgSSBkb24ndCBrbm93Cj4gPj4+ IHdoZXRoZXIgdGhpcyBpcyBjb3JyZWN0LCBvciB3aGV0aGVyIGl0IHdvcmtzIC0tIGJ1dCBmZWVs IGZyZWUgdG8gdGFrZQo+ID4+PiBpZGVhcyBmcm9tIGl0IGlmIGl0IGhlbHBzLgo+ID4+Pgo+ID4+ PiBBY2N1bXVsYXRvcnMgYXJlIDMyIGJpdHMuICBUaGlzIHByb3ZpZGVzIGZvciBhIGZhaXIgbnVt YmVyIG9mIGl0ZXJhdGlvbnMKPiA+Pj4gd2l0aG91dCBvdmVyZmxvdywgYnV0IGxhcmdlIGlucHV0 IGRhdGEgd2lsbCBzdGlsbCByZXF1aXJlIHNwbGl0dGluZyBpbnRvCj4gPj4+IGNodW5rcywgd2l0 aCBtb2R1bG8gcmVkdWN0aW9uIHN0ZXBzIGluIGJldHdlZW4uICBUaGVyZSBhcmUgcmF0aGVyIGEg bG90Cj4gPj4+IG9mIHNlcmlhbCBkZXBlbmRlbmNpZXMgaW4gdGhlIGNvcmUgbG9vcCwgYnV0IHNp bmNlIHRoZSBvcGVyYXRpb25zCj4gPj4+IGludm9sdmVkIGFyZSByZWxhdGl2ZWx5IGNoZWFwLCB0 aGlzIGlzIHByb2JhYmx5IG5vdCBhIHNpZ25pZmljYW50IGlzc3VlCj4gPj4+IGluIHByYWN0aWNl OiB0aGUgbG9hZC10by11c2UgZGVwZW5kZW5jeSBpcyBwcm9iYWJseSB0aGUgYmlnZ2VyIGNvbmNl cm4uCj4gPj4+IFBpcGVsaW5lZCBsb29wIHVucm9sbGluZyBjb3VsZCBhZGRyZXNzIHRoZXNlIGlm IG5lY2Vzc2FyeS4KPiA+Pj4KPiA+Pj4gVGhlIGhvcml6b250YWwgcmVkdWN0aW9ucyAoVUFERFYp IHN0aWxsIHByb2JhYmx5IGRvbid0IG5lZWQgdG8gYmUgZG9uZQo+ID4+PiB1bnRpbCBhZnRlciB0 aGUgbGFzdCBjaHVuay4KPiA+Pj4KPiA+Pj4KPiA+Pj4gQmV3YXJlOiBJIHdhc24ndCBjYXJlZnVs IHdpdGggdGhlIGluaXRpYWwgdmFsdWVzIGZvciBCbiAvIEFuLCBzbyBzb21lCj4gPj4+IGFkZGl0 aW9uYWwgYWRqdXN0bWVudHMgbWlnaHQgYmUgbmVlZGVkLi4uCj4gPj4+Cj4gPj4+IC0tODwtLQo+ ID4+Pgo+ID4+PiAJcHRydWUgICBwUC5zCj4gPj4+IAlwdHJ1ZSAgIHBBLnMKPiA+Pj4KPiA+Pj4g CW1vdiAgICAgekEucywgIzAgICAgICAgICAgICAgICAgLy8gYWNjdW11bGF0b3IgZm9yIEFuCj4g Pj4+IAltb3YgICAgIHpCLnMsICMwICAgICAgICAgICAgICAgIC8vIGFjY3VtdWxhdG9yIGZvciBC bgo+ID4+PiAJaW5kZXggICB6Si5zLCAjMCwgIzEgICAgICAgICAgICAvLyB6Si5zID0gWzAsIDEs IC4uIFYtMV0KPiA+Pj4KPiA+Pj4gCW1vdiAgICAgelYucywgIzAKPiA+Pj4gCWluY3cgICAgelYu cyAgICAgICAgICAgICAgICAgICAgLy8gelYucyA9IFtWLCBWLCAuLiBWXQo+ID4+Cj4gPj4gV2hl biBJIGFjdHVhbGx5IHRlc3RlZCB0aGlzIGNvZGUsIEkgZm91bmQgdGhhdCB0aGUgYnl0ZSBsZW5n dGggb2YgdGhlCj4gPj4gdGVzdCBtdXN0IGJlIGVxdWFsIHRvIHRoZSB2ZWN0b3IgbGVuZ3RoIGRp dmlkZWQgYnkgNCAodGhhdCBpcywgYW4gaW50ZWdlcgo+ID4+IG11bHRpcGxlIG9mIHRoZSBudW1i ZXIgb2Ygd29yZHMgaW4gdGhlIFNWRSkgYW5kIHRoZSByZXN1bHQgaXMgY29ycmVjdC4KPiA+Pgo+ ID4+IEFuZCBJIHRoaW5rIG9uZSBvZiB0aGUgcmVhc29ucyBpcyB0aGF0IHRoZSB2YWx1ZSBzdG9y ZWQgaW4gelYucyBuZWVkcyB0byBiZQo+ID4+IGNoYW5nZWQgaW4gdGhlIGxhc3QgY3ljbGUuIEl0 IHNob3VsZCBiZSBjaGFuZ2VkIHRvIHRoZSBhY3R1YWwgbnVtYmVyIG9mCj4gPj4gYnl0ZXMgcmVt YWluaW5nIGluIHRoZSBsYXN0IGN5Y2xlLiA6KQo+ID4gCj4gPiBBaCB5ZXMsIHlvdSdyZSBxdWl0 ZSByaWdodCBhYm91dCB0aGlzLiAgSW4gbXkgZGVyaXZhdGlvbiBhYm92ZSwgdiB3aWxsCj4gPiBu ZWVkIHRvIGJlIHNtYWxsZXIgdGhhbiB0aGUgdmVjdG9yIGxlbmd0aCB3aGVuIHByb2Nlc3Npbmcg dGhlIGZpbmFsLAo+ID4gcGFydGlhbCBibG9jayAoaWYgYW55KS4KPiA+IAo+ID4+Cj4gPj4+Cj4g Pj4+IC8vIHdoZXJlIFYgaXMgbnVtYmVyIG9mIGVsZW1lbnRzIHBlciBibG9jawo+ID4+PiAvLyAg ICAgID0gdGhlIG51bWJlciBvZiAzMi1iaXQgZWxlbWVudHMgdGhhdCBmaXQgaW4gYSBaLXJlZ2lz dGVyCj4gPj4+Cj4gPj4+IAlhZGQgICAgIHhMaW1pdCwgeFgsIHhMZW4KPiA+Pj4gCWIgICAgICAg c3RhcnQKPiA+Pj4KPiA+Pj4gbG9vcDogICAKPiA+Pj4gCWxkMWIgICAgelgucywgcFAveiwgW3hY XQo+ID4+PiAJaW5jdyAgICB4WAo+ID4+Cj4gPj4gSW4gb3JkZXIgdG8gdmVyaWZ5IG15IGNvbmpl Y3R1cmUsIEkgYWRkZWQgYSBiaXQgb2YgY29kZSB0byBoZXJlLCB3aGljaCBpcyB0bwo+ID4+IHN1 YnRyYWN0IHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIGZyb20gelYgaW4gdGhlIGxhc3QgbG9vcC4g QnV0IGl0IGlzIGNvcnJlY3QKPiA+PiBvbmx5IHdoZW4gdGhlIG51bWJlciBvZiBieXRlcyBpcyBs ZXNzIHRoYW4gb25lIGN5Y2xlLiBUZXN0IGNhc2VzIHRoYXQgZXhjZWVkCj4gPj4gb25lIGNvbXBs ZXRlIGN5Y2xlIHdpbGwgYWxzbyBmYWlsLgo+ID4+Cj4gPj4gU28gSSBndWVzcyBiZWZvcmUgY2Fs Y3VsYXRpbmcgdGhlIGxhc3QgY3ljbGUsIHpBIHNob3VsZCBiZSBzdW1tZWQgZmlyc3QsCj4gPj4g YmVjYXVzZSBiZWZvcmUgdGhlIGVuZCBvZiB0aGUgY3ljbGUsIHpBIGFuZCB6QiBhcmUgc2NhdHRl cmVkIGluIHRoZSBlbGVtZW50cwo+ID4+IG9mIHRoZSB2ZWN0b3IsIGlmIHRoZSBsYXN0IGN5Y2xl IGNhbGN1bGF0ZXMgekIsIG9ubHkgcGFydCBvZiB6QSBpcyBzdW1tZWQKPiA+PiAoIEJlY2F1c2Ug cFAvbSBkb2VzIG5vdCBjb3VudCBpbmFjdGl2ZSBlbGVtZW50cyksIGl0IHNob3VsZCBiZSBpbmNv bXBsZXRlLgo+ID4+Cj4gPj4gVGhpcyBpcyBqdXN0IG15IGd1ZXNzIGFuZCBoYXMgbm90IHlldCBi ZWVuIHZlcmlmaWVkLjopCj4gPiAKPiA+IEkgdGhpbmsgekEgc2hvdWxkbid0IGJlIHdyb25nLCBz aW5jZSB0aGF0IG9ubHkgYWNjdW11bGF0ZXMgYWN0aXZlCj4gPiBlbGVtZW50cyBhbnl3YXkuICBJ IHRoaW5rIGl0J3MgdGhlIGJvZ3VzIHpWIG11bHRpcGxpZXIgaW52b2x2ZWQgaW4gdGhlCj4gPiB1 cGRhdGUgdG8gekIgdGhhdCBpcyB0aGUgcHJvYmxlbS4KPiA+IAo+ID4+Pgo+ID4+PiAJYWRkICAg ICB6QS5zLCBwUC9tLCB6QS5zLCB6WC5zICAgICAgICAvLyB6QS5zICs9IHpYLnMKPiA+Pj4KPiA+ Pj4gCW1zYiAgICAgelgucywgcFAvbSwgekoucywgekIucyAgICAgICAgLy8gelgucyA6PSB6Qi5z IC0gelgucyAqIHpKLnMKPiA+Pj4KPiA+Pj4gCW1vdnByZnggekIsIHpBCj4gPj4+IAltYWQgICAg IHpCLnMsIHBQL20sIHpWLnMsIHpYLnMgICAgICAgIC8vIHpCLnMgOj0gelgucyArIHpBLnMgKiBW Cj4gCj4gSSBmb3VuZCB0aGUgYnVnIEkgZW5jb3VudGVyZWQgZWFybGllciwgdGhhdCBpcywgdGhl IGNhbGN1bGF0aW9uIG9mIHpCIGhlcmUKPiBuZWVkcyB0byB1c2UgcEEgd2l0aCBhbGwgZWxlbWVu dHMgYWN0aXZhdGVkLiBUaGUgcmVhc29uIGlzIHRoZSBzYW1lIGFzIG15Cj4gcHJldmlvdXMgZ3Vl c3MsIGJlY2F1c2UgYWxsIGVsZW1lbnRzIG9mIHpBIHNob3VsZCBiZSBpbnZvbHZlZCB3aGVuIGNh bGN1bGF0aW5nIHpCLgo+IEJlY2F1c2UgdGhlIG9yaWdpbmFsIGNhbGN1bGF0aW9uIGZvcm11bGEg aXMgbGlrZSB0aGlzLgo+IAo+IEZvciBleGFtcGxlOgo+IEluIHRoZSBsYXN0IGxvb3A6Cj4gCWxl ZnQgYnl0ZSBpczoJICAzIHwgICA0IHwgIFwwIHwKPiAJekEucyBpczoJMTAwIHwgMjAwIHwgMTAw IHwgMjAwIChzdW0gPSA2MDApCj4gCXBQLnMgaXM6CSAgMSB8ICAgMSB8ICAgMCB8ICAgMCAoT25s eSBhY3RpdmF0ZSB0aGUgZmlyc3QgMiBjaGFubmVscykKPiAKPiBBdCB0aGlzIHRpbWUsIGlmIHRo ZSBjYWxjdWxhdGlvbiBvZiB6QiBvbmx5IHRha2VzIHRoZSBmaXJzdCAyIGFjdGl2ZSBlbGVtZW50 cywgdGhlIGRhdGEKPiBpcyBpbmNvbXBsZXRlLCBiZWNhdXNlIGFjY29yZGluZyB0byB0aGUgZGVz Y3JpcHRpb24gb2YgdGhlIG9yaWdpbmFsIGFsZ29yaXRobSwgekIgaXMgYWx3YXlzCj4gYmFzZWQg b24gdGhlIHN1bSBvZiBhbGwgdGhlIGFjY3VtdWxhdGVkIGJ5dGVzLgoKWWVzLCB5b3UncmUgcXVp dGUgcmlnaHQgaGVyZTogelggaXMgcGFydGlhbDogb25seSB0aGUgZWxlbWVudHMgcFAgYXJlCnZh bGlkOyBidXQgYWxsIGVsZW1lbnRzIG9mIHpBIGFuZCB6QiBhcmUgYWx3YXlzIHZhbGlkLiAgSSB3 YXMgZm9jdXNpbmcKdG9vIG11Y2ggb24gdGhlIGhhbmRsaW5nIG9mIHRoZSBwYXJ0aWFsIGlucHV0 IGJsb2NrLgoKPiAKPiBIZXJlIHdlIGNhbiBzaW1wbHkgY2hhbmdlIHRoZSBwcmVkaWN0aW9uIHJl Z2lzdGVyIHVzZWQgaW4gdGhlIHR3byBzZW50ZW5jZXMgcmVsYXRlZCB0bwo+IHpCIHRvIHRoZSBv bmUgdGhhdCBpcyBhbGwgdHJ1ZSAoaXQgaXMgcEEgaW4gb3VyIGNvZGUpLCBsaWtlIHRoaXM6Cj4g CW1zYiAgICAgelgucywgcEEvbSwgekoucywgekIucyAgICAgICAgLy8gelgucyA6PSB6Qi5zIC0g elgucyAqIHpKLnMKCkFyZSB5b3Ugc3VyZSBhYm91dCB0aGlzPyAgSW4gYSBmaW5hbCBwYXJ0aWFs IGJsb2NrLCB0aGUgdHJhaWxpbmcKZWxlbWVudHMgb2YgelgucyBiZXlvbmQgcFAgd2lsbCBiZSBs ZWZ0b3ZlciBqdW5rIGZyb20gdGhlIGxhc3QKaXRlcmF0aW9uLgoKVGhpcyBtaWdodCByZXF1aXJl IGEgYml0IG1vcmUgdGhvdWdodCBpbiBvcmRlciB0byBnZXQgdGhlIGZpbmFsIGJsb2NrCmhhbmRs aW5nIGNvcnJlY3QuCgo+IAltb3ZwcmZ4IHpCLCB6QQo+IAltYWQgICAgIHpCLnMsIHBBL20sIHpW LnMsIHpYLnMgICAgICAgIC8vIHpCLnMgOj0gelgucyArIHpBLnMgKiBWCj4gCj4gPj4+IHN0YXJ0 OiAgCj4gPj4+IAl3aGlsZWxvIHBQLnMsIHhYLCB4TGltaXQKPiA+Pj4gCWIuZmlyc3QgbG9vcAo+ ID4gCj4gPiBUaGVyZSBhcmUgYSBmZXcgb3B0aW9ucywgSSBndWVzcy4KPiA+IAo+ID4gT25lIHdh eSBpcyB0byB1c2UgQ05UUCBpbnNpZGUgdGhlIGxvb3AgdG8gZ2V0IHRoZSBudW1iZXIgb2YgYWN0 aXZlCj4gPiBlbGVtZW50cywgaW5zdGVhZCBvZiBqdXN0IHNldHRpbmcgelYgaW4gYWR2YW5jZS4g IFRoaXMgYXBwcm9hY2ggbWF5IGFkZAo+ID4gYSBzbGlnaHQgb3ZlcmhlYWQsIGJ1dCBpdCBpcyB3 b3J0aCBleHBlcmltZW50aW5nIHdpdGggaXQuICBJZiB0aGUKPiA+IG92ZXJoZWFkIGlzIG5lZ2xp YmlibGUsIHRoZW4gdGhpcyBhcHByb2FjaCBoYXMgdGhlIGV4YW1wbGUgb2YgYmVpbmcKPiA+IHNp bXBsZSB0byB1bmRlcnN0YW5kLgo+ID4gCj4gPiBBbHRlcm5hdGl2ZWx5LCB5b3UgY291bGQgZG8g YW4gYWRqdXN0bWVudCBhZnRlciB0aGUgbG9vcCBlbmRzIHRvCj4gPiBzdWJ0cmFjdCB0aGUgYXBw cm9wcmlhdGUgYW1vdW50cyBmcm9tIHpCLiAgVW5mb3J0dW5hdGVseSwgcFAgaGFzIGFscmVhZHkK PiA+IGJlZW4gb3ZlcndyaXR0ZW4gYnkgdGhlIHRpbWUgdGhlIGxvb3AgZW5kcy4gIElmIGNvdWxk IGJlIGJhY2tlZCB1cCBpbnRvCj4gPiBhbm90aGVyIFAtcmVnaXN0ZXIgYmVmb3JlIG92ZXJ3cml0 aW5nIGl0OiB0aGlzIHNob3VsZCBiZSBwcmV0dHkgbG93LQo+ID4gb3ZlcmhlYWQuCj4gPiAKPiA+ IEEgZmluYWwgb3B0aW9uIHdvdWxkIGJlIHRvIGNoYW5nZSB0aGUgYi5maXJzdCB0byBhIGIubGFz dCwgc28gdGhhdCB0aGUKPiA+IGxvb3AgZW5kcyBhZnRlciB0aGUgZmluYWwgZnVsbCBibG9jay4g IFRoZW4gY29weS1wYXN0ZSB0aGUgbG9vcCBib2R5IHRvCj4gPiBleGVjdXRlIG9uY2UgbW9yZSwg YnV0IHVzaW5nIENOVFAgdG8gZ2V0IHRoZSBlbGVtZW50IGNvdW50IHRvIG11bHRpcGx5Cj4gPiBi eSwgYXMgZGVzY3JpYmVkIGFib3ZlLiAgVGhpcyBtYWtlcyB0aGUgY29kZSBhIGJpdCBsYXJnZXIs IGJ1dCBpdAo+ID4gcHJvYmFibHkgdGhlIGJlc3QtcGVyZm9ybWFuY2Ugb3B0aW9uLiAgWW91IG1h eSBiZSBhYmxlIHRvIHJvdGF0ZSB0aGUKPiA+IGxvb3Agc28gdGhhdCBpdCBicmVha3Mgb3V0IGFm dGVyIHVwZGF0aW5nIHpBICh3aGljaCBJSVVDIGRvZXNuJ3QgbmVlZCB0bwo+ID4gYmUgZG9uZSBp biBhIHNwZWNpYWwgd2F5IGZvciB0aGUgcGFydGlhbCBibG9jaykuICBUaGlzIHdvdWxkIG1lYW4g eW91Cj4gPiBvbmx5IGhhdmUgdG8gc3BlY2lhbGlzZSB0aGUgekIgdXBkYXRlIGNvZGUuCj4gCj4g UmVnYXJkaW5nIHRoZSBsYXN0IGxvb3AsIEkgdHJpZWQgdG8gd3JhcCBhbm90aGVyIGxheWVyIGJl Zm9yZSBhbmQgYWZ0ZXIgdGhlCj4gY29yZSBsb29wLCBhbmQgSSBoYXZlIHZlcmlmaWVkIGl0cyBj b3JyZWN0bmVzcy4KPiBNeSBjb2RlIGlzIGF0IHRoZSBlbmQgb2YgdGhpcyBlbWFpbC4KPiAKPiA+ IAo+ID4+Pgo+ID4+PiAvLyBDb2xsZWN0IHRoZSBwYXJ0aWFsIHN1bXMgdG9nZXRoZXI6Cj4gPj4+ Cj4gPj4+IAl1YWRkdiAgIGQwLCBwQSwgejAucwo+ID4+PiAJdWFkZHYgICBkMSwgcEEsIHoxLnMK PiA+Pj4KPiA+Pj4gLy8gRmluYWxseSwgYWRkIDEgdG8gZDAsIGFuZCB4TGVuIHRvIGQxLCBhbmQg ZG8gbW9kdWxvIHJlZHVjdGlvbi4KPiA+Pj4KPiA+Pj4gLS0+OC0tCj4gPj4+Cj4gPj4+IFsuLi5d Cj4gPj4+Cj4gPj4+IENoZWVycwo+ID4+PiAtLS1EYXZlCj4gPj4+IC4KPiA+Pj4KPiA+Pgo+ID4+ IFRoZSBjb2RlIHlvdSBzZW50IG1lIHByb3ZpZGVzIGEgY29ycmVjdCB3YXkgdG8gZGVhbCB3aXRo IHRyYWlsaW5nIGJ5dGVzLAo+ID4+IEkgbmVlZCB0byBzcGVuZCBzb21lIG1vcmUgdGltZSB0byBk ZWJ1ZyB0aGUgcHJvYmxlbSBlbmNvdW50ZXJlZCBhYm92ZS4KPiA+PiBUaGFuayB5b3UhCj4gPj4K PiA+PiBDaGVlcnMuXl9eCj4gPiAKPiA+IEkgd2FzIGNoZWVraWx5IGxlYXZpbmcgdGhlIHRlc3Rp bmcgYW5kIGRlYnVnZ2luZyBmb3IgeW91IHRvIGRvIDopCj4gPiAKPiA+IFBhcnQgb2YgbXkgcmVh c29uIGZvciBpbnRlcmVzdCBpbiB0aGlzIGlzIHRoYXQgaWYgd2UgZW5hYmxlIFNWRSBpbiB0aGUK PiA+IGtlcm5lbCwgaXQgd291bGQgYmUgZ29vZCB0byBoYXZlIHNvbWUgY2xlYW4gZXhhbXBsZXMg Zm9yIHBlb3BsZSB0bwo+ID4gZm9sbG93IC0tIGV2ZW4gaWYgbm90IHRoaXMgYWxnby4gIFNWRSBp cyBhIGJpdCBkaWZmZXJlbnQgdG8gdXNlCj4gPiBjb21wYXJlZCB3aXRoIGZpeGVkLWxlbmd0aCB2 ZWN0b3IgSVNBcywgc28gd29ya2VkIGV4YW1wbGVzIGFyZSBhbHdheXMKPiA+IHVzZWZ1bC4KPiBZ ZXMgaXQgaXMgbmVjZXNzYXJ5Lgo+IAo+ID4gCj4gPiBDaGVlcnMKPiA+IC0tLURhdmUKPiA+IC4K PiA+IAo+IAo+IFRoaXMgaXMgdGhlIG1haW4gcGFydCBvZiBteSBuZXdseSBtb2RpZmllZCBjb2Rl Ogo+IC0tODwtLQo+ICAgICAgICAgcHRydWUgICBwMC5zCj4gICAgICAgICBwdHJ1ZSAgIHAxLnMK PiAKPiAgICAgICAgIG1vdiAgICAgekEucywgIzAKPiAgICAgICAgIG1vdiAgICAgekIucywgIzAK PiAgICAgICAgIGluZGV4ICAgekoucywgIzAsICMxCj4gICAgICAgICBtb3YgICAgIHpWLnMsICMw Cj4gICAgICAgICBpbmN3ICAgIHpWLnMKPiAKPiAgICAgICAgIGFkZCAgICAgeExpbWl0LCB4MSwg eDIKPiAgICAgICAgIGIgICAgICAgc3RhcnQJCS8vRW50ZXIgdGhlIGNvcmUgbG9vcCBmaXJzdAo+ IAo+IHRyYWlsbG9vcDoJCQkvLyBMYXN0IGN5Y2xlIGVudHJhbmNlCj4gICAgICAgICBjbnRwICAg IHg2LCBwMSwgcDAucwkvLyBHZXQgYWN0aXZlIGVsZW1lbnQgY291bnQgb2YgbGFzdCBjeWNsZQo+ ICAgICAgICAgY3B5ICAgICB6Vi5zLCBwMS9tLCB3NgkvLyBTZXQgelYgdG8gdGhlIGFjdHVhbCB2 YWx1ZS4KCk5vdGUgdGhhdCB5b3UgY2FuIGFsc28gd3JpdGUgIm1vdiIgaGVyZSwgYnV0IEknbSBu b3Qgc3VyZSB3aGljaCBhbGlhcyBpcwpwcmVmZXJyZWQuCgo+IGxvb3A6CQkJCS8vIENvcmUgbG9v cCBlbnRyYW5jZQo+ICAgICAgICAgbGQxYiAgICB6WC5zLCBwMC96LCBbeDFdCj4gICAgICAgICBp bmN3ICAgIHgxCj4gCj4gICAgICAgICBhZGQgICAgIHpBLnMsIHAwL20sIHpBLnMsIHpYLnMJLy8g VGhlIGNhbGN1bGF0aW9uIG9mIHpBIHN0aWxsIG5lZWRzIHRvIHVzZSBwMAo+ICAgICAgICAgbXNi ICAgICB6WC5zLCBwMS9tLCB6Si5zLCB6Qi5zCS8vIENoYW5nZSBwIHJlZ2lzdGVyIGhlcmUKPiAg ICAgICAgIG1vdnByZnggekIsIHpBCj4gICAgICAgICBtYWQgICAgIHpCLnMsIHAxL20sIHpWLnMs IHpYLnMJLy8gQ2hhbmdlIHAgcmVnaXN0ZXIgaGVyZQoKQXMgZGlzY3Vzc2VkIGFib3ZlLCBhcmUg eW91IHN1cmUgdGhpcyBpcyBjb3JyZWN0IG5vdz8KCj4gc3RhcnQ6Cj4gICAgICAgICB3aGlsZWxv IHAwLnMsIHgxLCB4TGltaXQKPiAgICAgICAgIGIubGFzdCAgbG9vcAkJLy8gVGhlIGNvbmRpdGlv biBmb3IgdGhlIGNvcmUgbG9vcCB0byBjb250aW51ZSBpcyB0aGF0IGIubGFzdCBpcyB0cnVlCj4g ICAgICAgICBiLmZpcnN0IHRyYWlsbG9vcAkvLyBJZiBiLmxhc3QgaXMgZmFsc2UgYW5kIGIuZmly c3QgaXMgdHJ1ZSwgaXQgbWVhbnMgdGhlIGxhc3QgY3ljbGUKPiAKPiAgICAgICAgIHVhZGR2ICAg ZDAsIHAxLCB6QS5zCj4gICAgICAgICB1YWRkdiAgIGQxLCBwMSwgekIucwo+IAo+ICAgICAgICAg bW92ICAgICB4MTIsIHYwLjJkWzBdCj4gICAgICAgICBtb3YgICAgIHgxMywgdjEuMmRbMF0KClRo ZSAiMiIgaGVyZSBzZWVtcyBub3QgdG8gYmUgcmVxdWlyZWQgYnkgdGhlIHN5bnRheCwgYWx0aG91 Z2ggaXQncwpoYXJtbGVzcy4KCj4gICAgICAgICBhZGQgICAgIHgxMCwgeDEwLCB4MTIKPiAgICAg ICAgIGFkZCAgICAgeDExLCB4MTEsIHgxMwo+ICAgICAgICAgYWRkICAgICB4MTEsIHgxMSwgeDIK CklmIHgxMCBhbmQgeDExIGFyZSB1c2VkIGFzIGFjY211bGF0b3JzIGJ5IHRoZSBjYWxsZXIsIEkg Z3Vlc3MgdGhpcyB3b3Jrcy4KCj4gCj4gICAgICAgICBtb2Q2NTUyMSAgICAgICAgMTAsIDE0LCAx Mgo+ICAgICAgICAgbW9kNjU1MjEgICAgICAgIDExLCAxNCwgMTIKPiAgICAgICAgIGxzbCAgICAg eDExLCB4MTEsICMxNgo+ICAgICAgICAgb3JyICAgICB4MCwgeDEwLCB4MTEKPiAgICAgICAgIHJl dAo+IC0tPjgtLQo+IAo+IEFmdGVyIHRoaXMgbW9kaWZpY2F0aW9uLCBUaGUgdGVzdCByZXN1bHRz IGFyZSBjb3JyZWN0IHdoZW4gdGhlIGRhdGEgbGVuZ3RoIGlzIGxlc3MgdGhhbiBhYm91dCA4IEti eXRlLAo+IHBhcnQgQSB3aWxsIHN0aWxsIGJlIGNvcnJlY3QgYWZ0ZXIgOEssIGFuZCBhbiBvdmVy ZmxvdyBlcnJvciB3aWxsIG9jY3VyIGluIHBhcnQgQi4gVGhpcyBpcyBiZWNhdXNlIEEKPiBvbmx5 IGFjY3VtdWxhdGVzIGFsbCB0aGUgYnl0ZXMsIGFuZCB0aGUgYWNjdW11bGF0aXZlIGFjY2VsZXJh dGlvbiBvZiBCIGV4cGFuZHMgZmFzdGVyLCBiZWNhdXNlIHRoZQo+IGFjY3VtdWxhdGl2ZSBmb3Jt dWxhIG9mIEIgaXM6Cj4gCUIgPSAoMSArIEQxKSArICgxICsgRDEgKyBEMikgKyAuLi4gKyAoMSAr IEQxICsgRDIgKyAuLi4gKyBEbikgKG1vZCA2NTUyMSkKPiAgICAgICAgICAgID0gbsOXRDEgKyAo buKIkjEpw5dEMiArIChu4oiSMinDl0QzICsgLi4uICsgRG4gKyBuIChtb2QgNjU1MjEpCj4gCj4g SWYgd2UgdGFrZSB0aGUgYXZlcmFnZSB2YWx1ZSBvZiBEeCB0byAxMjggYW5kIG4gdG8gODE5MjoK PiAJQiA9ICgxICsgMiArIC4uLiArIDgxMjkpICogMTI4ICsgODE5Mgo+IAkgID0gNCwyOTUsNDk5 LDc3NiAoMzJiaXQgb3ZlcmZsb3cpCj4gCj4gU28gSSB0aGluayB0aGUgMzItYml0IGFjY3VtdWxh dG9yIGlzIHN0aWxsIG5vdCBlbm91Z2ggZm9yIHBhcnQgQiBoZXJlLiA6KQo+IAo+IC0tIAo+IEJl c3QgcmVnYXJkcywKPiBMaSBRaWFuZwoKVGhhdCBtYWtlcyBzZW5zZS4gIEkgaGFkbid0IHRyaWVk IHRvIGNhbGN1bGF0ZSB0aGUgYWN0dWFsIGJvdW5kLgoKSXQgbWF5IGJlIHdvcnRoIHRyeWluZyB0 aGlzIHdpdGggNjQtYml0IGFjY3VtdWxhdG9ycy4gIFRoaXMgd2lsbApwcm9iYWJseSBzbG93IHRo aW5ncyBkb3duLCBidXQgaXQgZGVwZW5kcyBvbiB0aGUgcmVsYXRpdmUgY29tcHV0YXRpb24gLwpt ZW1vcnkgdGhyb3VnaHB1dCBleGhpYml0ZWQgYnkgdGhlIGhhcmR3YXJlLgoKSSB0aGluayB0aGUg Y29kZSBjYW4ndCBiZSBidWxsZXRwcm9vZiB3aXRob3V0IGJyZWFraW5nIHRoZSBpbnB1dCBpbnRv CmNodW5rcyBhbnl3YXksIHRob3VnaC4KCkNoZWVycwotLS1EYXZlCgpfX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcg bGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmlu ZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==