From mboxrd@z Thu Jan 1 00:00:00 1970 From: msalter@redhat.com (Mark Salter) Date: Tue, 19 Jul 2016 08:48:57 -0400 Subject: [PATCH v22 1/8] arm64: kdump: reserve memory for crash dump kernel In-Reply-To: <20160719104103.GB20990@arm.com> References: <20160712050514.22307-1-takahiro.akashi@linaro.org> <20160712050514.22307-2-takahiro.akashi@linaro.org> <20160719093906.GA20732@arm.com> <20160719102815.GE20774@linaro.org> <20160719104103.GB20990@arm.com> Message-ID: <1468932537.27473.6.camel@redhat.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On Tue, 2016-07-19 at 18:41 +0800, Dennis Chen wrote: > On Tue, Jul 19, 2016 at 07:28:16PM +0900, AKASHI Takahiro wrote: > > > > On Tue, Jul 19, 2016 at 05:39:07PM +0800, Dennis Chen wrote: > > > > > > Hello AKASHI, > > > > > > On Tue, Jul 12, 2016 at 02:05:07PM +0900, AKASHI Takahiro wrote: > > > > > > > > On the startup of primary kernel, the memory region used by crash dump > > > > kernel must be specified by "crashkernel=" kernel parameter. > > > > reserve_crashkernel() will allocate and reserve the region for later use. > > > > > > > > User space tools, like kexec-tools, will be able to find that region as > > > > ??????- "Crash kernel" in /proc/iomem, or > > > > ??????- "linux,crashkernel-base" and "linux,crashkernel-size" under > > > > ????????/sys/firmware/devicetree/base/chosen > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > Signed-off-by: Mark Salter > > > > Signed-off-by: Pratyush Anand > > > > Reviewed-by: James Morse > > > > --- > > > > ?arch/arm64/kernel/setup.c |???7 ++- > > > > ?arch/arm64/mm/init.c??????| 115 ++++++++++++++++++++++++++++++++++++++++++++++ > > > > ?2 files changed, 121 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c > > > > index c1509e6..cb5eee0 100644 > > > > --- a/arch/arm64/kernel/setup.c > > > > +++ b/arch/arm64/kernel/setup.c > > > > @@ -31,7 +31,6 @@ > > > > ?#include > > > > ?#include > > > > ?#include > > > > -#include > > > > ?#include > > > > ?#include > > > > ?#include > > > > @@ -222,6 +221,12 @@ static void __init request_standard_resources(void) > > > > ??????????????????kernel_data.end <= res->end) > > > > ??????????????????????request_resource(res, &kernel_data); > > > > ??????} > > > > + > > > > +#ifdef CONFIG_KEXEC_CORE > > > > +?????/* User space tools will find "Crash kernel" region in /proc/iomem. */ > > > > +?????if (crashk_res.end) > > > > +?????????????insert_resource(&iomem_resource, &crashk_res); > > > > +#endif > > > > ?} > > > > > > > > ?u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; > > > > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c > > > > index 2ade7a6..51b1302 100644 > > > > --- a/arch/arm64/mm/init.c > > > > +++ b/arch/arm64/mm/init.c > > > > @@ -29,11 +29,13 @@ > > > > ?#include > > > > ?#include > > > > ?#include > > > > +#include > > > > ?#include > > > > ?#include > > > > ?#include > > > > ?#include > > > > ?#include > > > > +#include > > > > > > > > ?#include > > > > ?#include > > > > @@ -76,6 +78,117 @@ static int __init early_initrd(char *p) > > > > ?early_param("initrd", early_initrd); > > > > ?#endif > > > > > > > > +#ifdef CONFIG_KEXEC_CORE > > > > +static unsigned long long crash_size, crash_base; > > > > +static struct property crash_base_prop = { > > > > +?????.name = "linux,crashkernel-base", > > > > +?????.length = sizeof(u64), > > > > +?????.value = &crash_base > > > > +}; > > > > +static struct property crash_size_prop = { > > > > +?????.name = "linux,crashkernel-size", > > > > +?????.length = sizeof(u64), > > > > +?????.value = &crash_size, > > > > +}; > > > > + > > > > +static int __init export_crashkernel(void) > > > > +{ > > > > +?????struct device_node *node; > > > > +?????int ret; > > > > + > > > > +?????if (!crashk_res.end) > > > > +?????????????return 0; > > > > + > > > > +?????crash_base = cpu_to_be64(crashk_res.start); > > > > +?????crash_size = cpu_to_be64(crashk_res.end - crashk_res.start + 1); > > > > + > > > > +?????/* Add /chosen/linux,crashkernel-* properties */ > > > > +?????node = of_find_node_by_path("/chosen"); > > > > +?????if (!node) > > > > +?????????????return -ENOENT; > > > > + > > > > +?????/* > > > > +??????* There might be existing crash kernel properties, but we can't > > > > +??????* be sure what's in them, so remove them. > > > > +??????*/ > > > > +?????of_remove_property(node, of_find_property(node, > > > > +?????????????????????????????"linux,crashkernel-base", NULL)); > > > > +?????of_remove_property(node, of_find_property(node, > > > > +?????????????????????????????"linux,crashkernel-size", NULL)); > > > > + > > > > +?????ret = of_add_property(node, &crash_base_prop); > > > > +?????if (ret) > > > > +?????????????goto ret_err; > > > > + > > > > +?????ret = of_add_property(node, &crash_size_prop); > > > > +?????if (ret) > > > > +?????????????goto ret_err; > > > > + > > > > +?????return 0; > > > > + > > > > +ret_err: > > > > +?????pr_warn("Exporting crashkernel region to device tree failed\n"); > > > > +?????return ret; > > > > +} > > > > +late_initcall(export_crashkernel); > > > > + > > > > +/* > > > > + * reserve_crashkernel() - reserves memory for crash kernel > > > > + * > > > > + * This function reserves memory area given in "crashkernel=" kernel command > > > > + * line parameter. The memory reserved is used by dump capture kernel when > > > > + * primary kernel is crashing. > > > > + */ > > > > +static void __init reserve_crashkernel(void) > > > > +{ > > > > +?????int ret; > > > > + > > > > +?????ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(), > > > > +?????????????????????????????&crash_size, &crash_base); > > > > +?????/* no crashkernel= or invalid value specified */ > > > > +?????if (ret || !crash_size) > > > > +?????????????return; > > > > + > > > > +?????if (crash_base == 0) { > > > > +?????????????/* Current arm64 boot protocol requires 2MB alignment */ > > > > +?????????????crash_base = memblock_find_in_range(0, > > > > +?????????????????????????????MEMBLOCK_ALLOC_ACCESSIBLE, crash_size, SZ_2M); > > > > +?????????????if (crash_base == 0) { > > > > +?????????????????????pr_warn("Unable to allocate crashkernel (size:%llx)\n", > > > > +?????????????????????????????crash_size); > > > > +?????????????????????return; > > > > +?????????????} > > > > +?????????????memblock_reserve(crash_base, crash_size); > > > > > > > I am not pretty sure the context here, but > > > can we use below code piece instead of the above lines? > > > ????????if (crash_base == 0) > > > ????????????????memblock_alloc(crash_size, SZ_2M); > > Either would be fine here. > > > Hello AKASHI, maybe you can succeed to find the base with memblock_find_in_range(),? > but that doesn't mean you will also succeed to reserve them with memblock_reserve followed. We avoid memblock_alloc() here because it panics on failure. This could happen if user asks for an unusually large crashkernel size. Better to print a message and keep booting. Checking the return value of memblock_reserve() seems like a good thing to do though. > > Thanks, > Dennis > > > > > > Thanks, > > -Takahiro AKASHI > > > > > > > > Thanks, > > > Dennis > > > > > > > > > > > + > > > > +?????} else { > > > > +?????????????/* User specifies base address explicitly. */ > > > > +?????????????if (!memblock_is_region_memory(crash_base, crash_size) || > > > > +?????????????????????memblock_is_region_reserved(crash_base, crash_size)) { > > > > +?????????????????????pr_warn("crashkernel has wrong address or size\n"); > > > > +?????????????????????return; > > > > +?????????????} > > > > + > > > > +?????????????if (!IS_ALIGNED(crash_base, SZ_2M)) { > > > > +?????????????????????pr_warn("crashkernel base address is not 2MB aligned\n"); > > > > +?????????????????????return; > > > > +?????????????} > > > > + > > > > +?????????????memblock_reserve(crash_base, crash_size); > > > > +?????} > > > > + > > > > +?????pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n", > > > > +?????????????crash_size >> 20, crash_base >> 20); > > > > + > > > > +?????crashk_res.start = crash_base; > > > > +?????crashk_res.end = crash_base + crash_size - 1; > > > > +} > > > > +#else > > > > +static void __init reserve_crashkernel(void) > > > > +{ > > > > +?????; > > > > +} > > > > +#endif /* CONFIG_KEXEC_CORE */ > > > > + > > > > ?/* > > > > ? * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It > > > > ? * currently assumes that for memory starting above 4G, 32-bit devices will > > > > @@ -289,6 +402,8 @@ void __init arm64_memblock_init(void) > > > > ??????} > > > > ?#endif > > > > > > > > +?????reserve_crashkernel(); > > > > + > > > > ??????early_init_fdt_scan_reserved_mem(); > > > > > > > > ??????/* 4GB maximum for 32-bit only capable devices */ > > > > -- > > > > 2.9.0 > > > > > > > > > > > > _______________________________________________ > > > > linux-arm-kernel mailing list > > > > linux-arm-kernel at lists.infradead.org > > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > > > > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Message-ID: <1468932537.27473.6.camel@redhat.com> Subject: Re: [PATCH v22 1/8] arm64: kdump: reserve memory for crash dump kernel From: Mark Salter Date: Tue, 19 Jul 2016 08:48:57 -0400 In-Reply-To: <20160719104103.GB20990@arm.com> References: <20160712050514.22307-1-takahiro.akashi@linaro.org> <20160712050514.22307-2-takahiro.akashi@linaro.org> <20160719093906.GA20732@arm.com> <20160719102815.GE20774@linaro.org> <20160719104103.GB20990@arm.com> Mime-Version: 1.0 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "kexec" Errors-To: kexec-bounces+dwmw2=infradead.org@lists.infradead.org To: Dennis Chen , AKASHI Takahiro , catalin.marinas@arm.com, will.deacon@arm.com, mark.rutland@arm.com, Pratyush Anand , geoff@infradead.org, kexec@lists.infradead.org, robh+dt@kernel.org, james.morse@arm.com, bauerman@linux.vnet.ibm.com, dyoung@redhat.com, linux-arm-kernel@lists.infradead.org Cc: nd@arm.com T24gVHVlLCAyMDE2LTA3LTE5IGF0IDE4OjQxICswODAwLCBEZW5uaXMgQ2hlbiB3cm90ZToKPiBP biBUdWUsIEp1bCAxOSwgMjAxNiBhdCAwNzoyODoxNlBNICswOTAwLCBBS0FTSEkgVGFrYWhpcm8g d3JvdGU6Cj4gPiAKPiA+IE9uIFR1ZSwgSnVsIDE5LCAyMDE2IGF0IDA1OjM5OjA3UE0gKzA4MDAs IERlbm5pcyBDaGVuIHdyb3RlOgo+ID4gPiAKPiA+ID4gSGVsbG8gQUtBU0hJLAo+ID4gPiAKPiA+ ID4gT24gVHVlLCBKdWwgMTIsIDIwMTYgYXQgMDI6MDU6MDdQTSArMDkwMCwgQUtBU0hJIFRha2Fo aXJvIHdyb3RlOgo+ID4gPiA+IAo+ID4gPiA+IE9uIHRoZSBzdGFydHVwIG9mIHByaW1hcnkga2Vy bmVsLCB0aGUgbWVtb3J5IHJlZ2lvbiB1c2VkIGJ5IGNyYXNoIGR1bXAKPiA+ID4gPiBrZXJuZWwg bXVzdCBiZSBzcGVjaWZpZWQgYnkgImNyYXNoa2VybmVsPSIga2VybmVsIHBhcmFtZXRlci4KPiA+ ID4gPiByZXNlcnZlX2NyYXNoa2VybmVsKCkgd2lsbCBhbGxvY2F0ZSBhbmQgcmVzZXJ2ZSB0aGUg cmVnaW9uIGZvciBsYXRlciB1c2UuCj4gPiA+ID4gCj4gPiA+ID4gVXNlciBzcGFjZSB0b29scywg bGlrZSBrZXhlYy10b29scywgd2lsbCBiZSBhYmxlIHRvIGZpbmQgdGhhdCByZWdpb24gYXMKPiA+ ID4gPiDCoMKgwqDCoMKgwqAtICJDcmFzaCBrZXJuZWwiIGluIC9wcm9jL2lvbWVtLCBvcgo+ID4g PiA+IMKgwqDCoMKgwqDCoC0gImxpbnV4LGNyYXNoa2VybmVsLWJhc2UiIGFuZCAibGludXgsY3Jh c2hrZXJuZWwtc2l6ZSIgdW5kZXIKPiA+ID4gPiDCoMKgwqDCoMKgwqDCoMKgL3N5cy9maXJtd2Fy ZS9kZXZpY2V0cmVlL2Jhc2UvY2hvc2VuCj4gPiA+ID4gCj4gPiA+ID4gU2lnbmVkLW9mZi1ieTog QUtBU0hJIFRha2FoaXJvIDx0YWthaGlyby5ha2FzaGlAbGluYXJvLm9yZz4KPiA+ID4gPiBTaWdu ZWQtb2ZmLWJ5OiBNYXJrIFNhbHRlciA8bXNhbHRlckByZWRoYXQuY29tPgo+ID4gPiA+IFNpZ25l ZC1vZmYtYnk6IFByYXR5dXNoIEFuYW5kIDxwYW5hbmRAcmVkaGF0LmNvbT4KPiA+ID4gPiBSZXZp ZXdlZC1ieTogSmFtZXMgTW9yc2UgPGphbWVzLm1vcnNlQGFybS5jb20+Cj4gPiA+ID4gLS0tCj4g PiA+ID4gwqBhcmNoL2FybTY0L2tlcm5lbC9zZXR1cC5jIHzCoMKgwqA3ICsrLQo+ID4gPiA+IMKg YXJjaC9hcm02NC9tbS9pbml0LmPCoMKgwqDCoMKgwqB8IDExNSArKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrCj4gPiA+ID4gwqAyIGZpbGVzIGNoYW5nZWQsIDEy MSBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0pCj4gPiA+ID4gCj4gPiA+ID4gZGlmZiAtLWdp dCBhL2FyY2gvYXJtNjQva2VybmVsL3NldHVwLmMgYi9hcmNoL2FybTY0L2tlcm5lbC9zZXR1cC5j Cj4gPiA+ID4gaW5kZXggYzE1MDllNi4uY2I1ZWVlMCAxMDA2NDQKPiA+ID4gPiAtLS0gYS9hcmNo L2FybTY0L2tlcm5lbC9zZXR1cC5jCj4gPiA+ID4gKysrIGIvYXJjaC9hcm02NC9rZXJuZWwvc2V0 dXAuYwo+ID4gPiA+IEBAIC0zMSw3ICszMSw2IEBACj4gPiA+ID4gwqAjaW5jbHVkZSA8bGludXgv c2NyZWVuX2luZm8uaD4KPiA+ID4gPiDCoCNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4gPiA+ID4g wqAjaW5jbHVkZSA8bGludXgva2V4ZWMuaD4KPiA+ID4gPiAtI2luY2x1ZGUgPGxpbnV4L2NyYXNo X2R1bXAuaD4KPiA+ID4gPiDCoCNpbmNsdWRlIDxsaW51eC9yb290X2Rldi5oPgo+ID4gPiA+IMKg I2luY2x1ZGUgPGxpbnV4L2NwdS5oPgo+ID4gPiA+IMKgI2luY2x1ZGUgPGxpbnV4L2ludGVycnVw dC5oPgo+ID4gPiA+IEBAIC0yMjIsNiArMjIxLDEyIEBAIHN0YXRpYyB2b2lkIF9faW5pdCByZXF1 ZXN0X3N0YW5kYXJkX3Jlc291cmNlcyh2b2lkKQo+ID4gPiA+IMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoGtlcm5lbF9kYXRhLmVuZCA8PSByZXMtPmVuZCkKPiA+ID4gPiDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHJlcXVlc3RfcmVzb3VyY2Uo cmVzLCAma2VybmVsX2RhdGEpOwo+ID4gPiA+IMKgwqDCoMKgwqDCoH0KPiA+ID4gPiArCj4gPiA+ ID4gKyNpZmRlZiBDT05GSUdfS0VYRUNfQ09SRQo+ID4gPiA+ICvCoMKgwqDCoMKgLyogVXNlciBz cGFjZSB0b29scyB3aWxsIGZpbmQgIkNyYXNoIGtlcm5lbCIgcmVnaW9uIGluIC9wcm9jL2lvbWVt LiAqLwo+ID4gPiA+ICvCoMKgwqDCoMKgaWYgKGNyYXNoa19yZXMuZW5kKQo+ID4gPiA+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoGluc2VydF9yZXNvdXJjZSgmaW9tZW1fcmVzb3VyY2UsICZj cmFzaGtfcmVzKTsKPiA+ID4gPiArI2VuZGlmCj4gPiA+ID4gwqB9Cj4gPiA+ID4gCj4gPiA+ID4g wqB1NjQgX19jcHVfbG9naWNhbF9tYXBbTlJfQ1BVU10gPSB7IFswIC4uLiBOUl9DUFVTLTFdID0g SU5WQUxJRF9IV0lEIH07Cj4gPiA+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtNjQvbW0vaW5pdC5j IGIvYXJjaC9hcm02NC9tbS9pbml0LmMKPiA+ID4gPiBpbmRleCAyYWRlN2E2Li41MWIxMzAyIDEw MDY0NAo+ID4gPiA+IC0tLSBhL2FyY2gvYXJtNjQvbW0vaW5pdC5jCj4gPiA+ID4gKysrIGIvYXJj aC9hcm02NC9tbS9pbml0LmMKPiA+ID4gPiBAQCAtMjksMTEgKzI5LDEzIEBACj4gPiA+ID4gwqAj aW5jbHVkZSA8bGludXgvZ2ZwLmg+Cj4gPiA+ID4gwqAjaW5jbHVkZSA8bGludXgvbWVtYmxvY2su aD4KPiA+ID4gPiDCoCNpbmNsdWRlIDxsaW51eC9zb3J0Lmg+Cj4gPiA+ID4gKyNpbmNsdWRlIDxs aW51eC9vZi5oPgo+ID4gPiA+IMKgI2luY2x1ZGUgPGxpbnV4L29mX2ZkdC5oPgo+ID4gPiA+IMKg I2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+Cj4gPiA+ID4gwqAjaW5jbHVkZSA8bGludXgv ZG1hLWNvbnRpZ3VvdXMuaD4KPiA+ID4gPiDCoCNpbmNsdWRlIDxsaW51eC9lZmkuaD4KPiA+ID4g PiDCoCNpbmNsdWRlIDxsaW51eC9zd2lvdGxiLmg+Cj4gPiA+ID4gKyNpbmNsdWRlIDxsaW51eC9r ZXhlYy5oPgo+ID4gPiA+IAo+ID4gPiA+IMKgI2luY2x1ZGUgPGFzbS9ib290Lmg+Cj4gPiA+ID4g wqAjaW5jbHVkZSA8YXNtL2ZpeG1hcC5oPgo+ID4gPiA+IEBAIC03Niw2ICs3OCwxMTcgQEAgc3Rh dGljIGludCBfX2luaXQgZWFybHlfaW5pdHJkKGNoYXIgKnApCj4gPiA+ID4gwqBlYXJseV9wYXJh bSgiaW5pdHJkIiwgZWFybHlfaW5pdHJkKTsKPiA+ID4gPiDCoCNlbmRpZgo+ID4gPiA+IAo+ID4g PiA+ICsjaWZkZWYgQ09ORklHX0tFWEVDX0NPUkUKPiA+ID4gPiArc3RhdGljIHVuc2lnbmVkIGxv bmcgbG9uZyBjcmFzaF9zaXplLCBjcmFzaF9iYXNlOwo+ID4gPiA+ICtzdGF0aWMgc3RydWN0IHBy b3BlcnR5IGNyYXNoX2Jhc2VfcHJvcCA9IHsKPiA+ID4gPiArwqDCoMKgwqDCoC5uYW1lID0gImxp bnV4LGNyYXNoa2VybmVsLWJhc2UiLAo+ID4gPiA+ICvCoMKgwqDCoMKgLmxlbmd0aCA9IHNpemVv Zih1NjQpLAo+ID4gPiA+ICvCoMKgwqDCoMKgLnZhbHVlID0gJmNyYXNoX2Jhc2UKPiA+ID4gPiAr fTsKPiA+ID4gPiArc3RhdGljIHN0cnVjdCBwcm9wZXJ0eSBjcmFzaF9zaXplX3Byb3AgPSB7Cj4g PiA+ID4gK8KgwqDCoMKgwqAubmFtZSA9ICJsaW51eCxjcmFzaGtlcm5lbC1zaXplIiwKPiA+ID4g PiArwqDCoMKgwqDCoC5sZW5ndGggPSBzaXplb2YodTY0KSwKPiA+ID4gPiArwqDCoMKgwqDCoC52 YWx1ZSA9ICZjcmFzaF9zaXplLAo+ID4gPiA+ICt9Owo+ID4gPiA+ICsKPiA+ID4gPiArc3RhdGlj IGludCBfX2luaXQgZXhwb3J0X2NyYXNoa2VybmVsKHZvaWQpCj4gPiA+ID4gK3sKPiA+ID4gPiAr wqDCoMKgwqDCoHN0cnVjdCBkZXZpY2Vfbm9kZSAqbm9kZTsKPiA+ID4gPiArwqDCoMKgwqDCoGlu dCByZXQ7Cj4gPiA+ID4gKwo+ID4gPiA+ICvCoMKgwqDCoMKgaWYgKCFjcmFzaGtfcmVzLmVuZCkK PiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqByZXR1cm4gMDsKPiA+ID4gPiArCj4g PiA+ID4gK8KgwqDCoMKgwqBjcmFzaF9iYXNlID0gY3B1X3RvX2JlNjQoY3Jhc2hrX3Jlcy5zdGFy dCk7Cj4gPiA+ID4gK8KgwqDCoMKgwqBjcmFzaF9zaXplID0gY3B1X3RvX2JlNjQoY3Jhc2hrX3Jl cy5lbmQgLSBjcmFzaGtfcmVzLnN0YXJ0ICsgMSk7Cj4gPiA+ID4gKwo+ID4gPiA+ICvCoMKgwqDC oMKgLyogQWRkIC9jaG9zZW4vbGludXgsY3Jhc2hrZXJuZWwtKiBwcm9wZXJ0aWVzICovCj4gPiA+ ID4gK8KgwqDCoMKgwqBub2RlID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9jaG9zZW4iKTsKPiA+ ID4gPiArwqDCoMKgwqDCoGlmICghbm9kZSkKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqByZXR1cm4gLUVOT0VOVDsKPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoMKgwqAvKgo+ID4g PiA+ICvCoMKgwqDCoMKgwqAqIFRoZXJlIG1pZ2h0IGJlIGV4aXN0aW5nIGNyYXNoIGtlcm5lbCBw cm9wZXJ0aWVzLCBidXQgd2UgY2FuJ3QKPiA+ID4gPiArwqDCoMKgwqDCoMKgKiBiZSBzdXJlIHdo YXQncyBpbiB0aGVtLCBzbyByZW1vdmUgdGhlbS4KPiA+ID4gPiArwqDCoMKgwqDCoMKgKi8KPiA+ ID4gPiArwqDCoMKgwqDCoG9mX3JlbW92ZV9wcm9wZXJ0eShub2RlLCBvZl9maW5kX3Byb3BlcnR5 KG5vZGUsCj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAibGludXgsY3Jhc2hrZXJuZWwtYmFzZSIsIE5VTEwpKTsKPiA+ID4g PiArwqDCoMKgwqDCoG9mX3JlbW92ZV9wcm9wZXJ0eShub2RlLCBvZl9maW5kX3Byb3BlcnR5KG5v ZGUsCj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqAibGludXgsY3Jhc2hrZXJuZWwtc2l6ZSIsIE5VTEwpKTsKPiA+ID4gPiAr Cj4gPiA+ID4gK8KgwqDCoMKgwqByZXQgPSBvZl9hZGRfcHJvcGVydHkobm9kZSwgJmNyYXNoX2Jh c2VfcHJvcCk7Cj4gPiA+ID4gK8KgwqDCoMKgwqBpZiAocmV0KQo+ID4gPiA+ICvCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoGdvdG8gcmV0X2VycjsKPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoMKg wqByZXQgPSBvZl9hZGRfcHJvcGVydHkobm9kZSwgJmNyYXNoX3NpemVfcHJvcCk7Cj4gPiA+ID4g K8KgwqDCoMKgwqBpZiAocmV0KQo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGdv dG8gcmV0X2VycjsKPiA+ID4gPiArCj4gPiA+ID4gK8KgwqDCoMKgwqByZXR1cm4gMDsKPiA+ID4g PiArCj4gPiA+ID4gK3JldF9lcnI6Cj4gPiA+ID4gK8KgwqDCoMKgwqBwcl93YXJuKCJFeHBvcnRp bmcgY3Jhc2hrZXJuZWwgcmVnaW9uIHRvIGRldmljZSB0cmVlIGZhaWxlZFxuIik7Cj4gPiA+ID4g K8KgwqDCoMKgwqByZXR1cm4gcmV0Owo+ID4gPiA+ICt9Cj4gPiA+ID4gK2xhdGVfaW5pdGNhbGwo ZXhwb3J0X2NyYXNoa2VybmVsKTsKPiA+ID4gPiArCj4gPiA+ID4gKy8qCj4gPiA+ID4gKyAqIHJl c2VydmVfY3Jhc2hrZXJuZWwoKSAtIHJlc2VydmVzIG1lbW9yeSBmb3IgY3Jhc2gga2VybmVsCj4g PiA+ID4gKyAqCj4gPiA+ID4gKyAqIFRoaXMgZnVuY3Rpb24gcmVzZXJ2ZXMgbWVtb3J5IGFyZWEg Z2l2ZW4gaW4gImNyYXNoa2VybmVsPSIga2VybmVsIGNvbW1hbmQKPiA+ID4gPiArICogbGluZSBw YXJhbWV0ZXIuIFRoZSBtZW1vcnkgcmVzZXJ2ZWQgaXMgdXNlZCBieSBkdW1wIGNhcHR1cmUga2Vy bmVsIHdoZW4KPiA+ID4gPiArICogcHJpbWFyeSBrZXJuZWwgaXMgY3Jhc2hpbmcuCj4gPiA+ID4g KyAqLwo+ID4gPiA+ICtzdGF0aWMgdm9pZCBfX2luaXQgcmVzZXJ2ZV9jcmFzaGtlcm5lbCh2b2lk KQo+ID4gPiA+ICt7Cj4gPiA+ID4gK8KgwqDCoMKgwqBpbnQgcmV0Owo+ID4gPiA+ICsKPiA+ID4g PiArwqDCoMKgwqDCoHJldCA9IHBhcnNlX2NyYXNoa2VybmVsKGJvb3RfY29tbWFuZF9saW5lLCBt ZW1ibG9ja19waHlzX21lbV9zaXplKCksCj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAmY3Jhc2hfc2l6ZSwgJmNyYXNoX2Jh c2UpOwo+ID4gPiA+ICvCoMKgwqDCoMKgLyogbm8gY3Jhc2hrZXJuZWw9IG9yIGludmFsaWQgdmFs dWUgc3BlY2lmaWVkICovCj4gPiA+ID4gK8KgwqDCoMKgwqBpZiAocmV0IHx8ICFjcmFzaF9zaXpl KQo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHJldHVybjsKPiA+ID4gPiArCj4g PiA+ID4gK8KgwqDCoMKgwqBpZiAoY3Jhc2hfYmFzZSA9PSAwKSB7Cj4gPiA+ID4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgLyogQ3VycmVudCBhcm02NCBib290IHByb3RvY29sIHJlcXVpcmVz IDJNQiBhbGlnbm1lbnQgKi8KPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBjcmFz aF9iYXNlID0gbWVtYmxvY2tfZmluZF9pbl9yYW5nZSgwLAo+ID4gPiA+ICvCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgTUVNQkxPQ0tfQUxM T0NfQUNDRVNTSUJMRSwgY3Jhc2hfc2l6ZSwgU1pfMk0pOwo+ID4gPiA+ICvCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoGlmIChjcmFzaF9iYXNlID09IDApIHsKPiA+ID4gPiArwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgcHJfd2FybigiVW5hYmxlIHRvIGFsbG9jYXRl IGNyYXNoa2VybmVsIChzaXplOiVsbHgpXG4iLAo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgY3Jhc2hfc2l6ZSk7Cj4gPiA+ ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHJldHVybjsKPiA+ ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB9Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgbWVtYmxvY2tfcmVzZXJ2ZShjcmFzaF9iYXNlLCBjcmFzaF9zaXplKTsKPiA+ ID4gPiAKPiA+ID4gSSBhbSBub3QgcHJldHR5IHN1cmUgdGhlIGNvbnRleHQgaGVyZSwgYnV0Cj4g PiA+IGNhbiB3ZSB1c2UgYmVsb3cgY29kZSBwaWVjZSBpbnN0ZWFkIG9mIHRoZSBhYm92ZSBsaW5l cz8KPiA+ID4gwqDCoMKgwqDCoMKgwqDCoGlmIChjcmFzaF9iYXNlID09IDApCj4gPiA+IMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgbWVtYmxvY2tfYWxsb2MoY3Jhc2hfc2l6ZSwgU1pf Mk0pOwo+ID4gRWl0aGVyIHdvdWxkIGJlIGZpbmUgaGVyZS4KPiA+IAo+IEhlbGxvIEFLQVNISSwg bWF5YmUgeW91IGNhbiBzdWNjZWVkIHRvIGZpbmQgdGhlIGJhc2Ugd2l0aCBtZW1ibG9ja19maW5k X2luX3JhbmdlKCkswqAKPiBidXQgdGhhdCBkb2Vzbid0IG1lYW4geW91IHdpbGwgYWxzbyBzdWNj ZWVkIHRvIHJlc2VydmUgdGhlbSB3aXRoIG1lbWJsb2NrX3Jlc2VydmUgZm9sbG93ZWQuCgpXZSBh dm9pZCBtZW1ibG9ja19hbGxvYygpIGhlcmUgYmVjYXVzZSBpdCBwYW5pY3Mgb24gZmFpbHVyZS4g VGhpcyBjb3VsZCBoYXBwZW4KaWYgdXNlciBhc2tzIGZvciBhbiB1bnVzdWFsbHkgbGFyZ2UgY3Jh c2hrZXJuZWwgc2l6ZS4gQmV0dGVyIHRvIHByaW50IGEgbWVzc2FnZQphbmQga2VlcCBib290aW5n LiBDaGVja2luZyB0aGUgcmV0dXJuIHZhbHVlIG9mIG1lbWJsb2NrX3Jlc2VydmUoKSBzZWVtcyBs aWtlIGEKZ29vZCB0aGluZyB0byBkbyB0aG91Z2guCgoKPiAKPiBUaGFua3MsCj4gRGVubmlzCj4g PiAKPiA+IAo+ID4gVGhhbmtzLAo+ID4gLVRha2FoaXJvIEFLQVNISQo+ID4gCj4gPiA+IAo+ID4g PiBUaGFua3MsCj4gPiA+IERlbm5pcwo+ID4gPiAKPiA+ID4gPiAKPiA+ID4gPiArCj4gPiA+ID4g K8KgwqDCoMKgwqB9IGVsc2Ugewo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoC8q IFVzZXIgc3BlY2lmaWVzIGJhc2UgYWRkcmVzcyBleHBsaWNpdGx5LiAqLwo+ID4gPiA+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoGlmICghbWVtYmxvY2tfaXNfcmVnaW9uX21lbW9yeShjcmFz aF9iYXNlLCBjcmFzaF9zaXplKSB8fAo+ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqBtZW1ibG9ja19pc19yZWdpb25fcmVzZXJ2ZWQoY3Jhc2hfYmFzZSwg Y3Jhc2hfc2l6ZSkpIHsKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgcHJfd2FybigiY3Jhc2hrZXJuZWwgaGFzIHdyb25nIGFkZHJlc3Mgb3Igc2l6ZVxu Iik7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHJl dHVybjsKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB9Cj4gPiA+ID4gKwo+ID4g PiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGlmICghSVNfQUxJR05FRChjcmFzaF9iYXNl LCBTWl8yTSkpIHsKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgcHJfd2FybigiY3Jhc2hrZXJuZWwgYmFzZSBhZGRyZXNzIGlzIG5vdCAyTUIgYWxpZ25l ZFxuIik7Cj4gPiA+ID4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oHJldHVybjsKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB9Cj4gPiA+ID4gKwo+ ID4gPiA+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoG1lbWJsb2NrX3Jlc2VydmUoY3Jhc2hf YmFzZSwgY3Jhc2hfc2l6ZSk7Cj4gPiA+ID4gK8KgwqDCoMKgwqB9Cj4gPiA+ID4gKwo+ID4gPiA+ ICvCoMKgwqDCoMKgcHJfaW5mbygiUmVzZXJ2aW5nICVsbGRNQiBvZiBtZW1vcnkgYXQgJWxsZE1C IGZvciBjcmFzaGtlcm5lbFxuIiwKPiA+ID4gPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBj cmFzaF9zaXplID4+IDIwLCBjcmFzaF9iYXNlID4+IDIwKTsKPiA+ID4gPiArCj4gPiA+ID4gK8Kg wqDCoMKgwqBjcmFzaGtfcmVzLnN0YXJ0ID0gY3Jhc2hfYmFzZTsKPiA+ID4gPiArwqDCoMKgwqDC oGNyYXNoa19yZXMuZW5kID0gY3Jhc2hfYmFzZSArIGNyYXNoX3NpemUgLSAxOwo+ID4gPiA+ICt9 Cj4gPiA+ID4gKyNlbHNlCj4gPiA+ID4gK3N0YXRpYyB2b2lkIF9faW5pdCByZXNlcnZlX2NyYXNo a2VybmVsKHZvaWQpCj4gPiA+ID4gK3sKPiA+ID4gPiArwqDCoMKgwqDCoDsKPiA+ID4gPiArfQo+ ID4gPiA+ICsjZW5kaWYgLyogQ09ORklHX0tFWEVDX0NPUkUgKi8KPiA+ID4gPiArCj4gPiA+ID4g wqAvKgo+ID4gPiA+IMKgICogUmV0dXJuIHRoZSBtYXhpbXVtIHBoeXNpY2FsIGFkZHJlc3MgZm9y IFpPTkVfRE1BIChETUFfQklUX01BU0soMzIpKS4gSXQKPiA+ID4gPiDCoCAqIGN1cnJlbnRseSBh c3N1bWVzIHRoYXQgZm9yIG1lbW9yeSBzdGFydGluZyBhYm92ZSA0RywgMzItYml0IGRldmljZXMg d2lsbAo+ID4gPiA+IEBAIC0yODksNiArNDAyLDggQEAgdm9pZCBfX2luaXQgYXJtNjRfbWVtYmxv Y2tfaW5pdCh2b2lkKQo+ID4gPiA+IMKgwqDCoMKgwqDCoH0KPiA+ID4gPiDCoCNlbmRpZgo+ID4g PiA+IAo+ID4gPiA+ICvCoMKgwqDCoMKgcmVzZXJ2ZV9jcmFzaGtlcm5lbCgpOwo+ID4gPiA+ICsK PiA+ID4gPiDCoMKgwqDCoMKgwqBlYXJseV9pbml0X2ZkdF9zY2FuX3Jlc2VydmVkX21lbSgpOwo+ ID4gPiA+IAo+ID4gPiA+IMKgwqDCoMKgwqDCoC8qIDRHQiBtYXhpbXVtIGZvciAzMi1iaXQgb25s eSBjYXBhYmxlIGRldmljZXMgKi8KPiA+ID4gPiAtLQo+ID4gPiA+IDIuOS4wCj4gPiA+ID4gCj4g PiA+ID4gCj4gPiA+ID4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX18KPiA+ID4gPiBsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdAo+ID4gPiA+IGxpbnV4 LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwo+ID4gPiA+IGh0dHA6Ly9saXN0cy5pbmZy YWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo+ID4gPiA+IAoKCl9f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmtleGVjIG1haWxp bmcgbGlzdAprZXhlY0BsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQu b3JnL21haWxtYW4vbGlzdGluZm8va2V4ZWMK