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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8885C433F5 for ; Sat, 20 Nov 2021 13:49:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232158AbhKTNmH (ORCPT ); Sat, 20 Nov 2021 08:42:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229539AbhKTNmG (ORCPT ); Sat, 20 Nov 2021 08:42:06 -0500 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 781EAC061574 for ; Sat, 20 Nov 2021 05:39:02 -0800 (PST) Received: by mail-lf1-x12c.google.com with SMTP id bu18so57248220lfb.0 for ; Sat, 20 Nov 2021 05:39:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding:content-language; bh=87cVwmsOyzRtODMfQvo3i1gOs01RxXi43XiAXYC9uZU=; b=EdqlKkn1SBMZl5J1aPqnuvHZl1J9QT6p0FJPPvguJNUNs8vipEmaQK1+1j2AYsWnHR JyYIfMoVMiyB8UluyhIldsEyuFYMheD5AkASUvwVPKsTJLQwutjvkTMWZ8jmNL3ASLdK S7Mol04GTg/RFBB00dksds2mAWgRVeVmDzvseKU65wvWXWaCYV9SBdf4MTBa/+b56bhQ iClZOq2tVLe/Mr9gQpC/p4hM0SP80loQm1sx6e2ZDehxSeMVmT1vQUqk2fIQVjpwtwFC 3yW1CoYQmx+HTmJHYlRjb7WXdX8pEpaUocCRfVbTSboXJMlM/dPc8QJnwTi4m0DE2UQm e0ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=87cVwmsOyzRtODMfQvo3i1gOs01RxXi43XiAXYC9uZU=; b=akdJRnBchqOqzPG4NNXvnPmQ6i7bQL7GpO8ctfsliHTSkBze5d3tOeitmOzuxjD0LY vdZnEoQfOIbgz68grDSVEBSLUdvrB4IHb2X2C7S4AGzb3nwz7jo5zAXhlZEw3Z615VTu IAUC4qiE4Tws/mXWvoyj74hzmbe8Rb6InO/1GY3z7Trr0pkcIEIyfjI+E7degtLpEv9H 1lmQershY//OXoedEbwxMLsb93reNaspBwvRO3I0fmMrQd4MdtJpH+1Zo5NPtKA9BRuH kN2EgiqXI7Fx+mPqhpzfbLHedNYL8Wsf8nC4xecTCAW3I+j8l/IpS9giEvWLVqBHpUAR Z4TA== X-Gm-Message-State: AOAM530dJbUAAY6rhJ8wlLFJS7LCaHqiyLVWPTVmU15LCp87eI92adcu p6Lxy2KC3WwkACjvilApE5c= X-Google-Smtp-Source: ABdhPJxOLTeL6kIUTEm12QQG2lBcTnCGLQfsvbJ+xjMD5gpYjA0x+qhdxLzHybe818jhpOAM2tAV8w== X-Received: by 2002:a2e:9953:: with SMTP id r19mr33626907ljj.442.1637415540697; Sat, 20 Nov 2021 05:39:00 -0800 (PST) Received: from [192.168.1.7] ([212.22.223.21]) by smtp.gmail.com with ESMTPSA id bd27sm229655ljb.127.2021.11.20.05.38.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 20 Nov 2021 05:39:00 -0800 (PST) Subject: Re: [PATCH V2 4/4] arm/xen: Read extended regions from DT and init Xen resource To: Stefano Stabellini Cc: xen-devel@lists.xenproject.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Oleksandr Tyshchenko , Russell King , Boris Ostrovsky , Juergen Gross , Julien Grall References: <1635264312-3796-1-git-send-email-olekstysh@gmail.com> <1635264312-3796-5-git-send-email-olekstysh@gmail.com> <237f832d-5175-5653-18ee-058a7d7fa7a6@gmail.com> From: Oleksandr Message-ID: Date: Sat, 20 Nov 2021 15:38:59 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 20.11.21 04:36, Stefano Stabellini wrote: Hi Stefano > On Fri, 19 Nov 2021, Oleksandr wrote: >> On 19.11.21 03:19, Stefano Stabellini wrote: >>> On Wed, 10 Nov 2021, Oleksandr wrote: >>>> On 28.10.21 04:40, Stefano Stabellini wrote: >>>> >>>> Hi Stefano >>>> >>>> I am sorry for the late response. >>>> >>>>> On Tue, 26 Oct 2021, Oleksandr Tyshchenko wrote: >>>>>> From: Oleksandr Tyshchenko >>>>>> >>>>>> This patch implements arch_xen_unpopulated_init() on Arm where >>>>>> the extended regions (if any) are gathered from DT and inserted >>>>>> into passed Xen resource to be used as unused address space >>>>>> for Xen scratch pages by unpopulated-alloc code. >>>>>> >>>>>> The extended region (safe range) is a region of guest physical >>>>>> address space which is unused and could be safely used to create >>>>>> grant/foreign mappings instead of wasting real RAM pages from >>>>>> the domain memory for establishing these mappings. >>>>>> >>>>>> The extended regions are chosen by the hypervisor at the domain >>>>>> creation time and advertised to it via "reg" property under >>>>>> hypervisor node in the guest device-tree. As region 0 is reserved >>>>>> for grant table space (always present), the indexes for extended >>>>>> regions are 1...N. >>>>>> >>>>>> If arch_xen_unpopulated_init() fails for some reason the default >>>>>> behaviour will be restored (allocate xenballooned pages). >>>>>> >>>>>> This patch also removes XEN_UNPOPULATED_ALLOC dependency on x86. >>>>>> >>>>>> Signed-off-by: Oleksandr Tyshchenko >>>>>> --- >>>>>> Changes RFC -> V2: >>>>>> - new patch, instead of >>>>>> "[RFC PATCH 2/2] xen/unpopulated-alloc: Query hypervisor to >>>>>> provide >>>>>> unallocated space" >>>>>> --- >>>>>> arch/arm/xen/enlighten.c | 112 >>>>>> +++++++++++++++++++++++++++++++++++++++++++++++ >>>>>> drivers/xen/Kconfig | 2 +- >>>>>> 2 files changed, 113 insertions(+), 1 deletion(-) >>>>>> >>>>>> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c >>>>>> index dea46ec..1a1e0d3 100644 >>>>>> --- a/arch/arm/xen/enlighten.c >>>>>> +++ b/arch/arm/xen/enlighten.c >>>>>> @@ -62,6 +62,7 @@ static __read_mostly unsigned int xen_events_irq; >>>>>> static phys_addr_t xen_grant_frames; >>>>>> #define GRANT_TABLE_INDEX 0 >>>>>> +#define EXT_REGION_INDEX 1 >>>>>> uint32_t xen_start_flags; >>>>>> EXPORT_SYMBOL(xen_start_flags); >>>>>> @@ -303,6 +304,117 @@ static void __init xen_acpi_guest_init(void) >>>>>> #endif >>>>>> } >>>>>> +#ifdef CONFIG_XEN_UNPOPULATED_ALLOC >>>>>> +int arch_xen_unpopulated_init(struct resource *res) >>>>>> +{ >>>>>> + struct device_node *np; >>>>>> + struct resource *regs, *tmp_res; >>>>>> + uint64_t min_gpaddr = -1, max_gpaddr = 0; >>>>>> + unsigned int i, nr_reg = 0; >>>>>> + struct range mhp_range; >>>>>> + int rc; >>>>>> + >>>>>> + if (!xen_domain()) >>>>>> + return -ENODEV; >>>>>> + >>>>>> + np = of_find_compatible_node(NULL, NULL, "xen,xen"); >>>>>> + if (WARN_ON(!np)) >>>>>> + return -ENODEV; >>>>>> + >>>>>> + /* Skip region 0 which is reserved for grant table space */ >>>>>> + while (of_get_address(np, nr_reg + EXT_REGION_INDEX, NULL, >>>>>> NULL)) >>>>>> + nr_reg++; >>>>>> + if (!nr_reg) { >>>>>> + pr_err("No extended regions are found\n"); >>>>>> + return -EINVAL; >>>>>> + } >>>>>> + >>>>>> + regs = kcalloc(nr_reg, sizeof(*regs), GFP_KERNEL); >>>>>> + if (!regs) >>>>>> + return -ENOMEM; >>>>>> + >>>>>> + /* >>>>>> + * Create resource from extended regions provided by the >>>>>> hypervisor to >>>>>> be >>>>>> + * used as unused address space for Xen scratch pages. >>>>>> + */ >>>>>> + for (i = 0; i < nr_reg; i++) { >>>>>> + rc = of_address_to_resource(np, i + EXT_REGION_INDEX, >>>>>> ®s[i]); >>>>>> + if (rc) >>>>>> + goto err; >>>>>> + >>>>>> + if (max_gpaddr < regs[i].end) >>>>>> + max_gpaddr = regs[i].end; >>>>>> + if (min_gpaddr > regs[i].start) >>>>>> + min_gpaddr = regs[i].start; >>>>>> + } >>>>>> + >>>>>> + /* Check whether the resource range is within the hotpluggable >>>>>> range >>>>>> */ >>>>>> + mhp_range = mhp_get_pluggable_range(true); >>>>>> + if (min_gpaddr < mhp_range.start) >>>>>> + min_gpaddr = mhp_range.start; >>>>>> + if (max_gpaddr > mhp_range.end) >>>>>> + max_gpaddr = mhp_range.end; >>>>>> + >>>>>> + res->start = min_gpaddr; >>>>>> + res->end = max_gpaddr; >>>>>> + >>>>>> + /* >>>>>> + * Mark holes between extended regions as unavailable. The >>>>>> rest of >>>>>> that >>>>>> + * address space will be available for the allocation. >>>>>> + */ >>>>>> + for (i = 1; i < nr_reg; i++) { >>>>>> + resource_size_t start, end; >>>>>> + >>>>>> + start = regs[i - 1].end + 1; >>>>>> + end = regs[i].start - 1; >>>>>> + >>>>>> + if (start > (end + 1)) { >>>>> Should this be: >>>>> >>>>> if (start >= end) >>>>> >>>>> ? >>>> Yes, we can do this here (since the checks are equivalent) but ... >>>> >>>>>> + rc = -EINVAL; >>>>>> + goto err; >>>>>> + } >>>>>> + >>>>>> + /* There is no hole between regions */ >>>>>> + if (start == (end + 1)) >>>>> Also here, shouldn't it be: >>>>> >>>>> if (start == end) >>>>> >>>>> ? >>>>    ... not here. >>>> >>>> As >>>> >>>> "(start == (end + 1))" is equal to "(regs[i - 1].end + 1 == >>>> regs[i].start)" >>>> >>>> but >>>> >>>> "(start == end)" is equal to "(regs[i - 1].end + 1 == regs[i].start - 1)" >>> OK. But the check: >>> >>> if (start >= end) >>> >>> Actually covers both cases so that's the only check we need? >> Sorry, I don't entirely understand the question. >> Is the question to use only a single check in that loop? >> >> Paste the updated code which I have locally for the convenience. >> >>  [snip] >> >>     /* >>      * Mark holes between extended regions as unavailable. The rest of that >>      * address space will be available for the allocation. >>      */ >>     for (i = 1; i < nr_reg; i++) { >>         resource_size_t start, end; >> >>         start = regs[i - 1].end + 1; >>         end = regs[i].start - 1; >> >>         if (start > (end + 1)) { >>             rc = -EINVAL; >>             goto err; >>         } >> >>         /* There is no hole between regions */ >>         if (start == (end + 1)) >>             continue; >> >>         tmp_res = kzalloc(sizeof(*tmp_res), GFP_KERNEL); >>         if (!tmp_res) { >>             rc = -ENOMEM; >>             goto err; >>         } >> >>         tmp_res->name = "Unavailable space"; >>         tmp_res->start = start; >>         tmp_res->end = end; >> >>         rc = insert_resource(&xen_resource, tmp_res); >>         if (rc) { >>             pr_err("Cannot insert resource %pR (%d)\n", tmp_res, rc); >>             kfree(tmp_res); >>             goto err; >>         } >>     } >> >> [snip] >> >> >> 1. The first check is to detect an overlap (which is a wrong configuration, >> correct?) and bail out if true (for example, regX: 0x81000000...0x82FFFFFF and >> regY: 0x82000000...0x83FFFFFF). >> 2. The second check is just to skip current iteration as there is no >> space/hole between regions (for example, regX: 0x81000000...0x82FFFFFF and >> regY: 0x83000000...0x83FFFFFF). >> Therefore I think they should be distinguished. >> >> Yes, both check could be transformed to a single one, but this way the >> overlaps will be ignored: >> if (start >= (end + 1)) >>     continue; >> >> Or I really missed something? > You are right it is better to distinguish the two cases. I suggest the > code below because I think it is a clearer, even if it might be slightly > less efficient. I don't feel too strongly about it though. > > resource_size_t start, end; > > /* There is no hole between regions */ > if ( regs[i - 1].end + 1 == regs[i].start ) > continue; > > if ( regs[i - 1].end + 1 > regs[i].start) { > rc = -EINVAL; > goto err; > } > > start = regs[i - 1].end + 1; > end = regs[i].start - 1; OK, let's make code clearer, will do. -- Regards, Oleksandr Tyshchenko 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 9F864C433EF for ; Sat, 20 Nov 2021 13:41:15 +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-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:Cc:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=gtAYKEfk/aNVdNUELJS1L7DWWzhvZjnm+UlWcRJLMxY=; b=L8FoMRzVEjrhgqlvnNByPsnzwl 5M0oEHv8QI1kGTcZ7tDfEA21X91WsjCaBzFIr6v/7OjLCG1vBXdBC0ETvM/tO3eLtX95vB2hXOteK lzNuoVPLMNFeKrytiXynBToicB8k6D7S5aZZCKetKDkwLUjFTCFUdEc0Os9WCq8Z3zuwGyGTZ3wJJ wGNFKpPluWeDb1cgHiIgk/64tjNHk4tN5YkHjTqX1vUoHRXbI+Q5lByZrZcVNZlryDEQ5qw0/HDJY BFoA9NKa9IlcLuw3tzE0iKRPR1xbNsGz/ruIHlq6ANumUOGAbR1kKE8OKyNK5SWRGIfQrO0NYgaPZ BqKTyw1g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1moQaC-00CakA-4H; Sat, 20 Nov 2021 13:39:08 +0000 Received: from mail-lf1-x12d.google.com ([2a00:1450:4864:20::12d]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1moQa7-00Cajq-V0 for linux-arm-kernel@lists.infradead.org; Sat, 20 Nov 2021 13:39:05 +0000 Received: by mail-lf1-x12d.google.com with SMTP id l22so56755407lfg.7 for ; Sat, 20 Nov 2021 05:39:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding:content-language; bh=87cVwmsOyzRtODMfQvo3i1gOs01RxXi43XiAXYC9uZU=; b=EdqlKkn1SBMZl5J1aPqnuvHZl1J9QT6p0FJPPvguJNUNs8vipEmaQK1+1j2AYsWnHR JyYIfMoVMiyB8UluyhIldsEyuFYMheD5AkASUvwVPKsTJLQwutjvkTMWZ8jmNL3ASLdK S7Mol04GTg/RFBB00dksds2mAWgRVeVmDzvseKU65wvWXWaCYV9SBdf4MTBa/+b56bhQ iClZOq2tVLe/Mr9gQpC/p4hM0SP80loQm1sx6e2ZDehxSeMVmT1vQUqk2fIQVjpwtwFC 3yW1CoYQmx+HTmJHYlRjb7WXdX8pEpaUocCRfVbTSboXJMlM/dPc8QJnwTi4m0DE2UQm e0ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=87cVwmsOyzRtODMfQvo3i1gOs01RxXi43XiAXYC9uZU=; b=Kh8v9IPREuNz6f3TBwnw5NMNUifGm6pGvhigieIYrGIYf76UF9FAQU3CO/PBtTi6Tu vJwy3xq6AlfMxw4RjL6R3PxSAdMi2lqvZ6RzK5p7RZIFcW1SII336vCeR3Ti/PnHCS2b C0rAdm5yyNQSJX53wvl9p3YYfq+WJd/2/G4fbw9pc8H6RfE6WlweB9e2yNjOQa1eX99a MIUIXXgVmstFlxzNZE9nKBHJhM66uiaA56gVHrai/DTlmNb53xwGjZ7+wOkfx8BF+p1c GwwfjFF5Zf9GcH8F6ZfyovUbU3RkD9eKvD8nauV+yR9jInyJlhfxF2CsfC6XyB3IEzsu 07IQ== X-Gm-Message-State: AOAM530zZirGad+AO4TTGvqZWf6cuYtOpxKsrTeRVw5Qz89PfAvToZob EbSIFcy7n+OGW6w5sLgJ4UM= X-Google-Smtp-Source: ABdhPJxOLTeL6kIUTEm12QQG2lBcTnCGLQfsvbJ+xjMD5gpYjA0x+qhdxLzHybe818jhpOAM2tAV8w== X-Received: by 2002:a2e:9953:: with SMTP id r19mr33626907ljj.442.1637415540697; Sat, 20 Nov 2021 05:39:00 -0800 (PST) Received: from [192.168.1.7] ([212.22.223.21]) by smtp.gmail.com with ESMTPSA id bd27sm229655ljb.127.2021.11.20.05.38.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 20 Nov 2021 05:39:00 -0800 (PST) Subject: Re: [PATCH V2 4/4] arm/xen: Read extended regions from DT and init Xen resource To: Stefano Stabellini Cc: xen-devel@lists.xenproject.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Oleksandr Tyshchenko , Russell King , Boris Ostrovsky , Juergen Gross , Julien Grall References: <1635264312-3796-1-git-send-email-olekstysh@gmail.com> <1635264312-3796-5-git-send-email-olekstysh@gmail.com> <237f832d-5175-5653-18ee-058a7d7fa7a6@gmail.com> From: Oleksandr Message-ID: Date: Sat, 20 Nov 2021 15:38:59 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211120_053904_034696_D6E2D565 X-CRM114-Status: GOOD ( 36.85 ) 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-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Ck9uIDIwLjExLjIxIDA0OjM2LCBTdGVmYW5vIFN0YWJlbGxpbmkgd3JvdGU6CgoKSGkgU3RlZmFu bwoKPiBPbiBGcmksIDE5IE5vdiAyMDIxLCBPbGVrc2FuZHIgd3JvdGU6Cj4+IE9uIDE5LjExLjIx IDAzOjE5LCBTdGVmYW5vIFN0YWJlbGxpbmkgd3JvdGU6Cj4+PiBPbiBXZWQsIDEwIE5vdiAyMDIx LCBPbGVrc2FuZHIgd3JvdGU6Cj4+Pj4gT24gMjguMTAuMjEgMDQ6NDAsIFN0ZWZhbm8gU3RhYmVs bGluaSB3cm90ZToKPj4+Pgo+Pj4+IEhpIFN0ZWZhbm8KPj4+Pgo+Pj4+IEkgYW0gc29ycnkgZm9y IHRoZSBsYXRlIHJlc3BvbnNlLgo+Pj4+Cj4+Pj4+IE9uIFR1ZSwgMjYgT2N0IDIwMjEsIE9sZWtz YW5kciBUeXNoY2hlbmtvIHdyb3RlOgo+Pj4+Pj4gRnJvbTogT2xla3NhbmRyIFR5c2hjaGVua28g PG9sZWtzYW5kcl90eXNoY2hlbmtvQGVwYW0uY29tPgo+Pj4+Pj4KPj4+Pj4+IFRoaXMgcGF0Y2gg aW1wbGVtZW50cyBhcmNoX3hlbl91bnBvcHVsYXRlZF9pbml0KCkgb24gQXJtIHdoZXJlCj4+Pj4+ PiB0aGUgZXh0ZW5kZWQgcmVnaW9ucyAoaWYgYW55KSBhcmUgZ2F0aGVyZWQgZnJvbSBEVCBhbmQg aW5zZXJ0ZWQKPj4+Pj4+IGludG8gcGFzc2VkIFhlbiByZXNvdXJjZSB0byBiZSB1c2VkIGFzIHVu dXNlZCBhZGRyZXNzIHNwYWNlCj4+Pj4+PiBmb3IgWGVuIHNjcmF0Y2ggcGFnZXMgYnkgdW5wb3B1 bGF0ZWQtYWxsb2MgY29kZS4KPj4+Pj4+Cj4+Pj4+PiBUaGUgZXh0ZW5kZWQgcmVnaW9uIChzYWZl IHJhbmdlKSBpcyBhIHJlZ2lvbiBvZiBndWVzdCBwaHlzaWNhbAo+Pj4+Pj4gYWRkcmVzcyBzcGFj ZSB3aGljaCBpcyB1bnVzZWQgYW5kIGNvdWxkIGJlIHNhZmVseSB1c2VkIHRvIGNyZWF0ZQo+Pj4+ Pj4gZ3JhbnQvZm9yZWlnbiBtYXBwaW5ncyBpbnN0ZWFkIG9mIHdhc3RpbmcgcmVhbCBSQU0gcGFn ZXMgZnJvbQo+Pj4+Pj4gdGhlIGRvbWFpbiBtZW1vcnkgZm9yIGVzdGFibGlzaGluZyB0aGVzZSBt YXBwaW5ncy4KPj4+Pj4+Cj4+Pj4+PiBUaGUgZXh0ZW5kZWQgcmVnaW9ucyBhcmUgY2hvc2VuIGJ5 IHRoZSBoeXBlcnZpc29yIGF0IHRoZSBkb21haW4KPj4+Pj4+IGNyZWF0aW9uIHRpbWUgYW5kIGFk dmVydGlzZWQgdG8gaXQgdmlhICJyZWciIHByb3BlcnR5IHVuZGVyCj4+Pj4+PiBoeXBlcnZpc29y IG5vZGUgaW4gdGhlIGd1ZXN0IGRldmljZS10cmVlLiBBcyByZWdpb24gMCBpcyByZXNlcnZlZAo+ Pj4+Pj4gZm9yIGdyYW50IHRhYmxlIHNwYWNlIChhbHdheXMgcHJlc2VudCksIHRoZSBpbmRleGVz IGZvciBleHRlbmRlZAo+Pj4+Pj4gcmVnaW9ucyBhcmUgMS4uLk4uCj4+Pj4+Pgo+Pj4+Pj4gSWYg YXJjaF94ZW5fdW5wb3B1bGF0ZWRfaW5pdCgpIGZhaWxzIGZvciBzb21lIHJlYXNvbiB0aGUgZGVm YXVsdAo+Pj4+Pj4gYmVoYXZpb3VyIHdpbGwgYmUgcmVzdG9yZWQgKGFsbG9jYXRlIHhlbmJhbGxv b25lZCBwYWdlcykuCj4+Pj4+Pgo+Pj4+Pj4gVGhpcyBwYXRjaCBhbHNvIHJlbW92ZXMgWEVOX1VO UE9QVUxBVEVEX0FMTE9DIGRlcGVuZGVuY3kgb24geDg2Lgo+Pj4+Pj4KPj4+Pj4+IFNpZ25lZC1v ZmYtYnk6IE9sZWtzYW5kciBUeXNoY2hlbmtvIDxvbGVrc2FuZHJfdHlzaGNoZW5rb0BlcGFtLmNv bT4KPj4+Pj4+IC0tLQo+Pj4+Pj4gQ2hhbmdlcyBSRkMgLT4gVjI6Cj4+Pj4+PiAgICAgICAtIG5l dyBwYXRjaCwgaW5zdGVhZCBvZgo+Pj4+Pj4gICAgICAgICJbUkZDIFBBVENIIDIvMl0geGVuL3Vu cG9wdWxhdGVkLWFsbG9jOiBRdWVyeSBoeXBlcnZpc29yIHRvCj4+Pj4+PiBwcm92aWRlCj4+Pj4+ PiB1bmFsbG9jYXRlZCBzcGFjZSIKPj4+Pj4+IC0tLQo+Pj4+Pj4gICAgIGFyY2gvYXJtL3hlbi9l bmxpZ2h0ZW4uYyB8IDExMgo+Pj4+Pj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysKPj4+Pj4+ICAgICBkcml2ZXJzL3hlbi9LY29uZmlnICAgICAgfCAgIDIg Ky0KPj4+Pj4+ICAgICAyIGZpbGVzIGNoYW5nZWQsIDExMyBpbnNlcnRpb25zKCspLCAxIGRlbGV0 aW9uKC0pCj4+Pj4+Pgo+Pj4+Pj4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtL3hlbi9lbmxpZ2h0ZW4u YyBiL2FyY2gvYXJtL3hlbi9lbmxpZ2h0ZW4uYwo+Pj4+Pj4gaW5kZXggZGVhNDZlYy4uMWExZTBk MyAxMDA2NDQKPj4+Pj4+IC0tLSBhL2FyY2gvYXJtL3hlbi9lbmxpZ2h0ZW4uYwo+Pj4+Pj4gKysr IGIvYXJjaC9hcm0veGVuL2VubGlnaHRlbi5jCj4+Pj4+PiBAQCAtNjIsNiArNjIsNyBAQCBzdGF0 aWMgX19yZWFkX21vc3RseSB1bnNpZ25lZCBpbnQgeGVuX2V2ZW50c19pcnE7Cj4+Pj4+PiAgICAg c3RhdGljIHBoeXNfYWRkcl90IHhlbl9ncmFudF9mcmFtZXM7Cj4+Pj4+PiAgICAgICAjZGVmaW5l IEdSQU5UX1RBQkxFX0lOREVYICAgMAo+Pj4+Pj4gKyNkZWZpbmUgRVhUX1JFR0lPTl9JTkRFWCAg ICAxCj4+Pj4+PiAgICAgICB1aW50MzJfdCB4ZW5fc3RhcnRfZmxhZ3M7Cj4+Pj4+PiAgICAgRVhQ T1JUX1NZTUJPTCh4ZW5fc3RhcnRfZmxhZ3MpOwo+Pj4+Pj4gQEAgLTMwMyw2ICszMDQsMTE3IEBA IHN0YXRpYyB2b2lkIF9faW5pdCB4ZW5fYWNwaV9ndWVzdF9pbml0KHZvaWQpCj4+Pj4+PiAgICAg I2VuZGlmCj4+Pj4+PiAgICAgfQo+Pj4+Pj4gICAgICsjaWZkZWYgQ09ORklHX1hFTl9VTlBPUFVM QVRFRF9BTExPQwo+Pj4+Pj4gK2ludCBhcmNoX3hlbl91bnBvcHVsYXRlZF9pbml0KHN0cnVjdCBy ZXNvdXJjZSAqcmVzKQo+Pj4+Pj4gK3sKPj4+Pj4+ICsJc3RydWN0IGRldmljZV9ub2RlICpucDsK Pj4+Pj4+ICsJc3RydWN0IHJlc291cmNlICpyZWdzLCAqdG1wX3JlczsKPj4+Pj4+ICsJdWludDY0 X3QgbWluX2dwYWRkciA9IC0xLCBtYXhfZ3BhZGRyID0gMDsKPj4+Pj4+ICsJdW5zaWduZWQgaW50 IGksIG5yX3JlZyA9IDA7Cj4+Pj4+PiArCXN0cnVjdCByYW5nZSBtaHBfcmFuZ2U7Cj4+Pj4+PiAr CWludCByYzsKPj4+Pj4+ICsKPj4+Pj4+ICsJaWYgKCF4ZW5fZG9tYWluKCkpCj4+Pj4+PiArCQly ZXR1cm4gLUVOT0RFVjsKPj4+Pj4+ICsKPj4+Pj4+ICsJbnAgPSBvZl9maW5kX2NvbXBhdGlibGVf bm9kZShOVUxMLCBOVUxMLCAieGVuLHhlbiIpOwo+Pj4+Pj4gKwlpZiAoV0FSTl9PTighbnApKQo+ Pj4+Pj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4+Pj4+PiArCj4+Pj4+PiArCS8qIFNraXAgcmVnaW9u IDAgd2hpY2ggaXMgcmVzZXJ2ZWQgZm9yIGdyYW50IHRhYmxlIHNwYWNlICovCj4+Pj4+PiArCXdo aWxlIChvZl9nZXRfYWRkcmVzcyhucCwgbnJfcmVnICsgRVhUX1JFR0lPTl9JTkRFWCwgTlVMTCwK Pj4+Pj4+IE5VTEwpKQo+Pj4+Pj4gKwkJbnJfcmVnKys7Cj4+Pj4+PiArCWlmICghbnJfcmVnKSB7 Cj4+Pj4+PiArCQlwcl9lcnIoIk5vIGV4dGVuZGVkIHJlZ2lvbnMgYXJlIGZvdW5kXG4iKTsKPj4+ Pj4+ICsJCXJldHVybiAtRUlOVkFMOwo+Pj4+Pj4gKwl9Cj4+Pj4+PiArCj4+Pj4+PiArCXJlZ3Mg PSBrY2FsbG9jKG5yX3JlZywgc2l6ZW9mKCpyZWdzKSwgR0ZQX0tFUk5FTCk7Cj4+Pj4+PiArCWlm ICghcmVncykKPj4+Pj4+ICsJCXJldHVybiAtRU5PTUVNOwo+Pj4+Pj4gKwo+Pj4+Pj4gKwkvKgo+ Pj4+Pj4gKwkgKiBDcmVhdGUgcmVzb3VyY2UgZnJvbSBleHRlbmRlZCByZWdpb25zIHByb3ZpZGVk IGJ5IHRoZQo+Pj4+Pj4gaHlwZXJ2aXNvciB0bwo+Pj4+Pj4gYmUKPj4+Pj4+ICsJICogdXNlZCBh cyB1bnVzZWQgYWRkcmVzcyBzcGFjZSBmb3IgWGVuIHNjcmF0Y2ggcGFnZXMuCj4+Pj4+PiArCSAq Lwo+Pj4+Pj4gKwlmb3IgKGkgPSAwOyBpIDwgbnJfcmVnOyBpKyspIHsKPj4+Pj4+ICsJCXJjID0g b2ZfYWRkcmVzc190b19yZXNvdXJjZShucCwgaSArIEVYVF9SRUdJT05fSU5ERVgsCj4+Pj4+PiAm cmVnc1tpXSk7Cj4+Pj4+PiArCQlpZiAocmMpCj4+Pj4+PiArCQkJZ290byBlcnI7Cj4+Pj4+PiAr Cj4+Pj4+PiArCQlpZiAobWF4X2dwYWRkciA8IHJlZ3NbaV0uZW5kKQo+Pj4+Pj4gKwkJCW1heF9n cGFkZHIgPSByZWdzW2ldLmVuZDsKPj4+Pj4+ICsJCWlmIChtaW5fZ3BhZGRyID4gcmVnc1tpXS5z dGFydCkKPj4+Pj4+ICsJCQltaW5fZ3BhZGRyID0gcmVnc1tpXS5zdGFydDsKPj4+Pj4+ICsJfQo+ Pj4+Pj4gKwo+Pj4+Pj4gKwkvKiBDaGVjayB3aGV0aGVyIHRoZSByZXNvdXJjZSByYW5nZSBpcyB3 aXRoaW4gdGhlIGhvdHBsdWdnYWJsZQo+Pj4+Pj4gcmFuZ2UKPj4+Pj4+ICovCj4+Pj4+PiArCW1o cF9yYW5nZSA9IG1ocF9nZXRfcGx1Z2dhYmxlX3JhbmdlKHRydWUpOwo+Pj4+Pj4gKwlpZiAobWlu X2dwYWRkciA8IG1ocF9yYW5nZS5zdGFydCkKPj4+Pj4+ICsJCW1pbl9ncGFkZHIgPSBtaHBfcmFu Z2Uuc3RhcnQ7Cj4+Pj4+PiArCWlmIChtYXhfZ3BhZGRyID4gbWhwX3JhbmdlLmVuZCkKPj4+Pj4+ ICsJCW1heF9ncGFkZHIgPSBtaHBfcmFuZ2UuZW5kOwo+Pj4+Pj4gKwo+Pj4+Pj4gKwlyZXMtPnN0 YXJ0ID0gbWluX2dwYWRkcjsKPj4+Pj4+ICsJcmVzLT5lbmQgPSBtYXhfZ3BhZGRyOwo+Pj4+Pj4g Kwo+Pj4+Pj4gKwkvKgo+Pj4+Pj4gKwkgKiBNYXJrIGhvbGVzIGJldHdlZW4gZXh0ZW5kZWQgcmVn aW9ucyBhcyB1bmF2YWlsYWJsZS4gVGhlCj4+Pj4+PiByZXN0IG9mCj4+Pj4+PiB0aGF0Cj4+Pj4+ PiArCSAqIGFkZHJlc3Mgc3BhY2Ugd2lsbCBiZSBhdmFpbGFibGUgZm9yIHRoZSBhbGxvY2F0aW9u Lgo+Pj4+Pj4gKwkgKi8KPj4+Pj4+ICsJZm9yIChpID0gMTsgaSA8IG5yX3JlZzsgaSsrKSB7Cj4+ Pj4+PiArCQlyZXNvdXJjZV9zaXplX3Qgc3RhcnQsIGVuZDsKPj4+Pj4+ICsKPj4+Pj4+ICsJCXN0 YXJ0ID0gcmVnc1tpIC0gMV0uZW5kICsgMTsKPj4+Pj4+ICsJCWVuZCA9IHJlZ3NbaV0uc3RhcnQg LSAxOwo+Pj4+Pj4gKwo+Pj4+Pj4gKwkJaWYgKHN0YXJ0ID4gKGVuZCArIDEpKSB7Cj4+Pj4+IFNo b3VsZCB0aGlzIGJlOgo+Pj4+Pgo+Pj4+PiBpZiAoc3RhcnQgPj0gZW5kKQo+Pj4+Pgo+Pj4+PiA/ Cj4+Pj4gWWVzLCB3ZSBjYW4gZG8gdGhpcyBoZXJlIChzaW5jZSB0aGUgY2hlY2tzIGFyZSBlcXVp dmFsZW50KSBidXQgLi4uCj4+Pj4KPj4+Pj4+ICsJCQlyYyA9IC1FSU5WQUw7Cj4+Pj4+PiArCQkJ Z290byBlcnI7Cj4+Pj4+PiArCQl9Cj4+Pj4+PiArCj4+Pj4+PiArCQkvKiBUaGVyZSBpcyBubyBo b2xlIGJldHdlZW4gcmVnaW9ucyAqLwo+Pj4+Pj4gKwkJaWYgKHN0YXJ0ID09IChlbmQgKyAxKSkK Pj4+Pj4gQWxzbyBoZXJlLCBzaG91bGRuJ3QgaXQgYmU6Cj4+Pj4+Cj4+Pj4+IGlmIChzdGFydCA9 PSBlbmQpCj4+Pj4+Cj4+Pj4+ID8KPj4+PiAgIMKgwqAgLi4uIG5vdCBoZXJlLgo+Pj4+Cj4+Pj4g QXMKPj4+Pgo+Pj4+ICIoc3RhcnQgPT0gKGVuZCArIDEpKSIgaXMgZXF1YWwgdG8gIihyZWdzW2kg LSAxXS5lbmQgKyAxID09Cj4+Pj4gcmVnc1tpXS5zdGFydCkiCj4+Pj4KPj4+PiBidXQKPj4+Pgo+ Pj4+ICIoc3RhcnQgPT0gZW5kKSIgaXMgZXF1YWwgdG8gIihyZWdzW2kgLSAxXS5lbmQgKyAxID09 IHJlZ3NbaV0uc3RhcnQgLSAxKSIKPj4+ICAgIE9LLiBCdXQgdGhlIGNoZWNrOgo+Pj4KPj4+ICAg ICBpZiAoc3RhcnQgPj0gZW5kKQo+Pj4KPj4+IEFjdHVhbGx5IGNvdmVycyBib3RoIGNhc2VzIHNv IHRoYXQncyB0aGUgb25seSBjaGVjayB3ZSBuZWVkPwo+PiBTb3JyeSwgSSBkb24ndCBlbnRpcmVs eSB1bmRlcnN0YW5kIHRoZSBxdWVzdGlvbi4KPj4gSXMgdGhlIHF1ZXN0aW9uIHRvIHVzZSBvbmx5 IGEgc2luZ2xlIGNoZWNrIGluIHRoYXQgbG9vcD8KPj4KPj4gUGFzdGUgdGhlIHVwZGF0ZWQgY29k ZSB3aGljaCBJIGhhdmUgbG9jYWxseSBmb3IgdGhlIGNvbnZlbmllbmNlLgo+Pgo+PiAgwqBbc25p cF0KPj4KPj4gIMKgwqDCoCAvKgo+PiAgwqDCoMKgwqAgKiBNYXJrIGhvbGVzIGJldHdlZW4gZXh0 ZW5kZWQgcmVnaW9ucyBhcyB1bmF2YWlsYWJsZS4gVGhlIHJlc3Qgb2YgdGhhdAo+PiAgwqDCoMKg wqAgKiBhZGRyZXNzIHNwYWNlIHdpbGwgYmUgYXZhaWxhYmxlIGZvciB0aGUgYWxsb2NhdGlvbi4K Pj4gIMKgwqDCoMKgICovCj4+ICDCoMKgwqAgZm9yIChpID0gMTsgaSA8IG5yX3JlZzsgaSsrKSB7 Cj4+ICDCoMKgwqDCoMKgwqDCoCByZXNvdXJjZV9zaXplX3Qgc3RhcnQsIGVuZDsKPj4KPj4gIMKg wqDCoMKgwqDCoMKgIHN0YXJ0ID0gcmVnc1tpIC0gMV0uZW5kICsgMTsKPj4gIMKgwqDCoMKgwqDC oMKgIGVuZCA9IHJlZ3NbaV0uc3RhcnQgLSAxOwo+Pgo+PiAgwqDCoMKgwqDCoMKgwqAgaWYgKHN0 YXJ0ID4gKGVuZCArIDEpKSB7Cj4+ICDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHJjID0gLUVJTlZB TDsKPj4gIMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZ290byBlcnI7Cj4+ICDCoMKgwqDCoMKgwqDC oCB9Cj4+Cj4+ICDCoMKgwqDCoMKgwqDCoCAvKiBUaGVyZSBpcyBubyBob2xlIGJldHdlZW4gcmVn aW9ucyAqLwo+PiAgwqDCoMKgwqDCoMKgwqAgaWYgKHN0YXJ0ID09IChlbmQgKyAxKSkKPj4gIMKg wqDCoMKgwqDCoMKgwqDCoMKgwqAgY29udGludWU7Cj4+Cj4+ICDCoMKgwqDCoMKgwqDCoCB0bXBf cmVzID0ga3phbGxvYyhzaXplb2YoKnRtcF9yZXMpLCBHRlBfS0VSTkVMKTsKPj4gIMKgwqDCoMKg wqDCoMKgIGlmICghdG1wX3Jlcykgewo+PiAgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCByYyA9IC1F Tk9NRU07Cj4+ICDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGdvdG8gZXJyOwo+PiAgwqDCoMKgwqDC oMKgwqAgfQo+Pgo+PiAgwqDCoMKgwqDCoMKgwqAgdG1wX3Jlcy0+bmFtZSA9ICJVbmF2YWlsYWJs ZSBzcGFjZSI7Cj4+ICDCoMKgwqDCoMKgwqDCoCB0bXBfcmVzLT5zdGFydCA9IHN0YXJ0Owo+PiAg wqDCoMKgwqDCoMKgwqAgdG1wX3Jlcy0+ZW5kID0gZW5kOwo+Pgo+PiAgwqDCoMKgwqDCoMKgwqAg cmMgPSBpbnNlcnRfcmVzb3VyY2UoJnhlbl9yZXNvdXJjZSwgdG1wX3Jlcyk7Cj4+ICDCoMKgwqDC oMKgwqDCoCBpZiAocmMpIHsKPj4gIMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcHJfZXJyKCJDYW5u b3QgaW5zZXJ0IHJlc291cmNlICVwUiAoJWQpXG4iLCB0bXBfcmVzLCByYyk7Cj4+ICDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIGtmcmVlKHRtcF9yZXMpOwo+PiAgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCBnb3RvIGVycjsKPj4gIMKgwqDCoMKgwqDCoMKgIH0KPj4gIMKgwqDCoCB9Cj4+Cj4+IFtzbmlw XQo+Pgo+Pgo+PiAxLiBUaGUgZmlyc3QgY2hlY2sgaXMgdG8gZGV0ZWN0IGFuIG92ZXJsYXAgKHdo aWNoIGlzIGEgd3JvbmcgY29uZmlndXJhdGlvbiwKPj4gY29ycmVjdD8pIGFuZCBiYWlsIG91dCBp ZiB0cnVlIChmb3IgZXhhbXBsZSwgcmVnWDogMHg4MTAwMDAwMC4uLjB4ODJGRkZGRkYgYW5kCj4+ IHJlZ1k6IDB4ODIwMDAwMDAuLi4weDgzRkZGRkZGKS4KPj4gMi4gVGhlIHNlY29uZCBjaGVjayBp cyBqdXN0IHRvIHNraXAgY3VycmVudCBpdGVyYXRpb24gYXMgdGhlcmUgaXMgbm8KPj4gc3BhY2Uv aG9sZSBiZXR3ZWVuIHJlZ2lvbnMgKGZvciBleGFtcGxlLCByZWdYOiAweDgxMDAwMDAwLi4uMHg4 MkZGRkZGRiBhbmQKPj4gcmVnWTogMHg4MzAwMDAwMC4uLjB4ODNGRkZGRkYpLgo+PiBUaGVyZWZv cmUgSSB0aGluayB0aGV5IHNob3VsZCBiZSBkaXN0aW5ndWlzaGVkLgo+Pgo+PiBZZXMsIGJvdGgg Y2hlY2sgY291bGQgYmUgdHJhbnNmb3JtZWQgdG8gYSBzaW5nbGUgb25lLCBidXQgdGhpcyB3YXkg dGhlCj4+IG92ZXJsYXBzIHdpbGwgYmUgaWdub3JlZDoKPj4gaWYgKHN0YXJ0ID49IChlbmQgKyAx KSkKPj4gIMKgwqDCoCBjb250aW51ZTsKPj4KPj4gT3IgSSByZWFsbHkgbWlzc2VkIHNvbWV0aGlu Zz8KPiBZb3UgYXJlIHJpZ2h0IGl0IGlzIGJldHRlciB0byBkaXN0aW5ndWlzaCB0aGUgdHdvIGNh c2VzLiBJIHN1Z2dlc3QgdGhlCj4gY29kZSBiZWxvdyBiZWNhdXNlIEkgdGhpbmsgaXQgaXMgYSBj bGVhcmVyLCBldmVuIGlmIGl0IG1pZ2h0IGJlIHNsaWdodGx5Cj4gbGVzcyBlZmZpY2llbnQuIEkg ZG9uJ3QgZmVlbCB0b28gc3Ryb25nbHkgYWJvdXQgaXQgdGhvdWdoLgo+Cj4gCQlyZXNvdXJjZV9z aXplX3Qgc3RhcnQsIGVuZDsKPgo+IAkJLyogVGhlcmUgaXMgbm8gaG9sZSBiZXR3ZWVuIHJlZ2lv bnMgKi8KPiAJCWlmICggcmVnc1tpIC0gMV0uZW5kICsgMSA9PSByZWdzW2ldLnN0YXJ0ICkKPiAJ CQljb250aW51ZTsKPgo+IAkJaWYgKCByZWdzW2kgLSAxXS5lbmQgKyAxID4gcmVnc1tpXS5zdGFy dCkgewo+IAkJCXJjID0gLUVJTlZBTDsKPiAJCQlnb3RvIGVycjsKPiAJCX0KPgo+IAkJc3RhcnQg PSByZWdzW2kgLSAxXS5lbmQgKyAxOwo+IAkJZW5kID0gcmVnc1tpXS5zdGFydCAtIDE7CgpPSywg bGV0J3MgbWFrZSBjb2RlIGNsZWFyZXIsIHdpbGwgZG8uCgoKLS0gClJlZ2FyZHMsCgpPbGVrc2Fu ZHIgVHlzaGNoZW5rbwoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlz dHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3Rp bmZvL2xpbnV4LWFybS1rZXJuZWwK