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 X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD58AC433DB for ; Mon, 22 Mar 2021 21:25:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 700DB6196C for ; Mon, 22 Mar 2021 21:25:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229893AbhCVVZE (ORCPT ); Mon, 22 Mar 2021 17:25:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229614AbhCVVYq (ORCPT ); Mon, 22 Mar 2021 17:24:46 -0400 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5104C061574 for ; Mon, 22 Mar 2021 14:24:46 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id il9-20020a17090b1649b0290114bcb0d6c2so3948076pjb.0 for ; Mon, 22 Mar 2021 14:24:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=ls47ly2r1yJSc2qz/NChgyi+cfX5mUnCmGYOZl6q61w=; b=kTNNkmmac2vU0jIA2DPGg9vC9up2iIm8gq41GJT1P9/DoliJ2PyeGhplKuDIsjUzbv lBM9wxOevwW0WNSK2R2ry0L/yD5h3XHnZSgNYw7UxQwa3aS9iJBbue4VIc7WVoWkOqbv x4d1/BfKy+Cf2pE5SRSID6XNZQMWqR73V6TkF62V8BEE4THJits+Vxyasqzj9ZdFKxLn HCl+hYPne9bMa89sj5PzadLFJJmb2GYFY0NiF7us6aY5kEaduPcEr7Qkjlihx+vlJotT WaKop3ZBJjMDqjqQ4t8CjG+mKOkwDED9/5PUmSLSTTwtXoAZrWyNXtjTaSgxFdT4q8+N OqXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=ls47ly2r1yJSc2qz/NChgyi+cfX5mUnCmGYOZl6q61w=; b=TAUE/iqGdCiOha6C8+fZmx/EUc9xJgHZSqxeSpOWeTRkgYy1rJlGXa4umxwozT2MAR OZe+antJW29rI53tbWYx5cVj+S8ifgdG+VbaZZO+JyM7bXgQcmORvSLpzebNwIP4hwln zzzgIE2ioDUvBlo4vJanIYtRNfVw5+7m+qzDm8xsLLoIAYZ8bdAdfiyyZjDbbF3nQWGe qkSHerf/GsajIE3U/1tAUjMDq6Pz22Ryqo79FFlsBuNQcPrTQMDHVSvveG45Yh7xIca4 lmZlFrbijKF6dxpqZzQIT7dqaZIOMPXUNrZIl2mhKbAoeW5QdnO3nMOi8DfUxYBNJ4Cb KcTg== X-Gm-Message-State: AOAM532cy2wzIJrWOAASTFw8yHjlJvyXuLfm76/FZ3jf7XjFupCJ983+ Y4YE6VtFlH+1hRpe8yPzzhKopQ== X-Google-Smtp-Source: ABdhPJzy5TfsE1Wys9wPyD27PGF635HkCqd0Ik8OrkoyHAeCqAB+J5XCyM7lu4GHTfJpjwqY0Jc3ng== X-Received: by 2002:a17:90a:9d82:: with SMTP id k2mr1035857pjp.48.1616448285943; Mon, 22 Mar 2021 14:24:45 -0700 (PDT) Received: from xps15 (S0106889e681aac74.cg.shawcable.net. [68.147.0.187]) by smtp.gmail.com with ESMTPSA id fh19sm321916pjb.33.2021.03.22.14.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 14:24:45 -0700 (PDT) Date: Mon, 22 Mar 2021 15:24:43 -0600 From: Mathieu Poirier To: Mike Leach Cc: Suzuki K Poulose , linux-arm-kernel , Linux Kernel Mailing List , Anshuman Khandual , Leo Yan Subject: Re: [PATCH v4 18/19] coresight: sink: Add TRBE driver Message-ID: <20210322212443.GB1684006@xps15> References: <20210225193543.2920532-1-suzuki.poulose@arm.com> <20210225193543.2920532-19-suzuki.poulose@arm.com> <5685C840-7F03-4A53-9183-D5771308F5B8@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Mar 19, 2021 at 11:55:10AM +0000, Mike Leach wrote: > HI Suzuki, > > On Fri, 19 Mar 2021 at 10:30, Suzuki K Poulose wrote: > > > > Hi Mike > > > > > On 8 Mar 2021, at 17:26, Mike Leach wrote: > > > > > > Hi Suzuki, > > > > > > On Thu, 25 Feb 2021 at 19:36, Suzuki K Poulose wrote: > > >> > > >> From: Anshuman Khandual > > >> > > >> Trace Buffer Extension (TRBE) implements a trace buffer per CPU which is > > >> accessible via the system registers. The TRBE supports different addressing > > >> modes including CPU virtual address and buffer modes including the circular > > >> buffer mode. The TRBE buffer is addressed by a base pointer (TRBBASER_EL1), > > >> an write pointer (TRBPTR_EL1) and a limit pointer (TRBLIMITR_EL1). But the > > >> access to the trace buffer could be prohibited by a higher exception level > > >> (EL3 or EL2), indicated by TRBIDR_EL1.P. The TRBE can also generate a CPU > > >> private interrupt (PPI) on address translation errors and when the buffer > > >> is full. Overall implementation here is inspired from the Arm SPE driver. > > >> > > >> Cc: Mathieu Poirier > > >> Cc: Mike Leach > > >> Cc: Suzuki K Poulose > > >> Signed-off-by: Anshuman Khandual > > >> Signed-off-by: Suzuki K Poulose > > >> > > >> + > > >> +static unsigned long arm_trbe_update_buffer(struct coresight_device *csdev, > > >> + struct perf_output_handle *handle, > > >> + void *config) > > >> +{ > > >> + struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); > > >> + struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); > > >> + struct trbe_buf *buf = config; > > >> + enum trbe_fault_action act; > > >> + unsigned long size, offset; > > >> + unsigned long write, base, status; > > >> + unsigned long flags; > > >> + > > >> + WARN_ON(buf->cpudata != cpudata); > > >> + WARN_ON(cpudata->cpu != smp_processor_id()); > > >> + WARN_ON(cpudata->drvdata != drvdata); > > >> + if (cpudata->mode != CS_MODE_PERF) > > >> + return 0; > > >> + > > >> + perf_aux_output_flag(handle, PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW); > > >> + > > >> + /* > > >> + * We are about to disable the TRBE. And this could in turn > > >> + * fill up the buffer triggering, an IRQ. This could be consumed > > >> + * by the PE asynchronously, causing a race here against > > >> + * the IRQ handler in closing out the handle. So, let us > > >> + * make sure the IRQ can't trigger while we are collecting > > >> + * the buffer. We also make sure that a WRAP event is handled > > >> + * accordingly. > > >> + */ > > >> + local_irq_save(flags); > > >> + > > >> + /* > > >> + * If the TRBE was disabled due to lack of space in the AUX buffer or a > > >> + * spurious fault, the driver leaves it disabled, truncating the buffer. > > >> + * Since the etm_perf driver expects to close out the AUX buffer, the > > >> + * driver skips it. Thus, just pass in 0 size here to indicate that the > > >> + * buffer was truncated. > > >> + */ > > >> + if (!is_trbe_enabled()) { > > >> + size = 0; > > >> + goto done; > > >> + } > > >> + /* > > >> + * perf handle structure needs to be shared with the TRBE IRQ handler for > > >> + * capturing trace data and restarting the handle. There is a probability > > >> + * of an undefined reference based crash when etm event is being stopped > > >> + * while a TRBE IRQ also getting processed. This happens due the release > > >> + * of perf handle via perf_aux_output_end() in etm_event_stop(). Stopping > > >> + * the TRBE here will ensure that no IRQ could be generated when the perf > > >> + * handle gets freed in etm_event_stop(). > > >> + */ > > >> + trbe_drain_and_disable_local(); > > >> + write = get_trbe_write_pointer(); > > >> + base = get_trbe_base_pointer(); > > >> + > > >> + /* Check if there is a pending interrupt and handle it here */ > > >> + status = read_sysreg_s(SYS_TRBSR_EL1); > > >> + if (is_trbe_irq(status)) { > > >> + > > >> + /* > > >> + * Now that we are handling the IRQ here, clear the IRQ > > >> + * from the status, to let the irq handler know that it > > >> + * is taken care of. > > >> + */ > > >> + clr_trbe_irq(); > > >> + isb(); > > >> + > > >> + act = trbe_get_fault_act(status); > > >> + /* > > >> + * If this was not due to a WRAP event, we have some > > >> + * errors and as such buffer is empty. > > >> + */ > > >> + if (act != TRBE_FAULT_ACT_WRAP) { > > >> + size = 0; > > >> + goto done; > > >> + } > > > > > > We are using TRBE FILL mode - which halts capture on a full buffer and > > > triggers the IRQ, without disabling the source first. > > > This means that the mode is inherently lossy (unless by some unlikely > > > co-incidence the last byte that caused the wrap was also the last byte > > > to be sent from an ETE that was in the process of being disabled.) > > > Therefore we must have a perf_aux_output_flag(handle, > > > PERF_AUX_FLAG_TRUNCATED) call in here to signal that some trace was > > > lost, for consistence of operation with ETR etc, and intelpt. > > > > > > > I agree that the there is a bit of loss here due to the FILL mode. But it is not comparable to that of the ETR. In this case, the WRAP event is triggered when we flush the ETE. i.e, this could be mostly due to the fact that the tracing was enabled for the kernel mode and the last few bytes of trace which caused the FILL belong to the code responsible for stopping the components in the CoreSight trace. I personally do not think this data is of any interest to the user. > > Otherwise, if the data didn’t belong to the perf event side, it should have triggered the IRQ. > > > > This is true in case of the buffer overflow interrupt too, with a bit more data lost. i.e, since the interrupt is PPI, the overflow is triggered when the buffer is full (which includes the data that is cached in the TRBE). But there could be a bit of data that is still cached in the ETE, before it is captured in the trace. And the moment we get a FILL event, we stop executing anything that is relevant for the Trace session (as we are in the driver handling the interrupt). > > And then we reconfigure the buffer to continue the execution. Now, the interrupt delivery is not necessarily synchronous and there could be data lost in the interval between WRAP event and the IRQ is triggered. > > > > I am OK with suggesting that there was some loss of trace data during the session, if we hit WRAP event. But this could cause worry to the consumers that they lost too much of trace data of their interest, while that is not the case. > > > > We can never know what has been lost. It may be some trace around the > driver of no interest to the user, it may also be an event or > timestamp related to an earlier marker - which could be highly > relevant. > With ETR we do not know how much is lost on wrap - it might be one > byte, it might be much more - but the point is we mark as truncated > for _any_ amount. > > It is unfortunate that we will see multiple buffers marked as > truncated - but this is far better than creating the false impression > that no trace has been lost - that there is a continuous record where > there is not. > For some users - such as autofdo where sampling is taking place anyway > - truncated buffers probably do not matter. For others - who are > looking to trace a specific section of code - then they need to be > aware that there could be decode anomolies relating to buffer wrap. > I think Mike has a point here - we should report it to users when data gets lost, no matter how small that lost is. If that is a problem they always have the choice of dedicating more pages to the AUX buffer. Thanks, Mathieu > Regards > > Mike > > > >> +static inline unsigned long get_trbe_limit_pointer(void) > > >> +{ > > >> + u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); > > >> + unsigned long limit = (trblimitr >> TRBLIMITR_LIMIT_SHIFT) & TRBLIMITR_LIMIT_MASK; > > >> + unsigned long addr = limit << TRBLIMITR_LIMIT_SHIFT; > > > > > > Could this not be: > > > unsigned long addr = trblimitr & (TRBLIMITR_LIMIT_MASK << > > > TRBLIMITR_LIMIT_SHIFT); > > > like the base ponter below? > > > > > > > Sure, it can be consistent. > > > > > > >> + > > >> + WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); > > >> + return addr; > > >> +} > > >> + > > >> +static inline unsigned long get_trbe_base_pointer(void) > > >> +{ > > >> + u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1); > > >> + unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT); > > >> + > > >> + WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); > > >> + return addr; > > >> +} > > >> + > > > > Thank you for the review > > > > Kind regards > > Suzuki > > > > > -- > Mike Leach > Principal Engineer, ARM Ltd. > Manchester Design Centre. UK 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 X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1AB21C433DB for ; Mon, 22 Mar 2021 21:26:36 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 540376196C for ; Mon, 22 Mar 2021 21:26:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 540376196C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; 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=gCUZb6kgO9GWbk+xLdo1lVQAw1w1wvIEQyI8H5JDYb4=; b=Z+yFlHesgSAJywZVQcN6AtpUw jm4bRCiiR8U26Mna9In16X7TUZIMMRtHV8sQpTtltnKooJ76MMUnF5q4DloO8+Ry24V16CUsv4lLO P04g3fvrSE3xEAyNA5wDPG/CEED4F9z2VmoJfD99upErJInJ8O6G7CPvbYDm1PYsiipf3gWhvIzQs Q0joQm5SnPjN8SU1A7T2vBFcYFIoChwDbsfKG9gUXDDqnWgyGZT6+3LCdnPI0oEAb6fs86ksoDG6o 1Dr0ieLV7zaH0SGL5B5rDdBH3uyvBSwl3qs5bmGDsmSTbhjoMImtUcfa3SNBJL+KONuJrc/Z4OESH kZcpEl9gQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lOS2h-00CZze-9V; Mon, 22 Mar 2021 21:24:55 +0000 Received: from mail-pj1-x1031.google.com ([2607:f8b0:4864:20::1031]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lOS2Z-00CZyt-Pk for linux-arm-kernel@lists.infradead.org; Mon, 22 Mar 2021 21:24:50 +0000 Received: by mail-pj1-x1031.google.com with SMTP id kk2-20020a17090b4a02b02900c777aa746fso9192521pjb.3 for ; Mon, 22 Mar 2021 14:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=ls47ly2r1yJSc2qz/NChgyi+cfX5mUnCmGYOZl6q61w=; b=kTNNkmmac2vU0jIA2DPGg9vC9up2iIm8gq41GJT1P9/DoliJ2PyeGhplKuDIsjUzbv lBM9wxOevwW0WNSK2R2ry0L/yD5h3XHnZSgNYw7UxQwa3aS9iJBbue4VIc7WVoWkOqbv x4d1/BfKy+Cf2pE5SRSID6XNZQMWqR73V6TkF62V8BEE4THJits+Vxyasqzj9ZdFKxLn HCl+hYPne9bMa89sj5PzadLFJJmb2GYFY0NiF7us6aY5kEaduPcEr7Qkjlihx+vlJotT WaKop3ZBJjMDqjqQ4t8CjG+mKOkwDED9/5PUmSLSTTwtXoAZrWyNXtjTaSgxFdT4q8+N OqXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=ls47ly2r1yJSc2qz/NChgyi+cfX5mUnCmGYOZl6q61w=; b=FMlsEifFUJiHkEyUNrAxynEa8gLFg53Nwx14TOWxYMfITZdlXxPb5q7AoXkz5ugO81 KGQe/E7+NYrY9/IFN90222L+RhYmmS5Em6Nk1mJMneWIIyPaZoN+blp1W8wg+Ek1B0My 7DnvmYTZBwZAvsqDqIeGCPqTFP4DkD4GFbvgMYIHeqVAw+jVS/G+1tsuQrSr+gNtO3oE /4F41n/SQ5Va7cEyMsAFsxt/b00DorYKXn/qKVw+m3VszAf3Wi7swqASrAxM/9Ubvj5W a0vgOPhVkC7lbDs7ERrXirYKqY1g2i2xZuZNp+DmtAf2XuipKs/mDf1nrh2lm9jJKa4+ zKxQ== X-Gm-Message-State: AOAM533sPmoFhdIm8rHRtBnjo1UWzKnMzl0i+YiQ4rOk9IJPci4Q547e sAAKyWG8Stk+OGNZysDOOjy8AgTlX3ok6Q== X-Google-Smtp-Source: ABdhPJzy5TfsE1Wys9wPyD27PGF635HkCqd0Ik8OrkoyHAeCqAB+J5XCyM7lu4GHTfJpjwqY0Jc3ng== X-Received: by 2002:a17:90a:9d82:: with SMTP id k2mr1035857pjp.48.1616448285943; Mon, 22 Mar 2021 14:24:45 -0700 (PDT) Received: from xps15 (S0106889e681aac74.cg.shawcable.net. [68.147.0.187]) by smtp.gmail.com with ESMTPSA id fh19sm321916pjb.33.2021.03.22.14.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 14:24:45 -0700 (PDT) Date: Mon, 22 Mar 2021 15:24:43 -0600 From: Mathieu Poirier To: Mike Leach Cc: Suzuki K Poulose , linux-arm-kernel , Linux Kernel Mailing List , Anshuman Khandual , Leo Yan Subject: Re: [PATCH v4 18/19] coresight: sink: Add TRBE driver Message-ID: <20210322212443.GB1684006@xps15> References: <20210225193543.2920532-1-suzuki.poulose@arm.com> <20210225193543.2920532-19-suzuki.poulose@arm.com> <5685C840-7F03-4A53-9183-D5771308F5B8@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210322_212448_057244_27E17C2B X-CRM114-Status: GOOD ( 64.15 ) 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 T24gRnJpLCBNYXIgMTksIDIwMjEgYXQgMTE6NTU6MTBBTSArMDAwMCwgTWlrZSBMZWFjaCB3cm90 ZToKPiBISSBTdXp1a2ksCj4gCj4gT24gRnJpLCAxOSBNYXIgMjAyMSBhdCAxMDozMCwgU3V6dWtp IEsgUG91bG9zZSA8c3V6dWtpLnBvdWxvc2VAYXJtLmNvbT4gd3JvdGU6Cj4gPgo+ID4gSGkgTWlr ZQo+ID4KPiA+ID4gT24gOCBNYXIgMjAyMSwgYXQgMTc6MjYsIE1pa2UgTGVhY2ggPG1pa2UubGVh Y2hAbGluYXJvLm9yZz4gd3JvdGU6Cj4gPiA+Cj4gPiA+IEhpIFN1enVraSwKPiA+ID4KPiA+ID4g T24gVGh1LCAyNSBGZWIgMjAyMSBhdCAxOTozNiwgU3V6dWtpIEsgUG91bG9zZSA8c3V6dWtpLnBv dWxvc2VAYXJtLmNvbT4gd3JvdGU6Cj4gPiA+Pgo+ID4gPj4gRnJvbTogQW5zaHVtYW4gS2hhbmR1 YWwgPGFuc2h1bWFuLmtoYW5kdWFsQGFybS5jb20+Cj4gPiA+Pgo+ID4gPj4gVHJhY2UgQnVmZmVy IEV4dGVuc2lvbiAoVFJCRSkgaW1wbGVtZW50cyBhIHRyYWNlIGJ1ZmZlciBwZXIgQ1BVIHdoaWNo IGlzCj4gPiA+PiBhY2Nlc3NpYmxlIHZpYSB0aGUgc3lzdGVtIHJlZ2lzdGVycy4gVGhlIFRSQkUg c3VwcG9ydHMgZGlmZmVyZW50IGFkZHJlc3NpbmcKPiA+ID4+IG1vZGVzIGluY2x1ZGluZyBDUFUg dmlydHVhbCBhZGRyZXNzIGFuZCBidWZmZXIgbW9kZXMgaW5jbHVkaW5nIHRoZSBjaXJjdWxhcgo+ ID4gPj4gYnVmZmVyIG1vZGUuIFRoZSBUUkJFIGJ1ZmZlciBpcyBhZGRyZXNzZWQgYnkgYSBiYXNl IHBvaW50ZXIgKFRSQkJBU0VSX0VMMSksCj4gPiA+PiBhbiB3cml0ZSBwb2ludGVyIChUUkJQVFJf RUwxKSBhbmQgYSBsaW1pdCBwb2ludGVyIChUUkJMSU1JVFJfRUwxKS4gQnV0IHRoZQo+ID4gPj4g YWNjZXNzIHRvIHRoZSB0cmFjZSBidWZmZXIgY291bGQgYmUgcHJvaGliaXRlZCBieSBhIGhpZ2hl ciBleGNlcHRpb24gbGV2ZWwKPiA+ID4+IChFTDMgb3IgRUwyKSwgaW5kaWNhdGVkIGJ5IFRSQklE Ul9FTDEuUC4gVGhlIFRSQkUgY2FuIGFsc28gZ2VuZXJhdGUgYSBDUFUKPiA+ID4+IHByaXZhdGUg aW50ZXJydXB0IChQUEkpIG9uIGFkZHJlc3MgdHJhbnNsYXRpb24gZXJyb3JzIGFuZCB3aGVuIHRo ZSBidWZmZXIKPiA+ID4+IGlzIGZ1bGwuIE92ZXJhbGwgaW1wbGVtZW50YXRpb24gaGVyZSBpcyBp bnNwaXJlZCBmcm9tIHRoZSBBcm0gU1BFIGRyaXZlci4KPiA+ID4+Cj4gPiA+PiBDYzogTWF0aGll dSBQb2lyaWVyIDxtYXRoaWV1LnBvaXJpZXJAbGluYXJvLm9yZz4KPiA+ID4+IENjOiBNaWtlIExl YWNoIDxtaWtlLmxlYWNoQGxpbmFyby5vcmc+Cj4gPiA+PiBDYzogU3V6dWtpIEsgUG91bG9zZSA8 c3V6dWtpLnBvdWxvc2VAYXJtLmNvbT4KPiA+ID4+IFNpZ25lZC1vZmYtYnk6IEFuc2h1bWFuIEto YW5kdWFsIDxhbnNodW1hbi5raGFuZHVhbEBhcm0uY29tPgo+ID4gPj4gU2lnbmVkLW9mZi1ieTog U3V6dWtpIEsgUG91bG9zZSA8c3V6dWtpLnBvdWxvc2VAYXJtLmNvbT4KPiA+ID4+Cj4gPiA+PiAr Cj4gPiA+PiArc3RhdGljIHVuc2lnbmVkIGxvbmcgYXJtX3RyYmVfdXBkYXRlX2J1ZmZlcihzdHJ1 Y3QgY29yZXNpZ2h0X2RldmljZSAqY3NkZXYsCj4gPiA+PiArICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBwZXJmX291dHB1dF9oYW5kbGUgKmhhbmRsZSwK PiA+ID4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCAq Y29uZmlnKQo+ID4gPj4gK3sKPiA+ID4+ICsgICAgICAgc3RydWN0IHRyYmVfZHJ2ZGF0YSAqZHJ2 ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShjc2Rldi0+ZGV2LnBhcmVudCk7Cj4gPiA+PiArICAgICAg IHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNwdWRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoJmNzZGV2LT5k ZXYpOwo+ID4gPj4gKyAgICAgICBzdHJ1Y3QgdHJiZV9idWYgKmJ1ZiA9IGNvbmZpZzsKPiA+ID4+ ICsgICAgICAgZW51bSB0cmJlX2ZhdWx0X2FjdGlvbiBhY3Q7Cj4gPiA+PiArICAgICAgIHVuc2ln bmVkIGxvbmcgc2l6ZSwgb2Zmc2V0Owo+ID4gPj4gKyAgICAgICB1bnNpZ25lZCBsb25nIHdyaXRl LCBiYXNlLCBzdGF0dXM7Cj4gPiA+PiArICAgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gPiA+ PiArCj4gPiA+PiArICAgICAgIFdBUk5fT04oYnVmLT5jcHVkYXRhICE9IGNwdWRhdGEpOwo+ID4g Pj4gKyAgICAgICBXQVJOX09OKGNwdWRhdGEtPmNwdSAhPSBzbXBfcHJvY2Vzc29yX2lkKCkpOwo+ ID4gPj4gKyAgICAgICBXQVJOX09OKGNwdWRhdGEtPmRydmRhdGEgIT0gZHJ2ZGF0YSk7Cj4gPiA+ PiArICAgICAgIGlmIChjcHVkYXRhLT5tb2RlICE9IENTX01PREVfUEVSRikKPiA+ID4+ICsgICAg ICAgICAgICAgICByZXR1cm4gMDsKPiA+ID4+ICsKPiA+ID4+ICsgICAgICAgcGVyZl9hdXhfb3V0 cHV0X2ZsYWcoaGFuZGxlLCBQRVJGX0FVWF9GTEFHX0NPUkVTSUdIVF9GT1JNQVRfUkFXKTsKPiA+ ID4+ICsKPiA+ID4+ICsgICAgICAgLyoKPiA+ID4+ICsgICAgICAgICogV2UgYXJlIGFib3V0IHRv IGRpc2FibGUgdGhlIFRSQkUuIEFuZCB0aGlzIGNvdWxkIGluIHR1cm4KPiA+ID4+ICsgICAgICAg ICogZmlsbCB1cCB0aGUgYnVmZmVyIHRyaWdnZXJpbmcsIGFuIElSUS4gVGhpcyBjb3VsZCBiZSBj b25zdW1lZAo+ID4gPj4gKyAgICAgICAgKiBieSB0aGUgUEUgYXN5bmNocm9ub3VzbHksIGNhdXNp bmcgYSByYWNlIGhlcmUgYWdhaW5zdAo+ID4gPj4gKyAgICAgICAgKiB0aGUgSVJRIGhhbmRsZXIg aW4gY2xvc2luZyBvdXQgdGhlIGhhbmRsZS4gU28sIGxldCB1cwo+ID4gPj4gKyAgICAgICAgKiBt YWtlIHN1cmUgdGhlIElSUSBjYW4ndCB0cmlnZ2VyIHdoaWxlIHdlIGFyZSBjb2xsZWN0aW5nCj4g PiA+PiArICAgICAgICAqIHRoZSBidWZmZXIuIFdlIGFsc28gbWFrZSBzdXJlIHRoYXQgYSBXUkFQ IGV2ZW50IGlzIGhhbmRsZWQKPiA+ID4+ICsgICAgICAgICogYWNjb3JkaW5nbHkuCj4gPiA+PiAr ICAgICAgICAqLwo+ID4gPj4gKyAgICAgICBsb2NhbF9pcnFfc2F2ZShmbGFncyk7Cj4gPiA+PiAr Cj4gPiA+PiArICAgICAgIC8qCj4gPiA+PiArICAgICAgICAqIElmIHRoZSBUUkJFIHdhcyBkaXNh YmxlZCBkdWUgdG8gbGFjayBvZiBzcGFjZSBpbiB0aGUgQVVYIGJ1ZmZlciBvciBhCj4gPiA+PiAr ICAgICAgICAqIHNwdXJpb3VzIGZhdWx0LCB0aGUgZHJpdmVyIGxlYXZlcyBpdCBkaXNhYmxlZCwg dHJ1bmNhdGluZyB0aGUgYnVmZmVyLgo+ID4gPj4gKyAgICAgICAgKiBTaW5jZSB0aGUgZXRtX3Bl cmYgZHJpdmVyIGV4cGVjdHMgdG8gY2xvc2Ugb3V0IHRoZSBBVVggYnVmZmVyLCB0aGUKPiA+ID4+ ICsgICAgICAgICogZHJpdmVyIHNraXBzIGl0LiBUaHVzLCBqdXN0IHBhc3MgaW4gMCBzaXplIGhl cmUgdG8gaW5kaWNhdGUgdGhhdCB0aGUKPiA+ID4+ICsgICAgICAgICogYnVmZmVyIHdhcyB0cnVu Y2F0ZWQuCj4gPiA+PiArICAgICAgICAqLwo+ID4gPj4gKyAgICAgICBpZiAoIWlzX3RyYmVfZW5h YmxlZCgpKSB7Cj4gPiA+PiArICAgICAgICAgICAgICAgc2l6ZSA9IDA7Cj4gPiA+PiArICAgICAg ICAgICAgICAgZ290byBkb25lOwo+ID4gPj4gKyAgICAgICB9Cj4gPiA+PiArICAgICAgIC8qCj4g PiA+PiArICAgICAgICAqIHBlcmYgaGFuZGxlIHN0cnVjdHVyZSBuZWVkcyB0byBiZSBzaGFyZWQg d2l0aCB0aGUgVFJCRSBJUlEgaGFuZGxlciBmb3IKPiA+ID4+ICsgICAgICAgICogY2FwdHVyaW5n IHRyYWNlIGRhdGEgYW5kIHJlc3RhcnRpbmcgdGhlIGhhbmRsZS4gVGhlcmUgaXMgYSBwcm9iYWJp bGl0eQo+ID4gPj4gKyAgICAgICAgKiBvZiBhbiB1bmRlZmluZWQgcmVmZXJlbmNlIGJhc2VkIGNy YXNoIHdoZW4gZXRtIGV2ZW50IGlzIGJlaW5nIHN0b3BwZWQKPiA+ID4+ICsgICAgICAgICogd2hp bGUgYSBUUkJFIElSUSBhbHNvIGdldHRpbmcgcHJvY2Vzc2VkLiBUaGlzIGhhcHBlbnMgZHVlIHRo ZSByZWxlYXNlCj4gPiA+PiArICAgICAgICAqIG9mIHBlcmYgaGFuZGxlIHZpYSBwZXJmX2F1eF9v dXRwdXRfZW5kKCkgaW4gZXRtX2V2ZW50X3N0b3AoKS4gU3RvcHBpbmcKPiA+ID4+ICsgICAgICAg ICogdGhlIFRSQkUgaGVyZSB3aWxsIGVuc3VyZSB0aGF0IG5vIElSUSBjb3VsZCBiZSBnZW5lcmF0 ZWQgd2hlbiB0aGUgcGVyZgo+ID4gPj4gKyAgICAgICAgKiBoYW5kbGUgZ2V0cyBmcmVlZCBpbiBl dG1fZXZlbnRfc3RvcCgpLgo+ID4gPj4gKyAgICAgICAgKi8KPiA+ID4+ICsgICAgICAgdHJiZV9k cmFpbl9hbmRfZGlzYWJsZV9sb2NhbCgpOwo+ID4gPj4gKyAgICAgICB3cml0ZSA9IGdldF90cmJl X3dyaXRlX3BvaW50ZXIoKTsKPiA+ID4+ICsgICAgICAgYmFzZSA9IGdldF90cmJlX2Jhc2VfcG9p bnRlcigpOwo+ID4gPj4gKwo+ID4gPj4gKyAgICAgICAvKiBDaGVjayBpZiB0aGVyZSBpcyBhIHBl bmRpbmcgaW50ZXJydXB0IGFuZCBoYW5kbGUgaXQgaGVyZSAqLwo+ID4gPj4gKyAgICAgICBzdGF0 dXMgPSByZWFkX3N5c3JlZ19zKFNZU19UUkJTUl9FTDEpOwo+ID4gPj4gKyAgICAgICBpZiAoaXNf dHJiZV9pcnEoc3RhdHVzKSkgewo+ID4gPj4gKwo+ID4gPj4gKyAgICAgICAgICAgICAgIC8qCj4g PiA+PiArICAgICAgICAgICAgICAgICogTm93IHRoYXQgd2UgYXJlIGhhbmRsaW5nIHRoZSBJUlEg aGVyZSwgY2xlYXIgdGhlIElSUQo+ID4gPj4gKyAgICAgICAgICAgICAgICAqIGZyb20gdGhlIHN0 YXR1cywgdG8gbGV0IHRoZSBpcnEgaGFuZGxlciBrbm93IHRoYXQgaXQKPiA+ID4+ICsgICAgICAg ICAgICAgICAgKiBpcyB0YWtlbiBjYXJlIG9mLgo+ID4gPj4gKyAgICAgICAgICAgICAgICAqLwo+ ID4gPj4gKyAgICAgICAgICAgICAgIGNscl90cmJlX2lycSgpOwo+ID4gPj4gKyAgICAgICAgICAg ICAgIGlzYigpOwo+ID4gPj4gKwo+ID4gPj4gKyAgICAgICAgICAgICAgIGFjdCA9IHRyYmVfZ2V0 X2ZhdWx0X2FjdChzdGF0dXMpOwo+ID4gPj4gKyAgICAgICAgICAgICAgIC8qCj4gPiA+PiArICAg ICAgICAgICAgICAgICogSWYgdGhpcyB3YXMgbm90IGR1ZSB0byBhIFdSQVAgZXZlbnQsIHdlIGhh dmUgc29tZQo+ID4gPj4gKyAgICAgICAgICAgICAgICAqIGVycm9ycyBhbmQgYXMgc3VjaCBidWZm ZXIgaXMgZW1wdHkuCj4gPiA+PiArICAgICAgICAgICAgICAgICovCj4gPiA+PiArICAgICAgICAg ICAgICAgaWYgKGFjdCAhPSBUUkJFX0ZBVUxUX0FDVF9XUkFQKSB7Cj4gPiA+PiArICAgICAgICAg ICAgICAgICAgICAgICBzaXplID0gMDsKPiA+ID4+ICsgICAgICAgICAgICAgICAgICAgICAgIGdv dG8gZG9uZTsKPiA+ID4+ICsgICAgICAgICAgICAgICB9Cj4gPiA+Cj4gPiA+IFdlIGFyZSB1c2lu ZyBUUkJFIEZJTEwgbW9kZSAtIHdoaWNoIGhhbHRzIGNhcHR1cmUgb24gYSBmdWxsIGJ1ZmZlciBh bmQKPiA+ID4gdHJpZ2dlcnMgdGhlIElSUSwgd2l0aG91dCBkaXNhYmxpbmcgdGhlIHNvdXJjZSBm aXJzdC4KPiA+ID4gVGhpcyBtZWFucyB0aGF0IHRoZSBtb2RlIGlzIGluaGVyZW50bHkgbG9zc3kg KHVubGVzcyBieSBzb21lIHVubGlrZWx5Cj4gPiA+IGNvLWluY2lkZW5jZSB0aGUgbGFzdCBieXRl IHRoYXQgY2F1c2VkIHRoZSB3cmFwIHdhcyBhbHNvIHRoZSBsYXN0IGJ5dGUKPiA+ID4gdG8gYmUg c2VudCBmcm9tIGFuIEVURSB0aGF0IHdhcyBpbiB0aGUgcHJvY2VzcyBvZiBiZWluZyBkaXNhYmxl ZC4pCj4gPiA+IFRoZXJlZm9yZSB3ZSBtdXN0IGhhdmUgYSBwZXJmX2F1eF9vdXRwdXRfZmxhZyho YW5kbGUsCj4gPiA+IFBFUkZfQVVYX0ZMQUdfVFJVTkNBVEVEKSBjYWxsIGluIGhlcmUgdG8gc2ln bmFsIHRoYXQgc29tZSB0cmFjZSB3YXMKPiA+ID4gbG9zdCwgZm9yIGNvbnNpc3RlbmNlIG9mIG9w ZXJhdGlvbiB3aXRoIEVUUiBldGMsIGFuZCBpbnRlbHB0Lgo+ID4gPgo+ID4KPiA+IEkgYWdyZWUg dGhhdCB0aGUgdGhlcmUgaXMgYSBiaXQgb2YgbG9zcyBoZXJlIGR1ZSB0byB0aGUgRklMTCBtb2Rl LiBCdXQgaXQgaXMgbm90ICBjb21wYXJhYmxlIHRvIHRoYXQgb2YgdGhlIEVUUi4gSW4gdGhpcyBj YXNlLCB0aGUgV1JBUCBldmVudCBpcyB0cmlnZ2VyZWQgd2hlbiB3ZSBmbHVzaCB0aGUgRVRFLiBp LmUsIHRoaXMgY291bGQgYmUgbW9zdGx5IGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSB0cmFjaW5n IHdhcyBlbmFibGVkIGZvciB0aGUga2VybmVsIG1vZGUgYW5kIHRoZSBsYXN0IGZldyBieXRlcyBv ZiB0cmFjZSB3aGljaCBjYXVzZWQgdGhlIEZJTEwgYmVsb25nIHRvIHRoZSBjb2RlIHJlc3BvbnNp YmxlIGZvciBzdG9wcGluZyB0aGUgY29tcG9uZW50cyBpbiB0aGUgQ29yZVNpZ2h0IHRyYWNlLiBJ IHBlcnNvbmFsbHkgZG8gbm90IHRoaW5rIHRoaXMgZGF0YSBpcyBvZiBhbnkgaW50ZXJlc3QgdG8g dGhlIHVzZXIuCj4gPiBPdGhlcndpc2UsIGlmIHRoZSBkYXRhIGRpZG7igJl0IGJlbG9uZyB0byB0 aGUgcGVyZiBldmVudCBzaWRlLCBpdCBzaG91bGQgaGF2ZSB0cmlnZ2VyZWQgdGhlIElSUS4KPiA+ Cj4gPiBUaGlzIGlzIHRydWUgaW4gY2FzZSBvZiB0aGUgYnVmZmVyIG92ZXJmbG93IGludGVycnVw dCB0b28sIHdpdGggYSBiaXQgbW9yZSBkYXRhIGxvc3QuIGkuZSwgc2luY2UgdGhlIGludGVycnVw dCBpcyBQUEksIHRoZSBvdmVyZmxvdyBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgYnVmZmVyIGlzIGZ1 bGwgKHdoaWNoIGluY2x1ZGVzIHRoZSBkYXRhIHRoYXQgaXMgY2FjaGVkIGluIHRoZSBUUkJFKS4g QnV0IHRoZXJlIGNvdWxkIGJlIGEgYml0IG9mIGRhdGEgdGhhdCBpcyBzdGlsbCBjYWNoZWQgaW4g dGhlIEVURSwgYmVmb3JlIGl0IGlzIGNhcHR1cmVkIGluIHRoZSB0cmFjZS4gQW5kIHRoZSBtb21l bnQgd2UgZ2V0IGEgRklMTCBldmVudCwgd2Ugc3RvcCBleGVjdXRpbmcgYW55dGhpbmcgdGhhdCBp cyByZWxldmFudCBmb3IgdGhlIFRyYWNlIHNlc3Npb24gKGFzIHdlIGFyZSBpbiB0aGUgZHJpdmVy IGhhbmRsaW5nIHRoZSBpbnRlcnJ1cHQpLgo+ID4gQW5kIHRoZW4gd2UgcmVjb25maWd1cmUgdGhl IGJ1ZmZlciB0byBjb250aW51ZSB0aGUgZXhlY3V0aW9uLiBOb3csIHRoZSBpbnRlcnJ1cHQgZGVs aXZlcnkgaXMgbm90IG5lY2Vzc2FyaWx5IHN5bmNocm9ub3VzIGFuZCB0aGVyZSBjb3VsZCBiZSBk YXRhIGxvc3QgaW4gdGhlIGludGVydmFsIGJldHdlZW4gV1JBUCBldmVudCBhbmQgdGhlIElSUSBp cyB0cmlnZ2VyZWQuCj4gPgo+ID4gSSBhbSBPSyB3aXRoIHN1Z2dlc3RpbmcgdGhhdCB0aGVyZSB3 YXMgc29tZSBsb3NzIG9mIHRyYWNlIGRhdGEgZHVyaW5nIHRoZSBzZXNzaW9uLCBpZiB3ZSBoaXQg V1JBUCBldmVudC4gQnV0IHRoaXMgY291bGQgY2F1c2Ugd29ycnkgdG8gdGhlIGNvbnN1bWVycyB0 aGF0IHRoZXkgbG9zdCB0b28gbXVjaCBvZiB0cmFjZSBkYXRhIG9mIHRoZWlyIGludGVyZXN0LCB3 aGlsZSB0aGF0IGlzIG5vdCB0aGUgY2FzZS4KPiA+Cj4gCj4gV2UgY2FuIG5ldmVyIGtub3cgd2hh dCBoYXMgYmVlbiBsb3N0LiBJdCBtYXkgYmUgc29tZSB0cmFjZSBhcm91bmQgdGhlCj4gZHJpdmVy IG9mIG5vIGludGVyZXN0IHRvIHRoZSB1c2VyLCBpdCBtYXkgYWxzbyBiZSBhbiBldmVudCBvcgo+ IHRpbWVzdGFtcCByZWxhdGVkIHRvIGFuIGVhcmxpZXIgbWFya2VyIC0gd2hpY2ggY291bGQgYmUg aGlnaGx5Cj4gcmVsZXZhbnQuCj4gV2l0aCBFVFIgd2UgZG8gbm90IGtub3cgaG93IG11Y2ggaXMg bG9zdCBvbiB3cmFwIC0gaXQgbWlnaHQgYmUgb25lCj4gYnl0ZSwgaXQgbWlnaHQgYmUgbXVjaCBt b3JlIC0gYnV0IHRoZSBwb2ludCBpcyB3ZSBtYXJrIGFzIHRydW5jYXRlZAo+IGZvciBfYW55XyBh bW91bnQuCj4gCj4gSXQgaXMgdW5mb3J0dW5hdGUgdGhhdCB3ZSB3aWxsIHNlZSBtdWx0aXBsZSBi dWZmZXJzIG1hcmtlZCBhcwo+IHRydW5jYXRlZCAtIGJ1dCB0aGlzIGlzIGZhciBiZXR0ZXIgdGhh biBjcmVhdGluZyB0aGUgZmFsc2UgaW1wcmVzc2lvbgo+IHRoYXQgbm8gdHJhY2UgaGFzIGJlZW4g bG9zdCAtIHRoYXQgdGhlcmUgaXMgYSBjb250aW51b3VzIHJlY29yZCB3aGVyZQo+IHRoZXJlIGlz IG5vdC4KPiBGb3Igc29tZSB1c2VycyAtIHN1Y2ggYXMgYXV0b2ZkbyB3aGVyZSBzYW1wbGluZyBp cyB0YWtpbmcgcGxhY2UgYW55d2F5Cj4gLSB0cnVuY2F0ZWQgYnVmZmVycyBwcm9iYWJseSBkbyBu b3QgbWF0dGVyLiBGb3Igb3RoZXJzIC0gd2hvIGFyZQo+IGxvb2tpbmcgdG8gdHJhY2UgYSBzcGVj aWZpYyBzZWN0aW9uIG9mIGNvZGUgLSB0aGVuIHRoZXkgbmVlZCB0byBiZQo+IGF3YXJlIHRoYXQg dGhlcmUgY291bGQgYmUgZGVjb2RlIGFub21vbGllcyByZWxhdGluZyB0byBidWZmZXIgd3JhcC4K PgoKSSB0aGluayBNaWtlIGhhcyBhIHBvaW50IGhlcmUgLSB3ZSBzaG91bGQgcmVwb3J0IGl0IHRv IHVzZXJzIHdoZW4gZGF0YSBnZXRzCmxvc3QsIG5vIG1hdHRlciBob3cgc21hbGwgdGhhdCBsb3N0 IGlzLiBJZiB0aGF0IGlzIGEgcHJvYmxlbSB0aGV5IGFsd2F5cyBoYXZlCnRoZSBjaG9pY2Ugb2Yg ZGVkaWNhdGluZyBtb3JlIHBhZ2VzIHRvIHRoZSBBVVggYnVmZmVyLgoKVGhhbmtzLApNYXRoaWV1 IAogCj4gUmVnYXJkcwo+IAo+IE1pa2UKPiAKPiA+ID4+ICtzdGF0aWMgaW5saW5lIHVuc2lnbmVk IGxvbmcgZ2V0X3RyYmVfbGltaXRfcG9pbnRlcih2b2lkKQo+ID4gPj4gK3sKPiA+ID4+ICsgICAg ICAgdTY0IHRyYmxpbWl0ciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQkxJTUlUUl9FTDEpOwo+ID4g Pj4gKyAgICAgICB1bnNpZ25lZCBsb25nIGxpbWl0ID0gKHRyYmxpbWl0ciA+PiBUUkJMSU1JVFJf TElNSVRfU0hJRlQpICYgVFJCTElNSVRSX0xJTUlUX01BU0s7Cj4gPiA+PiArICAgICAgIHVuc2ln bmVkIGxvbmcgYWRkciA9IGxpbWl0IDw8IFRSQkxJTUlUUl9MSU1JVF9TSElGVDsKPiA+ID4KPiA+ ID4gQ291bGQgdGhpcyBub3QgYmU6Cj4gPiA+IHVuc2lnbmVkIGxvbmcgYWRkciA9IHRyYmxpbWl0 ciAmIChUUkJMSU1JVFJfTElNSVRfTUFTSyA8PAo+ID4gPiBUUkJMSU1JVFJfTElNSVRfU0hJRlQp Owo+ID4gPiBsaWtlIHRoZSBiYXNlIHBvbnRlciBiZWxvdz8KPiA+ID4KPiA+Cj4gPiBTdXJlLCBp dCBjYW4gYmUgY29uc2lzdGVudC4KPiA+Cj4gPgo+ID4gPj4gKwo+ID4gPj4gKyAgICAgICBXQVJO X09OKCFJU19BTElHTkVEKGFkZHIsIFBBR0VfU0laRSkpOwo+ID4gPj4gKyAgICAgICByZXR1cm4g YWRkcjsKPiA+ID4+ICt9Cj4gPiA+PiArCj4gPiA+PiArc3RhdGljIGlubGluZSB1bnNpZ25lZCBs b25nIGdldF90cmJlX2Jhc2VfcG9pbnRlcih2b2lkKQo+ID4gPj4gK3sKPiA+ID4+ICsgICAgICAg dTY0IHRyYmJhc2VyID0gcmVhZF9zeXNyZWdfcyhTWVNfVFJCQkFTRVJfRUwxKTsKPiA+ID4+ICsg ICAgICAgdW5zaWduZWQgbG9uZyBhZGRyID0gdHJiYmFzZXIgJiAoVFJCQkFTRVJfQkFTRV9NQVNL IDw8IFRSQkJBU0VSX0JBU0VfU0hJRlQpOwo+ID4gPj4gKwo+ID4gPj4gKyAgICAgICBXQVJOX09O KCFJU19BTElHTkVEKGFkZHIsIFBBR0VfU0laRSkpOwo+ID4gPj4gKyAgICAgICByZXR1cm4gYWRk cjsKPiA+ID4+ICt9Cj4gPiA+PiArCj4gPgo+ID4gVGhhbmsgeW91IGZvciB0aGUgcmV2aWV3Cj4g Pgo+ID4gS2luZCByZWdhcmRzCj4gPiBTdXp1a2kKPiA+Cj4gCj4gCj4gLS0gCj4gTWlrZSBMZWFj aAo+IFByaW5jaXBhbCBFbmdpbmVlciwgQVJNIEx0ZC4KPiBNYW5jaGVzdGVyIERlc2lnbiBDZW50 cmUuIFVLCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwps aW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJh ZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51 eC1hcm0ta2VybmVsCg==