From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 516DA2C1BF for ; Wed, 13 Dec 2023 13:05:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com 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 3DF5CC15; Wed, 13 Dec 2023 05:05:54 -0800 (PST) Received: from raptor (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1B5EB3F762; Wed, 13 Dec 2023 05:05:02 -0800 (PST) Date: Wed, 13 Dec 2023 13:04:56 +0000 From: Alexandru Elisei To: Rob Herring Cc: catalin.marinas@arm.com, will@kernel.org, oliver.upton@linux.dev, maz@kernel.org, james.morse@arm.com, suzuki.poulose@arm.com, yuzenghui@huawei.com, arnd@arndb.de, akpm@linux-foundation.org, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, mhiramat@kernel.org, rppt@kernel.org, hughd@google.com, pcc@google.com, steven.price@arm.com, anshuman.khandual@arm.com, vincenzo.frascino@arm.com, david@redhat.com, eugenis@google.com, kcc@google.com, hyesoo.yu@samsung.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org Subject: Re: [PATCH RFC v2 11/27] arm64: mte: Reserve tag storage memory Message-ID: References: <20231119165721.9849-1-alexandru.elisei@arm.com> <20231119165721.9849-12-alexandru.elisei@arm.com> Precedence: bulk X-Mailing-List: kvmarm@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Hi Rob, On Tue, Dec 12, 2023 at 12:44:06PM -0600, Rob Herring wrote: > On Tue, Dec 12, 2023 at 10:38 AM Alexandru Elisei > wrote: > > > > Hi Rob, > > > > Thank you so much for the feedback, I'm not very familiar with device tree, > > and any comments are very useful. > > > > On Mon, Dec 11, 2023 at 11:29:40AM -0600, Rob Herring wrote: > > > On Sun, Nov 19, 2023 at 10:59 AM Alexandru Elisei > > > wrote: > > > > > > > > Allow the kernel to get the size and location of the MTE tag storage > > > > regions from the DTB. This memory is marked as reserved for now. > > > > > > > > The DTB node for the tag storage region is defined as: > > > > > > > > tags0: tag-storage@8f8000000 { > > > > compatible = "arm,mte-tag-storage"; > > > > reg = <0x08 0xf8000000 0x00 0x4000000>; > > > > block-size = <0x1000>; > > > > memory = <&memory0>; // Associated tagged memory node > > > > }; > > > > > > I skimmed thru the discussion some. If this memory range is within > > > main RAM, then it definitely belongs in /reserved-memory. > > > > Ok, will do that. > > > > If you don't mind, why do you say that it definitely belongs in > > reserved-memory? I'm not trying to argue otherwise, I'm curious about the > > motivation. > > Simply so that /memory nodes describe all possible memory and > /reserved-memory is just adding restrictions. It's also because > /reserved-memory is what gets handled early, and we don't need > multiple things to handle early. > > > Tag storage is not DMA and can live anywhere in memory. > > Then why put it in DT at all? The only reason CMA is there is to set > the size. It's not even clear to me we need CMA in DT either. The > reasoning long ago was the kernel didn't do a good job of moving and > reclaiming contiguous space, but that's supposed to be better now (and > most h/w figured out they need IOMMUs). > > But for tag storage you know the size as it is a function of the > memory size, right? After all, you are validating the size is correct. > I guess there is still the aspect of whether you want enable MTE or > not which could be done in a variety of ways. Oh, sorry, my bad, I should have been clearer about this. I don't want to put it in the DT as a "linux,cma" node. But I want it to be managed by CMA. > > > In > > arm64_memblock_init(), the kernel first removes the memory that it cannot > > address from memblock. For example, because it has been compiled with > > CONFIG_ARM64_VA_BITS_39=y. And then calls > > early_init_fdt_scan_reserved_mem(). > > > > What happens if reserved memory is above what the kernel can address? > > I would hope the kernel handles it. That's the kernel's problem unless > there's some h/w limitation to access some region. The DT can't have > things dependent on the kernel config. I would hope so too, that's why I was surprised when I put reserved memory at 1TB in a 39 bit VA kernel and got a panic. > > > From my testing, when the kernel is compiled with 39 bit VA, if I use > > reserved memory to discover tag storage the lives above the virtua address > > limit and then I try to use CMA to manage the tag storage memory, I get a > > kernel panic: > > Looks like we should handle that better... I guess we don't need to tackle that problem right now. I don't know of many systems in the wild that have memory above the 1TB address. > > >> [ 0.000000] Reserved memory: created CMA memory pool at 0x0000010000000000, size 64 MiB > > [ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool > > [ 0.000000] OF: reserved mem: 0x0000010000000000..0x0000010003ffffff (65536 KiB) map reusable linux,cma > > [..] > > [ 0.806945] Unable to handle kernel paging request at virtual address 00000001fe000000 > > [ 0.807277] Mem abort info: > > [ 0.807277] ESR = 0x0000000096000005 > > [ 0.807693] EC = 0x25: DABT (current EL), IL = 32 bits > > [ 0.808110] SET = 0, FnV = 0 > > [ 0.808443] EA = 0, S1PTW = 0 > > [ 0.808526] FSC = 0x05: level 1 translation fault > > [ 0.808943] Data abort info: > > [ 0.808943] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 > > [ 0.809360] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 > > [ 0.809776] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 > > [ 0.810221] [00000001fe000000] user address but active_mm is swapper > > [..] > > [ 0.820887] Call trace: > > [ 0.821027] cma_init_reserved_areas+0xc4/0x378 > > > > > > > > You need a binding for this too. > > > > By binding you mean having an yaml file in dt-schem [1] describing the tag > > storage node, right? > > Yes, but in the kernel tree is fine. Cool, thanks. > > [...] > > > > > +static int __init tag_storage_of_flat_get_range(unsigned long node, const __be32 *reg, > > > > + int reg_len, struct range *range) > > > > +{ > > > > + int addr_cells = dt_root_addr_cells; > > > > + int size_cells = dt_root_size_cells; > > > > + u64 size; > > > > + > > > > + if (reg_len / 4 > addr_cells + size_cells) > > > > + return -EINVAL; > > > > + > > > > + range->start = PHYS_PFN(of_read_number(reg, addr_cells)); > > > > + size = PHYS_PFN(of_read_number(reg + addr_cells, size_cells)); > > > > + if (size == 0) { > > > > + pr_err("Invalid node"); > > > > + return -EINVAL; > > > > + } > > > > + range->end = range->start + size - 1; > > > > > > We have a function to read (and translate which you forgot) addresses. > > > Add what's missing rather than open code your own. > > > > I must have missed that there's already a function to read addresses. Would > > you mind pointing me in the right direction? > > drivers/of/fdt_address.c > > Though it doesn't provide getting the size, so that will have to be added. Ok, will do! > > > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int __init tag_storage_of_flat_get_tag_range(unsigned long node, > > > > + struct range *tag_range) > > > > +{ > > > > + const __be32 *reg; > > > > + int reg_len; > > > > + > > > > + reg = of_get_flat_dt_prop(node, "reg", ®_len); > > > > + if (reg == NULL) { > > > > + pr_err("Invalid metadata node"); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + return tag_storage_of_flat_get_range(node, reg, reg_len, tag_range); > > > > +} > > > > + > > > > +static int __init tag_storage_of_flat_get_memory_range(unsigned long node, struct range *mem) > > > > +{ > > > > + const __be32 *reg; > > > > + int reg_len; > > > > + > > > > + reg = of_get_flat_dt_prop(node, "linux,usable-memory", ®_len); > > > > + if (reg == NULL) > > > > + reg = of_get_flat_dt_prop(node, "reg", ®_len); > > > > + > > > > + if (reg == NULL) { > > > > + pr_err("Invalid memory node"); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + return tag_storage_of_flat_get_range(node, reg, reg_len, mem); > > > > +} > > > > + > > > > +struct find_memory_node_arg { > > > > + unsigned long node; > > > > + u32 phandle; > > > > +}; > > > > + > > > > +static int __init fdt_find_memory_node(unsigned long node, const char *uname, > > > > + int depth, void *data) > > > > +{ > > > > + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); > > > > + struct find_memory_node_arg *arg = data; > > > > + > > > > + if (depth != 1 || !type || strcmp(type, "memory") != 0) > > > > + return 0; > > > > + > > > > + if (of_get_flat_dt_phandle(node) == arg->phandle) { > > > > + arg->node = node; > > > > + return 1; > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int __init tag_storage_get_memory_node(unsigned long tag_node, unsigned long *mem_node) > > > > +{ > > > > + struct find_memory_node_arg arg = { 0 }; > > > > + const __be32 *memory_prop; > > > > + u32 mem_phandle; > > > > + int ret, reg_len; > > > > + > > > > + memory_prop = of_get_flat_dt_prop(tag_node, "memory", ®_len); > > > > + if (!memory_prop) { > > > > + pr_err("Missing 'memory' property in the tag storage node"); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + mem_phandle = be32_to_cpup(memory_prop); > > > > + arg.phandle = mem_phandle; > > > > + > > > > + ret = of_scan_flat_dt(fdt_find_memory_node, &arg); > > > > > > Do not use of_scan_flat_dt. It is a relic predating libfdt which can > > > get a node by phandle directly. > > > > I used that because that's what drivers/of/fdt.c uses. With reserved memory > > I shouldn't need it, because struct reserved_mem already includes a > > phandle. > > Check again. Only some arch/ code (mostly powerpc) uses it. I've > killed off most of it. You're right, I think I grep'ed for a different function name in drivers/of/fdt.c Either way, the message is clear: no of_scan_flat_dt(). > > > > > > + if (ret != 1) { > > > > + pr_err("Associated memory node not found"); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + *mem_node = arg.node; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int __init tag_storage_of_flat_read_u32(unsigned long node, const char *propname, > > > > + u32 *retval) > > > > > > If you are going to make a generic function, make it for everyone. > > > > Sure. If I still need it, should I put the function in > > include/linux/of_fdt.h? > > Yes. Noted. > > > > > +{ > > > > + const __be32 *reg; > > > > + > > > > + reg = of_get_flat_dt_prop(node, propname, NULL); > > > > + if (!reg) > > > > + return -EINVAL; > > > > + > > > > + *retval = be32_to_cpup(reg); > > > > + return 0; > > > > +} > > > > + > > > > +static u32 __init get_block_size_pages(u32 block_size_bytes) > > > > +{ > > > > + u32 a = PAGE_SIZE; > > > > + u32 b = block_size_bytes; > > > > + u32 r; > > > > + > > > > + /* Find greatest common divisor using the Euclidian algorithm. */ > > > > + do { > > > > + r = a % b; > > > > + a = b; > > > > + b = r; > > > > + } while (b != 0); > > > > + > > > > + return PHYS_PFN(PAGE_SIZE * block_size_bytes / a); > > > > +} > > > > + > > > > +static int __init fdt_init_tag_storage(unsigned long node, const char *uname, > > > > + int depth, void *data) > > > > +{ > > > > + struct tag_region *region; > > > > + unsigned long mem_node; > > > > + struct range *mem_range; > > > > + struct range *tag_range; > > > > + u32 block_size_bytes; > > > > + u32 nid = 0; > > > > + int ret; > > > > + > > > > + if (depth != 1 || !strstr(uname, "tag-storage")) > > > > + return 0; > > > > + > > > > + if (!of_flat_dt_is_compatible(node, "arm,mte-tag-storage")) > > > > + return 0; > > > > + > > > > + if (num_tag_regions == MAX_TAG_REGIONS) { > > > > + pr_err("Maximum number of tag storage regions exceeded"); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + region = &tag_regions[num_tag_regions]; > > > > + mem_range = ®ion->mem_range; > > > > + tag_range = ®ion->tag_range; > > > > + > > > > + ret = tag_storage_of_flat_get_tag_range(node, tag_range); > > > > + if (ret) { > > > > + pr_err("Invalid tag storage node"); > > > > + return ret; > > > > + } > > > > + > > > > + ret = tag_storage_get_memory_node(node, &mem_node); > > > > + if (ret) > > > > + return ret; > > > > + > > > > + ret = tag_storage_of_flat_get_memory_range(mem_node, mem_range); > > > > + if (ret) { > > > > + pr_err("Invalid address for associated data memory node"); > > > > + return ret; > > > > + } > > > > + > > > > + /* The tag region must exactly match the corresponding memory. */ > > > > + if (range_len(tag_range) * 32 != range_len(mem_range)) { > > > > + pr_err("Tag storage region 0x%llx-0x%llx does not cover the memory region 0x%llx-0x%llx", > > > > + PFN_PHYS(tag_range->start), PFN_PHYS(tag_range->end), > > > > + PFN_PHYS(mem_range->start), PFN_PHYS(mem_range->end)); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + ret = tag_storage_of_flat_read_u32(node, "block-size", &block_size_bytes); > > > > + if (ret || block_size_bytes == 0) { > > > > + pr_err("Invalid or missing 'block-size' property"); > > > > + return -EINVAL; > > > > + } > > > > + region->block_size = get_block_size_pages(block_size_bytes); > > > > + if (range_len(tag_range) % region->block_size != 0) { > > > > + pr_err("Tag storage region size 0x%llx is not a multiple of block size %u", > > > > + PFN_PHYS(range_len(tag_range)), region->block_size); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + ret = tag_storage_of_flat_read_u32(mem_node, "numa-node-id", &nid); > > > > > > I was going to say we already have a way to associate memory nodes > > > other nodes using "numa-node-id", so the "memory" phandle property is > > > somewhat redundant. Maybe the tag node should have a numa-node-id. > > > With that, it looks like you don't even need to access the /memory > > > node. Avoiding that would be good for 2 reasons. It avoids parsing > > > memory nodes twice and it's not the kernel's job to validate the DT. > > > Really, if you want memory info, you should use memblock to get it > > > because all the special cases of memory layout are handled. For > > > example you can have memory nodes with multiple 'reg' entries or > > > multiple memory nodes or both, and then some of those could be > > > contiguous. > > > > I need to have a memory node associated with the tag storage node because > > there is a static relationship between a page from "normal" memory and its > > associated tag storage. If the code doesn't know that the memory region > > A..B has the corresponding tag storage in the region X..Y, then it doesn't > > know which tag storage to reserve when a page is allocated as tagged. > > > > In the example above, assuming that page P is allocated as tagged, the > > corresponding tag storage page that needs to be reserved is: > > > > tag_storage_pfn = (page_to_pfn(P) - PHYS_PFN(A)) / 32* + PHYS_PFN(X) > > > > numa-node-id is not enough for this, because as far I know you can have > > multiple memory regions withing the same numa node. > > Okay. Great, glad we are on the same page. Thanks, Alex 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 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 08BEBC4332F for ; Wed, 13 Dec 2023 13:05:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc: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=Gb7eBf37bI+3kZv0udRFKAE7SDS6bqceBTkj/XJF7CY=; b=x7g2htvnZ4kngD /PaX5/vSVOxH+leJepFyc+q7nzbqbnsVSivBW6KnDHTLxHycMw298gM8hPUk8rxCSg5mtA8ggR5/j dHXDlItkfLKp/VbCBSB0mPNHMPOftbf6X/4GaelMi8/eIaRBtBElDIK+uWSYLJXRUnOe3j0DTeyUF CbOm+4HtbFsO9OvnJC5aRveOifdp4mk/GBuI/YPmsl8IAjkOIIW7pVJYI7eCzJmMvhJ3/XEEmthfs DIriiHItySz3ZDSGbqQOyy0RzPVidGPfoRPB1lDiofZYprOtiYF5X72ciIofmziqI4oa2qC36ZAke wTP4bh9bApo2CG3I/7IA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rDOvM-00Ejof-09; Wed, 13 Dec 2023 13:05:16 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rDOvH-00EjmQ-2c for linux-arm-kernel@lists.infradead.org; Wed, 13 Dec 2023 13:05:14 +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 3DF5CC15; Wed, 13 Dec 2023 05:05:54 -0800 (PST) Received: from raptor (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1B5EB3F762; Wed, 13 Dec 2023 05:05:02 -0800 (PST) Date: Wed, 13 Dec 2023 13:04:56 +0000 From: Alexandru Elisei To: Rob Herring Cc: catalin.marinas@arm.com, will@kernel.org, oliver.upton@linux.dev, maz@kernel.org, james.morse@arm.com, suzuki.poulose@arm.com, yuzenghui@huawei.com, arnd@arndb.de, akpm@linux-foundation.org, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, mhiramat@kernel.org, rppt@kernel.org, hughd@google.com, pcc@google.com, steven.price@arm.com, anshuman.khandual@arm.com, vincenzo.frascino@arm.com, david@redhat.com, eugenis@google.com, kcc@google.com, hyesoo.yu@samsung.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org Subject: Re: [PATCH RFC v2 11/27] arm64: mte: Reserve tag storage memory Message-ID: References: <20231119165721.9849-1-alexandru.elisei@arm.com> <20231119165721.9849-12-alexandru.elisei@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231213_050511_947673_E04D13B9 X-CRM114-Status: GOOD ( 61.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 SGkgUm9iLAoKT24gVHVlLCBEZWMgMTIsIDIwMjMgYXQgMTI6NDQ6MDZQTSAtMDYwMCwgUm9iIEhl cnJpbmcgd3JvdGU6Cj4gT24gVHVlLCBEZWMgMTIsIDIwMjMgYXQgMTA6MzjigK9BTSBBbGV4YW5k cnUgRWxpc2VpCj4gPGFsZXhhbmRydS5lbGlzZWlAYXJtLmNvbT4gd3JvdGU6Cj4gPgo+ID4gSGkg Um9iLAo+ID4KPiA+IFRoYW5rIHlvdSBzbyBtdWNoIGZvciB0aGUgZmVlZGJhY2ssIEknbSBub3Qg dmVyeSBmYW1pbGlhciB3aXRoIGRldmljZSB0cmVlLAo+ID4gYW5kIGFueSBjb21tZW50cyBhcmUg dmVyeSB1c2VmdWwuCj4gPgo+ID4gT24gTW9uLCBEZWMgMTEsIDIwMjMgYXQgMTE6Mjk6NDBBTSAt MDYwMCwgUm9iIEhlcnJpbmcgd3JvdGU6Cj4gPiA+IE9uIFN1biwgTm92IDE5LCAyMDIzIGF0IDEw OjU54oCvQU0gQWxleGFuZHJ1IEVsaXNlaQo+ID4gPiA8YWxleGFuZHJ1LmVsaXNlaUBhcm0uY29t PiB3cm90ZToKPiA+ID4gPgo+ID4gPiA+IEFsbG93IHRoZSBrZXJuZWwgdG8gZ2V0IHRoZSBzaXpl IGFuZCBsb2NhdGlvbiBvZiB0aGUgTVRFIHRhZyBzdG9yYWdlCj4gPiA+ID4gcmVnaW9ucyBmcm9t IHRoZSBEVEIuIFRoaXMgbWVtb3J5IGlzIG1hcmtlZCBhcyByZXNlcnZlZCBmb3Igbm93Lgo+ID4g PiA+Cj4gPiA+ID4gVGhlIERUQiBub2RlIGZvciB0aGUgdGFnIHN0b3JhZ2UgcmVnaW9uIGlzIGRl ZmluZWQgYXM6Cj4gPiA+ID4KPiA+ID4gPiAgICAgICAgIHRhZ3MwOiB0YWctc3RvcmFnZUA4Zjgw MDAwMDAgewo+ID4gPiA+ICAgICAgICAgICAgICAgICBjb21wYXRpYmxlID0gImFybSxtdGUtdGFn LXN0b3JhZ2UiOwo+ID4gPiA+ICAgICAgICAgICAgICAgICByZWcgPSA8MHgwOCAweGY4MDAwMDAw IDB4MDAgMHg0MDAwMDAwPjsKPiA+ID4gPiAgICAgICAgICAgICAgICAgYmxvY2stc2l6ZSA9IDww eDEwMDA+Owo+ID4gPiA+ICAgICAgICAgICAgICAgICBtZW1vcnkgPSA8Jm1lbW9yeTA+OyAgICAv LyBBc3NvY2lhdGVkIHRhZ2dlZCBtZW1vcnkgbm9kZQo+ID4gPiA+ICAgICAgICAgfTsKPiA+ID4K PiA+ID4gSSBza2ltbWVkIHRocnUgdGhlIGRpc2N1c3Npb24gc29tZS4gSWYgdGhpcyBtZW1vcnkg cmFuZ2UgaXMgd2l0aGluCj4gPiA+IG1haW4gUkFNLCB0aGVuIGl0IGRlZmluaXRlbHkgYmVsb25n cyBpbiAvcmVzZXJ2ZWQtbWVtb3J5Lgo+ID4KPiA+IE9rLCB3aWxsIGRvIHRoYXQuCj4gPgo+ID4g SWYgeW91IGRvbid0IG1pbmQsIHdoeSBkbyB5b3Ugc2F5IHRoYXQgaXQgZGVmaW5pdGVseSBiZWxv bmdzIGluCj4gPiByZXNlcnZlZC1tZW1vcnk/IEknbSBub3QgdHJ5aW5nIHRvIGFyZ3VlIG90aGVy d2lzZSwgSSdtIGN1cmlvdXMgYWJvdXQgdGhlCj4gPiBtb3RpdmF0aW9uLgo+IAo+IFNpbXBseSBz byB0aGF0IC9tZW1vcnkgbm9kZXMgZGVzY3JpYmUgYWxsIHBvc3NpYmxlIG1lbW9yeSBhbmQKPiAv cmVzZXJ2ZWQtbWVtb3J5IGlzIGp1c3QgYWRkaW5nIHJlc3RyaWN0aW9ucy4gSXQncyBhbHNvIGJl Y2F1c2UKPiAvcmVzZXJ2ZWQtbWVtb3J5IGlzIHdoYXQgZ2V0cyBoYW5kbGVkIGVhcmx5LCBhbmQg d2UgZG9uJ3QgbmVlZAo+IG11bHRpcGxlIHRoaW5ncyB0byBoYW5kbGUgZWFybHkuCj4gCj4gPiBU YWcgc3RvcmFnZSBpcyBub3QgRE1BIGFuZCBjYW4gbGl2ZSBhbnl3aGVyZSBpbiBtZW1vcnkuCj4g Cj4gVGhlbiB3aHkgcHV0IGl0IGluIERUIGF0IGFsbD8gVGhlIG9ubHkgcmVhc29uIENNQSBpcyB0 aGVyZSBpcyB0byBzZXQKPiB0aGUgc2l6ZS4gSXQncyBub3QgZXZlbiBjbGVhciB0byBtZSB3ZSBu ZWVkIENNQSBpbiBEVCBlaXRoZXIuIFRoZQo+IHJlYXNvbmluZyBsb25nIGFnbyB3YXMgdGhlIGtl cm5lbCBkaWRuJ3QgZG8gYSBnb29kIGpvYiBvZiBtb3ZpbmcgYW5kCj4gcmVjbGFpbWluZyBjb250 aWd1b3VzIHNwYWNlLCBidXQgdGhhdCdzIHN1cHBvc2VkIHRvIGJlIGJldHRlciBub3cgKGFuZAo+ IG1vc3QgaC93IGZpZ3VyZWQgb3V0IHRoZXkgbmVlZCBJT01NVXMpLgo+IAo+IEJ1dCBmb3IgdGFn IHN0b3JhZ2UgeW91IGtub3cgdGhlIHNpemUgYXMgaXQgaXMgYSBmdW5jdGlvbiBvZiB0aGUKPiBt ZW1vcnkgc2l6ZSwgcmlnaHQ/IEFmdGVyIGFsbCwgeW91IGFyZSB2YWxpZGF0aW5nIHRoZSBzaXpl IGlzIGNvcnJlY3QuCj4gSSBndWVzcyB0aGVyZSBpcyBzdGlsbCB0aGUgYXNwZWN0IG9mIHdoZXRo ZXIgeW91IHdhbnQgZW5hYmxlIE1URSBvcgo+IG5vdCB3aGljaCBjb3VsZCBiZSBkb25lIGluIGEg dmFyaWV0eSBvZiB3YXlzLgoKT2gsIHNvcnJ5LCBteSBiYWQsIEkgc2hvdWxkIGhhdmUgYmVlbiBj bGVhcmVyIGFib3V0IHRoaXMuIEkgZG9uJ3Qgd2FudCB0bwpwdXQgaXQgaW4gdGhlIERUIGFzIGEg ImxpbnV4LGNtYSIgbm9kZS4gQnV0IEkgd2FudCBpdCB0byBiZSBtYW5hZ2VkIGJ5IENNQS4KCj4g Cj4gPiBJbgo+ID4gYXJtNjRfbWVtYmxvY2tfaW5pdCgpLCB0aGUga2VybmVsIGZpcnN0IHJlbW92 ZXMgdGhlIG1lbW9yeSB0aGF0IGl0IGNhbm5vdAo+ID4gYWRkcmVzcyBmcm9tIG1lbWJsb2NrLiBG b3IgZXhhbXBsZSwgYmVjYXVzZSBpdCBoYXMgYmVlbiBjb21waWxlZCB3aXRoCj4gPiBDT05GSUdf QVJNNjRfVkFfQklUU18zOT15LiBBbmQgdGhlbiBjYWxscwo+ID4gZWFybHlfaW5pdF9mZHRfc2Nh bl9yZXNlcnZlZF9tZW0oKS4KPiA+Cj4gPiBXaGF0IGhhcHBlbnMgaWYgcmVzZXJ2ZWQgbWVtb3J5 IGlzIGFib3ZlIHdoYXQgdGhlIGtlcm5lbCBjYW4gYWRkcmVzcz8KPiAKPiBJIHdvdWxkIGhvcGUg dGhlIGtlcm5lbCBoYW5kbGVzIGl0LiBUaGF0J3MgdGhlIGtlcm5lbCdzIHByb2JsZW0gdW5sZXNz Cj4gdGhlcmUncyBzb21lIGgvdyBsaW1pdGF0aW9uIHRvIGFjY2VzcyBzb21lIHJlZ2lvbi4gVGhl IERUIGNhbid0IGhhdmUKPiB0aGluZ3MgZGVwZW5kZW50IG9uIHRoZSBrZXJuZWwgY29uZmlnLgoK SSB3b3VsZCBob3BlIHNvIHRvbywgdGhhdCdzIHdoeSBJIHdhcyBzdXJwcmlzZWQgd2hlbiBJIHB1 dCByZXNlcnZlZCBtZW1vcnkKYXQgMVRCIGluIGEgMzkgYml0IFZBIGtlcm5lbCBhbmQgZ290IGEg cGFuaWMuCgo+IAo+ID4gRnJvbSBteSB0ZXN0aW5nLCB3aGVuIHRoZSBrZXJuZWwgaXMgY29tcGls ZWQgd2l0aCAzOSBiaXQgVkEsIGlmIEkgdXNlCj4gPiByZXNlcnZlZCBtZW1vcnkgdG8gZGlzY292 ZXIgdGFnIHN0b3JhZ2UgdGhlIGxpdmVzIGFib3ZlIHRoZSB2aXJ0dWEgYWRkcmVzcwo+ID4gbGlt aXQgYW5kIHRoZW4gSSB0cnkgdG8gdXNlIENNQSB0byBtYW5hZ2UgdGhlIHRhZyBzdG9yYWdlIG1l bW9yeSwgSSBnZXQgYQo+ID4ga2VybmVsIHBhbmljOgo+IAo+IExvb2tzIGxpa2Ugd2Ugc2hvdWxk IGhhbmRsZSB0aGF0IGJldHRlci4uLgoKSSBndWVzcyB3ZSBkb24ndCBuZWVkIHRvIHRhY2tsZSB0 aGF0IHByb2JsZW0gcmlnaHQgbm93LiBJIGRvbid0IGtub3cgb2YKbWFueSBzeXN0ZW1zIGluIHRo ZSB3aWxkIHRoYXQgaGF2ZSBtZW1vcnkgYWJvdmUgdGhlIDFUQiBhZGRyZXNzLgoKPiAKPiA+PiBb ICAgIDAuMDAwMDAwXSBSZXNlcnZlZCBtZW1vcnk6IGNyZWF0ZWQgQ01BIG1lbW9yeSBwb29sIGF0 IDB4MDAwMDAxMDAwMDAwMDAwMCwgc2l6ZSA2NCBNaUIKPiA+IFsgICAgMC4wMDAwMDBdIE9GOiBy ZXNlcnZlZCBtZW06IGluaXRpYWxpemVkIG5vZGUgbGludXgsY21hLCBjb21wYXRpYmxlIGlkIHNo YXJlZC1kbWEtcG9vbAo+ID4gWyAgICAwLjAwMDAwMF0gT0Y6IHJlc2VydmVkIG1lbTogMHgwMDAw MDEwMDAwMDAwMDAwLi4weDAwMDAwMTAwMDNmZmZmZmYgKDY1NTM2IEtpQikgbWFwIHJldXNhYmxl IGxpbnV4LGNtYQo+ID4gWy4uXQo+ID4gWyAgICAwLjgwNjk0NV0gVW5hYmxlIHRvIGhhbmRsZSBr ZXJuZWwgcGFnaW5nIHJlcXVlc3QgYXQgdmlydHVhbCBhZGRyZXNzIDAwMDAwMDAxZmUwMDAwMDAK PiA+IFsgICAgMC44MDcyNzddIE1lbSBhYm9ydCBpbmZvOgo+ID4gWyAgICAwLjgwNzI3N10gICBF U1IgPSAweDAwMDAwMDAwOTYwMDAwMDUKPiA+IFsgICAgMC44MDc2OTNdICAgRUMgPSAweDI1OiBE QUJUIChjdXJyZW50IEVMKSwgSUwgPSAzMiBiaXRzCj4gPiBbICAgIDAuODA4MTEwXSAgIFNFVCA9 IDAsIEZuViA9IDAKPiA+IFsgICAgMC44MDg0NDNdICAgRUEgPSAwLCBTMVBUVyA9IDAKPiA+IFsg ICAgMC44MDg1MjZdICAgRlNDID0gMHgwNTogbGV2ZWwgMSB0cmFuc2xhdGlvbiBmYXVsdAo+ID4g WyAgICAwLjgwODk0M10gRGF0YSBhYm9ydCBpbmZvOgo+ID4gWyAgICAwLjgwODk0M10gICBJU1Yg PSAwLCBJU1MgPSAweDAwMDAwMDA1LCBJU1MyID0gMHgwMDAwMDAwMAo+ID4gWyAgICAwLjgwOTM2 MF0gICBDTSA9IDAsIFduUiA9IDAsIFRuRCA9IDAsIFRhZ0FjY2VzcyA9IDAKPiA+IFsgICAgMC44 MDk3NzZdICAgR0NTID0gMCwgT3ZlcmxheSA9IDAsIERpcnR5Qml0ID0gMCwgWHMgPSAwCj4gPiBb ICAgIDAuODEwMjIxXSBbMDAwMDAwMDFmZTAwMDAwMF0gdXNlciBhZGRyZXNzIGJ1dCBhY3RpdmVf bW0gaXMgc3dhcHBlcgo+ID4gWy4uXQo+ID4gWyAgICAwLjgyMDg4N10gQ2FsbCB0cmFjZToKPiA+ IFsgICAgMC44MjEwMjddICBjbWFfaW5pdF9yZXNlcnZlZF9hcmVhcysweGM0LzB4Mzc4Cj4gPgo+ ID4gPgo+ID4gPiBZb3UgbmVlZCBhIGJpbmRpbmcgZm9yIHRoaXMgdG9vLgo+ID4KPiA+IEJ5IGJp bmRpbmcgeW91IG1lYW4gaGF2aW5nIGFuIHlhbWwgZmlsZSBpbiBkdC1zY2hlbSBbMV0gZGVzY3Jp YmluZyB0aGUgdGFnCj4gPiBzdG9yYWdlIG5vZGUsIHJpZ2h0Pwo+IAo+IFllcywgYnV0IGluIHRo ZSBrZXJuZWwgdHJlZSBpcyBmaW5lLgoKQ29vbCwgdGhhbmtzLgoKPiAKPiBbLi4uXQo+IAo+ID4g PiA+ICtzdGF0aWMgaW50IF9faW5pdCB0YWdfc3RvcmFnZV9vZl9mbGF0X2dldF9yYW5nZSh1bnNp Z25lZCBsb25nIG5vZGUsIGNvbnN0IF9fYmUzMiAqcmVnLAo+ID4gPiA+ICsgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCByZWdfbGVuLCBzdHJ1Y3QgcmFu Z2UgKnJhbmdlKQo+ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBpbnQgYWRkcl9jZWxscyA9IGR0 X3Jvb3RfYWRkcl9jZWxsczsKPiA+ID4gPiArICAgICAgIGludCBzaXplX2NlbGxzID0gZHRfcm9v dF9zaXplX2NlbGxzOwo+ID4gPiA+ICsgICAgICAgdTY0IHNpemU7Cj4gPiA+ID4gKwo+ID4gPiA+ ICsgICAgICAgaWYgKHJlZ19sZW4gLyA0ID4gYWRkcl9jZWxscyArIHNpemVfY2VsbHMpCj4gPiA+ ID4gKyAgICAgICAgICAgICAgIHJldHVybiAtRUlOVkFMOwo+ID4gPiA+ICsKPiA+ID4gPiArICAg ICAgIHJhbmdlLT5zdGFydCA9IFBIWVNfUEZOKG9mX3JlYWRfbnVtYmVyKHJlZywgYWRkcl9jZWxs cykpOwo+ID4gPiA+ICsgICAgICAgc2l6ZSA9IFBIWVNfUEZOKG9mX3JlYWRfbnVtYmVyKHJlZyAr IGFkZHJfY2VsbHMsIHNpemVfY2VsbHMpKTsKPiA+ID4gPiArICAgICAgIGlmIChzaXplID09IDAp IHsKPiA+ID4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJJbnZhbGlkIG5vZGUiKTsKPiA+ID4g PiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiA+ID4gKyAgICAgICB9Cj4gPiA+ ID4gKyAgICAgICByYW5nZS0+ZW5kID0gcmFuZ2UtPnN0YXJ0ICsgc2l6ZSAtIDE7Cj4gPiA+Cj4g PiA+IFdlIGhhdmUgYSBmdW5jdGlvbiB0byByZWFkIChhbmQgdHJhbnNsYXRlIHdoaWNoIHlvdSBm b3Jnb3QpIGFkZHJlc3Nlcy4KPiA+ID4gQWRkIHdoYXQncyBtaXNzaW5nIHJhdGhlciB0aGFuIG9w ZW4gY29kZSB5b3VyIG93bi4KPiA+Cj4gPiBJIG11c3QgaGF2ZSBtaXNzZWQgdGhhdCB0aGVyZSdz IGFscmVhZHkgYSBmdW5jdGlvbiB0byByZWFkIGFkZHJlc3Nlcy4gV291bGQKPiA+IHlvdSBtaW5k IHBvaW50aW5nIG1lIGluIHRoZSByaWdodCBkaXJlY3Rpb24/Cj4gCj4gZHJpdmVycy9vZi9mZHRf YWRkcmVzcy5jCj4gCj4gVGhvdWdoIGl0IGRvZXNuJ3QgcHJvdmlkZSBnZXR0aW5nIHRoZSBzaXpl LCBzbyB0aGF0IHdpbGwgaGF2ZSB0byBiZSBhZGRlZC4KCk9rLCB3aWxsIGRvIQoKPiAKPiAKPiA+ ID4gPiArCj4gPiA+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ID4gPiArfQo+ID4gPiA+ICsKPiA+ ID4gPiArc3RhdGljIGludCBfX2luaXQgdGFnX3N0b3JhZ2Vfb2ZfZmxhdF9nZXRfdGFnX3Jhbmdl KHVuc2lnbmVkIGxvbmcgbm9kZSwKPiA+ID4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHJhbmdlICp0YWdfcmFuZ2UpCj4gPiA+ID4g K3sKPiA+ID4gPiArICAgICAgIGNvbnN0IF9fYmUzMiAqcmVnOwo+ID4gPiA+ICsgICAgICAgaW50 IHJlZ19sZW47Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAgcmVnID0gb2ZfZ2V0X2ZsYXRfZHRf cHJvcChub2RlLCAicmVnIiwgJnJlZ19sZW4pOwo+ID4gPiA+ICsgICAgICAgaWYgKHJlZyA9PSBO VUxMKSB7Cj4gPiA+ID4gKyAgICAgICAgICAgICAgIHByX2VycigiSW52YWxpZCBtZXRhZGF0YSBu b2RlIik7Cj4gPiA+ID4gKyAgICAgICAgICAgICAgIHJldHVybiAtRUlOVkFMOwo+ID4gPiA+ICsg ICAgICAgfQo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIHJldHVybiB0YWdfc3RvcmFnZV9vZl9m bGF0X2dldF9yYW5nZShub2RlLCByZWcsIHJlZ19sZW4sIHRhZ19yYW5nZSk7Cj4gPiA+ID4gK30K PiA+ID4gPiArCj4gPiA+ID4gK3N0YXRpYyBpbnQgX19pbml0IHRhZ19zdG9yYWdlX29mX2ZsYXRf Z2V0X21lbW9yeV9yYW5nZSh1bnNpZ25lZCBsb25nIG5vZGUsIHN0cnVjdCByYW5nZSAqbWVtKQo+ ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBjb25zdCBfX2JlMzIgKnJlZzsKPiA+ID4gPiArICAg ICAgIGludCByZWdfbGVuOwo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIHJlZyA9IG9mX2dldF9m bGF0X2R0X3Byb3Aobm9kZSwgImxpbnV4LHVzYWJsZS1tZW1vcnkiLCAmcmVnX2xlbik7Cj4gPiA+ ID4gKyAgICAgICBpZiAocmVnID09IE5VTEwpCj4gPiA+ID4gKyAgICAgICAgICAgICAgIHJlZyA9 IG9mX2dldF9mbGF0X2R0X3Byb3Aobm9kZSwgInJlZyIsICZyZWdfbGVuKTsKPiA+ID4gPiArCj4g PiA+ID4gKyAgICAgICBpZiAocmVnID09IE5VTEwpIHsKPiA+ID4gPiArICAgICAgICAgICAgICAg cHJfZXJyKCJJbnZhbGlkIG1lbW9yeSBub2RlIik7Cj4gPiA+ID4gKyAgICAgICAgICAgICAgIHJl dHVybiAtRUlOVkFMOwo+ID4gPiA+ICsgICAgICAgfQo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAg IHJldHVybiB0YWdfc3RvcmFnZV9vZl9mbGF0X2dldF9yYW5nZShub2RlLCByZWcsIHJlZ19sZW4s IG1lbSk7Cj4gPiA+ID4gK30KPiA+ID4gPiArCj4gPiA+ID4gK3N0cnVjdCBmaW5kX21lbW9yeV9u b2RlX2FyZyB7Cj4gPiA+ID4gKyAgICAgICB1bnNpZ25lZCBsb25nIG5vZGU7Cj4gPiA+ID4gKyAg ICAgICB1MzIgcGhhbmRsZTsKPiA+ID4gPiArfTsKPiA+ID4gPiArCj4gPiA+ID4gK3N0YXRpYyBp bnQgX19pbml0IGZkdF9maW5kX21lbW9yeV9ub2RlKHVuc2lnbmVkIGxvbmcgbm9kZSwgY29uc3Qg Y2hhciAqdW5hbWUsCj4gPiA+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgaW50IGRlcHRoLCB2b2lkICpkYXRhKQo+ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBjb25z dCBjaGFyICp0eXBlID0gb2ZfZ2V0X2ZsYXRfZHRfcHJvcChub2RlLCAiZGV2aWNlX3R5cGUiLCBO VUxMKTsKPiA+ID4gPiArICAgICAgIHN0cnVjdCBmaW5kX21lbW9yeV9ub2RlX2FyZyAqYXJnID0g ZGF0YTsKPiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICBpZiAoZGVwdGggIT0gMSB8fCAhdHlwZSB8 fCBzdHJjbXAodHlwZSwgIm1lbW9yeSIpICE9IDApCj4gPiA+ID4gKyAgICAgICAgICAgICAgIHJl dHVybiAwOwo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIGlmIChvZl9nZXRfZmxhdF9kdF9waGFu ZGxlKG5vZGUpID09IGFyZy0+cGhhbmRsZSkgewo+ID4gPiA+ICsgICAgICAgICAgICAgICBhcmct Pm5vZGUgPSBub2RlOwo+ID4gPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gMTsKPiA+ID4gPiAr ICAgICAgIH0KPiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ID4gPiArfQo+ ID4gPiA+ICsKPiA+ID4gPiArc3RhdGljIGludCBfX2luaXQgdGFnX3N0b3JhZ2VfZ2V0X21lbW9y eV9ub2RlKHVuc2lnbmVkIGxvbmcgdGFnX25vZGUsIHVuc2lnbmVkIGxvbmcgKm1lbV9ub2RlKQo+ ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBzdHJ1Y3QgZmluZF9tZW1vcnlfbm9kZV9hcmcgYXJn ID0geyAwIH07Cj4gPiA+ID4gKyAgICAgICBjb25zdCBfX2JlMzIgKm1lbW9yeV9wcm9wOwo+ID4g PiA+ICsgICAgICAgdTMyIG1lbV9waGFuZGxlOwo+ID4gPiA+ICsgICAgICAgaW50IHJldCwgcmVn X2xlbjsKPiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICBtZW1vcnlfcHJvcCA9IG9mX2dldF9mbGF0 X2R0X3Byb3AodGFnX25vZGUsICJtZW1vcnkiLCAmcmVnX2xlbik7Cj4gPiA+ID4gKyAgICAgICBp ZiAoIW1lbW9yeV9wcm9wKSB7Cj4gPiA+ID4gKyAgICAgICAgICAgICAgIHByX2VycigiTWlzc2lu ZyAnbWVtb3J5JyBwcm9wZXJ0eSBpbiB0aGUgdGFnIHN0b3JhZ2Ugbm9kZSIpOwo+ID4gPiA+ICsg ICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ID4gPiArICAgICAgIH0KPiA+ID4gPiAr Cj4gPiA+ID4gKyAgICAgICBtZW1fcGhhbmRsZSA9IGJlMzJfdG9fY3B1cChtZW1vcnlfcHJvcCk7 Cj4gPiA+ID4gKyAgICAgICBhcmcucGhhbmRsZSA9IG1lbV9waGFuZGxlOwo+ID4gPiA+ICsKPiA+ ID4gPiArICAgICAgIHJldCA9IG9mX3NjYW5fZmxhdF9kdChmZHRfZmluZF9tZW1vcnlfbm9kZSwg JmFyZyk7Cj4gPiA+Cj4gPiA+IERvIG5vdCB1c2Ugb2Zfc2Nhbl9mbGF0X2R0LiBJdCBpcyBhIHJl bGljIHByZWRhdGluZyBsaWJmZHQgd2hpY2ggY2FuCj4gPiA+IGdldCBhIG5vZGUgYnkgcGhhbmRs ZSBkaXJlY3RseS4KPiA+Cj4gPiBJIHVzZWQgdGhhdCBiZWNhdXNlIHRoYXQncyB3aGF0IGRyaXZl cnMvb2YvZmR0LmMgdXNlcy4gV2l0aCByZXNlcnZlZCBtZW1vcnkKPiA+IEkgc2hvdWxkbid0IG5l ZWQgaXQsIGJlY2F1c2Ugc3RydWN0IHJlc2VydmVkX21lbSBhbHJlYWR5IGluY2x1ZGVzIGEKPiA+ IHBoYW5kbGUuCj4gCj4gQ2hlY2sgYWdhaW4uIE9ubHkgc29tZSBhcmNoLyBjb2RlIChtb3N0bHkg cG93ZXJwYykgdXNlcyBpdC4gSSd2ZQo+IGtpbGxlZCBvZmYgbW9zdCBvZiBpdC4KCllvdSdyZSBy aWdodCwgSSB0aGluayBJIGdyZXAnZWQgZm9yIGEgZGlmZmVyZW50IGZ1bmN0aW9uIG5hbWUgaW4K ZHJpdmVycy9vZi9mZHQuYyBFaXRoZXIgd2F5LCB0aGUgbWVzc2FnZSBpcyBjbGVhcjogbm8gb2Zf c2Nhbl9mbGF0X2R0KCkuCgo+IAo+IAo+ID4gPiA+ICsgICAgICAgaWYgKHJldCAhPSAxKSB7Cj4g PiA+ID4gKyAgICAgICAgICAgICAgIHByX2VycigiQXNzb2NpYXRlZCBtZW1vcnkgbm9kZSBub3Qg Zm91bmQiKTsKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiA+ID4g KyAgICAgICB9Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAgKm1lbV9ub2RlID0gYXJnLm5vZGU7 Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAgcmV0dXJuIDA7Cj4gPiA+ID4gK30KPiA+ID4gPiAr Cj4gPiA+ID4gK3N0YXRpYyBpbnQgX19pbml0IHRhZ19zdG9yYWdlX29mX2ZsYXRfcmVhZF91MzIo dW5zaWduZWQgbG9uZyBub2RlLCBjb25zdCBjaGFyICpwcm9wbmFtZSwKPiA+ID4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHUzMiAqcmV0dmFsKQo+ID4g Pgo+ID4gPiBJZiB5b3UgYXJlIGdvaW5nIHRvIG1ha2UgYSBnZW5lcmljIGZ1bmN0aW9uLCBtYWtl IGl0IGZvciBldmVyeW9uZS4KPiA+Cj4gPiBTdXJlLiBJZiBJIHN0aWxsIG5lZWQgaXQsIHNob3Vs ZCBJIHB1dCB0aGUgZnVuY3Rpb24gaW4KPiA+IGluY2x1ZGUvbGludXgvb2ZfZmR0Lmg/Cj4gCj4g WWVzLgoKTm90ZWQuCgo+IAo+ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBjb25zdCBfX2JlMzIg KnJlZzsKPiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICByZWcgPSBvZl9nZXRfZmxhdF9kdF9wcm9w KG5vZGUsIHByb3BuYW1lLCBOVUxMKTsKPiA+ID4gPiArICAgICAgIGlmICghcmVnKQo+ID4gPiA+ ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ID4gPiArCj4gPiA+ID4gKyAgICAg ICAqcmV0dmFsID0gYmUzMl90b19jcHVwKHJlZyk7Cj4gPiA+ID4gKyAgICAgICByZXR1cm4gMDsK PiA+ID4gPiArfQo+ID4gPiA+ICsKPiA+ID4gPiArc3RhdGljIHUzMiBfX2luaXQgZ2V0X2Jsb2Nr X3NpemVfcGFnZXModTMyIGJsb2NrX3NpemVfYnl0ZXMpCj4gPiA+ID4gK3sKPiA+ID4gPiArICAg ICAgIHUzMiBhID0gUEFHRV9TSVpFOwo+ID4gPiA+ICsgICAgICAgdTMyIGIgPSBibG9ja19zaXpl X2J5dGVzOwo+ID4gPiA+ICsgICAgICAgdTMyIHI7Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAg LyogRmluZCBncmVhdGVzdCBjb21tb24gZGl2aXNvciB1c2luZyB0aGUgRXVjbGlkaWFuIGFsZ29y aXRobS4gKi8KPiA+ID4gPiArICAgICAgIGRvIHsKPiA+ID4gPiArICAgICAgICAgICAgICAgciA9 IGEgJSBiOwo+ID4gPiA+ICsgICAgICAgICAgICAgICBhID0gYjsKPiA+ID4gPiArICAgICAgICAg ICAgICAgYiA9IHI7Cj4gPiA+ID4gKyAgICAgICB9IHdoaWxlIChiICE9IDApOwo+ID4gPiA+ICsK PiA+ID4gPiArICAgICAgIHJldHVybiBQSFlTX1BGTihQQUdFX1NJWkUgKiBibG9ja19zaXplX2J5 dGVzIC8gYSk7Cj4gPiA+ID4gK30KPiA+ID4gPiArCj4gPiA+ID4gK3N0YXRpYyBpbnQgX19pbml0 IGZkdF9pbml0X3RhZ19zdG9yYWdlKHVuc2lnbmVkIGxvbmcgbm9kZSwgY29uc3QgY2hhciAqdW5h bWUsCj4gPiA+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IGRl cHRoLCB2b2lkICpkYXRhKQo+ID4gPiA+ICt7Cj4gPiA+ID4gKyAgICAgICBzdHJ1Y3QgdGFnX3Jl Z2lvbiAqcmVnaW9uOwo+ID4gPiA+ICsgICAgICAgdW5zaWduZWQgbG9uZyBtZW1fbm9kZTsKPiA+ ID4gPiArICAgICAgIHN0cnVjdCByYW5nZSAqbWVtX3JhbmdlOwo+ID4gPiA+ICsgICAgICAgc3Ry dWN0IHJhbmdlICp0YWdfcmFuZ2U7Cj4gPiA+ID4gKyAgICAgICB1MzIgYmxvY2tfc2l6ZV9ieXRl czsKPiA+ID4gPiArICAgICAgIHUzMiBuaWQgPSAwOwo+ID4gPiA+ICsgICAgICAgaW50IHJldDsK PiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICBpZiAoZGVwdGggIT0gMSB8fCAhc3Ryc3RyKHVuYW1l LCAidGFnLXN0b3JhZ2UiKSkKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIDA7Cj4gPiA+ ID4gKwo+ID4gPiA+ICsgICAgICAgaWYgKCFvZl9mbGF0X2R0X2lzX2NvbXBhdGlibGUobm9kZSwg ImFybSxtdGUtdGFnLXN0b3JhZ2UiKSkKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIDA7 Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAgaWYgKG51bV90YWdfcmVnaW9ucyA9PSBNQVhfVEFH X1JFR0lPTlMpIHsKPiA+ID4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJNYXhpbXVtIG51bWJl ciBvZiB0YWcgc3RvcmFnZSByZWdpb25zIGV4Y2VlZGVkIik7Cj4gPiA+ID4gKyAgICAgICAgICAg ICAgIHJldHVybiAtRUlOVkFMOwo+ID4gPiA+ICsgICAgICAgfQo+ID4gPiA+ICsKPiA+ID4gPiAr ICAgICAgIHJlZ2lvbiA9ICZ0YWdfcmVnaW9uc1tudW1fdGFnX3JlZ2lvbnNdOwo+ID4gPiA+ICsg ICAgICAgbWVtX3JhbmdlID0gJnJlZ2lvbi0+bWVtX3JhbmdlOwo+ID4gPiA+ICsgICAgICAgdGFn X3JhbmdlID0gJnJlZ2lvbi0+dGFnX3JhbmdlOwo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIHJl dCA9IHRhZ19zdG9yYWdlX29mX2ZsYXRfZ2V0X3RhZ19yYW5nZShub2RlLCB0YWdfcmFuZ2UpOwo+ ID4gPiA+ICsgICAgICAgaWYgKHJldCkgewo+ID4gPiA+ICsgICAgICAgICAgICAgICBwcl9lcnIo IkludmFsaWQgdGFnIHN0b3JhZ2Ugbm9kZSIpOwo+ID4gPiA+ICsgICAgICAgICAgICAgICByZXR1 cm4gcmV0Owo+ID4gPiA+ICsgICAgICAgfQo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIHJldCA9 IHRhZ19zdG9yYWdlX2dldF9tZW1vcnlfbm9kZShub2RlLCAmbWVtX25vZGUpOwo+ID4gPiA+ICsg ICAgICAgaWYgKHJldCkKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiA+ID4g PiArCj4gPiA+ID4gKyAgICAgICByZXQgPSB0YWdfc3RvcmFnZV9vZl9mbGF0X2dldF9tZW1vcnlf cmFuZ2UobWVtX25vZGUsIG1lbV9yYW5nZSk7Cj4gPiA+ID4gKyAgICAgICBpZiAocmV0KSB7Cj4g PiA+ID4gKyAgICAgICAgICAgICAgIHByX2VycigiSW52YWxpZCBhZGRyZXNzIGZvciBhc3NvY2lh dGVkIGRhdGEgbWVtb3J5IG5vZGUiKTsKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIHJl dDsKPiA+ID4gPiArICAgICAgIH0KPiA+ID4gPiArCj4gPiA+ID4gKyAgICAgICAvKiBUaGUgdGFn IHJlZ2lvbiBtdXN0IGV4YWN0bHkgbWF0Y2ggdGhlIGNvcnJlc3BvbmRpbmcgbWVtb3J5LiAqLwo+ ID4gPiA+ICsgICAgICAgaWYgKHJhbmdlX2xlbih0YWdfcmFuZ2UpICogMzIgIT0gcmFuZ2VfbGVu KG1lbV9yYW5nZSkpIHsKPiA+ID4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJUYWcgc3RvcmFn ZSByZWdpb24gMHglbGx4LTB4JWxseCBkb2VzIG5vdCBjb3ZlciB0aGUgbWVtb3J5IHJlZ2lvbiAw eCVsbHgtMHglbGx4IiwKPiA+ID4gPiArICAgICAgICAgICAgICAgICAgICAgIFBGTl9QSFlTKHRh Z19yYW5nZS0+c3RhcnQpLCBQRk5fUEhZUyh0YWdfcmFuZ2UtPmVuZCksCj4gPiA+ID4gKyAgICAg ICAgICAgICAgICAgICAgICBQRk5fUEhZUyhtZW1fcmFuZ2UtPnN0YXJ0KSwgUEZOX1BIWVMobWVt X3JhbmdlLT5lbmQpKTsKPiA+ID4gPiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4g PiA+ID4gKyAgICAgICB9Cj4gPiA+ID4gKwo+ID4gPiA+ICsgICAgICAgcmV0ID0gdGFnX3N0b3Jh Z2Vfb2ZfZmxhdF9yZWFkX3UzMihub2RlLCAiYmxvY2stc2l6ZSIsICZibG9ja19zaXplX2J5dGVz KTsKPiA+ID4gPiArICAgICAgIGlmIChyZXQgfHwgYmxvY2tfc2l6ZV9ieXRlcyA9PSAwKSB7Cj4g PiA+ID4gKyAgICAgICAgICAgICAgIHByX2VycigiSW52YWxpZCBvciBtaXNzaW5nICdibG9jay1z aXplJyBwcm9wZXJ0eSIpOwo+ID4gPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsK PiA+ID4gPiArICAgICAgIH0KPiA+ID4gPiArICAgICAgIHJlZ2lvbi0+YmxvY2tfc2l6ZSA9IGdl dF9ibG9ja19zaXplX3BhZ2VzKGJsb2NrX3NpemVfYnl0ZXMpOwo+ID4gPiA+ICsgICAgICAgaWYg KHJhbmdlX2xlbih0YWdfcmFuZ2UpICUgcmVnaW9uLT5ibG9ja19zaXplICE9IDApIHsKPiA+ID4g PiArICAgICAgICAgICAgICAgcHJfZXJyKCJUYWcgc3RvcmFnZSByZWdpb24gc2l6ZSAweCVsbHgg aXMgbm90IGEgbXVsdGlwbGUgb2YgYmxvY2sgc2l6ZSAldSIsCj4gPiA+ID4gKyAgICAgICAgICAg ICAgICAgICAgICBQRk5fUEhZUyhyYW5nZV9sZW4odGFnX3JhbmdlKSksIHJlZ2lvbi0+YmxvY2tf c2l6ZSk7Cj4gPiA+ID4gKyAgICAgICAgICAgICAgIHJldHVybiAtRUlOVkFMOwo+ID4gPiA+ICsg ICAgICAgfQo+ID4gPiA+ICsKPiA+ID4gPiArICAgICAgIHJldCA9IHRhZ19zdG9yYWdlX29mX2Zs YXRfcmVhZF91MzIobWVtX25vZGUsICJudW1hLW5vZGUtaWQiLCAmbmlkKTsKPiA+ID4KPiA+ID4g SSB3YXMgZ29pbmcgdG8gc2F5IHdlIGFscmVhZHkgaGF2ZSBhIHdheSB0byBhc3NvY2lhdGUgbWVt b3J5IG5vZGVzCj4gPiA+IG90aGVyIG5vZGVzIHVzaW5nICJudW1hLW5vZGUtaWQiLCBzbyB0aGUg Im1lbW9yeSIgcGhhbmRsZSBwcm9wZXJ0eSBpcwo+ID4gPiBzb21ld2hhdCByZWR1bmRhbnQuIE1h eWJlIHRoZSB0YWcgbm9kZSBzaG91bGQgaGF2ZSBhIG51bWEtbm9kZS1pZC4KPiA+ID4gV2l0aCB0 aGF0LCBpdCBsb29rcyBsaWtlIHlvdSBkb24ndCBldmVuIG5lZWQgdG8gYWNjZXNzIHRoZSAvbWVt b3J5Cj4gPiA+IG5vZGUuIEF2b2lkaW5nIHRoYXQgd291bGQgYmUgZ29vZCBmb3IgMiByZWFzb25z LiBJdCBhdm9pZHMgcGFyc2luZwo+ID4gPiBtZW1vcnkgbm9kZXMgdHdpY2UgYW5kIGl0J3Mgbm90 IHRoZSBrZXJuZWwncyBqb2IgdG8gdmFsaWRhdGUgdGhlIERULgo+ID4gPiBSZWFsbHksIGlmIHlv dSB3YW50IG1lbW9yeSBpbmZvLCB5b3Ugc2hvdWxkIHVzZSBtZW1ibG9jayB0byBnZXQgaXQKPiA+ ID4gYmVjYXVzZSBhbGwgdGhlIHNwZWNpYWwgY2FzZXMgb2YgbWVtb3J5IGxheW91dCBhcmUgaGFu ZGxlZC4gRm9yCj4gPiA+IGV4YW1wbGUgeW91IGNhbiBoYXZlIG1lbW9yeSBub2RlcyB3aXRoIG11 bHRpcGxlICdyZWcnIGVudHJpZXMgb3IKPiA+ID4gbXVsdGlwbGUgbWVtb3J5IG5vZGVzIG9yIGJv dGgsIGFuZCB0aGVuIHNvbWUgb2YgdGhvc2UgY291bGQgYmUKPiA+ID4gY29udGlndW91cy4KPiA+ Cj4gPiBJIG5lZWQgdG8gaGF2ZSBhIG1lbW9yeSBub2RlIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGFn IHN0b3JhZ2Ugbm9kZSBiZWNhdXNlCj4gPiB0aGVyZSBpcyBhIHN0YXRpYyByZWxhdGlvbnNoaXAg YmV0d2VlbiBhIHBhZ2UgZnJvbSAibm9ybWFsIiBtZW1vcnkgYW5kIGl0cwo+ID4gYXNzb2NpYXRl ZCB0YWcgc3RvcmFnZS4gSWYgdGhlIGNvZGUgZG9lc24ndCBrbm93IHRoYXQgdGhlIG1lbW9yeSBy ZWdpb24KPiA+IEEuLkIgaGFzIHRoZSBjb3JyZXNwb25kaW5nIHRhZyBzdG9yYWdlIGluIHRoZSBy ZWdpb24gWC4uWSwgdGhlbiBpdCBkb2Vzbid0Cj4gPiBrbm93IHdoaWNoIHRhZyBzdG9yYWdlIHRv IHJlc2VydmUgd2hlbiBhIHBhZ2UgaXMgYWxsb2NhdGVkIGFzIHRhZ2dlZC4KPiA+Cj4gPiBJbiB0 aGUgZXhhbXBsZSBhYm92ZSwgYXNzdW1pbmcgdGhhdCBwYWdlIFAgaXMgYWxsb2NhdGVkIGFzIHRh Z2dlZCwgdGhlCj4gPiBjb3JyZXNwb25kaW5nIHRhZyBzdG9yYWdlIHBhZ2UgdGhhdCBuZWVkcyB0 byBiZSByZXNlcnZlZCBpczoKPiA+Cj4gPiB0YWdfc3RvcmFnZV9wZm4gPSAocGFnZV90b19wZm4o UCkgLSBQSFlTX1BGTihBKSkgLyAzMiogKyBQSFlTX1BGTihYKQo+ID4KPiA+IG51bWEtbm9kZS1p ZCBpcyBub3QgZW5vdWdoIGZvciB0aGlzLCBiZWNhdXNlIGFzIGZhciBJIGtub3cgeW91IGNhbiBo YXZlCj4gPiBtdWx0aXBsZSBtZW1vcnkgcmVnaW9ucyB3aXRoaW5nIHRoZSBzYW1lIG51bWEgbm9k ZS4KPiAKPiBPa2F5LgoKR3JlYXQsIGdsYWQgd2UgYXJlIG9uIHRoZSBzYW1lIHBhZ2UuCgpUaGFu a3MsCkFsZXgKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f CmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5m cmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xp bnV4LWFybS1rZXJuZWwK