From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D64D48C04; Mon, 26 Jun 2023 12:23:41 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5889810E3; Mon, 26 Jun 2023 05:23:29 -0700 (PDT) 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 E14312F4; Mon, 26 Jun 2023 05:24:12 -0700 (PDT) Received: from FVFF77S0Q05N (unknown [10.57.23.38]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA5173F64C; Mon, 26 Jun 2023 05:23:22 -0700 (PDT) Date: Mon, 26 Jun 2023 13:23:17 +0100 From: Mark Rutland To: Puranjay Mohan Cc: Song Liu , Kent Overstreet , Mike Rapoport , Andy Lutomirski , Kees Cook , Linux Kernel Mailing List , Andrew Morton , Catalin Marinas , Christophe Leroy , "David S. Miller" , Dinh Nguyen , Heiko Carstens , Helge Deller , Huacai Chen , Luis Chamberlain , Michael Ellerman , Nadav Amit , "Naveen N. Rao" , Palmer Dabbelt , Rick P Edgecombe , "Russell King (Oracle)" , Steven Rostedt , Thomas Bogendoerfer , Thomas Gleixner , Will Deacon , bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, linux-mm@kvack.org, linux-modules@vger.kernel.org, linux-parisc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, loongarch@lists.linux.dev, netdev@vger.kernel.org, sparclinux@vger.kernel.org, the arch/x86 maintainers , pjt@google.com, torvalds@linux-foundation.org Subject: Re: [PATCH v2 02/12] mm: introduce execmem_text_alloc() and jit_text_alloc() Message-ID: References: <20230616085038.4121892-3-rppt@kernel.org> <20230618080027.GA52412@kernel.org> <20230625161417.GK52412@kernel.org> <90161ac9-3ca0-4c72-b1c4-ab1293e55445@app.fastmail.com> <20230625174257.GL52412@kernel.org> <20230625180741.jrrtkq55c4jrqh3t@moria.home.lan> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org 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: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net On Mon, Jun 26, 2023 at 11:54:02AM +0200, Puranjay Mohan wrote: > On Mon, Jun 26, 2023 at 8:13 AM Song Liu wrote: > > > > On Sun, Jun 25, 2023 at 11:07 AM Kent Overstreet > > wrote: > > > > > > On Sun, Jun 25, 2023 at 08:42:57PM +0300, Mike Rapoport wrote: > > > > On Sun, Jun 25, 2023 at 09:59:34AM -0700, Andy Lutomirski wrote: > > > > > > > > > > > > > > > On Sun, Jun 25, 2023, at 9:14 AM, Mike Rapoport wrote: > > > > > > On Mon, Jun 19, 2023 at 10:09:02AM -0700, Andy Lutomirski wrote: > > > > > >> > > > > > >> On Sun, Jun 18, 2023, at 1:00 AM, Mike Rapoport wrote: > > > > > >> > On Sat, Jun 17, 2023 at 01:38:29PM -0700, Andy Lutomirski wrote: > > > > > >> >> On Fri, Jun 16, 2023, at 1:50 AM, Mike Rapoport wrote: > > > > > >> >> > From: "Mike Rapoport (IBM)" > > > > > >> >> > > > > > > >> >> > module_alloc() is used everywhere as a mean to allocate memory for code. > > > > > >> >> > > > > > > >> >> > Beside being semantically wrong, this unnecessarily ties all subsystems > > > > > >> >> > that need to allocate code, such as ftrace, kprobes and BPF to modules > > > > > >> >> > and puts the burden of code allocation to the modules code. > > > > > >> >> > > > > > > >> >> > Several architectures override module_alloc() because of various > > > > > >> >> > constraints where the executable memory can be located and this causes > > > > > >> >> > additional obstacles for improvements of code allocation. > > > > > >> >> > > > > > > >> >> > Start splitting code allocation from modules by introducing > > > > > >> >> > execmem_text_alloc(), execmem_free(), jit_text_alloc(), jit_free() APIs. > > > > > >> >> > > > > > > >> >> > Initially, execmem_text_alloc() and jit_text_alloc() are wrappers for > > > > > >> >> > module_alloc() and execmem_free() and jit_free() are replacements of > > > > > >> >> > module_memfree() to allow updating all call sites to use the new APIs. > > > > > >> >> > > > > > > >> >> > The intention semantics for new allocation APIs: > > > > > >> >> > > > > > > >> >> > * execmem_text_alloc() should be used to allocate memory that must reside > > > > > >> >> > close to the kernel image, like loadable kernel modules and generated > > > > > >> >> > code that is restricted by relative addressing. > > > > > >> >> > > > > > > >> >> > * jit_text_alloc() should be used to allocate memory for generated code > > > > > >> >> > when there are no restrictions for the code placement. For > > > > > >> >> > architectures that require that any code is within certain distance > > > > > >> >> > from the kernel image, jit_text_alloc() will be essentially aliased to > > > > > >> >> > execmem_text_alloc(). > > > > > >> >> > > > > > > >> >> > > > > > >> >> Is there anything in this series to help users do the appropriate > > > > > >> >> synchronization when the actually populate the allocated memory with > > > > > >> >> code? See here, for example: > > > > > >> > > > > > > >> > This series only factors out the executable allocations from modules and > > > > > >> > puts them in a central place. > > > > > >> > Anything else would go on top after this lands. > > > > > >> > > > > > >> Hmm. > > > > > >> > > > > > >> On the one hand, there's nothing wrong with factoring out common code. On > > > > > >> the other hand, this is probably the right time to at least start > > > > > >> thinking about synchronization, at least to the extent that it might make > > > > > >> us want to change this API. (I'm not at all saying that this series > > > > > >> should require changes -- I'm just saying that this is a good time to > > > > > >> think about how this should work.) > > > > > >> > > > > > >> The current APIs, *and* the proposed jit_text_alloc() API, don't actually > > > > > >> look like the one think in the Linux ecosystem that actually > > > > > >> intelligently and efficiently maps new text into an address space: > > > > > >> mmap(). > > > > > >> > > > > > >> On x86, you can mmap() an existing file full of executable code PROT_EXEC > > > > > >> and jump to it with minimal synchronization (just the standard implicit > > > > > >> ordering in the kernel that populates the pages before setting up the > > > > > >> PTEs and whatever user synchronization is needed to avoid jumping into > > > > > >> the mapping before mmap() finishes). It works across CPUs, and the only > > > > > >> possible way userspace can screw it up (for a read-only mapping of > > > > > >> read-only text, anyway) is to jump to the mapping too early, in which > > > > > >> case userspace gets a page fault. Incoherence is impossible, and no one > > > > > >> needs to "serialize" (in the SDM sense). > > > > > >> > > > > > >> I think the same sequence (from userspace's perspective) works on other > > > > > >> architectures, too, although I think more cache management is needed on > > > > > >> the kernel's end. As far as I know, no Linux SMP architecture needs an > > > > > >> IPI to map executable text into usermode, but I could easily be wrong. > > > > > >> (IIRC RISC-V has very developer-unfriendly icache management, but I don't > > > > > >> remember the details.) > > > > > >> > > > > > >> Of course, using ptrace or any other FOLL_FORCE to modify text on x86 is > > > > > >> rather fraught, and I bet many things do it wrong when userspace is > > > > > >> multithreaded. But not in production because it's mostly not used in > > > > > >> production.) > > > > > >> > > > > > >> But jit_text_alloc() can't do this, because the order of operations > > > > > >> doesn't match. With jit_text_alloc(), the executable mapping shows up > > > > > >> before the text is populated, so there is no atomic change from not-there > > > > > >> to populated-and-executable. Which means that there is an opportunity > > > > > >> for CPUs, speculatively or otherwise, to start filling various caches > > > > > >> with intermediate states of the text, which means that various > > > > > >> architectures (even x86!) may need serialization. > > > > > >> > > > > > >> For eBPF- and module- like use cases, where JITting/code gen is quite > > > > > >> coarse-grained, perhaps something vaguely like: > > > > > >> > > > > > >> jit_text_alloc() -> returns a handle and an executable virtual address, > > > > > >> but does *not* map it there > > > > > >> jit_text_write() -> write to that handle > > > > > >> jit_text_map() -> map it and synchronize if needed (no sync needed on > > > > > >> x86, I think) > > > > > >> > > > > > >> could be more efficient and/or safer. > > > > > >> > > > > > >> (Modules could use this too. Getting alternatives right might take some > > > > > >> fiddling, because off the top of my head, this doesn't match how it works > > > > > >> now.) > > > > > >> > > > > > >> To make alternatives easier, this could work, maybe (haven't fully > > > > > >> thought it through): > > > > > >> > > > > > >> jit_text_alloc() > > > > > >> jit_text_map_rw_inplace() -> map at the target address, but RW, !X > > > > > >> > > > > > >> write the text and apply alternatives > > > > > >> > > > > > >> jit_text_finalize() -> change from RW to RX *and synchronize* > > > > > >> > > > > > >> jit_text_finalize() would either need to wait for RCU (possibly extra > > > > > >> heavy weight RCU to get "serialization") or send an IPI. > > > > > > > > > > > > This essentially how modules work now. The memory is allocated RW, written > > > > > > and updated with alternatives and then made ROX in the end with set_memory > > > > > > APIs. > > > > > > > > > > > > The issue with not having the memory mapped X when it's written is that we > > > > > > cannot use large pages to map it. One of the goals is to have executable > > > > > > memory mapped with large pages and make code allocator able to divide that > > > > > > page among several callers. > > > > > > > > > > > > So the idea was that jit_text_alloc() will have a cache of large pages > > > > > > mapped ROX, will allocate memory from those caches and there will be > > > > > > jit_update() that uses text poking for writing to that memory. > > > > > > > > > > > > Upon allocation of a large page to increase the cache, that large page will > > > > > > be "invalidated" by filling it with breakpoint instructions (e.g int3 on > > > > > > x86) > > > > > > > > > > Is this actually valid? In between int3 and real code, there’s a > > > > > potential torn read of real code mixed up with 0xcc. > > > > > > > > You mean while doing text poking? > > > > > > I think we've been getting distracted by text_poke(). text_poke() does > > > updates via a different virtual address which introduce new > > > synchroniation wrinkles, but it's not the main issue. > > > > > > As _think_ I understand it, the root of the issue is that speculative > > > execution - and that per Andy, speculative execution doesn't obey memory > > > barriers. > > > > > > I have _not_ dug into the details of how retpolines work and all the > > > spectre stuff that was going on, but - retpoline uses lfence, doesn't > > > it? And if speculative execution is the issue here, isn't retpoline what > > > we need? > > > > > > For this particular issue, I'm not sure "invalidate by filling with > > > illegal instructions" makes sense. For that to work, would the processor > > > have to execute a serialize operation and a retry on hitting an illegal > > > instruction - or perhaps we do in the interrupt handler? > > > > > > But if filling with illegal instructions does act as a speculation > > > barrier, then the issue is that a torn read could generate a legal but > > > incorrect instruction. > > > > What is a "torn read" here? I assume it is an instruction read that > > goes at the wrong instruction boundary (CISC). If this is correct, do > > we need to handle torn read caused by software bug, or hardware > > bit flip, or both? > > On ARM64 (RISC), torn reads can't happen because the instruction fetch > is word aligned. If we replace the whole instruction atomically then there > won't be half old - half new instruction fetches. Unfortunately, that's only guaranteed for a subset of instructions (e.g. B, NOP), and in general CPUs can fetch an instruction multiple times, and could fetch arbitrary portions of the instruction each time. Please see the "Concurrent Modification and Execution of instructions" rules in the ARM ARM. For arm64, in general, you need to inhibit any concurrent execution (e.g. by stopping-the-world) when patching text, and afterwards you need cache maintence followed by a context-syncrhonization-event (aking to an x86 serializing instruction) on CPUs which will execute the new instruction(s). There are a bunch of special cases where we can omit some of that, but in general the architectural guarnatees are *very* weak and require SW to perform several bits of work to guarantee the new instructions will be executed without issues. Thanks, Mark. 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 22530EB64DD for ; Mon, 26 Jun 2023 12:23:47 +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=MIM+arapBtGaRojVC8c5IBwavuFQUc7DKdj60q/usJY=; b=4L07QPuAB/wxWl szVcXNK//iFRau+feRHhYmUizwNVa/PON40nuHnGoVPRmSq2s1ZCRHt7EhqLhm2RzR8psOihCDbb3 jhD54mBDTE+G+4hiIV55aflsSaXQPh/ujqhIJjcPSRIo3tEF5O8YqJ60ZbzcMAxw/QQ6VuW9C2kxK piKMtobuZoJFWaStA+9N4QuF82SR3t35npCREJ/gOQpyG9k8yRT5SKr4u72HNmS1HsLWitDw/3SsI aBwq+PNnhB8tFI9iqU2LPSNHrQBSqjWi7O4O9D4g04RyCDgPLpErDTjiF7n4dwciRAEp4qMGd8t2E mjShVH8/XIbZooZ06QMQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qDlFu-00AC7e-0E; Mon, 26 Jun 2023 12:23:42 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qDlFp-00AC4e-0r; Mon, 26 Jun 2023 12:23:39 +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 E14312F4; Mon, 26 Jun 2023 05:24:12 -0700 (PDT) Received: from FVFF77S0Q05N (unknown [10.57.23.38]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA5173F64C; Mon, 26 Jun 2023 05:23:22 -0700 (PDT) Date: Mon, 26 Jun 2023 13:23:17 +0100 From: Mark Rutland To: Puranjay Mohan Cc: Song Liu , Kent Overstreet , Mike Rapoport , Andy Lutomirski , Kees Cook , Linux Kernel Mailing List , Andrew Morton , Catalin Marinas , Christophe Leroy , "David S. Miller" , Dinh Nguyen , Heiko Carstens , Helge Deller , Huacai Chen , Luis Chamberlain , Michael Ellerman , Nadav Amit , "Naveen N. Rao" , Palmer Dabbelt , Rick P Edgecombe , "Russell King (Oracle)" , Steven Rostedt , Thomas Bogendoerfer , Thomas Gleixner , Will Deacon , bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, linux-mm@kvack.org, linux-modules@vger.kernel.org, linux-parisc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, loongarch@lists.linux.dev, netdev@vger.kernel.org, sparclinux@vger.kernel.org, the arch/x86 maintainers , pjt@google.com, torvalds@linux-foundation.org Subject: Re: [PATCH v2 02/12] mm: introduce execmem_text_alloc() and jit_text_alloc() Message-ID: References: <20230616085038.4121892-3-rppt@kernel.org> <20230618080027.GA52412@kernel.org> <20230625161417.GK52412@kernel.org> <90161ac9-3ca0-4c72-b1c4-ab1293e55445@app.fastmail.com> <20230625174257.GL52412@kernel.org> <20230625180741.jrrtkq55c4jrqh3t@moria.home.lan> 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-20230626_052337_419074_70FA2467 X-CRM114-Status: GOOD ( 73.75 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org T24gTW9uLCBKdW4gMjYsIDIwMjMgYXQgMTE6NTQ6MDJBTSArMDIwMCwgUHVyYW5qYXkgTW9oYW4g d3JvdGU6Cj4gT24gTW9uLCBKdW4gMjYsIDIwMjMgYXQgODoxM+KAr0FNIFNvbmcgTGl1IDxzb25n QGtlcm5lbC5vcmc+IHdyb3RlOgo+ID4KPiA+IE9uIFN1biwgSnVuIDI1LCAyMDIzIGF0IDExOjA3 4oCvQU0gS2VudCBPdmVyc3RyZWV0Cj4gPiA8a2VudC5vdmVyc3RyZWV0QGxpbnV4LmRldj4gd3Jv dGU6Cj4gPiA+Cj4gPiA+IE9uIFN1biwgSnVuIDI1LCAyMDIzIGF0IDA4OjQyOjU3UE0gKzAzMDAs IE1pa2UgUmFwb3BvcnQgd3JvdGU6Cj4gPiA+ID4gT24gU3VuLCBKdW4gMjUsIDIwMjMgYXQgMDk6 NTk6MzRBTSAtMDcwMCwgQW5keSBMdXRvbWlyc2tpIHdyb3RlOgo+ID4gPiA+ID4KPiA+ID4gPiA+ Cj4gPiA+ID4gPiBPbiBTdW4sIEp1biAyNSwgMjAyMywgYXQgOToxNCBBTSwgTWlrZSBSYXBvcG9y dCB3cm90ZToKPiA+ID4gPiA+ID4gT24gTW9uLCBKdW4gMTksIDIwMjMgYXQgMTA6MDk6MDJBTSAt MDcwMCwgQW5keSBMdXRvbWlyc2tpIHdyb3RlOgo+ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IE9u IFN1biwgSnVuIDE4LCAyMDIzLCBhdCAxOjAwIEFNLCBNaWtlIFJhcG9wb3J0IHdyb3RlOgo+ID4g PiA+ID4gPj4gPiBPbiBTYXQsIEp1biAxNywgMjAyMyBhdCAwMTozODoyOVBNIC0wNzAwLCBBbmR5 IEx1dG9taXJza2kgd3JvdGU6Cj4gPiA+ID4gPiA+PiA+PiBPbiBGcmksIEp1biAxNiwgMjAyMywg YXQgMTo1MCBBTSwgTWlrZSBSYXBvcG9ydCB3cm90ZToKPiA+ID4gPiA+ID4+ID4+ID4gRnJvbTog Ik1pa2UgUmFwb3BvcnQgKElCTSkiIDxycHB0QGtlcm5lbC5vcmc+Cj4gPiA+ID4gPiA+PiA+PiA+ Cj4gPiA+ID4gPiA+PiA+PiA+IG1vZHVsZV9hbGxvYygpIGlzIHVzZWQgZXZlcnl3aGVyZSBhcyBh IG1lYW4gdG8gYWxsb2NhdGUgbWVtb3J5IGZvciBjb2RlLgo+ID4gPiA+ID4gPj4gPj4gPgo+ID4g PiA+ID4gPj4gPj4gPiBCZXNpZGUgYmVpbmcgc2VtYW50aWNhbGx5IHdyb25nLCB0aGlzIHVubmVj ZXNzYXJpbHkgdGllcyBhbGwgc3Vic3lzdGVtcwo+ID4gPiA+ID4gPj4gPj4gPiB0aGF0IG5lZWQg dG8gYWxsb2NhdGUgY29kZSwgc3VjaCBhcyBmdHJhY2UsIGtwcm9iZXMgYW5kIEJQRiB0byBtb2R1 bGVzCj4gPiA+ID4gPiA+PiA+PiA+IGFuZCBwdXRzIHRoZSBidXJkZW4gb2YgY29kZSBhbGxvY2F0 aW9uIHRvIHRoZSBtb2R1bGVzIGNvZGUuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+ PiA+IFNldmVyYWwgYXJjaGl0ZWN0dXJlcyBvdmVycmlkZSBtb2R1bGVfYWxsb2MoKSBiZWNhdXNl IG9mIHZhcmlvdXMKPiA+ID4gPiA+ID4+ID4+ID4gY29uc3RyYWludHMgd2hlcmUgdGhlIGV4ZWN1 dGFibGUgbWVtb3J5IGNhbiBiZSBsb2NhdGVkIGFuZCB0aGlzIGNhdXNlcwo+ID4gPiA+ID4gPj4g Pj4gPiBhZGRpdGlvbmFsIG9ic3RhY2xlcyBmb3IgaW1wcm92ZW1lbnRzIG9mIGNvZGUgYWxsb2Nh dGlvbi4KPiA+ID4gPiA+ID4+ID4+ID4KPiA+ID4gPiA+ID4+ID4+ID4gU3RhcnQgc3BsaXR0aW5n IGNvZGUgYWxsb2NhdGlvbiBmcm9tIG1vZHVsZXMgYnkgaW50cm9kdWNpbmcKPiA+ID4gPiA+ID4+ ID4+ID4gZXhlY21lbV90ZXh0X2FsbG9jKCksIGV4ZWNtZW1fZnJlZSgpLCBqaXRfdGV4dF9hbGxv YygpLCBqaXRfZnJlZSgpIEFQSXMuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+PiA+ IEluaXRpYWxseSwgZXhlY21lbV90ZXh0X2FsbG9jKCkgYW5kIGppdF90ZXh0X2FsbG9jKCkgYXJl IHdyYXBwZXJzIGZvcgo+ID4gPiA+ID4gPj4gPj4gPiBtb2R1bGVfYWxsb2MoKSBhbmQgZXhlY21l bV9mcmVlKCkgYW5kIGppdF9mcmVlKCkgYXJlIHJlcGxhY2VtZW50cyBvZgo+ID4gPiA+ID4gPj4g Pj4gPiBtb2R1bGVfbWVtZnJlZSgpIHRvIGFsbG93IHVwZGF0aW5nIGFsbCBjYWxsIHNpdGVzIHRv IHVzZSB0aGUgbmV3IEFQSXMuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+PiA+IFRo ZSBpbnRlbnRpb24gc2VtYW50aWNzIGZvciBuZXcgYWxsb2NhdGlvbiBBUElzOgo+ID4gPiA+ID4g Pj4gPj4gPgo+ID4gPiA+ID4gPj4gPj4gPiAqIGV4ZWNtZW1fdGV4dF9hbGxvYygpIHNob3VsZCBi ZSB1c2VkIHRvIGFsbG9jYXRlIG1lbW9yeSB0aGF0IG11c3QgcmVzaWRlCj4gPiA+ID4gPiA+PiA+ PiA+ICAgY2xvc2UgdG8gdGhlIGtlcm5lbCBpbWFnZSwgbGlrZSBsb2FkYWJsZSBrZXJuZWwgbW9k dWxlcyBhbmQgZ2VuZXJhdGVkCj4gPiA+ID4gPiA+PiA+PiA+ICAgY29kZSB0aGF0IGlzIHJlc3Ry aWN0ZWQgYnkgcmVsYXRpdmUgYWRkcmVzc2luZy4KPiA+ID4gPiA+ID4+ID4+ID4KPiA+ID4gPiA+ ID4+ID4+ID4gKiBqaXRfdGV4dF9hbGxvYygpIHNob3VsZCBiZSB1c2VkIHRvIGFsbG9jYXRlIG1l bW9yeSBmb3IgZ2VuZXJhdGVkIGNvZGUKPiA+ID4gPiA+ID4+ID4+ID4gICB3aGVuIHRoZXJlIGFy ZSBubyByZXN0cmljdGlvbnMgZm9yIHRoZSBjb2RlIHBsYWNlbWVudC4gRm9yCj4gPiA+ID4gPiA+ PiA+PiA+ICAgYXJjaGl0ZWN0dXJlcyB0aGF0IHJlcXVpcmUgdGhhdCBhbnkgY29kZSBpcyB3aXRo aW4gY2VydGFpbiBkaXN0YW5jZQo+ID4gPiA+ID4gPj4gPj4gPiAgIGZyb20gdGhlIGtlcm5lbCBp bWFnZSwgaml0X3RleHRfYWxsb2MoKSB3aWxsIGJlIGVzc2VudGlhbGx5IGFsaWFzZWQgdG8KPiA+ ID4gPiA+ID4+ID4+ID4gICBleGVjbWVtX3RleHRfYWxsb2MoKS4KPiA+ID4gPiA+ID4+ID4+ID4K PiA+ID4gPiA+ID4+ID4+Cj4gPiA+ID4gPiA+PiA+PiBJcyB0aGVyZSBhbnl0aGluZyBpbiB0aGlz IHNlcmllcyB0byBoZWxwIHVzZXJzIGRvIHRoZSBhcHByb3ByaWF0ZQo+ID4gPiA+ID4gPj4gPj4g c3luY2hyb25pemF0aW9uIHdoZW4gdGhlIGFjdHVhbGx5IHBvcHVsYXRlIHRoZSBhbGxvY2F0ZWQg bWVtb3J5IHdpdGgKPiA+ID4gPiA+ID4+ID4+IGNvZGU/ICBTZWUgaGVyZSwgZm9yIGV4YW1wbGU6 Cj4gPiA+ID4gPiA+PiA+Cj4gPiA+ID4gPiA+PiA+IFRoaXMgc2VyaWVzIG9ubHkgZmFjdG9ycyBv dXQgdGhlIGV4ZWN1dGFibGUgYWxsb2NhdGlvbnMgZnJvbSBtb2R1bGVzIGFuZAo+ID4gPiA+ID4g Pj4gPiBwdXRzIHRoZW0gaW4gYSBjZW50cmFsIHBsYWNlLgo+ID4gPiA+ID4gPj4gPiBBbnl0aGlu ZyBlbHNlIHdvdWxkIGdvIG9uIHRvcCBhZnRlciB0aGlzIGxhbmRzLgo+ID4gPiA+ID4gPj4KPiA+ ID4gPiA+ID4+IEhtbS4KPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiBPbiB0aGUgb25lIGhhbmQs IHRoZXJlJ3Mgbm90aGluZyB3cm9uZyB3aXRoIGZhY3RvcmluZyBvdXQgY29tbW9uIGNvZGUuIE9u Cj4gPiA+ID4gPiA+PiB0aGUgb3RoZXIgaGFuZCwgdGhpcyBpcyBwcm9iYWJseSB0aGUgcmlnaHQg dGltZSB0byBhdCBsZWFzdCBzdGFydAo+ID4gPiA+ID4gPj4gdGhpbmtpbmcgYWJvdXQgc3luY2hy b25pemF0aW9uLCBhdCBsZWFzdCB0byB0aGUgZXh0ZW50IHRoYXQgaXQgbWlnaHQgbWFrZQo+ID4g PiA+ID4gPj4gdXMgd2FudCB0byBjaGFuZ2UgdGhpcyBBUEkuICAoSSdtIG5vdCBhdCBhbGwgc2F5 aW5nIHRoYXQgdGhpcyBzZXJpZXMKPiA+ID4gPiA+ID4+IHNob3VsZCByZXF1aXJlIGNoYW5nZXMg LS0gSSdtIGp1c3Qgc2F5aW5nIHRoYXQgdGhpcyBpcyBhIGdvb2QgdGltZSB0bwo+ID4gPiA+ID4g Pj4gdGhpbmsgYWJvdXQgaG93IHRoaXMgc2hvdWxkIHdvcmsuKQo+ID4gPiA+ID4gPj4KPiA+ID4g PiA+ID4+IFRoZSBjdXJyZW50IEFQSXMsICphbmQqIHRoZSBwcm9wb3NlZCBqaXRfdGV4dF9hbGxv YygpIEFQSSwgZG9uJ3QgYWN0dWFsbHkKPiA+ID4gPiA+ID4+IGxvb2sgbGlrZSB0aGUgb25lIHRo aW5rIGluIHRoZSBMaW51eCBlY29zeXN0ZW0gdGhhdCBhY3R1YWxseQo+ID4gPiA+ID4gPj4gaW50 ZWxsaWdlbnRseSBhbmQgZWZmaWNpZW50bHkgbWFwcyBuZXcgdGV4dCBpbnRvIGFuIGFkZHJlc3Mg c3BhY2U6Cj4gPiA+ID4gPiA+PiBtbWFwKCkuCj4gPiA+ID4gPiA+Pgo+ID4gPiA+ID4gPj4gT24g eDg2LCB5b3UgY2FuIG1tYXAoKSBhbiBleGlzdGluZyBmaWxlIGZ1bGwgb2YgZXhlY3V0YWJsZSBj b2RlIFBST1RfRVhFQwo+ID4gPiA+ID4gPj4gYW5kIGp1bXAgdG8gaXQgd2l0aCBtaW5pbWFsIHN5 bmNocm9uaXphdGlvbiAoanVzdCB0aGUgc3RhbmRhcmQgaW1wbGljaXQKPiA+ID4gPiA+ID4+IG9y ZGVyaW5nIGluIHRoZSBrZXJuZWwgdGhhdCBwb3B1bGF0ZXMgdGhlIHBhZ2VzIGJlZm9yZSBzZXR0 aW5nIHVwIHRoZQo+ID4gPiA+ID4gPj4gUFRFcyBhbmQgd2hhdGV2ZXIgdXNlciBzeW5jaHJvbml6 YXRpb24gaXMgbmVlZGVkIHRvIGF2b2lkIGp1bXBpbmcgaW50bwo+ID4gPiA+ID4gPj4gdGhlIG1h cHBpbmcgYmVmb3JlIG1tYXAoKSBmaW5pc2hlcykuICBJdCB3b3JrcyBhY3Jvc3MgQ1BVcywgYW5k IHRoZSBvbmx5Cj4gPiA+ID4gPiA+PiBwb3NzaWJsZSB3YXkgdXNlcnNwYWNlIGNhbiBzY3JldyBp dCB1cCAoZm9yIGEgcmVhZC1vbmx5IG1hcHBpbmcgb2YKPiA+ID4gPiA+ID4+IHJlYWQtb25seSB0 ZXh0LCBhbnl3YXkpIGlzIHRvIGp1bXAgdG8gdGhlIG1hcHBpbmcgdG9vIGVhcmx5LCBpbiB3aGlj aAo+ID4gPiA+ID4gPj4gY2FzZSB1c2Vyc3BhY2UgZ2V0cyBhIHBhZ2UgZmF1bHQuICBJbmNvaGVy ZW5jZSBpcyBpbXBvc3NpYmxlLCBhbmQgbm8gb25lCj4gPiA+ID4gPiA+PiBuZWVkcyB0byAic2Vy aWFsaXplIiAoaW4gdGhlIFNETSBzZW5zZSkuCj4gPiA+ID4gPiA+Pgo+ID4gPiA+ID4gPj4gSSB0 aGluayB0aGUgc2FtZSBzZXF1ZW5jZSAoZnJvbSB1c2Vyc3BhY2UncyBwZXJzcGVjdGl2ZSkgd29y a3Mgb24gb3RoZXIKPiA+ID4gPiA+ID4+IGFyY2hpdGVjdHVyZXMsIHRvbywgYWx0aG91Z2ggSSB0 aGluayBtb3JlIGNhY2hlIG1hbmFnZW1lbnQgaXMgbmVlZGVkIG9uCj4gPiA+ID4gPiA+PiB0aGUg a2VybmVsJ3MgZW5kLiAgQXMgZmFyIGFzIEkga25vdywgbm8gTGludXggU01QIGFyY2hpdGVjdHVy ZSBuZWVkcyBhbgo+ID4gPiA+ID4gPj4gSVBJIHRvIG1hcCBleGVjdXRhYmxlIHRleHQgaW50byB1 c2VybW9kZSwgYnV0IEkgY291bGQgZWFzaWx5IGJlIHdyb25nLgo+ID4gPiA+ID4gPj4gKElJUkMg UklTQy1WIGhhcyB2ZXJ5IGRldmVsb3Blci11bmZyaWVuZGx5IGljYWNoZSBtYW5hZ2VtZW50LCBi dXQgSSBkb24ndAo+ID4gPiA+ID4gPj4gcmVtZW1iZXIgdGhlIGRldGFpbHMuKQo+ID4gPiA+ID4g Pj4KPiA+ID4gPiA+ID4+IE9mIGNvdXJzZSwgdXNpbmcgcHRyYWNlIG9yIGFueSBvdGhlciBGT0xM X0ZPUkNFIHRvIG1vZGlmeSB0ZXh0IG9uIHg4NiBpcwo+ID4gPiA+ID4gPj4gcmF0aGVyIGZyYXVn aHQsIGFuZCBJIGJldCBtYW55IHRoaW5ncyBkbyBpdCB3cm9uZyB3aGVuIHVzZXJzcGFjZSBpcwo+ ID4gPiA+ID4gPj4gbXVsdGl0aHJlYWRlZC4gIEJ1dCBub3QgaW4gcHJvZHVjdGlvbiBiZWNhdXNl IGl0J3MgbW9zdGx5IG5vdCB1c2VkIGluCj4gPiA+ID4gPiA+PiBwcm9kdWN0aW9uLikKPiA+ID4g PiA+ID4+Cj4gPiA+ID4gPiA+PiBCdXQgaml0X3RleHRfYWxsb2MoKSBjYW4ndCBkbyB0aGlzLCBi ZWNhdXNlIHRoZSBvcmRlciBvZiBvcGVyYXRpb25zCj4gPiA+ID4gPiA+PiBkb2Vzbid0IG1hdGNo LiAgV2l0aCBqaXRfdGV4dF9hbGxvYygpLCB0aGUgZXhlY3V0YWJsZSBtYXBwaW5nIHNob3dzIHVw Cj4gPiA+ID4gPiA+PiBiZWZvcmUgdGhlIHRleHQgaXMgcG9wdWxhdGVkLCBzbyB0aGVyZSBpcyBu byBhdG9taWMgY2hhbmdlIGZyb20gbm90LXRoZXJlCj4gPiA+ID4gPiA+PiB0byBwb3B1bGF0ZWQt YW5kLWV4ZWN1dGFibGUuICBXaGljaCBtZWFucyB0aGF0IHRoZXJlIGlzIGFuIG9wcG9ydHVuaXR5 Cj4gPiA+ID4gPiA+PiBmb3IgQ1BVcywgc3BlY3VsYXRpdmVseSBvciBvdGhlcndpc2UsIHRvIHN0 YXJ0IGZpbGxpbmcgdmFyaW91cyBjYWNoZXMKPiA+ID4gPiA+ID4+IHdpdGggaW50ZXJtZWRpYXRl IHN0YXRlcyBvZiB0aGUgdGV4dCwgd2hpY2ggbWVhbnMgdGhhdCB2YXJpb3VzCj4gPiA+ID4gPiA+ PiBhcmNoaXRlY3R1cmVzIChldmVuIHg4NiEpIG1heSBuZWVkIHNlcmlhbGl6YXRpb24uCj4gPiA+ ID4gPiA+Pgo+ID4gPiA+ID4gPj4gRm9yIGVCUEYtIGFuZCBtb2R1bGUtIGxpa2UgdXNlIGNhc2Vz LCB3aGVyZSBKSVR0aW5nL2NvZGUgZ2VuIGlzIHF1aXRlCj4gPiA+ID4gPiA+PiBjb2Fyc2UtZ3Jh aW5lZCwgcGVyaGFwcyBzb21ldGhpbmcgdmFndWVseSBsaWtlOgo+ID4gPiA+ID4gPj4KPiA+ID4g PiA+ID4+IGppdF90ZXh0X2FsbG9jKCkgLT4gcmV0dXJucyBhIGhhbmRsZSBhbmQgYW4gZXhlY3V0 YWJsZSB2aXJ0dWFsIGFkZHJlc3MsCj4gPiA+ID4gPiA+PiBidXQgZG9lcyAqbm90KiBtYXAgaXQg dGhlcmUKPiA+ID4gPiA+ID4+IGppdF90ZXh0X3dyaXRlKCkgLT4gd3JpdGUgdG8gdGhhdCBoYW5k bGUKPiA+ID4gPiA+ID4+IGppdF90ZXh0X21hcCgpIC0+IG1hcCBpdCBhbmQgc3luY2hyb25pemUg aWYgbmVlZGVkIChubyBzeW5jIG5lZWRlZCBvbgo+ID4gPiA+ID4gPj4geDg2LCBJIHRoaW5rKQo+ ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IGNvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGFuZC9vciBz YWZlci4KPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiAoTW9kdWxlcyBjb3VsZCB1c2UgdGhpcyB0 b28uICBHZXR0aW5nIGFsdGVybmF0aXZlcyByaWdodCBtaWdodCB0YWtlIHNvbWUKPiA+ID4gPiA+ ID4+IGZpZGRsaW5nLCBiZWNhdXNlIG9mZiB0aGUgdG9wIG9mIG15IGhlYWQsIHRoaXMgZG9lc24n dCBtYXRjaCBob3cgaXQgd29ya3MKPiA+ID4gPiA+ID4+IG5vdy4pCj4gPiA+ID4gPiA+Pgo+ID4g PiA+ID4gPj4gVG8gbWFrZSBhbHRlcm5hdGl2ZXMgZWFzaWVyLCB0aGlzIGNvdWxkIHdvcmssIG1h eWJlIChoYXZlbid0IGZ1bGx5Cj4gPiA+ID4gPiA+PiB0aG91Z2h0IGl0IHRocm91Z2gpOgo+ID4g PiA+ID4gPj4KPiA+ID4gPiA+ID4+IGppdF90ZXh0X2FsbG9jKCkKPiA+ID4gPiA+ID4+IGppdF90 ZXh0X21hcF9yd19pbnBsYWNlKCkgLT4gbWFwIGF0IHRoZSB0YXJnZXQgYWRkcmVzcywgYnV0IFJX LCAhWAo+ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IHdyaXRlIHRoZSB0ZXh0IGFuZCBhcHBseSBh bHRlcm5hdGl2ZXMKPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiBqaXRfdGV4dF9maW5hbGl6ZSgp IC0+IGNoYW5nZSBmcm9tIFJXIHRvIFJYICphbmQgc3luY2hyb25pemUqCj4gPiA+ID4gPiA+Pgo+ ID4gPiA+ID4gPj4gaml0X3RleHRfZmluYWxpemUoKSB3b3VsZCBlaXRoZXIgbmVlZCB0byB3YWl0 IGZvciBSQ1UgKHBvc3NpYmx5IGV4dHJhCj4gPiA+ID4gPiA+PiBoZWF2eSB3ZWlnaHQgUkNVIHRv IGdldCAic2VyaWFsaXphdGlvbiIpIG9yIHNlbmQgYW4gSVBJLgo+ID4gPiA+ID4gPgo+ID4gPiA+ ID4gPiBUaGlzIGVzc2VudGlhbGx5IGhvdyBtb2R1bGVzIHdvcmsgbm93LiBUaGUgbWVtb3J5IGlz IGFsbG9jYXRlZCBSVywgd3JpdHRlbgo+ID4gPiA+ID4gPiBhbmQgdXBkYXRlZCB3aXRoIGFsdGVy bmF0aXZlcyBhbmQgdGhlbiBtYWRlIFJPWCBpbiB0aGUgZW5kIHdpdGggc2V0X21lbW9yeQo+ID4g PiA+ID4gPiBBUElzLgo+ID4gPiA+ID4gPgo+ID4gPiA+ID4gPiBUaGUgaXNzdWUgd2l0aCBub3Qg aGF2aW5nIHRoZSBtZW1vcnkgbWFwcGVkIFggd2hlbiBpdCdzIHdyaXR0ZW4gaXMgdGhhdCB3ZQo+ ID4gPiA+ID4gPiBjYW5ub3QgdXNlIGxhcmdlIHBhZ2VzIHRvIG1hcCBpdC4gT25lIG9mIHRoZSBn b2FscyBpcyB0byBoYXZlIGV4ZWN1dGFibGUKPiA+ID4gPiA+ID4gbWVtb3J5IG1hcHBlZCB3aXRo IGxhcmdlIHBhZ2VzIGFuZCBtYWtlIGNvZGUgYWxsb2NhdG9yIGFibGUgdG8gZGl2aWRlIHRoYXQK PiA+ID4gPiA+ID4gcGFnZSBhbW9uZyBzZXZlcmFsIGNhbGxlcnMuCj4gPiA+ID4gPiA+Cj4gPiA+ ID4gPiA+IFNvIHRoZSBpZGVhIHdhcyB0aGF0IGppdF90ZXh0X2FsbG9jKCkgd2lsbCBoYXZlIGEg Y2FjaGUgb2YgbGFyZ2UgcGFnZXMKPiA+ID4gPiA+ID4gbWFwcGVkIFJPWCwgd2lsbCBhbGxvY2F0 ZSBtZW1vcnkgZnJvbSB0aG9zZSBjYWNoZXMgYW5kIHRoZXJlIHdpbGwgYmUKPiA+ID4gPiA+ID4g aml0X3VwZGF0ZSgpIHRoYXQgdXNlcyB0ZXh0IHBva2luZyBmb3Igd3JpdGluZyB0byB0aGF0IG1l bW9yeS4KPiA+ID4gPiA+ID4KPiA+ID4gPiA+ID4gVXBvbiBhbGxvY2F0aW9uIG9mIGEgbGFyZ2Ug cGFnZSB0byBpbmNyZWFzZSB0aGUgY2FjaGUsIHRoYXQgbGFyZ2UgcGFnZSB3aWxsCj4gPiA+ID4g PiA+IGJlICJpbnZhbGlkYXRlZCIgYnkgZmlsbGluZyBpdCB3aXRoIGJyZWFrcG9pbnQgaW5zdHJ1 Y3Rpb25zIChlLmcgaW50MyBvbgo+ID4gPiA+ID4gPiB4ODYpCj4gPiA+ID4gPgo+ID4gPiA+ID4g SXMgdGhpcyBhY3R1YWxseSB2YWxpZD8gIEluIGJldHdlZW4gaW50MyBhbmQgcmVhbCBjb2RlLCB0 aGVyZeKAmXMgYQo+ID4gPiA+ID4gcG90ZW50aWFsIHRvcm4gcmVhZCBvZiByZWFsIGNvZGUgbWl4 ZWQgdXAgd2l0aCAweGNjLgo+ID4gPiA+Cj4gPiA+ID4gWW91IG1lYW4gd2hpbGUgZG9pbmcgdGV4 dCBwb2tpbmc/Cj4gPiA+Cj4gPiA+IEkgdGhpbmsgd2UndmUgYmVlbiBnZXR0aW5nIGRpc3RyYWN0 ZWQgYnkgdGV4dF9wb2tlKCkuIHRleHRfcG9rZSgpIGRvZXMKPiA+ID4gdXBkYXRlcyB2aWEgYSBk aWZmZXJlbnQgdmlydHVhbCBhZGRyZXNzIHdoaWNoIGludHJvZHVjZSBuZXcKPiA+ID4gc3luY2hy b25pYXRpb24gd3JpbmtsZXMsIGJ1dCBpdCdzIG5vdCB0aGUgbWFpbiBpc3N1ZS4KPiA+ID4KPiA+ ID4gQXMgX3RoaW5rXyBJIHVuZGVyc3RhbmQgaXQsIHRoZSByb290IG9mIHRoZSBpc3N1ZSBpcyB0 aGF0IHNwZWN1bGF0aXZlCj4gPiA+IGV4ZWN1dGlvbiAtIGFuZCB0aGF0IHBlciBBbmR5LCBzcGVj dWxhdGl2ZSBleGVjdXRpb24gZG9lc24ndCBvYmV5IG1lbW9yeQo+ID4gPiBiYXJyaWVycy4KPiA+ ID4KPiA+ID4gSSBoYXZlIF9ub3RfIGR1ZyBpbnRvIHRoZSBkZXRhaWxzIG9mIGhvdyByZXRwb2xp bmVzIHdvcmsgYW5kIGFsbCB0aGUKPiA+ID4gc3BlY3RyZSBzdHVmZiB0aGF0IHdhcyBnb2luZyBv biwgYnV0IC0gcmV0cG9saW5lIHVzZXMgbGZlbmNlLCBkb2Vzbid0Cj4gPiA+IGl0PyBBbmQgaWYg c3BlY3VsYXRpdmUgZXhlY3V0aW9uIGlzIHRoZSBpc3N1ZSBoZXJlLCBpc24ndCByZXRwb2xpbmUg d2hhdAo+ID4gPiB3ZSBuZWVkPwo+ID4gPgo+ID4gPiBGb3IgdGhpcyBwYXJ0aWN1bGFyIGlzc3Vl LCBJJ20gbm90IHN1cmUgImludmFsaWRhdGUgYnkgZmlsbGluZyB3aXRoCj4gPiA+IGlsbGVnYWwg aW5zdHJ1Y3Rpb25zIiBtYWtlcyBzZW5zZS4gRm9yIHRoYXQgdG8gd29yaywgd291bGQgdGhlIHBy b2Nlc3Nvcgo+ID4gPiBoYXZlIHRvIGV4ZWN1dGUgYSBzZXJpYWxpemUgb3BlcmF0aW9uIGFuZCBh IHJldHJ5IG9uIGhpdHRpbmcgYW4gaWxsZWdhbAo+ID4gPiBpbnN0cnVjdGlvbiAtIG9yIHBlcmhh cHMgd2UgZG8gaW4gdGhlIGludGVycnVwdCBoYW5kbGVyPwo+ID4gPgo+ID4gPiBCdXQgaWYgZmls bGluZyB3aXRoIGlsbGVnYWwgaW5zdHJ1Y3Rpb25zIGRvZXMgYWN0IGFzIGEgc3BlY3VsYXRpb24K PiA+ID4gYmFycmllciwgdGhlbiB0aGUgaXNzdWUgaXMgdGhhdCBhIHRvcm4gcmVhZCBjb3VsZCBn ZW5lcmF0ZSBhIGxlZ2FsIGJ1dAo+ID4gPiBpbmNvcnJlY3QgaW5zdHJ1Y3Rpb24uCj4gPgo+ID4g V2hhdCBpcyBhICJ0b3JuIHJlYWQiIGhlcmU/IEkgYXNzdW1lIGl0IGlzIGFuIGluc3RydWN0aW9u IHJlYWQgdGhhdAo+ID4gZ29lcyBhdCB0aGUgd3JvbmcgaW5zdHJ1Y3Rpb24gYm91bmRhcnkgKENJ U0MpLiBJZiB0aGlzIGlzIGNvcnJlY3QsIGRvCj4gPiB3ZSBuZWVkIHRvIGhhbmRsZSB0b3JuIHJl YWQgY2F1c2VkIGJ5IHNvZnR3YXJlIGJ1Zywgb3IgaGFyZHdhcmUKPiA+IGJpdCBmbGlwLCBvciBi b3RoPwo+IAo+IE9uIEFSTTY0IChSSVNDKSwgdG9ybiByZWFkcyBjYW4ndCBoYXBwZW4gYmVjYXVz ZSB0aGUgaW5zdHJ1Y3Rpb24gZmV0Y2gKPiBpcyB3b3JkIGFsaWduZWQuIElmIHdlIHJlcGxhY2Ug dGhlIHdob2xlIGluc3RydWN0aW9uIGF0b21pY2FsbHkgdGhlbiB0aGVyZQo+IHdvbid0IGJlIGhh bGYgb2xkIC0gaGFsZiBuZXcgaW5zdHJ1Y3Rpb24gZmV0Y2hlcy4KClVuZm9ydHVuYXRlbHksIHRo YXQncyBvbmx5IGd1YXJhbnRlZWQgZm9yIGEgc3Vic2V0IG9mIGluc3RydWN0aW9ucyAoZS5nLiBC LApOT1ApLCBhbmQgaW4gZ2VuZXJhbCBDUFVzIGNhbiBmZXRjaCBhbiBpbnN0cnVjdGlvbiBtdWx0 aXBsZSB0aW1lcywgYW5kIGNvdWxkCmZldGNoIGFyYml0cmFyeSBwb3J0aW9ucyBvZiB0aGUgaW5z dHJ1Y3Rpb24gZWFjaCB0aW1lLgoKUGxlYXNlIHNlZSB0aGUgIkNvbmN1cnJlbnQgTW9kaWZpY2F0 aW9uIGFuZCBFeGVjdXRpb24gb2YgaW5zdHJ1Y3Rpb25zIiBydWxlcyBpbgp0aGUgQVJNIEFSTS4K CkZvciBhcm02NCwgaW4gZ2VuZXJhbCwgeW91IG5lZWQgdG8gaW5oaWJpdCBhbnkgY29uY3VycmVu dCBleGVjdXRpb24gKGUuZy4gYnkKc3RvcHBpbmctdGhlLXdvcmxkKSB3aGVuIHBhdGNoaW5nIHRl eHQsIGFuZCBhZnRlcndhcmRzIHlvdSBuZWVkIGNhY2hlIG1haW50ZW5jZQpmb2xsb3dlZCBieSBh IGNvbnRleHQtc3luY3Job25pemF0aW9uLWV2ZW50IChha2luZyB0byBhbiB4ODYgc2VyaWFsaXpp bmcKaW5zdHJ1Y3Rpb24pIG9uIENQVXMgd2hpY2ggd2lsbCBleGVjdXRlIHRoZSBuZXcgaW5zdHJ1 Y3Rpb24ocykuCgpUaGVyZSBhcmUgYSBidW5jaCBvZiBzcGVjaWFsIGNhc2VzIHdoZXJlIHdlIGNh biBvbWl0IHNvbWUgb2YgdGhhdCwgYnV0IGluCmdlbmVyYWwgdGhlIGFyY2hpdGVjdHVyYWwgZ3Vh cm5hdGVlcyBhcmUgKnZlcnkqIHdlYWsgYW5kIHJlcXVpcmUgU1cgdG8gcGVyZm9ybQpzZXZlcmFs IGJpdHMgb2Ygd29yayB0byBndWFyYW50ZWUgdGhlIG5ldyBpbnN0cnVjdGlvbnMgd2lsbCBiZSBl eGVjdXRlZCB3aXRob3V0IGlzc3Vlcy4KClRoYW5rcywKTWFyay4KCl9fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LXJpc2N2IG1haWxpbmcgbGlzdAps aW51eC1yaXNjdkBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3Jn L21haWxtYW4vbGlzdGluZm8vbGludXgtcmlzY3YK 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 lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (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 CCE29EB64D7 for ; Mon, 26 Jun 2023 12:24:42 +0000 (UTC) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4QqRqY0LQLz3btP for ; Mon, 26 Jun 2023 22:24:41 +1000 (AEST) Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=arm.com (client-ip=217.140.110.172; helo=foss.arm.com; envelope-from=mark.rutland@arm.com; receiver=lists.ozlabs.org) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lists.ozlabs.org (Postfix) with ESMTP id 4QqRpt0wmlz304p for ; Mon, 26 Jun 2023 22:24:02 +1000 (AEST) 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 E14312F4; Mon, 26 Jun 2023 05:24:12 -0700 (PDT) Received: from FVFF77S0Q05N (unknown [10.57.23.38]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA5173F64C; Mon, 26 Jun 2023 05:23:22 -0700 (PDT) Date: Mon, 26 Jun 2023 13:23:17 +0100 From: Mark Rutland To: Puranjay Mohan Subject: Re: [PATCH v2 02/12] mm: introduce execmem_text_alloc() and jit_text_alloc() Message-ID: References: <20230616085038.4121892-3-rppt@kernel.org> <20230618080027.GA52412@kernel.org> <20230625161417.GK52412@kernel.org> <90161ac9-3ca0-4c72-b1c4-ab1293e55445@app.fastmail.com> <20230625174257.GL52412@kernel.org> <20230625180741.jrrtkq55c4jrqh3t@moria.home.lan> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: the arch/x86 maintainers , loongarch@lists.linux.dev, Catalin Marinas , linux-mips@vger.kernel.org, Song Liu , sparclinux@vger.kernel.org, linux-riscv@lists.infradead.org, Nadav Amit , linux-s390@vger.kernel.org, Helge Deller , Huacai Chen , "Russell King \(Oracle\)" , torvalds@linux-foundation.org, "Naveen N. Rao" , pjt@google.com, linux-trace-kernel@vger.kernel.org, Kees Cook , Will Deacon , Heiko Carstens , Steven Rostedt , Andy Lutomirski , Thomas Gleixner , bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Thomas Bogendoerfer , linux-parisc@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, Kent Overstreet , Linux Kernel M ailing List , Dinh Nguyen , Luis Chamberlain , Palmer Dabbelt , linux-modules@vger.kernel.org, Andrew Morton , Rick P Edgecombe , linuxppc-dev@lists.ozlabs.org, "David S. Miller" , Mike Rapoport Errors-To: linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Sender: "Linuxppc-dev" On Mon, Jun 26, 2023 at 11:54:02AM +0200, Puranjay Mohan wrote: > On Mon, Jun 26, 2023 at 8:13 AM Song Liu wrote: > > > > On Sun, Jun 25, 2023 at 11:07 AM Kent Overstreet > > wrote: > > > > > > On Sun, Jun 25, 2023 at 08:42:57PM +0300, Mike Rapoport wrote: > > > > On Sun, Jun 25, 2023 at 09:59:34AM -0700, Andy Lutomirski wrote: > > > > > > > > > > > > > > > On Sun, Jun 25, 2023, at 9:14 AM, Mike Rapoport wrote: > > > > > > On Mon, Jun 19, 2023 at 10:09:02AM -0700, Andy Lutomirski wrote: > > > > > >> > > > > > >> On Sun, Jun 18, 2023, at 1:00 AM, Mike Rapoport wrote: > > > > > >> > On Sat, Jun 17, 2023 at 01:38:29PM -0700, Andy Lutomirski wrote: > > > > > >> >> On Fri, Jun 16, 2023, at 1:50 AM, Mike Rapoport wrote: > > > > > >> >> > From: "Mike Rapoport (IBM)" > > > > > >> >> > > > > > > >> >> > module_alloc() is used everywhere as a mean to allocate memory for code. > > > > > >> >> > > > > > > >> >> > Beside being semantically wrong, this unnecessarily ties all subsystems > > > > > >> >> > that need to allocate code, such as ftrace, kprobes and BPF to modules > > > > > >> >> > and puts the burden of code allocation to the modules code. > > > > > >> >> > > > > > > >> >> > Several architectures override module_alloc() because of various > > > > > >> >> > constraints where the executable memory can be located and this causes > > > > > >> >> > additional obstacles for improvements of code allocation. > > > > > >> >> > > > > > > >> >> > Start splitting code allocation from modules by introducing > > > > > >> >> > execmem_text_alloc(), execmem_free(), jit_text_alloc(), jit_free() APIs. > > > > > >> >> > > > > > > >> >> > Initially, execmem_text_alloc() and jit_text_alloc() are wrappers for > > > > > >> >> > module_alloc() and execmem_free() and jit_free() are replacements of > > > > > >> >> > module_memfree() to allow updating all call sites to use the new APIs. > > > > > >> >> > > > > > > >> >> > The intention semantics for new allocation APIs: > > > > > >> >> > > > > > > >> >> > * execmem_text_alloc() should be used to allocate memory that must reside > > > > > >> >> > close to the kernel image, like loadable kernel modules and generated > > > > > >> >> > code that is restricted by relative addressing. > > > > > >> >> > > > > > > >> >> > * jit_text_alloc() should be used to allocate memory for generated code > > > > > >> >> > when there are no restrictions for the code placement. For > > > > > >> >> > architectures that require that any code is within certain distance > > > > > >> >> > from the kernel image, jit_text_alloc() will be essentially aliased to > > > > > >> >> > execmem_text_alloc(). > > > > > >> >> > > > > > > >> >> > > > > > >> >> Is there anything in this series to help users do the appropriate > > > > > >> >> synchronization when the actually populate the allocated memory with > > > > > >> >> code? See here, for example: > > > > > >> > > > > > > >> > This series only factors out the executable allocations from modules and > > > > > >> > puts them in a central place. > > > > > >> > Anything else would go on top after this lands. > > > > > >> > > > > > >> Hmm. > > > > > >> > > > > > >> On the one hand, there's nothing wrong with factoring out common code. On > > > > > >> the other hand, this is probably the right time to at least start > > > > > >> thinking about synchronization, at least to the extent that it might make > > > > > >> us want to change this API. (I'm not at all saying that this series > > > > > >> should require changes -- I'm just saying that this is a good time to > > > > > >> think about how this should work.) > > > > > >> > > > > > >> The current APIs, *and* the proposed jit_text_alloc() API, don't actually > > > > > >> look like the one think in the Linux ecosystem that actually > > > > > >> intelligently and efficiently maps new text into an address space: > > > > > >> mmap(). > > > > > >> > > > > > >> On x86, you can mmap() an existing file full of executable code PROT_EXEC > > > > > >> and jump to it with minimal synchronization (just the standard implicit > > > > > >> ordering in the kernel that populates the pages before setting up the > > > > > >> PTEs and whatever user synchronization is needed to avoid jumping into > > > > > >> the mapping before mmap() finishes). It works across CPUs, and the only > > > > > >> possible way userspace can screw it up (for a read-only mapping of > > > > > >> read-only text, anyway) is to jump to the mapping too early, in which > > > > > >> case userspace gets a page fault. Incoherence is impossible, and no one > > > > > >> needs to "serialize" (in the SDM sense). > > > > > >> > > > > > >> I think the same sequence (from userspace's perspective) works on other > > > > > >> architectures, too, although I think more cache management is needed on > > > > > >> the kernel's end. As far as I know, no Linux SMP architecture needs an > > > > > >> IPI to map executable text into usermode, but I could easily be wrong. > > > > > >> (IIRC RISC-V has very developer-unfriendly icache management, but I don't > > > > > >> remember the details.) > > > > > >> > > > > > >> Of course, using ptrace or any other FOLL_FORCE to modify text on x86 is > > > > > >> rather fraught, and I bet many things do it wrong when userspace is > > > > > >> multithreaded. But not in production because it's mostly not used in > > > > > >> production.) > > > > > >> > > > > > >> But jit_text_alloc() can't do this, because the order of operations > > > > > >> doesn't match. With jit_text_alloc(), the executable mapping shows up > > > > > >> before the text is populated, so there is no atomic change from not-there > > > > > >> to populated-and-executable. Which means that there is an opportunity > > > > > >> for CPUs, speculatively or otherwise, to start filling various caches > > > > > >> with intermediate states of the text, which means that various > > > > > >> architectures (even x86!) may need serialization. > > > > > >> > > > > > >> For eBPF- and module- like use cases, where JITting/code gen is quite > > > > > >> coarse-grained, perhaps something vaguely like: > > > > > >> > > > > > >> jit_text_alloc() -> returns a handle and an executable virtual address, > > > > > >> but does *not* map it there > > > > > >> jit_text_write() -> write to that handle > > > > > >> jit_text_map() -> map it and synchronize if needed (no sync needed on > > > > > >> x86, I think) > > > > > >> > > > > > >> could be more efficient and/or safer. > > > > > >> > > > > > >> (Modules could use this too. Getting alternatives right might take some > > > > > >> fiddling, because off the top of my head, this doesn't match how it works > > > > > >> now.) > > > > > >> > > > > > >> To make alternatives easier, this could work, maybe (haven't fully > > > > > >> thought it through): > > > > > >> > > > > > >> jit_text_alloc() > > > > > >> jit_text_map_rw_inplace() -> map at the target address, but RW, !X > > > > > >> > > > > > >> write the text and apply alternatives > > > > > >> > > > > > >> jit_text_finalize() -> change from RW to RX *and synchronize* > > > > > >> > > > > > >> jit_text_finalize() would either need to wait for RCU (possibly extra > > > > > >> heavy weight RCU to get "serialization") or send an IPI. > > > > > > > > > > > > This essentially how modules work now. The memory is allocated RW, written > > > > > > and updated with alternatives and then made ROX in the end with set_memory > > > > > > APIs. > > > > > > > > > > > > The issue with not having the memory mapped X when it's written is that we > > > > > > cannot use large pages to map it. One of the goals is to have executable > > > > > > memory mapped with large pages and make code allocator able to divide that > > > > > > page among several callers. > > > > > > > > > > > > So the idea was that jit_text_alloc() will have a cache of large pages > > > > > > mapped ROX, will allocate memory from those caches and there will be > > > > > > jit_update() that uses text poking for writing to that memory. > > > > > > > > > > > > Upon allocation of a large page to increase the cache, that large page will > > > > > > be "invalidated" by filling it with breakpoint instructions (e.g int3 on > > > > > > x86) > > > > > > > > > > Is this actually valid? In between int3 and real code, there’s a > > > > > potential torn read of real code mixed up with 0xcc. > > > > > > > > You mean while doing text poking? > > > > > > I think we've been getting distracted by text_poke(). text_poke() does > > > updates via a different virtual address which introduce new > > > synchroniation wrinkles, but it's not the main issue. > > > > > > As _think_ I understand it, the root of the issue is that speculative > > > execution - and that per Andy, speculative execution doesn't obey memory > > > barriers. > > > > > > I have _not_ dug into the details of how retpolines work and all the > > > spectre stuff that was going on, but - retpoline uses lfence, doesn't > > > it? And if speculative execution is the issue here, isn't retpoline what > > > we need? > > > > > > For this particular issue, I'm not sure "invalidate by filling with > > > illegal instructions" makes sense. For that to work, would the processor > > > have to execute a serialize operation and a retry on hitting an illegal > > > instruction - or perhaps we do in the interrupt handler? > > > > > > But if filling with illegal instructions does act as a speculation > > > barrier, then the issue is that a torn read could generate a legal but > > > incorrect instruction. > > > > What is a "torn read" here? I assume it is an instruction read that > > goes at the wrong instruction boundary (CISC). If this is correct, do > > we need to handle torn read caused by software bug, or hardware > > bit flip, or both? > > On ARM64 (RISC), torn reads can't happen because the instruction fetch > is word aligned. If we replace the whole instruction atomically then there > won't be half old - half new instruction fetches. Unfortunately, that's only guaranteed for a subset of instructions (e.g. B, NOP), and in general CPUs can fetch an instruction multiple times, and could fetch arbitrary portions of the instruction each time. Please see the "Concurrent Modification and Execution of instructions" rules in the ARM ARM. For arm64, in general, you need to inhibit any concurrent execution (e.g. by stopping-the-world) when patching text, and afterwards you need cache maintence followed by a context-syncrhonization-event (aking to an x86 serializing instruction) on CPUs which will execute the new instruction(s). There are a bunch of special cases where we can omit some of that, but in general the architectural guarnatees are *very* weak and require SW to perform several bits of work to guarantee the new instructions will be executed without issues. Thanks, Mark. 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 530E7EB64D7 for ; Mon, 26 Jun 2023 12:24:11 +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=OSPc18OSYwux6tUsI4EkPXG6JtNSqy1B9yrGYnnZmFU=; b=K0ETpTR72llDZt mAadgZrPsmyBq9Af632gx7cHTD/1HFh/u5eh2LJiH3uPfXnOgcSDE2NR7JTUHbpIi9XdG6bUwxdoa dIuAE2zMCpdTXhY5ORzS5pSKL7UyispplFkL8iMNMd4sZ1VtawXPjzKdNV+cwfl4oafWOmYZszm05 qj3+hUhRneCQLIucFJ5zKD25D1LZVtHbiid++Z1uWJpWSbe6U9BSQe7S0t0sd9K/E8QZ31vW78XZ0 yZHgMR43T6fnpQ103tV3RBy5ZomyO7S/boKMDa9QEKToWGy5ubm0kFxYYMDHkbLz06H45BsFe26ng lzHSI4Nx4hnfMz4ydn3Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qDlFt-00AC7O-1s; Mon, 26 Jun 2023 12:23:41 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qDlFp-00AC4e-0r; Mon, 26 Jun 2023 12:23:39 +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 E14312F4; Mon, 26 Jun 2023 05:24:12 -0700 (PDT) Received: from FVFF77S0Q05N (unknown [10.57.23.38]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA5173F64C; Mon, 26 Jun 2023 05:23:22 -0700 (PDT) Date: Mon, 26 Jun 2023 13:23:17 +0100 From: Mark Rutland To: Puranjay Mohan Cc: Song Liu , Kent Overstreet , Mike Rapoport , Andy Lutomirski , Kees Cook , Linux Kernel Mailing List , Andrew Morton , Catalin Marinas , Christophe Leroy , "David S. Miller" , Dinh Nguyen , Heiko Carstens , Helge Deller , Huacai Chen , Luis Chamberlain , Michael Ellerman , Nadav Amit , "Naveen N. Rao" , Palmer Dabbelt , Rick P Edgecombe , "Russell King (Oracle)" , Steven Rostedt , Thomas Bogendoerfer , Thomas Gleixner , Will Deacon , bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, linux-mm@kvack.org, linux-modules@vger.kernel.org, linux-parisc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, loongarch@lists.linux.dev, netdev@vger.kernel.org, sparclinux@vger.kernel.org, the arch/x86 maintainers , pjt@google.com, torvalds@linux-foundation.org Subject: Re: [PATCH v2 02/12] mm: introduce execmem_text_alloc() and jit_text_alloc() Message-ID: References: <20230616085038.4121892-3-rppt@kernel.org> <20230618080027.GA52412@kernel.org> <20230625161417.GK52412@kernel.org> <90161ac9-3ca0-4c72-b1c4-ab1293e55445@app.fastmail.com> <20230625174257.GL52412@kernel.org> <20230625180741.jrrtkq55c4jrqh3t@moria.home.lan> 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-20230626_052337_419074_70FA2467 X-CRM114-Status: GOOD ( 73.75 ) 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 T24gTW9uLCBKdW4gMjYsIDIwMjMgYXQgMTE6NTQ6MDJBTSArMDIwMCwgUHVyYW5qYXkgTW9oYW4g d3JvdGU6Cj4gT24gTW9uLCBKdW4gMjYsIDIwMjMgYXQgODoxM+KAr0FNIFNvbmcgTGl1IDxzb25n QGtlcm5lbC5vcmc+IHdyb3RlOgo+ID4KPiA+IE9uIFN1biwgSnVuIDI1LCAyMDIzIGF0IDExOjA3 4oCvQU0gS2VudCBPdmVyc3RyZWV0Cj4gPiA8a2VudC5vdmVyc3RyZWV0QGxpbnV4LmRldj4gd3Jv dGU6Cj4gPiA+Cj4gPiA+IE9uIFN1biwgSnVuIDI1LCAyMDIzIGF0IDA4OjQyOjU3UE0gKzAzMDAs IE1pa2UgUmFwb3BvcnQgd3JvdGU6Cj4gPiA+ID4gT24gU3VuLCBKdW4gMjUsIDIwMjMgYXQgMDk6 NTk6MzRBTSAtMDcwMCwgQW5keSBMdXRvbWlyc2tpIHdyb3RlOgo+ID4gPiA+ID4KPiA+ID4gPiA+ Cj4gPiA+ID4gPiBPbiBTdW4sIEp1biAyNSwgMjAyMywgYXQgOToxNCBBTSwgTWlrZSBSYXBvcG9y dCB3cm90ZToKPiA+ID4gPiA+ID4gT24gTW9uLCBKdW4gMTksIDIwMjMgYXQgMTA6MDk6MDJBTSAt MDcwMCwgQW5keSBMdXRvbWlyc2tpIHdyb3RlOgo+ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IE9u IFN1biwgSnVuIDE4LCAyMDIzLCBhdCAxOjAwIEFNLCBNaWtlIFJhcG9wb3J0IHdyb3RlOgo+ID4g PiA+ID4gPj4gPiBPbiBTYXQsIEp1biAxNywgMjAyMyBhdCAwMTozODoyOVBNIC0wNzAwLCBBbmR5 IEx1dG9taXJza2kgd3JvdGU6Cj4gPiA+ID4gPiA+PiA+PiBPbiBGcmksIEp1biAxNiwgMjAyMywg YXQgMTo1MCBBTSwgTWlrZSBSYXBvcG9ydCB3cm90ZToKPiA+ID4gPiA+ID4+ID4+ID4gRnJvbTog Ik1pa2UgUmFwb3BvcnQgKElCTSkiIDxycHB0QGtlcm5lbC5vcmc+Cj4gPiA+ID4gPiA+PiA+PiA+ Cj4gPiA+ID4gPiA+PiA+PiA+IG1vZHVsZV9hbGxvYygpIGlzIHVzZWQgZXZlcnl3aGVyZSBhcyBh IG1lYW4gdG8gYWxsb2NhdGUgbWVtb3J5IGZvciBjb2RlLgo+ID4gPiA+ID4gPj4gPj4gPgo+ID4g PiA+ID4gPj4gPj4gPiBCZXNpZGUgYmVpbmcgc2VtYW50aWNhbGx5IHdyb25nLCB0aGlzIHVubmVj ZXNzYXJpbHkgdGllcyBhbGwgc3Vic3lzdGVtcwo+ID4gPiA+ID4gPj4gPj4gPiB0aGF0IG5lZWQg dG8gYWxsb2NhdGUgY29kZSwgc3VjaCBhcyBmdHJhY2UsIGtwcm9iZXMgYW5kIEJQRiB0byBtb2R1 bGVzCj4gPiA+ID4gPiA+PiA+PiA+IGFuZCBwdXRzIHRoZSBidXJkZW4gb2YgY29kZSBhbGxvY2F0 aW9uIHRvIHRoZSBtb2R1bGVzIGNvZGUuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+ PiA+IFNldmVyYWwgYXJjaGl0ZWN0dXJlcyBvdmVycmlkZSBtb2R1bGVfYWxsb2MoKSBiZWNhdXNl IG9mIHZhcmlvdXMKPiA+ID4gPiA+ID4+ID4+ID4gY29uc3RyYWludHMgd2hlcmUgdGhlIGV4ZWN1 dGFibGUgbWVtb3J5IGNhbiBiZSBsb2NhdGVkIGFuZCB0aGlzIGNhdXNlcwo+ID4gPiA+ID4gPj4g Pj4gPiBhZGRpdGlvbmFsIG9ic3RhY2xlcyBmb3IgaW1wcm92ZW1lbnRzIG9mIGNvZGUgYWxsb2Nh dGlvbi4KPiA+ID4gPiA+ID4+ID4+ID4KPiA+ID4gPiA+ID4+ID4+ID4gU3RhcnQgc3BsaXR0aW5n IGNvZGUgYWxsb2NhdGlvbiBmcm9tIG1vZHVsZXMgYnkgaW50cm9kdWNpbmcKPiA+ID4gPiA+ID4+ ID4+ID4gZXhlY21lbV90ZXh0X2FsbG9jKCksIGV4ZWNtZW1fZnJlZSgpLCBqaXRfdGV4dF9hbGxv YygpLCBqaXRfZnJlZSgpIEFQSXMuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+PiA+ IEluaXRpYWxseSwgZXhlY21lbV90ZXh0X2FsbG9jKCkgYW5kIGppdF90ZXh0X2FsbG9jKCkgYXJl IHdyYXBwZXJzIGZvcgo+ID4gPiA+ID4gPj4gPj4gPiBtb2R1bGVfYWxsb2MoKSBhbmQgZXhlY21l bV9mcmVlKCkgYW5kIGppdF9mcmVlKCkgYXJlIHJlcGxhY2VtZW50cyBvZgo+ID4gPiA+ID4gPj4g Pj4gPiBtb2R1bGVfbWVtZnJlZSgpIHRvIGFsbG93IHVwZGF0aW5nIGFsbCBjYWxsIHNpdGVzIHRv IHVzZSB0aGUgbmV3IEFQSXMuCj4gPiA+ID4gPiA+PiA+PiA+Cj4gPiA+ID4gPiA+PiA+PiA+IFRo ZSBpbnRlbnRpb24gc2VtYW50aWNzIGZvciBuZXcgYWxsb2NhdGlvbiBBUElzOgo+ID4gPiA+ID4g Pj4gPj4gPgo+ID4gPiA+ID4gPj4gPj4gPiAqIGV4ZWNtZW1fdGV4dF9hbGxvYygpIHNob3VsZCBi ZSB1c2VkIHRvIGFsbG9jYXRlIG1lbW9yeSB0aGF0IG11c3QgcmVzaWRlCj4gPiA+ID4gPiA+PiA+ PiA+ICAgY2xvc2UgdG8gdGhlIGtlcm5lbCBpbWFnZSwgbGlrZSBsb2FkYWJsZSBrZXJuZWwgbW9k dWxlcyBhbmQgZ2VuZXJhdGVkCj4gPiA+ID4gPiA+PiA+PiA+ICAgY29kZSB0aGF0IGlzIHJlc3Ry aWN0ZWQgYnkgcmVsYXRpdmUgYWRkcmVzc2luZy4KPiA+ID4gPiA+ID4+ID4+ID4KPiA+ID4gPiA+ ID4+ID4+ID4gKiBqaXRfdGV4dF9hbGxvYygpIHNob3VsZCBiZSB1c2VkIHRvIGFsbG9jYXRlIG1l bW9yeSBmb3IgZ2VuZXJhdGVkIGNvZGUKPiA+ID4gPiA+ID4+ID4+ID4gICB3aGVuIHRoZXJlIGFy ZSBubyByZXN0cmljdGlvbnMgZm9yIHRoZSBjb2RlIHBsYWNlbWVudC4gRm9yCj4gPiA+ID4gPiA+ PiA+PiA+ICAgYXJjaGl0ZWN0dXJlcyB0aGF0IHJlcXVpcmUgdGhhdCBhbnkgY29kZSBpcyB3aXRo aW4gY2VydGFpbiBkaXN0YW5jZQo+ID4gPiA+ID4gPj4gPj4gPiAgIGZyb20gdGhlIGtlcm5lbCBp bWFnZSwgaml0X3RleHRfYWxsb2MoKSB3aWxsIGJlIGVzc2VudGlhbGx5IGFsaWFzZWQgdG8KPiA+ ID4gPiA+ID4+ID4+ID4gICBleGVjbWVtX3RleHRfYWxsb2MoKS4KPiA+ID4gPiA+ID4+ID4+ID4K PiA+ID4gPiA+ID4+ID4+Cj4gPiA+ID4gPiA+PiA+PiBJcyB0aGVyZSBhbnl0aGluZyBpbiB0aGlz IHNlcmllcyB0byBoZWxwIHVzZXJzIGRvIHRoZSBhcHByb3ByaWF0ZQo+ID4gPiA+ID4gPj4gPj4g c3luY2hyb25pemF0aW9uIHdoZW4gdGhlIGFjdHVhbGx5IHBvcHVsYXRlIHRoZSBhbGxvY2F0ZWQg bWVtb3J5IHdpdGgKPiA+ID4gPiA+ID4+ID4+IGNvZGU/ICBTZWUgaGVyZSwgZm9yIGV4YW1wbGU6 Cj4gPiA+ID4gPiA+PiA+Cj4gPiA+ID4gPiA+PiA+IFRoaXMgc2VyaWVzIG9ubHkgZmFjdG9ycyBv dXQgdGhlIGV4ZWN1dGFibGUgYWxsb2NhdGlvbnMgZnJvbSBtb2R1bGVzIGFuZAo+ID4gPiA+ID4g Pj4gPiBwdXRzIHRoZW0gaW4gYSBjZW50cmFsIHBsYWNlLgo+ID4gPiA+ID4gPj4gPiBBbnl0aGlu ZyBlbHNlIHdvdWxkIGdvIG9uIHRvcCBhZnRlciB0aGlzIGxhbmRzLgo+ID4gPiA+ID4gPj4KPiA+ ID4gPiA+ID4+IEhtbS4KPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiBPbiB0aGUgb25lIGhhbmQs IHRoZXJlJ3Mgbm90aGluZyB3cm9uZyB3aXRoIGZhY3RvcmluZyBvdXQgY29tbW9uIGNvZGUuIE9u Cj4gPiA+ID4gPiA+PiB0aGUgb3RoZXIgaGFuZCwgdGhpcyBpcyBwcm9iYWJseSB0aGUgcmlnaHQg dGltZSB0byBhdCBsZWFzdCBzdGFydAo+ID4gPiA+ID4gPj4gdGhpbmtpbmcgYWJvdXQgc3luY2hy b25pemF0aW9uLCBhdCBsZWFzdCB0byB0aGUgZXh0ZW50IHRoYXQgaXQgbWlnaHQgbWFrZQo+ID4g PiA+ID4gPj4gdXMgd2FudCB0byBjaGFuZ2UgdGhpcyBBUEkuICAoSSdtIG5vdCBhdCBhbGwgc2F5 aW5nIHRoYXQgdGhpcyBzZXJpZXMKPiA+ID4gPiA+ID4+IHNob3VsZCByZXF1aXJlIGNoYW5nZXMg LS0gSSdtIGp1c3Qgc2F5aW5nIHRoYXQgdGhpcyBpcyBhIGdvb2QgdGltZSB0bwo+ID4gPiA+ID4g Pj4gdGhpbmsgYWJvdXQgaG93IHRoaXMgc2hvdWxkIHdvcmsuKQo+ID4gPiA+ID4gPj4KPiA+ID4g PiA+ID4+IFRoZSBjdXJyZW50IEFQSXMsICphbmQqIHRoZSBwcm9wb3NlZCBqaXRfdGV4dF9hbGxv YygpIEFQSSwgZG9uJ3QgYWN0dWFsbHkKPiA+ID4gPiA+ID4+IGxvb2sgbGlrZSB0aGUgb25lIHRo aW5rIGluIHRoZSBMaW51eCBlY29zeXN0ZW0gdGhhdCBhY3R1YWxseQo+ID4gPiA+ID4gPj4gaW50 ZWxsaWdlbnRseSBhbmQgZWZmaWNpZW50bHkgbWFwcyBuZXcgdGV4dCBpbnRvIGFuIGFkZHJlc3Mg c3BhY2U6Cj4gPiA+ID4gPiA+PiBtbWFwKCkuCj4gPiA+ID4gPiA+Pgo+ID4gPiA+ID4gPj4gT24g eDg2LCB5b3UgY2FuIG1tYXAoKSBhbiBleGlzdGluZyBmaWxlIGZ1bGwgb2YgZXhlY3V0YWJsZSBj b2RlIFBST1RfRVhFQwo+ID4gPiA+ID4gPj4gYW5kIGp1bXAgdG8gaXQgd2l0aCBtaW5pbWFsIHN5 bmNocm9uaXphdGlvbiAoanVzdCB0aGUgc3RhbmRhcmQgaW1wbGljaXQKPiA+ID4gPiA+ID4+IG9y ZGVyaW5nIGluIHRoZSBrZXJuZWwgdGhhdCBwb3B1bGF0ZXMgdGhlIHBhZ2VzIGJlZm9yZSBzZXR0 aW5nIHVwIHRoZQo+ID4gPiA+ID4gPj4gUFRFcyBhbmQgd2hhdGV2ZXIgdXNlciBzeW5jaHJvbml6 YXRpb24gaXMgbmVlZGVkIHRvIGF2b2lkIGp1bXBpbmcgaW50bwo+ID4gPiA+ID4gPj4gdGhlIG1h cHBpbmcgYmVmb3JlIG1tYXAoKSBmaW5pc2hlcykuICBJdCB3b3JrcyBhY3Jvc3MgQ1BVcywgYW5k IHRoZSBvbmx5Cj4gPiA+ID4gPiA+PiBwb3NzaWJsZSB3YXkgdXNlcnNwYWNlIGNhbiBzY3JldyBp dCB1cCAoZm9yIGEgcmVhZC1vbmx5IG1hcHBpbmcgb2YKPiA+ID4gPiA+ID4+IHJlYWQtb25seSB0 ZXh0LCBhbnl3YXkpIGlzIHRvIGp1bXAgdG8gdGhlIG1hcHBpbmcgdG9vIGVhcmx5LCBpbiB3aGlj aAo+ID4gPiA+ID4gPj4gY2FzZSB1c2Vyc3BhY2UgZ2V0cyBhIHBhZ2UgZmF1bHQuICBJbmNvaGVy ZW5jZSBpcyBpbXBvc3NpYmxlLCBhbmQgbm8gb25lCj4gPiA+ID4gPiA+PiBuZWVkcyB0byAic2Vy aWFsaXplIiAoaW4gdGhlIFNETSBzZW5zZSkuCj4gPiA+ID4gPiA+Pgo+ID4gPiA+ID4gPj4gSSB0 aGluayB0aGUgc2FtZSBzZXF1ZW5jZSAoZnJvbSB1c2Vyc3BhY2UncyBwZXJzcGVjdGl2ZSkgd29y a3Mgb24gb3RoZXIKPiA+ID4gPiA+ID4+IGFyY2hpdGVjdHVyZXMsIHRvbywgYWx0aG91Z2ggSSB0 aGluayBtb3JlIGNhY2hlIG1hbmFnZW1lbnQgaXMgbmVlZGVkIG9uCj4gPiA+ID4gPiA+PiB0aGUg a2VybmVsJ3MgZW5kLiAgQXMgZmFyIGFzIEkga25vdywgbm8gTGludXggU01QIGFyY2hpdGVjdHVy ZSBuZWVkcyBhbgo+ID4gPiA+ID4gPj4gSVBJIHRvIG1hcCBleGVjdXRhYmxlIHRleHQgaW50byB1 c2VybW9kZSwgYnV0IEkgY291bGQgZWFzaWx5IGJlIHdyb25nLgo+ID4gPiA+ID4gPj4gKElJUkMg UklTQy1WIGhhcyB2ZXJ5IGRldmVsb3Blci11bmZyaWVuZGx5IGljYWNoZSBtYW5hZ2VtZW50LCBi dXQgSSBkb24ndAo+ID4gPiA+ID4gPj4gcmVtZW1iZXIgdGhlIGRldGFpbHMuKQo+ID4gPiA+ID4g Pj4KPiA+ID4gPiA+ID4+IE9mIGNvdXJzZSwgdXNpbmcgcHRyYWNlIG9yIGFueSBvdGhlciBGT0xM X0ZPUkNFIHRvIG1vZGlmeSB0ZXh0IG9uIHg4NiBpcwo+ID4gPiA+ID4gPj4gcmF0aGVyIGZyYXVn aHQsIGFuZCBJIGJldCBtYW55IHRoaW5ncyBkbyBpdCB3cm9uZyB3aGVuIHVzZXJzcGFjZSBpcwo+ ID4gPiA+ID4gPj4gbXVsdGl0aHJlYWRlZC4gIEJ1dCBub3QgaW4gcHJvZHVjdGlvbiBiZWNhdXNl IGl0J3MgbW9zdGx5IG5vdCB1c2VkIGluCj4gPiA+ID4gPiA+PiBwcm9kdWN0aW9uLikKPiA+ID4g PiA+ID4+Cj4gPiA+ID4gPiA+PiBCdXQgaml0X3RleHRfYWxsb2MoKSBjYW4ndCBkbyB0aGlzLCBi ZWNhdXNlIHRoZSBvcmRlciBvZiBvcGVyYXRpb25zCj4gPiA+ID4gPiA+PiBkb2Vzbid0IG1hdGNo LiAgV2l0aCBqaXRfdGV4dF9hbGxvYygpLCB0aGUgZXhlY3V0YWJsZSBtYXBwaW5nIHNob3dzIHVw Cj4gPiA+ID4gPiA+PiBiZWZvcmUgdGhlIHRleHQgaXMgcG9wdWxhdGVkLCBzbyB0aGVyZSBpcyBu byBhdG9taWMgY2hhbmdlIGZyb20gbm90LXRoZXJlCj4gPiA+ID4gPiA+PiB0byBwb3B1bGF0ZWQt YW5kLWV4ZWN1dGFibGUuICBXaGljaCBtZWFucyB0aGF0IHRoZXJlIGlzIGFuIG9wcG9ydHVuaXR5 Cj4gPiA+ID4gPiA+PiBmb3IgQ1BVcywgc3BlY3VsYXRpdmVseSBvciBvdGhlcndpc2UsIHRvIHN0 YXJ0IGZpbGxpbmcgdmFyaW91cyBjYWNoZXMKPiA+ID4gPiA+ID4+IHdpdGggaW50ZXJtZWRpYXRl IHN0YXRlcyBvZiB0aGUgdGV4dCwgd2hpY2ggbWVhbnMgdGhhdCB2YXJpb3VzCj4gPiA+ID4gPiA+ PiBhcmNoaXRlY3R1cmVzIChldmVuIHg4NiEpIG1heSBuZWVkIHNlcmlhbGl6YXRpb24uCj4gPiA+ ID4gPiA+Pgo+ID4gPiA+ID4gPj4gRm9yIGVCUEYtIGFuZCBtb2R1bGUtIGxpa2UgdXNlIGNhc2Vz LCB3aGVyZSBKSVR0aW5nL2NvZGUgZ2VuIGlzIHF1aXRlCj4gPiA+ID4gPiA+PiBjb2Fyc2UtZ3Jh aW5lZCwgcGVyaGFwcyBzb21ldGhpbmcgdmFndWVseSBsaWtlOgo+ID4gPiA+ID4gPj4KPiA+ID4g PiA+ID4+IGppdF90ZXh0X2FsbG9jKCkgLT4gcmV0dXJucyBhIGhhbmRsZSBhbmQgYW4gZXhlY3V0 YWJsZSB2aXJ0dWFsIGFkZHJlc3MsCj4gPiA+ID4gPiA+PiBidXQgZG9lcyAqbm90KiBtYXAgaXQg dGhlcmUKPiA+ID4gPiA+ID4+IGppdF90ZXh0X3dyaXRlKCkgLT4gd3JpdGUgdG8gdGhhdCBoYW5k bGUKPiA+ID4gPiA+ID4+IGppdF90ZXh0X21hcCgpIC0+IG1hcCBpdCBhbmQgc3luY2hyb25pemUg aWYgbmVlZGVkIChubyBzeW5jIG5lZWRlZCBvbgo+ID4gPiA+ID4gPj4geDg2LCBJIHRoaW5rKQo+ ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IGNvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGFuZC9vciBz YWZlci4KPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiAoTW9kdWxlcyBjb3VsZCB1c2UgdGhpcyB0 b28uICBHZXR0aW5nIGFsdGVybmF0aXZlcyByaWdodCBtaWdodCB0YWtlIHNvbWUKPiA+ID4gPiA+ ID4+IGZpZGRsaW5nLCBiZWNhdXNlIG9mZiB0aGUgdG9wIG9mIG15IGhlYWQsIHRoaXMgZG9lc24n dCBtYXRjaCBob3cgaXQgd29ya3MKPiA+ID4gPiA+ID4+IG5vdy4pCj4gPiA+ID4gPiA+Pgo+ID4g PiA+ID4gPj4gVG8gbWFrZSBhbHRlcm5hdGl2ZXMgZWFzaWVyLCB0aGlzIGNvdWxkIHdvcmssIG1h eWJlIChoYXZlbid0IGZ1bGx5Cj4gPiA+ID4gPiA+PiB0aG91Z2h0IGl0IHRocm91Z2gpOgo+ID4g PiA+ID4gPj4KPiA+ID4gPiA+ID4+IGppdF90ZXh0X2FsbG9jKCkKPiA+ID4gPiA+ID4+IGppdF90 ZXh0X21hcF9yd19pbnBsYWNlKCkgLT4gbWFwIGF0IHRoZSB0YXJnZXQgYWRkcmVzcywgYnV0IFJX LCAhWAo+ID4gPiA+ID4gPj4KPiA+ID4gPiA+ID4+IHdyaXRlIHRoZSB0ZXh0IGFuZCBhcHBseSBh bHRlcm5hdGl2ZXMKPiA+ID4gPiA+ID4+Cj4gPiA+ID4gPiA+PiBqaXRfdGV4dF9maW5hbGl6ZSgp IC0+IGNoYW5nZSBmcm9tIFJXIHRvIFJYICphbmQgc3luY2hyb25pemUqCj4gPiA+ID4gPiA+Pgo+ ID4gPiA+ID4gPj4gaml0X3RleHRfZmluYWxpemUoKSB3b3VsZCBlaXRoZXIgbmVlZCB0byB3YWl0 IGZvciBSQ1UgKHBvc3NpYmx5IGV4dHJhCj4gPiA+ID4gPiA+PiBoZWF2eSB3ZWlnaHQgUkNVIHRv IGdldCAic2VyaWFsaXphdGlvbiIpIG9yIHNlbmQgYW4gSVBJLgo+ID4gPiA+ID4gPgo+ID4gPiA+ ID4gPiBUaGlzIGVzc2VudGlhbGx5IGhvdyBtb2R1bGVzIHdvcmsgbm93LiBUaGUgbWVtb3J5IGlz IGFsbG9jYXRlZCBSVywgd3JpdHRlbgo+ID4gPiA+ID4gPiBhbmQgdXBkYXRlZCB3aXRoIGFsdGVy bmF0aXZlcyBhbmQgdGhlbiBtYWRlIFJPWCBpbiB0aGUgZW5kIHdpdGggc2V0X21lbW9yeQo+ID4g PiA+ID4gPiBBUElzLgo+ID4gPiA+ID4gPgo+ID4gPiA+ID4gPiBUaGUgaXNzdWUgd2l0aCBub3Qg aGF2aW5nIHRoZSBtZW1vcnkgbWFwcGVkIFggd2hlbiBpdCdzIHdyaXR0ZW4gaXMgdGhhdCB3ZQo+ ID4gPiA+ID4gPiBjYW5ub3QgdXNlIGxhcmdlIHBhZ2VzIHRvIG1hcCBpdC4gT25lIG9mIHRoZSBn b2FscyBpcyB0byBoYXZlIGV4ZWN1dGFibGUKPiA+ID4gPiA+ID4gbWVtb3J5IG1hcHBlZCB3aXRo IGxhcmdlIHBhZ2VzIGFuZCBtYWtlIGNvZGUgYWxsb2NhdG9yIGFibGUgdG8gZGl2aWRlIHRoYXQK PiA+ID4gPiA+ID4gcGFnZSBhbW9uZyBzZXZlcmFsIGNhbGxlcnMuCj4gPiA+ID4gPiA+Cj4gPiA+ ID4gPiA+IFNvIHRoZSBpZGVhIHdhcyB0aGF0IGppdF90ZXh0X2FsbG9jKCkgd2lsbCBoYXZlIGEg Y2FjaGUgb2YgbGFyZ2UgcGFnZXMKPiA+ID4gPiA+ID4gbWFwcGVkIFJPWCwgd2lsbCBhbGxvY2F0 ZSBtZW1vcnkgZnJvbSB0aG9zZSBjYWNoZXMgYW5kIHRoZXJlIHdpbGwgYmUKPiA+ID4gPiA+ID4g aml0X3VwZGF0ZSgpIHRoYXQgdXNlcyB0ZXh0IHBva2luZyBmb3Igd3JpdGluZyB0byB0aGF0IG1l bW9yeS4KPiA+ID4gPiA+ID4KPiA+ID4gPiA+ID4gVXBvbiBhbGxvY2F0aW9uIG9mIGEgbGFyZ2Ug cGFnZSB0byBpbmNyZWFzZSB0aGUgY2FjaGUsIHRoYXQgbGFyZ2UgcGFnZSB3aWxsCj4gPiA+ID4g PiA+IGJlICJpbnZhbGlkYXRlZCIgYnkgZmlsbGluZyBpdCB3aXRoIGJyZWFrcG9pbnQgaW5zdHJ1 Y3Rpb25zIChlLmcgaW50MyBvbgo+ID4gPiA+ID4gPiB4ODYpCj4gPiA+ID4gPgo+ID4gPiA+ID4g SXMgdGhpcyBhY3R1YWxseSB2YWxpZD8gIEluIGJldHdlZW4gaW50MyBhbmQgcmVhbCBjb2RlLCB0 aGVyZeKAmXMgYQo+ID4gPiA+ID4gcG90ZW50aWFsIHRvcm4gcmVhZCBvZiByZWFsIGNvZGUgbWl4 ZWQgdXAgd2l0aCAweGNjLgo+ID4gPiA+Cj4gPiA+ID4gWW91IG1lYW4gd2hpbGUgZG9pbmcgdGV4 dCBwb2tpbmc/Cj4gPiA+Cj4gPiA+IEkgdGhpbmsgd2UndmUgYmVlbiBnZXR0aW5nIGRpc3RyYWN0 ZWQgYnkgdGV4dF9wb2tlKCkuIHRleHRfcG9rZSgpIGRvZXMKPiA+ID4gdXBkYXRlcyB2aWEgYSBk aWZmZXJlbnQgdmlydHVhbCBhZGRyZXNzIHdoaWNoIGludHJvZHVjZSBuZXcKPiA+ID4gc3luY2hy b25pYXRpb24gd3JpbmtsZXMsIGJ1dCBpdCdzIG5vdCB0aGUgbWFpbiBpc3N1ZS4KPiA+ID4KPiA+ ID4gQXMgX3RoaW5rXyBJIHVuZGVyc3RhbmQgaXQsIHRoZSByb290IG9mIHRoZSBpc3N1ZSBpcyB0 aGF0IHNwZWN1bGF0aXZlCj4gPiA+IGV4ZWN1dGlvbiAtIGFuZCB0aGF0IHBlciBBbmR5LCBzcGVj dWxhdGl2ZSBleGVjdXRpb24gZG9lc24ndCBvYmV5IG1lbW9yeQo+ID4gPiBiYXJyaWVycy4KPiA+ ID4KPiA+ID4gSSBoYXZlIF9ub3RfIGR1ZyBpbnRvIHRoZSBkZXRhaWxzIG9mIGhvdyByZXRwb2xp bmVzIHdvcmsgYW5kIGFsbCB0aGUKPiA+ID4gc3BlY3RyZSBzdHVmZiB0aGF0IHdhcyBnb2luZyBv biwgYnV0IC0gcmV0cG9saW5lIHVzZXMgbGZlbmNlLCBkb2Vzbid0Cj4gPiA+IGl0PyBBbmQgaWYg c3BlY3VsYXRpdmUgZXhlY3V0aW9uIGlzIHRoZSBpc3N1ZSBoZXJlLCBpc24ndCByZXRwb2xpbmUg d2hhdAo+ID4gPiB3ZSBuZWVkPwo+ID4gPgo+ID4gPiBGb3IgdGhpcyBwYXJ0aWN1bGFyIGlzc3Vl LCBJJ20gbm90IHN1cmUgImludmFsaWRhdGUgYnkgZmlsbGluZyB3aXRoCj4gPiA+IGlsbGVnYWwg aW5zdHJ1Y3Rpb25zIiBtYWtlcyBzZW5zZS4gRm9yIHRoYXQgdG8gd29yaywgd291bGQgdGhlIHBy b2Nlc3Nvcgo+ID4gPiBoYXZlIHRvIGV4ZWN1dGUgYSBzZXJpYWxpemUgb3BlcmF0aW9uIGFuZCBh IHJldHJ5IG9uIGhpdHRpbmcgYW4gaWxsZWdhbAo+ID4gPiBpbnN0cnVjdGlvbiAtIG9yIHBlcmhh cHMgd2UgZG8gaW4gdGhlIGludGVycnVwdCBoYW5kbGVyPwo+ID4gPgo+ID4gPiBCdXQgaWYgZmls bGluZyB3aXRoIGlsbGVnYWwgaW5zdHJ1Y3Rpb25zIGRvZXMgYWN0IGFzIGEgc3BlY3VsYXRpb24K PiA+ID4gYmFycmllciwgdGhlbiB0aGUgaXNzdWUgaXMgdGhhdCBhIHRvcm4gcmVhZCBjb3VsZCBn ZW5lcmF0ZSBhIGxlZ2FsIGJ1dAo+ID4gPiBpbmNvcnJlY3QgaW5zdHJ1Y3Rpb24uCj4gPgo+ID4g V2hhdCBpcyBhICJ0b3JuIHJlYWQiIGhlcmU/IEkgYXNzdW1lIGl0IGlzIGFuIGluc3RydWN0aW9u IHJlYWQgdGhhdAo+ID4gZ29lcyBhdCB0aGUgd3JvbmcgaW5zdHJ1Y3Rpb24gYm91bmRhcnkgKENJ U0MpLiBJZiB0aGlzIGlzIGNvcnJlY3QsIGRvCj4gPiB3ZSBuZWVkIHRvIGhhbmRsZSB0b3JuIHJl YWQgY2F1c2VkIGJ5IHNvZnR3YXJlIGJ1Zywgb3IgaGFyZHdhcmUKPiA+IGJpdCBmbGlwLCBvciBi b3RoPwo+IAo+IE9uIEFSTTY0IChSSVNDKSwgdG9ybiByZWFkcyBjYW4ndCBoYXBwZW4gYmVjYXVz ZSB0aGUgaW5zdHJ1Y3Rpb24gZmV0Y2gKPiBpcyB3b3JkIGFsaWduZWQuIElmIHdlIHJlcGxhY2Ug dGhlIHdob2xlIGluc3RydWN0aW9uIGF0b21pY2FsbHkgdGhlbiB0aGVyZQo+IHdvbid0IGJlIGhh bGYgb2xkIC0gaGFsZiBuZXcgaW5zdHJ1Y3Rpb24gZmV0Y2hlcy4KClVuZm9ydHVuYXRlbHksIHRo YXQncyBvbmx5IGd1YXJhbnRlZWQgZm9yIGEgc3Vic2V0IG9mIGluc3RydWN0aW9ucyAoZS5nLiBC LApOT1ApLCBhbmQgaW4gZ2VuZXJhbCBDUFVzIGNhbiBmZXRjaCBhbiBpbnN0cnVjdGlvbiBtdWx0 aXBsZSB0aW1lcywgYW5kIGNvdWxkCmZldGNoIGFyYml0cmFyeSBwb3J0aW9ucyBvZiB0aGUgaW5z dHJ1Y3Rpb24gZWFjaCB0aW1lLgoKUGxlYXNlIHNlZSB0aGUgIkNvbmN1cnJlbnQgTW9kaWZpY2F0 aW9uIGFuZCBFeGVjdXRpb24gb2YgaW5zdHJ1Y3Rpb25zIiBydWxlcyBpbgp0aGUgQVJNIEFSTS4K CkZvciBhcm02NCwgaW4gZ2VuZXJhbCwgeW91IG5lZWQgdG8gaW5oaWJpdCBhbnkgY29uY3VycmVu dCBleGVjdXRpb24gKGUuZy4gYnkKc3RvcHBpbmctdGhlLXdvcmxkKSB3aGVuIHBhdGNoaW5nIHRl eHQsIGFuZCBhZnRlcndhcmRzIHlvdSBuZWVkIGNhY2hlIG1haW50ZW5jZQpmb2xsb3dlZCBieSBh IGNvbnRleHQtc3luY3Job25pemF0aW9uLWV2ZW50IChha2luZyB0byBhbiB4ODYgc2VyaWFsaXpp bmcKaW5zdHJ1Y3Rpb24pIG9uIENQVXMgd2hpY2ggd2lsbCBleGVjdXRlIHRoZSBuZXcgaW5zdHJ1 Y3Rpb24ocykuCgpUaGVyZSBhcmUgYSBidW5jaCBvZiBzcGVjaWFsIGNhc2VzIHdoZXJlIHdlIGNh biBvbWl0IHNvbWUgb2YgdGhhdCwgYnV0IGluCmdlbmVyYWwgdGhlIGFyY2hpdGVjdHVyYWwgZ3Vh cm5hdGVlcyBhcmUgKnZlcnkqIHdlYWsgYW5kIHJlcXVpcmUgU1cgdG8gcGVyZm9ybQpzZXZlcmFs IGJpdHMgb2Ygd29yayB0byBndWFyYW50ZWUgdGhlIG5ldyBpbnN0cnVjdGlvbnMgd2lsbCBiZSBl eGVjdXRlZCB3aXRob3V0IGlzc3Vlcy4KClRoYW5rcywKTWFyay4KCl9fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBs aXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5m cmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK