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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0CC4BC2BD05 for ; Mon, 24 Jun 2024 09:12:25 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 827D16B00CE; Mon, 24 Jun 2024 05:12:25 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7B0AF6B00DC; Mon, 24 Jun 2024 05:12:25 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6035C6B00DE; Mon, 24 Jun 2024 05:12:25 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 39BE26B00CE for ; Mon, 24 Jun 2024 05:12:25 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 70D99A0CCF for ; Mon, 24 Jun 2024 09:12:24 +0000 (UTC) X-FDA: 82265216208.04.40B6B58 Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) by imf29.hostedemail.com (Postfix) with ESMTP id 7FD5812000C for ; Mon, 24 Jun 2024 09:12:22 +0000 (UTC) Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=qJPPgXWS; spf=pass (imf29.hostedemail.com: domain of alexghiti@rivosinc.com designates 209.85.208.52 as permitted sender) smtp.mailfrom=alexghiti@rivosinc.com; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1719220324; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=4NoT4tiFRv/s+FeKQz4hkIebjaFz81VgxqTnNTWpsr4=; b=ieGW7kYnoe4uS1BCoMdmAMmTsbZ26kIN/LJ9ivuWKwharINP5L7HfYgwICaPqWnNL1AIP4 UfwYzY1vdjd8v6fKHS5NdS/K2XdWgktNm3C+zuI2aQkGb7RLLyeh/A1b+ECDnJnQkhSwNd MOuT/3icxgtwDfZQDNyOp4dSUNj1Wdc= ARC-Authentication-Results: i=1; imf29.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=qJPPgXWS; spf=pass (imf29.hostedemail.com: domain of alexghiti@rivosinc.com designates 209.85.208.52 as permitted sender) smtp.mailfrom=alexghiti@rivosinc.com; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1719220324; a=rsa-sha256; cv=none; b=VYaiPIjG74B6wtFLTr9RWDlQh95133oyK/TaSFU7vB8t1XwPom4Vt1wJ98DPfaAE/ut2SV fMYVfL3PtLrc1QMwcSH6ZXGFbJ12eLcP3I+diakvUUALUAKcVbCENKjKlSjvwQK1vxHdcZ Tb67moINDd5yY5Ew6iW8M5QzWJSSme8= Received: by mail-ed1-f52.google.com with SMTP id 4fb4d7f45d1cf-57d4ee2aaabso1003344a12.2 for ; Mon, 24 Jun 2024 02:12:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1719220341; x=1719825141; darn=kvack.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=4NoT4tiFRv/s+FeKQz4hkIebjaFz81VgxqTnNTWpsr4=; b=qJPPgXWSyNsRLx457n9kBx1jZej/LEcVEdUKCQdVjATZ66guDOxGw1/cuNA5lIQgXn rrN3qbaVN+wOBlOlj9TbGQxPjiCDDhHxS9GELD3viRoPItpTN+BtUNDPo84bWpOBjNhn TkM47SWn5p7/pGdr75PzW8ZkRVkFX7C38u5KScDbglW4CA+PBSkcXOZhw77qTR5lqVHE nJ3J5R8SHKg7Iw7WY7/TqUpNMYfj3bD4h4w+taExdVnQiL0pxHR/dREOaDrSoiD0tf3C fWUEsl8N6ztvFs1lrTMAmP6GpE+EIP4n27E2njzlkiALvhyGj0lfMdlNmf9GRD0mFBLT VRUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719220341; x=1719825141; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4NoT4tiFRv/s+FeKQz4hkIebjaFz81VgxqTnNTWpsr4=; b=fdr9Q3mA8gXp0GL7JRQMV0KTkHkYjvh8/OTA3JYyoJPNxK4VDRxR/jypLyZRHAG6ls D0Flu5IDXYM8F/u6p5qOuY5gkhat3l/rP6TRLO7HRIekky04ue6+MoFyJKz+jRDRD5iU dsJMU0UJqVzT+Z71vv536P2cQrpzKT+p6SRa4pdyihvioGXqvMXJgZHZQskh8vi49ZPf vHo+Mgl3bajw3W12Zz/IMiG4DebMHUCcgiHru80hCACQk0JyXAZEuynzSIfQkibhp6jw 4a6Hy8FooyBIwZKm3RAMMaL3sKcz3tvP91uiBy1B5/9Nr9JlMIm+uONleg30wg7RQbV2 XDIQ== X-Forwarded-Encrypted: i=1; AJvYcCXC2x1RgPKGUp4pl2NrCvpZRsl/hh2zZ+FpBmdj+OqCMUF5W0fSmCS5qJK5h62f1ghkk+0qXffwtFdreRTwk7cT498= X-Gm-Message-State: AOJu0YwSKU56qBPz9wOlxEHybYU5CrMAJuW/FDz6ZtCFT3Ci6yGdxcwH UrJgCEFmZaNHRrOk1uQ3M1khFdwaysr3tYm+P8/VoX/EX6e7KfbTC25x795b/FADsrKwsRn9diy 9GBdqPpbaREc6fevurLLLgEjx+Vz+54GxiPeOSQ== X-Google-Smtp-Source: AGHT+IGOy1j2v/vnzuIJB74hDQeCKIWRk/xmWnBaWpSTtZNOYKsZi9s5l6T6gnMC8fUAqGl90e0IWUwxjj60WefOHUc= X-Received: by 2002:a50:9358:0:b0:57c:8022:a3db with SMTP id 4fb4d7f45d1cf-57d4bd5651amr2478104a12.6.1719220341013; Mon, 24 Jun 2024 02:12:21 -0700 (PDT) MIME-Version: 1.0 References: <20240605114100.315918-1-bjorn@kernel.org> <20240605114100.315918-7-bjorn@kernel.org> In-Reply-To: <20240605114100.315918-7-bjorn@kernel.org> From: Alexandre Ghiti Date: Mon, 24 Jun 2024 11:12:09 +0200 Message-ID: Subject: Re: [PATCH v4 06/11] riscv: mm: Add memory hotplugging support To: =?UTF-8?B?QmrDtnJuIFTDtnBlbA==?= Cc: Albert Ou , David Hildenbrand , Palmer Dabbelt , Paul Walmsley , linux-riscv@lists.infradead.org, Oscar Salvador , =?UTF-8?B?QmrDtnJuIFTDtnBlbA==?= , Andrew Bresticker , Chethan Seshadri , Lorenzo Stoakes , Santosh Mamila , Sivakumar Munnangi , Sunil V L , linux-kernel@vger.kernel.org, linux-mm@kvack.org, virtualization@lists.linux-foundation.org Content-Type: multipart/alternative; boundary="000000000000b7994d061b9f2d13" X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 7FD5812000C X-Stat-Signature: dgtkhugohxcntquasgoww8nhzjji9hxp X-Rspam-User: X-HE-Tag: 1719220342-96645 X-HE-Meta: U2FsdGVkX1/QZW59MxLISJ890O5VGCGnAcba8QQuUcUa5OJ5V4N9BugdGuSlrDZQWB1qy6rXhtEUm2yHlbOJQmXWvdVsHEL7G3F5f+qWQ52TuBO5NwsR9L41LUqrobnBOV9n4XMaMjBndWgnPq649pCe4JhtjWUzZv25FcEcMtvwVV0ngE3oN+YCaCxoOOguZOb5QiPNP7NvHuVANXGv9E+idaK1qUJe/2zggFHJKrpFKEiDVBnJ107AXBzfvfrj8ukFF+fQZhcREjF/Pe5sMAK8bxYCiUeeG3UcEcNK1qkKWooC46YkQjcLws+wjfK2Ic5o+GkttjNLDG9p+fGtnsk3z1OwnKsHEAQjqgwfj3pPqx7FYKy96eM9ktFfZLS5a9nzTY/mVlXJ5t5dKVjUfvBWkTHszT4NF+4lyCaXwKY7NuGwm58Fw3567YTpRawI3dXi3fQmNJKAqY//EQgkPTGgp1EuC0ifbSSGz6VcGR+kt6giTPD4GcnE0NAMl1jjuGEJbQvn5oj9zpg3J7gZvXpLssKneoRzVNX8MRS8h7fChZA8/chIxIYlgAuCZyLJJcwpvhpRpiI0Dd1z3AfQxoBrtV+Eij5PXbxMHZz3SiHa9G8wqViPv/73juiuDFVipALI87iXDqTXJreAc/JLQTGmNyUB29eFAljkgu0ymhGBVKAZjQZL027E5jbG2buO6qimsxDSzzK12Mb3oaiSOMPqxoYrzQnmgmpEWj6/g5OQBfK89XWqJXi7a9d0UGp100ncACNwPGnqvlsnHb6AybTdS4R0PSLDDvl0FlC0T9Du4sghCrE5CFgfqMQosXn/b7coEMwJzjfq6CbNKCBBr9r/JocxpfOnJWe5IhpDrzdwapFc53FmVvKnubuMUOFwuXnDNASkZqpCHnL4k77SsLZk4UkyhCysdu0sM0mWe6d9KNbcgcDPjgMBceiUYGZAR91VHd4eyDEFfU79bnL jMF+NwRw /ETbBKxmwA2JUuG4uvgaqISILX7GMbfr11NYxXTHnvqE0EnL5eId3w8D4WQnjNm/rtm23ReB+lubyNbkJSORXfpc4iH/jsYABuUGpI/JLXRyd6JlKebAqYs8u2Hyl1cJbmigOISUlDSZSbB791Q9HS9FnmEHdPRzx41frO6glZ/Dr6xXb/3v0V4pLHkexP3F+VtsQaVKdiJhe4mEgCasIkBfP62e3QsbbwTOEqzu0r2X6ICmT0lTbHcl3N3VO/qcDNV44QFME9Lw/ADdoVfIzZUsKnz2BhHWOoMsOZTSBJX+iQE7v18/CKjwVg+YU8Q6JovoN02dutHxe22EF39BYysI94b2nuBccW3ITyt+alWFIAeBFdGudaAis0hCAO312l7hulKiMavz2JWfRaYuPTlEPR37R8LwWlhEeOTFh17OpM3LYPk6yXpHz8A0JR92J0YHkCJ0yKIgsT5KK/7EhLQcDf5DsBIPFyzVY X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: --000000000000b7994d061b9f2d13 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, Jun 5, 2024 at 1:41=E2=80=AFPM Bj=C3=B6rn T=C3=B6pel wrote: > From: Bj=C3=B6rn T=C3=B6pel > > For an architecture to support memory hotplugging, a couple of > callbacks needs to be implemented: > > arch_add_memory() > This callback is responsible for adding the physical memory into the > direct map, and call into the memory hotplugging generic code via > __add_pages() that adds the corresponding struct page entries, and > updates the vmemmap mapping. > > arch_remove_memory() > This is the inverse of the callback above. > > vmemmap_free() > This function tears down the vmemmap mappings (if > CONFIG_SPARSEMEM_VMEMMAP is enabled), and also deallocates the > backing vmemmap pages. Note that for persistent memory, an > alternative allocator for the backing pages can be used; The > vmem_altmap. This means that when the backing pages are cleared, > extra care is needed so that the correct deallocation method is > used. > > arch_get_mappable_range() > This functions returns the PA range that the direct map can map. > Used by the MHP internals for sanity checks. > > The page table unmap/teardown functions are heavily based on code from > the x86 tree. The same remove_pgd_mapping() function is used in both > vmemmap_free() and arch_remove_memory(), but in the latter function > the backing pages are not removed. > > Signed-off-by: Bj=C3=B6rn T=C3=B6pel > --- > arch/riscv/mm/init.c | 267 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 267 insertions(+) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index 1f7e7c223bec..bfa2dea95354 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -1534,3 +1534,270 @@ struct execmem_info __init > *execmem_arch_setup(void) > } > #endif /* CONFIG_MMU */ > #endif /* CONFIG_EXECMEM */ > + > +#ifdef CONFIG_MEMORY_HOTPLUG > +static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd) > +{ > + struct page *page =3D pmd_page(*pmd); > + struct ptdesc *ptdesc =3D page_ptdesc(page); > + pte_t *pte; > + int i; > + > + for (i =3D 0; i < PTRS_PER_PTE; i++) { > + pte =3D pte_start + i; > + if (!pte_none(*pte)) > + return; > + } > + > + pagetable_pte_dtor(ptdesc); > + if (PageReserved(page)) > + free_reserved_page(page); > + else > + pagetable_free(ptdesc); > + pmd_clear(pmd); > +} > + > +static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud) > +{ > + struct page *page =3D pud_page(*pud); > + struct ptdesc *ptdesc =3D page_ptdesc(page); > + pmd_t *pmd; > + int i; > + > + for (i =3D 0; i < PTRS_PER_PMD; i++) { > + pmd =3D pmd_start + i; > + if (!pmd_none(*pmd)) > + return; > + } > + > + pagetable_pmd_dtor(ptdesc); > + if (PageReserved(page)) > + free_reserved_page(page); > + else > + pagetable_free(ptdesc); > + pud_clear(pud); > +} > + > +static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d) > +{ > + struct page *page =3D p4d_page(*p4d); > + pud_t *pud; > + int i; > + > + for (i =3D 0; i < PTRS_PER_PUD; i++) { > + pud =3D pud_start + i; > + if (!pud_none(*pud)) > + return; > + } > + > + if (PageReserved(page)) > + free_reserved_page(page); > + else > + free_pages((unsigned long)page_address(page), 0); > + p4d_clear(p4d); > +} > + > +static void __meminit free_vmemmap_storage(struct page *page, size_t siz= e, > + struct vmem_altmap *altmap) > +{ > + int order =3D get_order(size); > + > + if (altmap) { > + vmem_altmap_free(altmap, size >> PAGE_SHIFT); > + return; > + } > + > + if (PageReserved(page)) { > + unsigned int nr_pages =3D 1 << order; > + > + while (nr_pages--) > + free_reserved_page(page++); > + return; > + } > + > + free_pages((unsigned long)page_address(page), order); > +} > + > +static void __meminit remove_pte_mapping(pte_t *pte_base, unsigned long > addr, unsigned long end, > + bool is_vmemmap, struct > vmem_altmap *altmap) > +{ > + unsigned long next; > + pte_t *ptep, pte; > + > + for (; addr < end; addr =3D next) { > + next =3D (addr + PAGE_SIZE) & PAGE_MASK; > + if (next > end) > + next =3D end; > + > + ptep =3D pte_base + pte_index(addr); > + pte =3D ptep_get(ptep); > + if (!pte_present(*ptep)) > + continue; > + > + pte_clear(&init_mm, addr, ptep); > + if (is_vmemmap) > + free_vmemmap_storage(pte_page(pte), PAGE_SIZE, > altmap); > + } > +} > + > +static void __meminit remove_pmd_mapping(pmd_t *pmd_base, unsigned long > addr, unsigned long end, > + bool is_vmemmap, struct > vmem_altmap *altmap) > +{ > + unsigned long next; > + pte_t *pte_base; > + pmd_t *pmdp, pmd; > + > + for (; addr < end; addr =3D next) { > + next =3D pmd_addr_end(addr, end); > + pmdp =3D pmd_base + pmd_index(addr); > + pmd =3D pmdp_get(pmdp); > + if (!pmd_present(pmd)) > + continue; > + > + if (pmd_leaf(pmd)) { > + pmd_clear(pmdp); > + if (is_vmemmap) > + free_vmemmap_storage(pmd_page(pmd), > PMD_SIZE, altmap); > + continue; > + } > + > + pte_base =3D (pte_t *)pmd_page_vaddr(*pmdp); > + remove_pte_mapping(pte_base, addr, next, is_vmemmap, > altmap); > + free_pte_table(pte_base, pmdp); > + } > +} > + > +static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long > addr, unsigned long end, > + bool is_vmemmap, struct > vmem_altmap *altmap) > +{ > + unsigned long next; > + pud_t *pudp, pud; > + pmd_t *pmd_base; > + > + for (; addr < end; addr =3D next) { > + next =3D pud_addr_end(addr, end); > + pudp =3D pud_base + pud_index(addr); > + pud =3D pudp_get(pudp); > + if (!pud_present(pud)) > + continue; > + > + if (pud_leaf(pud)) { > + if (pgtable_l4_enabled) { > + pud_clear(pudp); > + if (is_vmemmap) > + > free_vmemmap_storage(pud_page(pud), PUD_SIZE, altmap); > + } > + continue; > + } > + > + pmd_base =3D pmd_offset(pudp, 0); > + remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, > altmap); > + > + if (pgtable_l4_enabled) > + free_pmd_table(pmd_base, pudp); > + } > +} > + > +static void __meminit remove_p4d_mapping(p4d_t *p4d_base, unsigned long > addr, unsigned long end, > + bool is_vmemmap, struct > vmem_altmap *altmap) > +{ > + unsigned long next; > + p4d_t *p4dp, p4d; > + pud_t *pud_base; > + > + for (; addr < end; addr =3D next) { > + next =3D p4d_addr_end(addr, end); > + p4dp =3D p4d_base + p4d_index(addr); > + p4d =3D p4dp_get(p4dp); > + if (!p4d_present(p4d)) > + continue; > + > + if (p4d_leaf(p4d)) { > + if (pgtable_l5_enabled) { > + p4d_clear(p4dp); > + if (is_vmemmap) > + > free_vmemmap_storage(p4d_page(p4d), P4D_SIZE, altmap); > + } > + continue; > + } > + > + pud_base =3D pud_offset(p4dp, 0); > + remove_pud_mapping(pud_base, addr, next, is_vmemmap, > altmap); > + > + if (pgtable_l5_enabled) > + free_pud_table(pud_base, p4dp); > + } > +} > + > +static void __meminit remove_pgd_mapping(unsigned long va, unsigned long > end, bool is_vmemmap, > + struct vmem_altmap *altmap) > +{ > + unsigned long addr, next; > + p4d_t *p4d_base; > + pgd_t *pgd; > + > + for (addr =3D va; addr < end; addr =3D next) { > + next =3D pgd_addr_end(addr, end); > + pgd =3D pgd_offset_k(addr); > + > + if (!pgd_present(*pgd)) > + continue; > + > + if (pgd_leaf(*pgd)) > + continue; > + > + p4d_base =3D p4d_offset(pgd, 0); > + remove_p4d_mapping(p4d_base, addr, next, is_vmemmap, > altmap); > + } > + > + flush_tlb_all(); > +} > + > +static void __meminit remove_linear_mapping(phys_addr_t start, u64 size) > +{ > + unsigned long va =3D (unsigned long)__va(start); > + unsigned long end =3D (unsigned long)__va(start + size); > + > + remove_pgd_mapping(va, end, false, NULL); > +} > + > +struct range arch_get_mappable_range(void) > +{ > + struct range mhp_range; > + > + mhp_range.start =3D __pa(PAGE_OFFSET); > + mhp_range.end =3D __pa(PAGE_END - 1); > + return mhp_range; > +} > + > +int __ref arch_add_memory(int nid, u64 start, u64 size, struct mhp_param= s > *params) > +{ > + int ret =3D 0; > + > + create_linear_mapping_range(start, start + size, 0, > ¶ms->pgprot); > + ret =3D __add_pages(nid, start >> PAGE_SHIFT, size >> PAGE_SHIFT, > params); > + if (ret) { > + remove_linear_mapping(start, size); > + goto out; > + } > + > + max_pfn =3D PFN_UP(start + size); > + max_low_pfn =3D max_pfn; > + > + out: > + flush_tlb_all(); > + return ret; > +} > + > +void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap > *altmap) > +{ > + __remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap); > + remove_linear_mapping(start, size); > + flush_tlb_all(); > +} > + > +void __ref vmemmap_free(unsigned long start, unsigned long end, struct > vmem_altmap *altmap) > +{ > + remove_pgd_mapping(start, end, true, altmap); > +} > +#endif /* CONFIG_MEMORY_HOTPLUG */ > -- > 2.43.0 > > Reviewed-by: Alexandre Ghiti Thanks, Alex --000000000000b7994d061b9f2d13 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdiBkaXI9Imx0ciI+T24gV2VkLCBKdW4gNSwgMjAyNCBhdCAxOjQx 4oCvUE0gQmrDtnJuIFTDtnBlbCAmbHQ7PGEgaHJlZj0ibWFpbHRvOmJqb3JuQGtlcm5lbC5vcmci PmJqb3JuQGtlcm5lbC5vcmc8L2E+Jmd0OyB3cm90ZTo8YnI+PC9kaXY+PGRpdiBjbGFzcz0iZ21h aWxfcXVvdGUiPjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjow cHggMHB4IDBweCAwLjhleDtib3JkZXItbGVmdDoxcHggc29saWQgcmdiKDIwNCwyMDQsMjA0KTtw YWRkaW5nLWxlZnQ6MWV4Ij5Gcm9tOiBCasO2cm4gVMO2cGVsICZsdDs8YSBocmVmPSJtYWlsdG86 Ympvcm5Acml2b3NpbmMuY29tIiB0YXJnZXQ9Il9ibGFuayI+Ympvcm5Acml2b3NpbmMuY29tPC9h PiZndDs8YnI+DQo8YnI+DQpGb3IgYW4gYXJjaGl0ZWN0dXJlIHRvIHN1cHBvcnQgbWVtb3J5IGhv dHBsdWdnaW5nLCBhIGNvdXBsZSBvZjxicj4NCmNhbGxiYWNrcyBuZWVkcyB0byBiZSBpbXBsZW1l bnRlZDo8YnI+DQo8YnI+DQrCoGFyY2hfYWRkX21lbW9yeSgpPGJyPg0KwqAgVGhpcyBjYWxsYmFj ayBpcyByZXNwb25zaWJsZSBmb3IgYWRkaW5nIHRoZSBwaHlzaWNhbCBtZW1vcnkgaW50byB0aGU8 YnI+DQrCoCBkaXJlY3QgbWFwLCBhbmQgY2FsbCBpbnRvIHRoZSBtZW1vcnkgaG90cGx1Z2dpbmcg Z2VuZXJpYyBjb2RlIHZpYTxicj4NCsKgIF9fYWRkX3BhZ2VzKCkgdGhhdCBhZGRzIHRoZSBjb3Jy ZXNwb25kaW5nIHN0cnVjdCBwYWdlIGVudHJpZXMsIGFuZDxicj4NCsKgIHVwZGF0ZXMgdGhlIHZt ZW1tYXAgbWFwcGluZy48YnI+DQo8YnI+DQrCoGFyY2hfcmVtb3ZlX21lbW9yeSgpPGJyPg0KwqAg VGhpcyBpcyB0aGUgaW52ZXJzZSBvZiB0aGUgY2FsbGJhY2sgYWJvdmUuPGJyPg0KPGJyPg0KwqB2 bWVtbWFwX2ZyZWUoKTxicj4NCsKgIFRoaXMgZnVuY3Rpb24gdGVhcnMgZG93biB0aGUgdm1lbW1h cCBtYXBwaW5ncyAoaWY8YnI+DQrCoCBDT05GSUdfU1BBUlNFTUVNX1ZNRU1NQVAgaXMgZW5hYmxl ZCksIGFuZCBhbHNvIGRlYWxsb2NhdGVzIHRoZTxicj4NCsKgIGJhY2tpbmcgdm1lbW1hcCBwYWdl cy4gTm90ZSB0aGF0IGZvciBwZXJzaXN0ZW50IG1lbW9yeSwgYW48YnI+DQrCoCBhbHRlcm5hdGl2 ZSBhbGxvY2F0b3IgZm9yIHRoZSBiYWNraW5nIHBhZ2VzIGNhbiBiZSB1c2VkOyBUaGU8YnI+DQrC oCB2bWVtX2FsdG1hcC4gVGhpcyBtZWFucyB0aGF0IHdoZW4gdGhlIGJhY2tpbmcgcGFnZXMgYXJl IGNsZWFyZWQsPGJyPg0KwqAgZXh0cmEgY2FyZSBpcyBuZWVkZWQgc28gdGhhdCB0aGUgY29ycmVj dCBkZWFsbG9jYXRpb24gbWV0aG9kIGlzPGJyPg0KwqAgdXNlZC48YnI+DQo8YnI+DQrCoGFyY2hf Z2V0X21hcHBhYmxlX3JhbmdlKCk8YnI+DQrCoCBUaGlzIGZ1bmN0aW9ucyByZXR1cm5zIHRoZSBQ QSByYW5nZSB0aGF0IHRoZSBkaXJlY3QgbWFwIGNhbiBtYXAuPGJyPg0KwqAgVXNlZCBieSB0aGUg TUhQIGludGVybmFscyBmb3Igc2FuaXR5IGNoZWNrcy48YnI+DQo8YnI+DQpUaGUgcGFnZSB0YWJs ZSB1bm1hcC90ZWFyZG93biBmdW5jdGlvbnMgYXJlIGhlYXZpbHkgYmFzZWQgb24gY29kZSBmcm9t PGJyPg0KdGhlIHg4NiB0cmVlLiBUaGUgc2FtZSByZW1vdmVfcGdkX21hcHBpbmcoKSBmdW5jdGlv biBpcyB1c2VkIGluIGJvdGg8YnI+DQp2bWVtbWFwX2ZyZWUoKSBhbmQgYXJjaF9yZW1vdmVfbWVt b3J5KCksIGJ1dCBpbiB0aGUgbGF0dGVyIGZ1bmN0aW9uPGJyPg0KdGhlIGJhY2tpbmcgcGFnZXMg YXJlIG5vdCByZW1vdmVkLjxicj4NCjxicj4NClNpZ25lZC1vZmYtYnk6IEJqw7ZybiBUw7ZwZWwg Jmx0OzxhIGhyZWY9Im1haWx0bzpiam9ybkByaXZvc2luYy5jb20iIHRhcmdldD0iX2JsYW5rIj5i am9ybkByaXZvc2luYy5jb208L2E+Jmd0Ozxicj4NCi0tLTxicj4NCsKgYXJjaC9yaXNjdi9tbS9p bml0LmMgfCAyNjcgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKzxi cj4NCsKgMSBmaWxlIGNoYW5nZWQsIDI2NyBpbnNlcnRpb25zKCspPGJyPg0KPGJyPg0KZGlmZiAt LWdpdCBhL2FyY2gvcmlzY3YvbW0vaW5pdC5jIGIvYXJjaC9yaXNjdi9tbS9pbml0LmM8YnI+DQpp bmRleCAxZjdlN2MyMjNiZWMuLmJmYTJkZWE5NTM1NCAxMDA2NDQ8YnI+DQotLS0gYS9hcmNoL3Jp c2N2L21tL2luaXQuYzxicj4NCisrKyBiL2FyY2gvcmlzY3YvbW0vaW5pdC5jPGJyPg0KQEAgLTE1 MzQsMyArMTUzNCwyNzAgQEAgc3RydWN0IGV4ZWNtZW1faW5mbyBfX2luaXQgKmV4ZWNtZW1fYXJj aF9zZXR1cCh2b2lkKTxicj4NCsKgfTxicj4NCsKgI2VuZGlmIC8qIENPTkZJR19NTVUgKi88YnI+ DQrCoCNlbmRpZiAvKiBDT05GSUdfRVhFQ01FTSAqLzxicj4NCis8YnI+DQorI2lmZGVmIENPTkZJ R19NRU1PUllfSE9UUExVRzxicj4NCitzdGF0aWMgdm9pZCBfX21lbWluaXQgZnJlZV9wdGVfdGFi bGUocHRlX3QgKnB0ZV9zdGFydCwgcG1kX3QgKnBtZCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDC oHN0cnVjdCBwYWdlICpwYWdlID0gcG1kX3BhZ2UoKnBtZCk7PGJyPg0KK8KgIMKgIMKgIMKgc3Ry dWN0IHB0ZGVzYyAqcHRkZXNjID0gcGFnZV9wdGRlc2MocGFnZSk7PGJyPg0KK8KgIMKgIMKgIMKg cHRlX3QgKnB0ZTs8YnI+DQorwqAgwqAgwqAgwqBpbnQgaTs8YnI+DQorPGJyPg0KK8KgIMKgIMKg IMKgZm9yIChpID0gMDsgaSAmbHQ7IFBUUlNfUEVSX1BURTsgaSsrKSB7PGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgcHRlID0gcHRlX3N0YXJ0ICsgaTs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBpZiAoIXB0ZV9ub25lKCpwdGUpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoHJldHVybjs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4NCivCoCDC oCDCoCDCoHBhZ2V0YWJsZV9wdGVfZHRvcihwdGRlc2MpOzxicj4NCivCoCDCoCDCoCDCoGlmIChQ YWdlUmVzZXJ2ZWQocGFnZSkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZnJlZV9yZXNl cnZlZF9wYWdlKHBhZ2UpOzxicj4NCivCoCDCoCDCoCDCoGVsc2U8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBwYWdldGFibGVfZnJlZShwdGRlc2MpOzxicj4NCivCoCDCoCDCoCDCoHBtZF9j bGVhcihwbWQpOzxicj4NCit9PGJyPg0KKzxicj4NCitzdGF0aWMgdm9pZCBfX21lbWluaXQgZnJl ZV9wbWRfdGFibGUocG1kX3QgKnBtZF9zdGFydCwgcHVkX3QgKnB1ZCk8YnI+DQorezxicj4NCivC oCDCoCDCoCDCoHN0cnVjdCBwYWdlICpwYWdlID0gcHVkX3BhZ2UoKnB1ZCk7PGJyPg0KK8KgIMKg IMKgIMKgc3RydWN0IHB0ZGVzYyAqcHRkZXNjID0gcGFnZV9wdGRlc2MocGFnZSk7PGJyPg0KK8Kg IMKgIMKgIMKgcG1kX3QgKnBtZDs8YnI+DQorwqAgwqAgwqAgwqBpbnQgaTs8YnI+DQorPGJyPg0K K8KgIMKgIMKgIMKgZm9yIChpID0gMDsgaSAmbHQ7IFBUUlNfUEVSX1BNRDsgaSsrKSB7PGJyPg0K K8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcG1kID0gcG1kX3N0YXJ0ICsgaTs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBpZiAoIXBtZF9ub25lKCpwbWQpKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybjs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxi cj4NCivCoCDCoCDCoCDCoHBhZ2V0YWJsZV9wbWRfZHRvcihwdGRlc2MpOzxicj4NCivCoCDCoCDC oCDCoGlmIChQYWdlUmVzZXJ2ZWQocGFnZSkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg ZnJlZV9yZXNlcnZlZF9wYWdlKHBhZ2UpOzxicj4NCivCoCDCoCDCoCDCoGVsc2U8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBwYWdldGFibGVfZnJlZShwdGRlc2MpOzxicj4NCivCoCDCoCDC oCDCoHB1ZF9jbGVhcihwdWQpOzxicj4NCit9PGJyPg0KKzxicj4NCitzdGF0aWMgdm9pZCBfX21l bWluaXQgZnJlZV9wdWRfdGFibGUocHVkX3QgKnB1ZF9zdGFydCwgcDRkX3QgKnA0ZCk8YnI+DQor ezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCBwYWdlICpwYWdlID0gcDRkX3BhZ2UoKnA0ZCk7PGJy Pg0KK8KgIMKgIMKgIMKgcHVkX3QgKnB1ZDs8YnI+DQorwqAgwqAgwqAgwqBpbnQgaTs8YnI+DQor PGJyPg0KK8KgIMKgIMKgIMKgZm9yIChpID0gMDsgaSAmbHQ7IFBUUlNfUEVSX1BVRDsgaSsrKSB7 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcHVkID0gcHVkX3N0YXJ0ICsgaTs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoIXB1ZF9ub25lKCpwdWQpKTxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybjs8YnI+DQorwqAgwqAgwqAgwqB9PGJy Pg0KKzxicj4NCivCoCDCoCDCoCDCoGlmIChQYWdlUmVzZXJ2ZWQocGFnZSkpPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgZnJlZV9yZXNlcnZlZF9wYWdlKHBhZ2UpOzxicj4NCivCoCDCoCDC oCDCoGVsc2U8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmcmVlX3BhZ2VzKCh1bnNpZ25l ZCBsb25nKXBhZ2VfYWRkcmVzcyhwYWdlKSwgMCk7PGJyPg0KK8KgIMKgIMKgIMKgcDRkX2NsZWFy KHA0ZCk7PGJyPg0KK308YnI+DQorPGJyPg0KK3N0YXRpYyB2b2lkIF9fbWVtaW5pdCBmcmVlX3Zt ZW1tYXBfc3RvcmFnZShzdHJ1Y3QgcGFnZSAqcGFnZSwgc2l6ZV90IHNpemUsPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IHN0cnVjdCB2bWVtX2FsdG1hcCAqYWx0bWFwKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgaW50 IG9yZGVyID0gZ2V0X29yZGVyKHNpemUpOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBpZiAoYWx0 bWFwKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgdm1lbV9hbHRtYXBfZnJlZShhbHRt YXAsIHNpemUgJmd0OyZndDsgUEFHRV9TSElGVCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgcmV0dXJuOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgaWYg KFBhZ2VSZXNlcnZlZChwYWdlKSkgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHVuc2ln bmVkIGludCBucl9wYWdlcyA9IDEgJmx0OyZsdDsgb3JkZXI7PGJyPg0KKzxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoHdoaWxlIChucl9wYWdlcy0tKTxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoGZyZWVfcmVzZXJ2ZWRfcGFnZShwYWdlKyspOzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHJldHVybjs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4N CivCoCDCoCDCoCDCoGZyZWVfcGFnZXMoKHVuc2lnbmVkIGxvbmcpcGFnZV9hZGRyZXNzKHBhZ2Up LCBvcmRlcik7PGJyPg0KK308YnI+DQorPGJyPg0KK3N0YXRpYyB2b2lkIF9fbWVtaW5pdCByZW1v dmVfcHRlX21hcHBpbmcocHRlX3QgKnB0ZV9iYXNlLCB1bnNpZ25lZCBsb25nIGFkZHIsIHVuc2ln bmVkIGxvbmcgZW5kLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBib29sIGlzX3ZtZW1tYXAsIHN0cnVjdCB2bWVtX2FsdG1h cCAqYWx0bWFwKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgdW5zaWduZWQgbG9uZyBuZXh0Ozxi cj4NCivCoCDCoCDCoCDCoHB0ZV90ICpwdGVwLCBwdGU7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDC oGZvciAoOyBhZGRyICZsdDsgZW5kOyBhZGRyID0gbmV4dCkgezxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoG5leHQgPSAoYWRkciArIFBBR0VfU0laRSkgJmFtcDsgUEFHRV9NQVNLOzxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChuZXh0ICZndDsgZW5kKTxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoG5leHQgPSBlbmQ7PGJyPg0KKzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoHB0ZXAgPSBwdGVfYmFzZSArIHB0ZV9pbmRleChhZGRyKTs8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwdGUgPSBwdGVwX2dldChwdGVwKTs8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoIXB0ZV9wcmVzZW50KCpwdGVwKSk8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjb250aW51ZTs8YnI+DQorPGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgIMKgcHRlX2NsZWFyKCZhbXA7aW5pdF9tbSwgYWRkciwgcHRlcCk7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGlzX3ZtZW1tYXApPGJyPg0KK8KgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgZnJlZV92bWVtbWFwX3N0b3JhZ2UocHRlX3BhZ2Uo cHRlKSwgUEFHRV9TSVpFLCBhbHRtYXApOzxicj4NCivCoCDCoCDCoCDCoH08YnI+DQorfTxicj4N Cis8YnI+DQorc3RhdGljIHZvaWQgX19tZW1pbml0IHJlbW92ZV9wbWRfbWFwcGluZyhwbWRfdCAq cG1kX2Jhc2UsIHVuc2lnbmVkIGxvbmcgYWRkciwgdW5zaWduZWQgbG9uZyBlbmQsPGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IGJvb2wgaXNfdm1lbW1hcCwgc3RydWN0IHZtZW1fYWx0bWFwICphbHRtYXApPGJyPg0KK3s8YnI+ DQorwqAgwqAgwqAgwqB1bnNpZ25lZCBsb25nIG5leHQ7PGJyPg0KK8KgIMKgIMKgIMKgcHRlX3Qg KnB0ZV9iYXNlOzxicj4NCivCoCDCoCDCoCDCoHBtZF90ICpwbWRwLCBwbWQ7PGJyPg0KKzxicj4N CivCoCDCoCDCoCDCoGZvciAoOyBhZGRyICZsdDsgZW5kOyBhZGRyID0gbmV4dCkgezxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoG5leHQgPSBwbWRfYWRkcl9lbmQoYWRkciwgZW5kKTs8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwbWRwID0gcG1kX2Jhc2UgKyBwbWRfaW5kZXgoYWRk cik7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcG1kID0gcG1kcF9nZXQocG1kcCk7PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKCFwbWRfcHJlc2VudChwbWQpKTxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNvbnRpbnVlOzxicj4NCis8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAocG1kX2xlYWYocG1kKSkgezxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBtZF9jbGVhcihwbWRwKTs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaXNfdm1lbW1hcCk8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmcmVlX3ZtZW1tYXBfc3Rv cmFnZShwbWRfcGFnZShwbWQpLCBQTURfU0laRSwgYWx0bWFwKTs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjb250aW51ZTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqB9PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHB0ZV9iYXNlID0gKHB0 ZV90ICopcG1kX3BhZ2VfdmFkZHIoKnBtZHApOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oHJlbW92ZV9wdGVfbWFwcGluZyhwdGVfYmFzZSwgYWRkciwgbmV4dCwgaXNfdm1lbW1hcCwgYWx0 bWFwKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBmcmVlX3B0ZV90YWJsZShwdGVfYmFz ZSwgcG1kcCk7PGJyPg0KK8KgIMKgIMKgIMKgfTxicj4NCit9PGJyPg0KKzxicj4NCitzdGF0aWMg dm9pZCBfX21lbWluaXQgcmVtb3ZlX3B1ZF9tYXBwaW5nKHB1ZF90ICpwdWRfYmFzZSwgdW5zaWdu ZWQgbG9uZyBhZGRyLCB1bnNpZ25lZCBsb25nIGVuZCw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYm9vbCBpc192bWVtbWFw LCBzdHJ1Y3Qgdm1lbV9hbHRtYXAgKmFsdG1hcCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHVu c2lnbmVkIGxvbmcgbmV4dDs8YnI+DQorwqAgwqAgwqAgwqBwdWRfdCAqcHVkcCwgcHVkOzxicj4N CivCoCDCoCDCoCDCoHBtZF90ICpwbWRfYmFzZTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgZm9y ICg7IGFkZHIgJmx0OyBlbmQ7IGFkZHIgPSBuZXh0KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgbmV4dCA9IHB1ZF9hZGRyX2VuZChhZGRyLCBlbmQpOzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoHB1ZHAgPSBwdWRfYmFzZSArIHB1ZF9pbmRleChhZGRyKTs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqBwdWQgPSBwdWRwX2dldChwdWRwKTs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqBpZiAoIXB1ZF9wcmVzZW50KHB1ZCkpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgY29udGludWU7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoGlmIChwdWRfbGVhZihwdWQpKSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaWYgKHBndGFibGVfbDRfZW5hYmxlZCkgezxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHB1ZF9jbGVhcihwdWRwKTs8YnI+DQor wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoaXNfdm1l bW1hcCk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqBmcmVlX3ZtZW1tYXBfc3RvcmFnZShwdWRfcGFnZShwdWQpLCBQVURfU0la RSwgYWx0bWFwKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgY29udGludWU7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgfTxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBwbWRfYmFzZSA9IHBtZF9vZmZzZXQocHVkcCwgMCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgcmVtb3ZlX3BtZF9tYXBwaW5nKHBtZF9iYXNlLCBhZGRyLCBuZXh0LCBpc192bWVtbWFw LCBhbHRtYXApOzxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAocGd0YWJs ZV9sNF9lbmFibGVkKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZy ZWVfcG1kX3RhYmxlKHBtZF9iYXNlLCBwdWRwKTs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KK308 YnI+DQorPGJyPg0KK3N0YXRpYyB2b2lkIF9fbWVtaW5pdCByZW1vdmVfcDRkX21hcHBpbmcocDRk X3QgKnA0ZF9iYXNlLCB1bnNpZ25lZCBsb25nIGFkZHIsIHVuc2lnbmVkIGxvbmcgZW5kLDxicj4N CivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBib29sIGlzX3ZtZW1tYXAsIHN0cnVjdCB2bWVtX2FsdG1hcCAqYWx0bWFwKTxicj4NCit7 PGJyPg0KK8KgIMKgIMKgIMKgdW5zaWduZWQgbG9uZyBuZXh0Ozxicj4NCivCoCDCoCDCoCDCoHA0 ZF90ICpwNGRwLCBwNGQ7PGJyPg0KK8KgIMKgIMKgIMKgcHVkX3QgKnB1ZF9iYXNlOzxicj4NCis8 YnI+DQorwqAgwqAgwqAgwqBmb3IgKDsgYWRkciAmbHQ7IGVuZDsgYWRkciA9IG5leHQpIHs8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBuZXh0ID0gcDRkX2FkZHJfZW5kKGFkZHIsIGVuZCk7 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcDRkcCA9IHA0ZF9iYXNlICsgcDRkX2luZGV4 KGFkZHIpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHA0ZCA9IHA0ZHBfZ2V0KHA0ZHAp Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmICghcDRkX3ByZXNlbnQocDRkKSk8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjb250aW51ZTs8YnI+DQorPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHA0ZF9sZWFmKHA0ZCkpIHs8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAocGd0YWJsZV9sNV9lbmFibGVkKSB7 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcDRk X2NsZWFyKHA0ZHApOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGlmIChpc192bWVtbWFwKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZyZWVfdm1lbW1hcF9zdG9yYWdlKHA0 ZF9wYWdlKHA0ZCksIFA0RF9TSVpFLCBhbHRtYXApOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoH08YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBjb250aW51ZTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoHB1ZF9iYXNlID0gcHVkX29mZnNldChwNGRwLCAwKTs8YnI+ DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZW1vdmVfcHVkX21hcHBpbmcocHVkX2Jhc2UsIGFk ZHIsIG5leHQsIGlzX3ZtZW1tYXAsIGFsdG1hcCk7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGlmIChwZ3RhYmxlX2w1X2VuYWJsZWQpPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgZnJlZV9wdWRfdGFibGUocHVkX2Jhc2UsIHA0ZHApOzxicj4NCivC oCDCoCDCoCDCoH08YnI+DQorfTxicj4NCis8YnI+DQorc3RhdGljIHZvaWQgX19tZW1pbml0IHJl bW92ZV9wZ2RfbWFwcGluZyh1bnNpZ25lZCBsb25nIHZhLCB1bnNpZ25lZCBsb25nIGVuZCwgYm9v bCBpc192bWVtbWFwLDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJ1Y3Qgdm1lbV9hbHRtYXAgKmFsdG1hcCk8YnI+DQor ezxicj4NCivCoCDCoCDCoCDCoHVuc2lnbmVkIGxvbmcgYWRkciwgbmV4dDs8YnI+DQorwqAgwqAg wqAgwqBwNGRfdCAqcDRkX2Jhc2U7PGJyPg0KK8KgIMKgIMKgIMKgcGdkX3QgKnBnZDs8YnI+DQor PGJyPg0KK8KgIMKgIMKgIMKgZm9yIChhZGRyID0gdmE7IGFkZHIgJmx0OyBlbmQ7IGFkZHIgPSBu ZXh0KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbmV4dCA9IHBnZF9hZGRyX2VuZChh ZGRyLCBlbmQpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHBnZCA9IHBnZF9vZmZzZXRf ayhhZGRyKTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKCFwZ2RfcHJl c2VudCgqcGdkKSk8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBjb250 aW51ZTs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKHBnZF9sZWFmKCpw Z2QpKTxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGNvbnRpbnVlOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBwNGRfYmFzZSA9IHA0ZF9vZmZzZXQo cGdkLCAwKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqByZW1vdmVfcDRkX21hcHBpbmco cDRkX2Jhc2UsIGFkZHIsIG5leHQsIGlzX3ZtZW1tYXAsIGFsdG1hcCk7PGJyPg0KK8KgIMKgIMKg IMKgfTxicj4NCis8YnI+DQorwqAgwqAgwqAgwqBmbHVzaF90bGJfYWxsKCk7PGJyPg0KK308YnI+ DQorPGJyPg0KK3N0YXRpYyB2b2lkIF9fbWVtaW5pdCByZW1vdmVfbGluZWFyX21hcHBpbmcocGh5 c19hZGRyX3Qgc3RhcnQsIHU2NCBzaXplKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKgdW5zaWdu ZWQgbG9uZyB2YSA9ICh1bnNpZ25lZCBsb25nKV9fdmEoc3RhcnQpOzxicj4NCivCoCDCoCDCoCDC oHVuc2lnbmVkIGxvbmcgZW5kID0gKHVuc2lnbmVkIGxvbmcpX192YShzdGFydCArIHNpemUpOzxi cj4NCis8YnI+DQorwqAgwqAgwqAgwqByZW1vdmVfcGdkX21hcHBpbmcodmEsIGVuZCwgZmFsc2Us IE5VTEwpOzxicj4NCit9PGJyPg0KKzxicj4NCitzdHJ1Y3QgcmFuZ2UgYXJjaF9nZXRfbWFwcGFi bGVfcmFuZ2Uodm9pZCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoHN0cnVjdCByYW5nZSBtaHBf cmFuZ2U7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoG1ocF9yYW5nZS5zdGFydCA9IF9fcGEoUEFH RV9PRkZTRVQpOzxicj4NCivCoCDCoCDCoCDCoG1ocF9yYW5nZS5lbmQgPSBfX3BhKFBBR0VfRU5E IC0gMSk7PGJyPg0KK8KgIMKgIMKgIMKgcmV0dXJuIG1ocF9yYW5nZTs8YnI+DQorfTxicj4NCis8 YnI+DQoraW50IF9fcmVmIGFyY2hfYWRkX21lbW9yeShpbnQgbmlkLCB1NjQgc3RhcnQsIHU2NCBz aXplLCBzdHJ1Y3QgbWhwX3BhcmFtcyAqcGFyYW1zKTxicj4NCit7PGJyPg0KK8KgIMKgIMKgIMKg aW50IHJldCA9IDA7PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoGNyZWF0ZV9saW5lYXJfbWFwcGlu Z19yYW5nZShzdGFydCwgc3RhcnQgKyBzaXplLCAwLCAmYW1wO3BhcmFtcy0mZ3Q7cGdwcm90KTs8 YnI+DQorwqAgwqAgwqAgwqByZXQgPSBfX2FkZF9wYWdlcyhuaWQsIHN0YXJ0ICZndDsmZ3Q7IFBB R0VfU0hJRlQsIHNpemUgJmd0OyZndDsgUEFHRV9TSElGVCwgcGFyYW1zKTs8YnI+DQorwqAgwqAg wqAgwqBpZiAocmV0KSB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcmVtb3ZlX2xpbmVh cl9tYXBwaW5nKHN0YXJ0LCBzaXplKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBnb3Rv IG91dDs8YnI+DQorwqAgwqAgwqAgwqB9PGJyPg0KKzxicj4NCivCoCDCoCDCoCDCoG1heF9wZm4g PSBQRk5fVVAoc3RhcnQgKyBzaXplKTs8YnI+DQorwqAgwqAgwqAgwqBtYXhfbG93X3BmbiA9IG1h eF9wZm47PGJyPg0KKzxicj4NCisgb3V0Ojxicj4NCivCoCDCoCDCoCDCoGZsdXNoX3RsYl9hbGwo KTs8YnI+DQorwqAgwqAgwqAgwqByZXR1cm4gcmV0Ozxicj4NCit9PGJyPg0KKzxicj4NCit2b2lk IF9fcmVmIGFyY2hfcmVtb3ZlX21lbW9yeSh1NjQgc3RhcnQsIHU2NCBzaXplLCBzdHJ1Y3Qgdm1l bV9hbHRtYXAgKmFsdG1hcCk8YnI+DQorezxicj4NCivCoCDCoCDCoCDCoF9fcmVtb3ZlX3BhZ2Vz KHN0YXJ0ICZndDsmZ3Q7IFBBR0VfU0hJRlQsIHNpemUgJmd0OyZndDsgUEFHRV9TSElGVCwgYWx0 bWFwKTs8YnI+DQorwqAgwqAgwqAgwqByZW1vdmVfbGluZWFyX21hcHBpbmcoc3RhcnQsIHNpemUp Ozxicj4NCivCoCDCoCDCoCDCoGZsdXNoX3RsYl9hbGwoKTs8YnI+DQorfTxicj4NCis8YnI+DQor dm9pZCBfX3JlZiB2bWVtbWFwX2ZyZWUodW5zaWduZWQgbG9uZyBzdGFydCwgdW5zaWduZWQgbG9u ZyBlbmQsIHN0cnVjdCB2bWVtX2FsdG1hcCAqYWx0bWFwKTxicj4NCit7PGJyPg0KK8KgIMKgIMKg IMKgcmVtb3ZlX3BnZF9tYXBwaW5nKHN0YXJ0LCBlbmQsIHRydWUsIGFsdG1hcCk7PGJyPg0KK308 YnI+DQorI2VuZGlmIC8qIENPTkZJR19NRU1PUllfSE9UUExVRyAqLzxicj4NCi0tIDxicj4NCjIu NDMuMDxicj4NCjxicj48L2Jsb2NrcXVvdGU+PGRpdj48YnI+PC9kaXY+PGRpdj5SZXZpZXdlZC1i eTogQWxleGFuZHJlIEdoaXRpICZsdDs8YSBocmVmPSJtYWlsdG86YWxleGdoaXRpQHJpdm9zaW5j LmNvbSI+YWxleGdoaXRpQHJpdm9zaW5jLmNvbTwvYT4mZ3Q7PC9kaXY+PGRpdj48YnI+PC9kaXY+ PGRpdj5UaGFua3MsPC9kaXY+PGRpdj48YnI+QWxleMKgPC9kaXY+PC9kaXY+PC9kaXY+DQo= --000000000000b7994d061b9f2d13--