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=-15.5 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 5F564C433E6 for ; Tue, 5 Jan 2021 09:31:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 15EA820756 for ; Tue, 5 Jan 2021 09:31:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728543AbhAEJa5 (ORCPT ); Tue, 5 Jan 2021 04:30:57 -0500 Received: from foss.arm.com ([217.140.110.172]:51472 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728285AbhAEJ3f (ORCPT ); Tue, 5 Jan 2021 04:29:35 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8E210101E; Tue, 5 Jan 2021 01:28:46 -0800 (PST) Received: from [192.168.0.130] (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 88BA33F719; Tue, 5 Jan 2021 01:28:43 -0800 (PST) Subject: Re: [PATCH 10/11] coresight: sink: Add TRBE driver To: Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org Cc: linux-kernel@vger.kernel.org, Mathieu Poirier , Mike Leach , Linu Cherian References: <1608717823-18387-1-git-send-email-anshuman.khandual@arm.com> <1608717823-18387-11-git-send-email-anshuman.khandual@arm.com> <92b5ae56-df5d-3772-0206-b50ea4080c4f@arm.com> From: Anshuman Khandual Message-ID: Date: Tue, 5 Jan 2021 14:59:03 +0530 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: <92b5ae56-df5d-3772-0206-b50ea4080c4f@arm.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 1/4/21 9:58 PM, Suzuki K Poulose wrote: > > Hi Anshuman, > > On 12/23/20 10:03 AM, Anshuman Khandual wrote: >> 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 >> --- > >> >>   Documentation/trace/coresight/coresight-trbe.rst |  39 + >>   arch/arm64/include/asm/sysreg.h                  |   2 + >>   drivers/hwtracing/coresight/Kconfig              |  11 + >>   drivers/hwtracing/coresight/Makefile             |   1 + >>   drivers/hwtracing/coresight/coresight-trbe.c     | 925 +++++++++++++++++++++++ >>   drivers/hwtracing/coresight/coresight-trbe.h     | 248 ++++++ >>   6 files changed, 1226 insertions(+) >>   create mode 100644 Documentation/trace/coresight/coresight-trbe.rst >>   create mode 100644 drivers/hwtracing/coresight/coresight-trbe.c >>   create mode 100644 drivers/hwtracing/coresight/coresight-trbe.h >> >> diff --git a/Documentation/trace/coresight/coresight-trbe.rst b/Documentation/trace/coresight/coresight-trbe.rst >> new file mode 100644 >> index 0000000..8b79850 >> --- /dev/null >> +++ b/Documentation/trace/coresight/coresight-trbe.rst >> @@ -0,0 +1,39 @@ >> +.. SPDX-License-Identifier: GPL-2.0 >> + >> +============================== >> +Trace Buffer Extension (TRBE). >> +============================== >> + >> +    :Author:   Anshuman Khandual >> +    :Date:     November 2020 >> + >> +Hardware Description >> +-------------------- >> + >> +Trace Buffer Extension (TRBE) is a percpu hardware which captures in system >> +memory, CPU traces generated from a corresponding percpu tracing unit. This >> +gets plugged in as a coresight sink device because the corresponding trace >> +genarators (ETE), are plugged in as source device. >> + >> +The TRBE is not compliant to CoreSight architecture specifications, but is >> +driven via the CoreSight driver framework to support the ETE (which is >> +CoreSight compliant) integration. >> + >> +Sysfs files and directories >> +--------------------------- >> + >> +The TRBE devices appear on the existing coresight bus alongside the other >> +coresight devices:: >> + >> +    >$ ls /sys/bus/coresight/devices >> +    trbe0  trbe1  trbe2 trbe3 >> + >> +The ``trbe`` named TRBEs are associated with a CPU.:: >> + >> +    >$ ls /sys/bus/coresight/devices/trbe0/ >> +    irq align dbm > > You may want to remove irq here. Sure, will do. > >> + >> +*Key file items are:-* >> +   * ``align``: TRBE write pointer alignment >> +   * ``dbm``: TRBE updates memory with access and dirty flags >> + >> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h >> index e6962b1..2a9bfb7 100644 >> --- a/arch/arm64/include/asm/sysreg.h >> +++ b/arch/arm64/include/asm/sysreg.h >> @@ -97,6 +97,7 @@ >>   #define SET_PSTATE_UAO(x)        __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift)) >>   #define SET_PSTATE_SSBS(x)        __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift)) >>   #define SET_PSTATE_TCO(x)        __emit_inst(0xd500401f | PSTATE_TCO | ((!!x) << PSTATE_Imm_shift)) >> +#define TSB_CSYNC            __emit_inst(0xd503225f) >>     #define __SYS_BARRIER_INSN(CRm, op2, Rt) \ >>       __emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f)) >> @@ -869,6 +870,7 @@ >>   #define ID_AA64MMFR2_CNP_SHIFT        0 >>     /* id_aa64dfr0 */ >> +#define ID_AA64DFR0_TRBE_SHIFT        44 >>   #define ID_AA64DFR0_TRACE_FILT_SHIFT    40 >>   #define ID_AA64DFR0_DOUBLELOCK_SHIFT    36 >>   #define ID_AA64DFR0_PMSVER_SHIFT    32 >> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig >> index c119824..0f5e101 100644 >> --- a/drivers/hwtracing/coresight/Kconfig >> +++ b/drivers/hwtracing/coresight/Kconfig >> @@ -156,6 +156,17 @@ config CORESIGHT_CTI >>         To compile this driver as a module, choose M here: the >>         module will be called coresight-cti. >>   +config CORESIGHT_TRBE >> +    bool "Trace Buffer Extension (TRBE) driver" >> +    depends on ARM64 >> +    help >> +      This driver provides support for percpu Trace Buffer Extension (TRBE). >> +      TRBE always needs to be used along with it's corresponding percpu ETE >> +      component. ETE generates trace data which is then captured with TRBE. >> +      Unlike traditional sink devices, TRBE is a CPU feature accessible via >> +      system registers. But it's explicit dependency with trace unit (ETE) >> +      requires it to be plugged in as a coresight sink device. >> + >>   config CORESIGHT_CTI_INTEGRATION_REGS >>       bool "Access CTI CoreSight Integration Registers" >>       depends on CORESIGHT_CTI >> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile >> index f20e357..d608165 100644 >> --- a/drivers/hwtracing/coresight/Makefile >> +++ b/drivers/hwtracing/coresight/Makefile >> @@ -21,5 +21,6 @@ obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o >>   obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o >>   obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o >>   obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o >> +obj-$(CONFIG_CORESIGHT_TRBE) += coresight-trbe.o >>   coresight-cti-y := coresight-cti-core.o    coresight-cti-platform.o \ >>              coresight-cti-sysfs.o >> diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c >> new file mode 100644 >> index 0000000..ba280e6 >> --- /dev/null >> +++ b/drivers/hwtracing/coresight/coresight-trbe.c >> @@ -0,0 +1,925 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * This driver enables Trace Buffer Extension (TRBE) as a per-cpu coresight >> + * sink device could then pair with an appropriate per-cpu coresight source >> + * device (ETE) thus generating required trace data. Trace can be enabled >> + * via the perf framework. >> + * >> + * Copyright (C) 2020 ARM Ltd. >> + * >> + * Author: Anshuman Khandual >> + */ >> +#define DRVNAME "arm_trbe" >> + >> +#define pr_fmt(fmt) DRVNAME ": " fmt >> + >> +#include "coresight-trbe.h" >> + >> +#define PERF_IDX2OFF(idx, buf) ((idx) % ((buf)->nr_pages << PAGE_SHIFT)) >> + >> +/* >> + * A padding packet that will help the user space tools >> + * in skipping relevant sections in the captured trace >> + * data which could not be decoded. > > You may want to add : > > TRBE doesn't support formatting the trace data, unlike the legacy CoreSight sinks > and thus we use ETE trace packets to pad the sections of buffer. Sure, will add. > > >> + */ >> +#define ETE_IGNORE_PACKET 0x70 >> + >> +enum trbe_fault_action { >> +    TRBE_FAULT_ACT_WRAP, >> +    TRBE_FAULT_ACT_SPURIOUS, >> +    TRBE_FAULT_ACT_FATAL, >> +}; >> + >> +struct trbe_buf { >> +    unsigned long trbe_base; >> +    unsigned long trbe_limit; >> +    unsigned long trbe_write; >> +    int nr_pages; >> +    void **pages; >> +    bool snapshot; >> +    struct trbe_cpudata *cpudata; >> +}; >> + >> +struct trbe_cpudata { >> +    bool trbe_dbm; >> +    u64 trbe_align; >> +    int cpu; >> +    enum cs_mode mode; >> +    struct trbe_buf *buf; >> +    struct trbe_drvdata *drvdata; >> +}; >> + >> +struct trbe_drvdata { >> +    struct trbe_cpudata __percpu *cpudata; >> +    struct perf_output_handle __percpu **handle; >> +    struct hlist_node hotplug_node; >> +    int irq; >> +    cpumask_t supported_cpus; >> +    enum cpuhp_state trbe_online; >> +    struct platform_device *pdev; >> +}; >> + >> +static int trbe_alloc_node(struct perf_event *event) >> +{ >> +    if (event->cpu == -1) >> +        return NUMA_NO_NODE; >> +    return cpu_to_node(event->cpu); >> +} >> + >> +static void set_trbe_flush(void) >> +{ >> +    asm(TSB_CSYNC); >> +    dsb(ish); >> +} >> + >> +static void trbe_disable_and_drain_local(void) >> +{ >> +    write_sysreg_s(0, SYS_TRBLIMITR_EL1); >> +    isb(); >> +    set_trbe_flush(); >> +} >> + >> +static void trbe_reset_local(void) >> +{ >> +    trbe_disable_and_drain_local(); >> +    write_sysreg_s(0, SYS_TRBPTR_EL1); >> +    write_sysreg_s(0, SYS_TRBBASER_EL1); >> +    write_sysreg_s(0, SYS_TRBSR_EL1); >> +    isb(); >> +} >> + >> +/* >> + * TRBE Buffer Management >> + * >> + * The TRBE buffer spans from the base pointer till the limit pointer. When enabled, >> + * it starts writing trace data from the write pointer onward till the limit pointer. >> + * When the write pointer reaches the address just before the limit pointer, it gets >> + * wrapped around again to the base pointer. This is called a TRBE wrap event which >> + * is accompanied by an IRQ. > > This is true for one of the modes of operation, the WRAP mode, which could be specified > in the comment. e.g, > > This is called a TRBE wrap event, which generates a maintenance interrupt when operated > in WRAP mode. Sure, will change. > > >  The write pointer again starts writing trace data from >> + * the base pointer until just before the limit pointer before getting wrapped again >> + * with an IRQ and this process just goes on as long as the TRBE is enabled. >> + * >> + *    Wrap around with an IRQ >> + *    ------ < ------ < ------- < ----- < ----- >> + *    |                    | >> + *    ------ > ------ > ------- > ----- > ----- >> + * >> + *    +---------------+-----------------------+ >> + *    |        |            | >> + *    +---------------+-----------------------+ >> + *    Base Pointer    Write Pointer        Limit Pointer >> + * >> + * The base and limit pointers always needs to be PAGE_SIZE aligned. But the write >> + * pointer can be aligned to the implementation defined TRBE trace buffer alignment >> + * as captured in trbe_cpudata->trbe_align. >> + * >> + * >> + *        head        tail        wakeup >> + *    +---------------------------------------+----- ~ ~ ------ >> + *    |$$$$$$$|################|$$$$$$$$$$$$$$|        | >> + *    +---------------------------------------+----- ~ ~ ------ >> + *    Base Pointer    Write Pointer        Limit Pointer >> + * >> + * The perf_output_handle indices (head, tail, wakeup) are monotonically increasing >> + * values which tracks all the driver writes and user reads from the perf auxiliary >> + * buffer. Generally [head..tail] is the area where the driver can write into unless >> + * the wakeup is behind the tail. Enabled TRBE buffer span needs to be adjusted and >> + * configured depending on the perf_output_handle indices, so that the driver does >> + * not override into areas in the perf auxiliary buffer which is being or yet to be >> + * consumed from the user space. The enabled TRBE buffer area is a moving subset of >> + * the allocated perf auxiliary buffer. >> + */ >> +static void trbe_pad_buf(struct perf_output_handle *handle, int len) >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    u64 head = PERF_IDX2OFF(handle->head, buf); >> + >> +    memset((void *) buf->trbe_base + head, ETE_IGNORE_PACKET, len); >> +    if (!buf->snapshot) >> +        perf_aux_output_skip(handle, len); >> +} >> + >> +static unsigned long trbe_snapshot_offset(struct perf_output_handle *handle) >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    u64 head = PERF_IDX2OFF(handle->head, buf); >> +    u64 limit = buf->nr_pages * PAGE_SIZE; >> + >> +    /* >> +     * The trace format isn't parseable in reverse, so clamp the limit >> +     * to half of the buffer size in snapshot mode so that the worst >> +     * case is half a buffer of records, as opposed to a single record. >> +     */ > > That is not true. We can pad the buffer with Ignore packets and the decoder could > skip forward until it finds an alignment synchronization packet. So, we could use > the full size of the buffer, unlike the SPE. Will rework this and update. > >> +    if (head < limit >> 1) >> +        limit >>= 1; >> + >> +    return limit; >> +} >> + >> +/* >> + * TRBE Limit Calculation >> + * >> + * The following markers are used to illustrate various TRBE buffer situations. >> + * >> + * $$$$ - Data area, unconsumed captured trace data, not to be overridden >> + * #### - Free area, enabled, trace will be written >> + * %%%% - Free area, disabled, trace will not be written >> + * ==== - Free area, padded with ETE_IGNORE_PACKET, trace will be skipped >> + */ > > Thanks for the nice ASCII art, it really helps to understand the scenarios. > >> +static unsigned long trbe_normal_offset(struct perf_output_handle *handle) >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    struct trbe_cpudata *cpudata = buf->cpudata; >> +    const u64 bufsize = buf->nr_pages * PAGE_SIZE; >> +    u64 limit = bufsize; >> +    u64 head, tail, wakeup; >> + >> +    head = PERF_IDX2OFF(handle->head, buf); >> + >> +    /* >> +     *        head >> +     *    ------->| >> +     *    | >> +     *    head    TRBE align    tail >> +     * +----|-------|---------------|-------+ >> +     * |$$$$|=======|###############|$$$$$$$| >> +     * +----|-------|---------------|-------+ >> +     * trbe_base                trbe_base + nr_pages >> +     * >> +     * Perf aux buffer output head position can be misaligned depending on >> +     * various factors including user space reads. In case misaligned, head >> +     * needs to be aligned before TRBE can be configured. Pad the alignment >> +     * gap with ETE_IGNORE_PACKET bytes that will be ignored by user tools >> +     * and skip this section thus advancing the head. >> +     */ >> +    if (!IS_ALIGNED(head, cpudata->trbe_align)) { >> +        unsigned long delta = roundup(head, cpudata->trbe_align) - head; >> + >> +        delta = min(delta, handle->size); >> +        trbe_pad_buf(handle, delta); >> +        head = PERF_IDX2OFF(handle->head, buf); >> +    } >> + >> +    /* >> +     *    head = tail (size = 0) >> +     * +----|-------------------------------+ >> +     * |$$$$|$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$    | >> +     * +----|-------------------------------+ >> +     * trbe_base                trbe_base + nr_pages >> +     * >> +     * Perf aux buffer does not have any space for the driver to write into. >> +     * Just communicate trace truncation event to the user space by marking >> +     * it with PERF_AUX_FLAG_TRUNCATED. >> +     */ >> +    if (!handle->size) { >> +        perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); >> +        return 0; >> +    } >> + >> +    /* Compute the tail and wakeup indices now that we've aligned head */ >> +    tail = PERF_IDX2OFF(handle->head + handle->size, buf); >> +    wakeup = PERF_IDX2OFF(handle->wakeup, buf); >> + >> +    /* >> +     * Lets calculate the buffer area which TRBE could write into. There >> +     * are three possible scenarios here. Limit needs to be aligned with >> +     * PAGE_SIZE per the TRBE requirement. Always avoid clobbering the >> +     * unconsumed data. >> +     * >> +     * 1) head < tail >> +     * >> +     *    head            tail >> +     * +----|-----------------------|-------+ >> +     * |$$$$|#######################|$$$$$$$| >> +     * +----|-----------------------|-------+ >> +     * trbe_base            limit    trbe_base + nr_pages >> +     * >> +     * TRBE could write into [head..tail] area. Unless the tail is right at >> +     * the end of the buffer, neither an wrap around nor an IRQ is expected >> +     * while being enabled. >> +     * >> +     * 2) head == tail >> +     * >> +     *    head = tail (size > 0) >> +     * +----|-------------------------------+ >> +     * |%%%%|###############################| >> +     * +----|-------------------------------+ >> +     * trbe_base                limit = trbe_base + nr_pages >> +     * >> +     * TRBE should just write into [head..base + nr_pages] area even though >> +     * the entire buffer is empty. Reason being, when the trace reaches the >> +     * end of the buffer, it will just wrap around with an IRQ giving an >> +     * opportunity to reconfigure the buffer. >> +     * >> +     * 3) tail < head >> +     * >> +     *    tail            head >> +     * +----|-----------------------|-------+ >> +     * |%%%%|$$$$$$$$$$$$$$$$$$$$$$$|#######| >> +     * +----|-----------------------|-------+ >> +     * trbe_base                limit = trbe_base + nr_pages >> +     * >> +     * TRBE should just write into [head..base + nr_pages] area even though >> +     * the [trbe_base..tail] is also empty. Reason being, when the trace >> +     * reaches the end of the buffer, it will just wrap around with an IRQ >> +     * giving an opportunity to reconfigure the buffer. >> +     */ >> +    if (head < tail) >> +        limit = round_down(tail, PAGE_SIZE); >> + >> +    /* >> +     * Wakeup may be arbitrarily far into the future. If it's not in the >> +     * current generation, either we'll wrap before hitting it, or it's >> +     * in the past and has been handled already. >> +     * >> +     * If there's a wakeup before we wrap, arrange to be woken up by the >> +     * page boundary following it. Keep the tail boundary if that's lower. >> +     * >> +     *    head        wakeup    tail >> +     * +----|---------------|-------|-------+ >> +     * |$$$$|###############|%%%%%%%|$$$$$$$| >> +     * +----|---------------|-------|-------+ >> +     * trbe_base        limit        trbe_base + nr_pages >> +     */ >> +    if (handle->wakeup < (handle->head + handle->size) && head <= wakeup) >> +        limit = min(limit, round_up(wakeup, PAGE_SIZE)); >> + >> +    /* >> +     * There are two situation when this can happen i.e limit is before >> +     * the head and hence TRBE cannot be configured. >> +     * >> +     * 1) head < tail (aligned down with PAGE_SIZE) and also they are both >> +     * within the same PAGE size range. >> +     * >> +     *            PAGE_SIZE >> +     *        |----------------------| >> +     * >> +     *        limit    head    tail >> +     * +------------|------|--------|-------+ >> +     * |$$$$$$$$$$$$$$$$$$$|========|$$$$$$$| >> +     * +------------|------|--------|-------+ >> +     * trbe_base                trbe_base + nr_pages >> +     * >> +     * 2) head < wakeup (aligned up with PAGE_SIZE) < tail and also both >> +     * head and wakeup are within same PAGE size range. >> +     * >> +     *        PAGE_SIZE >> +     *    |----------------------| >> +     * >> +     *    limit    head    wakeup  tail >> +     * +----|------|-------|--------|-------+ >> +     * |$$$$$$$$$$$|=======|========|$$$$$$$| >> +     * +----|------|-------|--------|-------+ >> +     * trbe_base                trbe_base + nr_pages >> +     */ >> +    if (limit > head) >> +        return limit; >> + >> +    trbe_pad_buf(handle, handle->size); >> +    perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); >> +    return 0; >> +} >> + >> +static unsigned long get_trbe_limit(struct perf_output_handle *handle) > > nit: The naming is a bit confusing with get_trbe_limit() and get_trbe_limit_pointer(). > One computes the TRBE buffer limit and the other reads the hardware Limit pointer. > It would be good if follow a scheme for the namings. > > e.g, trbe_limit_pointer() , trbe_base_pointer(), trbe__ for anything > that reads the hardware register. The current scheme is in the form get_trbe_XXX() where XXX is a TRBE hardware component e.g. get_trbe_base_pointer() get_trbe_limit_pointer() get_trbe_write_pointer() get_trbe_ec() get_trbe_bsc() get_trbe_address_align() get_trbe_flag_update() > > Or may be rename the get_trbe_limit() to compute_trbe_buffer_limit() This makes it clear, will change. > >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    unsigned long offset; >> + >> +    if (buf->snapshot) >> +        offset = trbe_snapshot_offset(handle); >> +    else >> +        offset = trbe_normal_offset(handle); >> +    return buf->trbe_base + offset; >> +} >> + >> +static void clear_trbe_state(void) > > nit: The name doesn't give much clue about what it is doing, especially, given > the following "set_trbe_state()" which does completely different from this "clear" > operation. I agree that these names could have been better. s/clear_trbe_state/trbe_reset_perf_state - Clears TRBE from current perf config s/set_trbe_state/trbe_prepare_perf_state - Prepares TRBE for the next perf config > > I would rather open code this with a write of 0 to trbsr in the caller. > >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    WARN_ON(is_trbe_enabled()); >> +    trbsr &= ~TRBSR_IRQ; >> +    trbsr &= ~TRBSR_TRG; >> +    trbsr &= ~TRBSR_WRAP; >> +    trbsr &= ~(TRBSR_EC_MASK << TRBSR_EC_SHIFT); >> +    trbsr &= ~(TRBSR_BSC_MASK << TRBSR_BSC_SHIFT); >> +    trbsr &= ~(TRBSR_FSC_MASK << TRBSR_FSC_SHIFT); > > BSC and FSC are the same fields under MSS, with their meanings determined by the EC field. Could just drop the FSC part if required. > > Could we simply write 0 to the register ? I would really like to avoid that. This function clearly enumerates all individual bit fields being cleared for resetting as well as preparing the TRBE for the next perf session. Converting this into a 0 write for SYS_TRBSR_EL1 sounds excessive and the only thing it would save is the register read. > >> +    write_sysreg_s(trbsr, SYS_TRBSR_EL1); >> +} >> + >> +static void set_trbe_state(void) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    trblimitr &= ~TRBLIMITR_NVM; >> +    trblimitr &= ~(TRBLIMITR_FILL_MODE_MASK << TRBLIMITR_FILL_MODE_SHIFT); >> +    trblimitr &= ~(TRBLIMITR_TRIG_MODE_MASK << TRBLIMITR_TRIG_MODE_SHIFT); >> +    trblimitr |= (TRBE_FILL_STOP & TRBLIMITR_FILL_MODE_MASK) << TRBLIMITR_FILL_MODE_SHIFT; >> +    trblimitr |= (TRBE_TRIGGER_IGNORE & TRBLIMITR_TRIG_MODE_MASK) << TRBLIMITR_TRIG_MODE_SHIFT; >> +    write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); > > Do we need to read-copy-update here ? Could we simply write 0 ? > Same as above comment, could we not simply opencode it at the caller ? > Clearly the names don't help. Will change the names as proposed or something better. But lets leave these functions as is. Besides TRBE_TRIGGER_IGNORE also has a positive value (i.e 3), writing all 0s into SYS_TRBLIMITR_EL1 will not be ideal. > >> +} >> + >> +static void trbe_enable_hw(struct trbe_buf *buf) >> +{ >> +    WARN_ON(buf->trbe_write < buf->trbe_base); >> +    WARN_ON(buf->trbe_write >= buf->trbe_limit); >> +    set_trbe_disabled(); >> +    clear_trbe_state(); >> +    set_trbe_state(); >> +    isb(); >> +    set_trbe_base_pointer(buf->trbe_base); >> +    set_trbe_limit_pointer(buf->trbe_limit); >> +    set_trbe_write_pointer(buf->trbe_write); > > Where do we set the fill mode ? TRBE_FILL_STOP has already been configured in set_trbe_state(). > >> +    isb(); >> +    set_trbe_running(); >> +    set_trbe_enabled(); >> +    set_trbe_flush(); >> +} >> + >> +static void *arm_trbe_alloc_buffer(struct coresight_device *csdev, >> +                   struct perf_event *event, void **pages, >> +                   int nr_pages, bool snapshot) >> +{ >> +    struct trbe_buf *buf; >> +    struct page **pglist; >> +    int i; >> + >> +    if ((nr_pages < 2) || (snapshot && (nr_pages & 1))) >> +        return NULL; >> + >> +    buf = kzalloc_node(sizeof(*buf), GFP_KERNEL, trbe_alloc_node(event)); >> +    if (IS_ERR(buf)) >> +        return ERR_PTR(-ENOMEM); >> + >> +    pglist = kcalloc(nr_pages, sizeof(*pglist), GFP_KERNEL); >> +    if (IS_ERR(pglist)) { >> +        kfree(buf); >> +        return ERR_PTR(-ENOMEM); >> +    } >> + >> +    for (i = 0; i < nr_pages; i++) >> +        pglist[i] = virt_to_page(pages[i]); >> + >> +    buf->trbe_base = (unsigned long) vmap(pglist, nr_pages, VM_MAP, PAGE_KERNEL); >> +    if (IS_ERR((void *) buf->trbe_base)) { >> +        kfree(pglist); >> +        kfree(buf); >> +        return ERR_PTR(buf->trbe_base); >> +    } >> +    buf->trbe_limit = buf->trbe_base + nr_pages * PAGE_SIZE; >> +    buf->trbe_write = buf->trbe_base; >> +    buf->snapshot = snapshot; >> +    buf->nr_pages = nr_pages; >> +    buf->pages = pages; >> +    kfree(pglist); >> +    return buf; >> +} >> + >> +void arm_trbe_free_buffer(void *config) >> +{ >> +    struct trbe_buf *buf = config; >> + >> +    vunmap((void *) buf->trbe_base); >> +    kfree(buf); >> +} >> + >> +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; >> +    unsigned long size, offset; >> + >> +    WARN_ON(buf->cpudata != cpudata); >> +    WARN_ON(cpudata->cpu != smp_processor_id()); >> +    WARN_ON(cpudata->drvdata != drvdata); >> +    if (cpudata->mode != CS_MODE_PERF) >> +        return -EINVAL; >> + >> +    offset = get_trbe_write_pointer() - get_trbe_base_pointer(); >> +    size = offset - PERF_IDX2OFF(handle->head, buf); >> +    if (buf->snapshot) >> +        handle->head += size; > > You may want to add in a comment why we keep the TRBE disabled here. Good point, will add. > >> +    trbe_reset_local(); >> +    return size; >> +} >> + >> +static int arm_trbe_enable(struct coresight_device *csdev, u32 mode, void *data) >> +{ >> +    struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); >> +    struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); >> +    struct perf_output_handle *handle = data; >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> + >> +    WARN_ON(cpudata->cpu != smp_processor_id()); >> +    WARN_ON(cpudata->drvdata != drvdata); >> +    if (mode != CS_MODE_PERF) >> +        return -EINVAL; >> + >> +    *this_cpu_ptr(drvdata->handle) = handle; >> +    cpudata->buf = buf; >> +    cpudata->mode = mode; >> +    buf->cpudata = cpudata; >> +    buf->trbe_write = buf->trbe_base + PERF_IDX2OFF(handle->head, buf); >> +    buf->trbe_limit = get_trbe_limit(handle); >> +    if (buf->trbe_limit == buf->trbe_base) { >> +        trbe_disable_and_drain_local(); >> +        return 0; >> +    } >> +    trbe_enable_hw(buf); >> +    return 0; >> +} >> + >> +static int arm_trbe_disable(struct coresight_device *csdev) >> +{ >> +    struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); >> +    struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); >> +    struct trbe_buf *buf = cpudata->buf; >> + >> +    WARN_ON(buf->cpudata != cpudata); >> +    WARN_ON(cpudata->cpu != smp_processor_id()); >> +    WARN_ON(cpudata->drvdata != drvdata); >> +    if (cpudata->mode != CS_MODE_PERF) >> +        return -EINVAL; >> + >> +    trbe_disable_and_drain_local(); >> +    buf->cpudata = NULL; >> +    cpudata->buf = NULL; >> +    cpudata->mode = CS_MODE_DISABLED; >> +    return 0; >> +} >> + >> +static void trbe_handle_fatal(struct perf_output_handle *handle) >> +{ >> +    perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); >> +    perf_aux_output_end(handle, 0); >> +    trbe_disable_and_drain_local(); >> +} >> + >> +static void trbe_handle_spurious(struct perf_output_handle *handle) >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> + >> +    buf->trbe_write = buf->trbe_base + PERF_IDX2OFF(handle->head, buf); >> +    buf->trbe_limit = get_trbe_limit(handle); >> +    if (buf->trbe_limit == buf->trbe_base) { >> +        trbe_disable_and_drain_local(); >> +        return; >> +    } >> +    trbe_enable_hw(buf); >> +} >> + >> +static void trbe_handle_overflow(struct perf_output_handle *handle) >> +{ >> +    struct perf_event *event = handle->event; >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    unsigned long offset, size; >> +    struct etm_event_data *event_data; >> + >> +    offset = get_trbe_limit_pointer() - get_trbe_base_pointer(); >> +    size = offset - PERF_IDX2OFF(handle->head, buf); >> +    if (buf->snapshot) >> +        handle->head = offset; >> +    perf_aux_output_end(handle, size); >> + >> +    event_data = perf_aux_output_begin(handle, event); >> +    if (!event_data) { >> +        event->hw.state |= PERF_HES_STOPPED; >> +        trbe_disable_and_drain_local(); >> +        perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); >> +        return; >> +    } >> +    buf->trbe_write = buf->trbe_base; >> +    buf->trbe_limit = get_trbe_limit(handle); >> +    if (buf->trbe_limit == buf->trbe_base) { >> +        trbe_disable_and_drain_local(); >> +        return; >> +    } >> +    *this_cpu_ptr(buf->cpudata->drvdata->handle) = handle; >> +    trbe_enable_hw(buf); >> +} >> + >> +static bool is_perf_trbe(struct perf_output_handle *handle) >> +{ >> +    struct trbe_buf *buf = etm_perf_sink_config(handle); >> +    struct trbe_cpudata *cpudata = buf->cpudata; >> +    struct trbe_drvdata *drvdata = cpudata->drvdata; >> +    int cpu = smp_processor_id(); >> + >> +    WARN_ON(buf->trbe_base != get_trbe_base_pointer()); >> +    WARN_ON(buf->trbe_limit != get_trbe_limit_pointer()); >> + >> +    if (cpudata->mode != CS_MODE_PERF) >> +        return false; >> + >> +    if (cpudata->cpu != cpu) >> +        return false; >> + >> +    if (!cpumask_test_cpu(cpu, &drvdata->supported_cpus)) >> +        return false; >> + >> +    return true; >> +} >> + >> +static enum trbe_fault_action trbe_get_fault_act(struct perf_output_handle *handle) >> +{ >> +    int ec = get_trbe_ec(); >> +    int bsc = get_trbe_bsc(); >> + >> +    WARN_ON(is_trbe_running()); >> +    if (is_trbe_trg() || is_trbe_abort()) >> +        return TRBE_FAULT_ACT_FATAL; >> + >> +    if ((ec == TRBE_EC_STAGE1_ABORT) || (ec == TRBE_EC_STAGE2_ABORT)) >> +        return TRBE_FAULT_ACT_FATAL; >> + >> +    if (is_trbe_wrap() && (ec == TRBE_EC_OTHERS) && (bsc == TRBE_BSC_FILLED)) { >> +        if (get_trbe_write_pointer() == get_trbe_base_pointer()) >> +            return TRBE_FAULT_ACT_WRAP; >> +    } >> +    return TRBE_FAULT_ACT_SPURIOUS; >> +} >> + >> +static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) >> +{ >> +    struct perf_output_handle **handle_ptr = dev; >> +    struct perf_output_handle *handle = *handle_ptr; >> +    enum trbe_fault_action act; >> + >> +    WARN_ON(!is_trbe_irq()); >> +    clr_trbe_irq(); >> + >> +    if (!perf_get_aux(handle)) >> +        return IRQ_NONE; >> + >> +    if (!is_perf_trbe(handle)) >> +        return IRQ_NONE; >> + >> +    irq_work_run(); >> + >> +    act = trbe_get_fault_act(handle); >> +    switch (act) { >> +    case TRBE_FAULT_ACT_WRAP: >> +        trbe_handle_overflow(handle); >> +        break; >> +    case TRBE_FAULT_ACT_SPURIOUS: >> +        trbe_handle_spurious(handle); >> +        break; >> +    case TRBE_FAULT_ACT_FATAL: >> +        trbe_handle_fatal(handle); >> +        break; >> +    } >> +    return IRQ_HANDLED; >> +} >> + >> +static const struct coresight_ops_sink arm_trbe_sink_ops = { >> +    .enable        = arm_trbe_enable, >> +    .disable    = arm_trbe_disable, >> +    .alloc_buffer    = arm_trbe_alloc_buffer, >> +    .free_buffer    = arm_trbe_free_buffer, >> +    .update_buffer    = arm_trbe_update_buffer, >> +}; >> + >> +static const struct coresight_ops arm_trbe_cs_ops = { >> +    .sink_ops    = &arm_trbe_sink_ops, >> +}; >> + >> +static ssize_t align_show(struct device *dev, struct device_attribute *attr, char *buf) >> +{ >> +    struct trbe_cpudata *cpudata = dev_get_drvdata(dev); >> + >> +    return sprintf(buf, "%llx\n", cpudata->trbe_align); >> +} >> +static DEVICE_ATTR_RO(align); >> + >> +static ssize_t dbm_show(struct device *dev, struct device_attribute *attr, char *buf) >> +{ >> +    struct trbe_cpudata *cpudata = dev_get_drvdata(dev); >> + >> +    return sprintf(buf, "%d\n", cpudata->trbe_dbm); >> +} >> +static DEVICE_ATTR_RO(dbm); >> + >> +static struct attribute *arm_trbe_attrs[] = { >> +    &dev_attr_align.attr, >> +    &dev_attr_dbm.attr, >> +    NULL, >> +}; >> + >> +static const struct attribute_group arm_trbe_group = { >> +    .attrs = arm_trbe_attrs, >> +}; >> + >> +static const struct attribute_group *arm_trbe_groups[] = { >> +    &arm_trbe_group, >> +    NULL, >> +}; >> + >> +static void arm_trbe_probe_coresight_cpu(void *info) >> +{ >> +    struct trbe_drvdata *drvdata = info; >> +    struct coresight_desc desc = { 0 }; >> +    int cpu = smp_processor_id(); >> +    struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu); >> +    struct coresight_device *trbe_csdev = per_cpu(csdev_sink, cpu); >> +    struct device *dev; >> + >> +    if (WARN_ON(!cpudata)) >> +        goto cpu_clear; >> + >> +    if (trbe_csdev) >> +        return; >> + >> +    cpudata->cpu = smp_processor_id(); >> +    cpudata->drvdata = drvdata; >> +    dev = &cpudata->drvdata->pdev->dev; >> + >> +    if (!is_trbe_available()) { >> +        pr_err("TRBE is not implemented on cpu %d\n", cpudata->cpu); >> +        goto cpu_clear; >> +    } >> + >> +    if (!is_trbe_programmable()) { >> +        pr_err("TRBE is owned in higher exception level on cpu %d\n", cpudata->cpu); >> +        goto cpu_clear; >> +    } >> +    desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DRVNAME, smp_processor_id()); >> +    if (IS_ERR(desc.name)) >> +        goto cpu_clear; >> + >> +    desc.type = CORESIGHT_DEV_TYPE_SINK; >> +    desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PERCPU_SYSMEM; >> +    desc.ops = &arm_trbe_cs_ops; >> +    desc.pdata = dev_get_platdata(dev); >> +    desc.groups = arm_trbe_groups; >> +    desc.dev = dev; >> +    trbe_csdev = coresight_register(&desc); >> +    if (IS_ERR(trbe_csdev)) >> +        goto cpu_clear; >> + >> +    dev_set_drvdata(&trbe_csdev->dev, cpudata); >> +    cpudata->trbe_dbm = get_trbe_flag_update(); >> +    cpudata->trbe_align = 1ULL << get_trbe_address_align(); >> +    if (cpudata->trbe_align > SZ_2K) { >> +        pr_err("Unsupported alignment on cpu %d\n", cpudata->cpu); >> +        goto cpu_clear; >> +    } >> +    per_cpu(csdev_sink, cpu) = trbe_csdev; >> +    trbe_reset_local(); >> +    enable_percpu_irq(drvdata->irq, IRQ_TYPE_NONE); >> +    return; >> +cpu_clear: >> +    cpumask_clear_cpu(cpudata->cpu, &cpudata->drvdata->supported_cpus); >> +} >> + >> +static void arm_trbe_remove_coresight_cpu(void *info) >> +{ >> +    int cpu = smp_processor_id(); >> +    struct trbe_drvdata *drvdata = info; >> +    struct trbe_cpudata *cpudata = per_cpu_ptr(drvdata->cpudata, cpu); >> +    struct coresight_device *trbe_csdev = per_cpu(csdev_sink, cpu); >> + >> +    if (trbe_csdev) { >> +        coresight_unregister(trbe_csdev); >> +        cpudata->drvdata = NULL; >> +        per_cpu(csdev_sink, cpu) = NULL; >> +    } >> +    disable_percpu_irq(drvdata->irq); >> +    trbe_reset_local(); >> +} >> + >> +static int arm_trbe_probe_coresight(struct trbe_drvdata *drvdata) >> +{ >> +    drvdata->cpudata = alloc_percpu(typeof(*drvdata->cpudata)); >> +    if (IS_ERR(drvdata->cpudata)) >> +        return PTR_ERR(drvdata->cpudata); >> + >> +    arm_trbe_probe_coresight_cpu(drvdata); >> +    smp_call_function_many(&drvdata->supported_cpus, arm_trbe_probe_coresight_cpu, drvdata, 1); >> +    return 0; >> +} >> + >> +static int arm_trbe_remove_coresight(struct trbe_drvdata *drvdata) >> +{ >> +    arm_trbe_remove_coresight_cpu(drvdata); >> +    smp_call_function_many(&drvdata->supported_cpus, arm_trbe_remove_coresight_cpu, drvdata, 1); >> +    free_percpu(drvdata->cpudata); >> +    return 0; >> +} >> + >> +static int arm_trbe_cpu_startup(unsigned int cpu, struct hlist_node *node) >> +{ >> +    struct trbe_drvdata *drvdata = hlist_entry_safe(node, struct trbe_drvdata, hotplug_node); >> + >> +    if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) { >> +        if (!per_cpu(csdev_sink, cpu) && (system_state == SYSTEM_RUNNING)) { > > Why is the system_state check relevant here ? I had a concern regarding whether arm_trbe_probe_coresight_cpu() invocations from arm_trbe_cpu_startup() might race with its invocations during boot from arm_trbe_device_probe(). Checking for runtime system_state would ensure that a complete TRBE probe on a given cpu is called only after the boot is complete. But if the race condition is really never possible, can just drop this check. > >> +            arm_trbe_probe_coresight_cpu(drvdata); >> +        } else { >> +            trbe_reset_local(); >> +            enable_percpu_irq(drvdata->irq, IRQ_TYPE_NONE); >> +        } >> +    } >> +    return 0; >> +} >> + >> +static int arm_trbe_cpu_teardown(unsigned int cpu, struct hlist_node *node) >> +{ >> +    struct trbe_drvdata *drvdata = hlist_entry_safe(node, struct trbe_drvdata, hotplug_node); >> + >> +    if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) { >> +        disable_percpu_irq(drvdata->irq); >> +        trbe_reset_local(); >> +    } >> +    return 0; >> +} >> + >> +static int arm_trbe_probe_cpuhp(struct trbe_drvdata *drvdata) >> +{ >> +    enum cpuhp_state trbe_online; >> + >> +    trbe_online = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, DRVNAME, >> +                    arm_trbe_cpu_startup, arm_trbe_cpu_teardown); >> +    if (trbe_online < 0) >> +        return -EINVAL; >> + >> +    if (cpuhp_state_add_instance(trbe_online, &drvdata->hotplug_node)) >> +        return -EINVAL; >> + >> +    drvdata->trbe_online = trbe_online; >> +    return 0; >> +} >> + >> +static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata) >> +{ >> +    cpuhp_remove_multi_state(drvdata->trbe_online); >> +} >> + >> +static int arm_trbe_probe_irq(struct platform_device *pdev, >> +                  struct trbe_drvdata *drvdata) >> +{ >> +    drvdata->irq = platform_get_irq(pdev, 0); >> +    if (!drvdata->irq) { >> +        pr_err("IRQ not found for the platform device\n"); >> +        return -ENXIO; >> +    } >> + >> +    if (!irq_is_percpu(drvdata->irq)) { >> +        pr_err("IRQ is not a PPI\n"); >> +        return -EINVAL; >> +    } >> + >> +    if (irq_get_percpu_devid_partition(drvdata->irq, &drvdata->supported_cpus)) >> +        return -EINVAL; >> + >> +    drvdata->handle = alloc_percpu(typeof(*drvdata->handle)); >> +    if (!drvdata->handle) >> +        return -ENOMEM; >> + >> +    if (request_percpu_irq(drvdata->irq, arm_trbe_irq_handler, DRVNAME, drvdata->handle)) { >> +        free_percpu(drvdata->handle); >> +        return -EINVAL; >> +    } >> +    return 0; >> +} >> + >> +static void arm_trbe_remove_irq(struct trbe_drvdata *drvdata) >> +{ >> +    free_percpu_irq(drvdata->irq, drvdata->handle); >> +    free_percpu(drvdata->handle); >> +} >> + >> +static int arm_trbe_device_probe(struct platform_device *pdev) >> +{ >> +    struct coresight_platform_data *pdata; >> +    struct trbe_drvdata *drvdata; >> +    struct device *dev = &pdev->dev; >> +    int ret; >> + >> +    drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); >> +    if (IS_ERR(drvdata)) >> +        return -ENOMEM; >> + >> +    pdata = coresight_get_platform_data(dev); >> +    if (IS_ERR(pdata)) { >> +        kfree(drvdata); >> +        return -ENOMEM; >> +    } >> + >> +    dev_set_drvdata(dev, drvdata); >> +    dev->platform_data = pdata; >> +    drvdata->pdev = pdev; >> +    ret = arm_trbe_probe_irq(pdev, drvdata); >> +    if (ret) >> +        goto irq_failed; >> + >> +    ret = arm_trbe_probe_coresight(drvdata); >> +    if (ret) >> +        goto probe_failed; >> + >> +    ret = arm_trbe_probe_cpuhp(drvdata); >> +    if (ret) >> +        goto cpuhp_failed; >> + >> +    return 0; >> +cpuhp_failed: >> +    arm_trbe_remove_coresight(drvdata); >> +probe_failed: >> +    arm_trbe_remove_irq(drvdata); >> +irq_failed: >> +    kfree(pdata); >> +    kfree(drvdata); >> +    return ret; >> +} >> + >> +static int arm_trbe_device_remove(struct platform_device *pdev) >> +{ >> +    struct coresight_platform_data *pdata = dev_get_platdata(&pdev->dev); >> +    struct trbe_drvdata *drvdata = platform_get_drvdata(pdev); >> + >> +    arm_trbe_remove_coresight(drvdata); >> +    arm_trbe_remove_cpuhp(drvdata); >> +    arm_trbe_remove_irq(drvdata); >> +    kfree(pdata); >> +    kfree(drvdata); >> +    return 0; >> +} >> + >> +static const struct of_device_id arm_trbe_of_match[] = { >> +    { .compatible = "arm,trace-buffer-extension",    .data = (void *)1 }, > > What is the significance of .data = 1 ? I guess this can also be dropped. > >> +    {}, >> +}; >> +MODULE_DEVICE_TABLE(of, arm_trbe_of_match); >> + >> +static struct platform_driver arm_trbe_driver = { >> +    .driver    = { >> +        .name = DRVNAME, >> +        .of_match_table = of_match_ptr(arm_trbe_of_match), >> +        .suppress_bind_attrs = true, >> +    }, >> +    .probe    = arm_trbe_device_probe, >> +    .remove    = arm_trbe_device_remove, >> +}; >> + >> +static int __init arm_trbe_init(void) >> +{ >> +    int ret; >> + >> +    ret = platform_driver_register(&arm_trbe_driver); >> +    if (!ret) >> +        return 0; >> + >> +    pr_err("Error registering %s platform driver\n", DRVNAME); >> +    return ret; >> +} >> + >> +static void __exit arm_trbe_exit(void) >> +{ >> +    platform_driver_unregister(&arm_trbe_driver); >> +} >> +module_init(arm_trbe_init); >> +module_exit(arm_trbe_exit); >> + >> +MODULE_AUTHOR("Anshuman Khandual "); >> +MODULE_DESCRIPTION("Arm Trace Buffer Extension (TRBE) driver"); >> +MODULE_LICENSE("GPL v2"); >> diff --git a/drivers/hwtracing/coresight/coresight-trbe.h b/drivers/hwtracing/coresight/coresight-trbe.h >> new file mode 100644 >> index 0000000..e956439 >> --- /dev/null >> +++ b/drivers/hwtracing/coresight/coresight-trbe.h >> @@ -0,0 +1,248 @@ >> +/* SPDX-License-Identifier: GPL-2.0 */ >> +/* >> + * This contains all required hardware related helper functions for >> + * Trace Buffer Extension (TRBE) driver in the coresight framework. >> + * >> + * Copyright (C) 2020 ARM Ltd. >> + * >> + * Author: Anshuman Khandual >> + */ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "coresight-etm-perf.h" >> + >> +DECLARE_PER_CPU(struct coresight_device *, csdev_sink); >> + >> +static inline bool is_trbe_available(void) >> +{ >> +    u64 aa64dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1); >> +    int trbe = cpuid_feature_extract_unsigned_field(aa64dfr0, ID_AA64DFR0_TRBE_SHIFT); >> + >> +    return trbe >= 0b0001; >> +} >> + >> +static inline bool is_trbe_enabled(void) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    return trblimitr & TRBLIMITR_ENABLE; >> +} >> + >> +#define TRBE_EC_OTHERS        0 >> +#define TRBE_EC_STAGE1_ABORT    36 >> +#define TRBE_EC_STAGE2_ABORT    37 >> + >> +static inline int get_trbe_ec(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK; >> +} >> + >> +#define TRBE_BSC_NOT_STOPPED    0 >> +#define    TRBE_BSC_FILLED        1 >> +#define TRBE_BSC_TRIGGERED    2 >> + >> +static inline int get_trbe_bsc(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK; >> +} >> + >> +static inline void clr_trbe_irq(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    trbsr &= ~TRBSR_IRQ; >> +    write_sysreg_s(trbsr, SYS_TRBSR_EL1); >> +} >> + >> +static inline bool is_trbe_irq(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return trbsr & TRBSR_IRQ; >> +} >> + >> +static inline bool is_trbe_trg(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return trbsr & TRBSR_TRG; >> +} >> + >> +static inline bool is_trbe_wrap(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return trbsr & TRBSR_WRAP; >> +} >> + >> +static inline bool is_trbe_abort(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return trbsr & TRBSR_ABORT; >> +} >> + >> +static inline bool is_trbe_running(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    return !(trbsr & TRBSR_STOP); >> +} >> + >> +static inline void set_trbe_running(void) >> +{ >> +    u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); >> + >> +    trbsr &= ~TRBSR_STOP; >> +    write_sysreg_s(trbsr, SYS_TRBSR_EL1); >> +} >> + >> +static inline void set_trbe_virtual_mode(void) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    trblimitr &= ~TRBLIMITR_NVM; >> +    write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); >> +} >> + >> +#define TRBE_TRIGGER_STOP    0 >> +#define TRBE_TRIGGER_IRQ    1 >> +#define TRBE_TRIGGER_IGNORE    3 >> + >> +static inline int get_trbe_trig_mode(void) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    return (trblimitr >> TRBLIMITR_TRIG_MODE_SHIFT) & TRBLIMITR_TRIG_MODE_MASK; >> +} >> + >> +static inline void set_trbe_trig_mode(int mode) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    trblimitr &= ~(TRBLIMITR_TRIG_MODE_MASK << TRBLIMITR_TRIG_MODE_SHIFT); >> +    trblimitr |= ((mode & TRBLIMITR_TRIG_MODE_MASK) << TRBLIMITR_TRIG_MODE_SHIFT); >> +    write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); >> +} >> + >> +#define TRBE_FILL_STOP        0 >> +#define TRBE_FILL_WRAP        1 >> +#define TRBE_FILL_CIRCULAR    3 >> + > > ---8>--- > >> +static inline int get_trbe_fill_mode(void) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    return (trblimitr >> TRBLIMITR_FILL_MODE_SHIFT) & TRBLIMITR_FILL_MODE_MASK; >> +} > + >> +static inline void set_trbe_fill_mode(int mode) >> +{ >> +    u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); >> + >> +    trblimitr &= ~(TRBLIMITR_FILL_MODE_MASK << TRBLIMITR_FILL_MODE_SHIFT); >> +    trblimitr |= ((mode & TRBLIMITR_FILL_MODE_MASK) << TRBLIMITR_FILL_MODE_SHIFT); >> +    write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); >> +} >> + > > Where do we use these ? I couldn't find any users. After directly configuring the TRBE state via [set|clear]_trbe_state() functions, these trig/fill mode related helpers are not used any more. Hence will just drop these. 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=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS, USER_AGENT_SANE_1 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 B779EC433DB for ; Tue, 5 Jan 2021 09:31:12 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 4159E20756 for ; Tue, 5 Jan 2021 09:31:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4159E20756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com 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=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=IAtJurd8EKPyGhGv4gGBY8ooUHEDAsFhSNvBvpUED8c=; b=nnWnSQX/JWEyNMF8bNoumnv2d dPlABTXrLqrfg0sNAqFtVQbNctO7ymrtLge7SH8/0NC/zpHVfm7x65o+CGgtvej90oWugqmMqNjut 0cG9ZaaGdW+rHBvQdxpyqtVBzfFPF8nbruR9fsag2IkxOkSRHoUXw8A4iIOCq1TD48eF5wiIa0rwI 8pxdGhZ/JB1jWz630BAYHf84RY8WSvyYZdNZ9duLGp6fnjlVxb4mZNVaqexHokb7pMPjpPcT29RiH lIk6t2h3ABPOlpNjxtV0Y83qBfr009jvyhZGJ7VVogqT4+BfyjnpmQnSbPX0zl/QJ5nTg/86YJYjv 5cwXCIKQw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kwieB-0000IQ-AH; Tue, 05 Jan 2021 09:28:59 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kwie7-0000Go-Ap for linux-arm-kernel@lists.infradead.org; Tue, 05 Jan 2021 09:28:57 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8E210101E; Tue, 5 Jan 2021 01:28:46 -0800 (PST) Received: from [192.168.0.130] (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 88BA33F719; Tue, 5 Jan 2021 01:28:43 -0800 (PST) Subject: Re: [PATCH 10/11] coresight: sink: Add TRBE driver To: Suzuki K Poulose , linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org References: <1608717823-18387-1-git-send-email-anshuman.khandual@arm.com> <1608717823-18387-11-git-send-email-anshuman.khandual@arm.com> <92b5ae56-df5d-3772-0206-b50ea4080c4f@arm.com> From: Anshuman Khandual Message-ID: Date: Tue, 5 Jan 2021 14:59:03 +0530 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: <92b5ae56-df5d-3772-0206-b50ea4080c4f@arm.com> Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210105_042855_552120_C9DCCAA2 X-CRM114-Status: GOOD ( 39.76 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Linu Cherian , linux-kernel@vger.kernel.org, Mathieu Poirier , Mike Leach 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 CgpPbiAxLzQvMjEgOTo1OCBQTSwgU3V6dWtpIEsgUG91bG9zZSB3cm90ZToKPiAKPiBIaSBBbnNo dW1hbiwKPiAKPiBPbiAxMi8yMy8yMCAxMDowMyBBTSwgQW5zaHVtYW4gS2hhbmR1YWwgd3JvdGU6 Cj4+IFRyYWNlIEJ1ZmZlciBFeHRlbnNpb24gKFRSQkUpIGltcGxlbWVudHMgYSB0cmFjZSBidWZm ZXIgcGVyIENQVSB3aGljaCBpcwo+PiBhY2Nlc3NpYmxlIHZpYSB0aGUgc3lzdGVtIHJlZ2lzdGVy cy4gVGhlIFRSQkUgc3VwcG9ydHMgZGlmZmVyZW50IGFkZHJlc3NpbmcKPj4gbW9kZXMgaW5jbHVk aW5nIENQVSB2aXJ0dWFsIGFkZHJlc3MgYW5kIGJ1ZmZlciBtb2RlcyBpbmNsdWRpbmcgdGhlIGNp cmN1bGFyCj4+IGJ1ZmZlciBtb2RlLiBUaGUgVFJCRSBidWZmZXIgaXMgYWRkcmVzc2VkIGJ5IGEg YmFzZSBwb2ludGVyIChUUkJCQVNFUl9FTDEpLAo+PiBhbiB3cml0ZSBwb2ludGVyIChUUkJQVFJf RUwxKSBhbmQgYSBsaW1pdCBwb2ludGVyIChUUkJMSU1JVFJfRUwxKS4gQnV0IHRoZQo+PiBhY2Nl c3MgdG8gdGhlIHRyYWNlIGJ1ZmZlciBjb3VsZCBiZSBwcm9oaWJpdGVkIGJ5IGEgaGlnaGVyIGV4 Y2VwdGlvbiBsZXZlbAo+PiAoRUwzIG9yIEVMMiksIGluZGljYXRlZCBieSBUUkJJRFJfRUwxLlAu IFRoZSBUUkJFIGNhbiBhbHNvIGdlbmVyYXRlIGEgQ1BVCj4+IHByaXZhdGUgaW50ZXJydXB0IChQ UEkpIG9uIGFkZHJlc3MgdHJhbnNsYXRpb24gZXJyb3JzIGFuZCB3aGVuIHRoZSBidWZmZXIKPj4g aXMgZnVsbC4gT3ZlcmFsbCBpbXBsZW1lbnRhdGlvbiBoZXJlIGlzIGluc3BpcmVkIGZyb20gdGhl IEFybSBTUEUgZHJpdmVyLgo+Pgo+PiBDYzogTWF0aGlldSBQb2lyaWVyIDxtYXRoaWV1LnBvaXJp ZXJAbGluYXJvLm9yZz4KPj4gQ2M6IE1pa2UgTGVhY2ggPG1pa2UubGVhY2hAbGluYXJvLm9yZz4K Pj4gQ2M6IFN1enVraSBLIFBvdWxvc2UgPHN1enVraS5wb3Vsb3NlQGFybS5jb20+Cj4+IFNpZ25l ZC1vZmYtYnk6IEFuc2h1bWFuIEtoYW5kdWFsIDxhbnNodW1hbi5raGFuZHVhbEBhcm0uY29tPgo+ PiAtLS0KPiAKPj4KPj4gwqAgRG9jdW1lbnRhdGlvbi90cmFjZS9jb3Jlc2lnaHQvY29yZXNpZ2h0 LXRyYmUucnN0IHzCoCAzOSArCj4+IMKgIGFyY2gvYXJtNjQvaW5jbHVkZS9hc20vc3lzcmVnLmjC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHzCoMKgIDIgKwo+PiDCoCBkcml2ZXJz L2h3dHJhY2luZy9jb3Jlc2lnaHQvS2NvbmZpZ8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHzC oCAxMSArCj4+IMKgIGRyaXZlcnMvaHd0cmFjaW5nL2NvcmVzaWdodC9NYWtlZmlsZcKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoCB8wqDCoCAxICsKPj4gwqAgZHJpdmVycy9od3RyYWNpbmcvY29yZXNp Z2h0L2NvcmVzaWdodC10cmJlLmPCoMKgwqDCoCB8IDkyNSArKysrKysrKysrKysrKysrKysrKysr Kwo+PiDCoCBkcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvY29yZXNpZ2h0LXRyYmUuaMKgwqDC oMKgIHwgMjQ4ICsrKysrKwo+PiDCoCA2IGZpbGVzIGNoYW5nZWQsIDEyMjYgaW5zZXJ0aW9ucygr KQo+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQgRG9jdW1lbnRhdGlvbi90cmFjZS9jb3Jlc2lnaHQv Y29yZXNpZ2h0LXRyYmUucnN0Cj4+IMKgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3dHJh Y2luZy9jb3Jlc2lnaHQvY29yZXNpZ2h0LXRyYmUuYwo+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy9od3RyYWNpbmcvY29yZXNpZ2h0L2NvcmVzaWdodC10cmJlLmgKPj4KPj4gZGlmZiAt LWdpdCBhL0RvY3VtZW50YXRpb24vdHJhY2UvY29yZXNpZ2h0L2NvcmVzaWdodC10cmJlLnJzdCBi L0RvY3VtZW50YXRpb24vdHJhY2UvY29yZXNpZ2h0L2NvcmVzaWdodC10cmJlLnJzdAo+PiBuZXcg ZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwLi44Yjc5ODUwCj4+IC0tLSAvZGV2L251 bGwKPj4gKysrIGIvRG9jdW1lbnRhdGlvbi90cmFjZS9jb3Jlc2lnaHQvY29yZXNpZ2h0LXRyYmUu cnN0Cj4+IEBAIC0wLDAgKzEsMzkgQEAKPj4gKy4uIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wCj4+ICsKPj4gKz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo+PiArVHJhY2Ug QnVmZmVyIEV4dGVuc2lvbiAoVFJCRSkuCj4+ICs9PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT0KPj4gKwo+PiArwqDCoMKgIDpBdXRob3I6wqDCoCBBbnNodW1hbiBLaGFuZHVhbCA8YW5zaHVt YW4ua2hhbmR1YWxAYXJtLmNvbT4KPj4gK8KgwqDCoCA6RGF0ZTrCoMKgwqDCoCBOb3ZlbWJlciAy MDIwCj4+ICsKPj4gK0hhcmR3YXJlIERlc2NyaXB0aW9uCj4+ICstLS0tLS0tLS0tLS0tLS0tLS0t LQo+PiArCj4+ICtUcmFjZSBCdWZmZXIgRXh0ZW5zaW9uIChUUkJFKSBpcyBhIHBlcmNwdSBoYXJk d2FyZSB3aGljaCBjYXB0dXJlcyBpbiBzeXN0ZW0KPj4gK21lbW9yeSwgQ1BVIHRyYWNlcyBnZW5l cmF0ZWQgZnJvbSBhIGNvcnJlc3BvbmRpbmcgcGVyY3B1IHRyYWNpbmcgdW5pdC4gVGhpcwo+PiAr Z2V0cyBwbHVnZ2VkIGluIGFzIGEgY29yZXNpZ2h0IHNpbmsgZGV2aWNlIGJlY2F1c2UgdGhlIGNv cnJlc3BvbmRpbmcgdHJhY2UKPj4gK2dlbmFyYXRvcnMgKEVURSksIGFyZSBwbHVnZ2VkIGluIGFz IHNvdXJjZSBkZXZpY2UuCj4+ICsKPj4gK1RoZSBUUkJFIGlzIG5vdCBjb21wbGlhbnQgdG8gQ29y ZVNpZ2h0IGFyY2hpdGVjdHVyZSBzcGVjaWZpY2F0aW9ucywgYnV0IGlzCj4+ICtkcml2ZW4gdmlh IHRoZSBDb3JlU2lnaHQgZHJpdmVyIGZyYW1ld29yayB0byBzdXBwb3J0IHRoZSBFVEUgKHdoaWNo IGlzCj4+ICtDb3JlU2lnaHQgY29tcGxpYW50KSBpbnRlZ3JhdGlvbi4KPj4gKwo+PiArU3lzZnMg ZmlsZXMgYW5kIGRpcmVjdG9yaWVzCj4+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4g Kwo+PiArVGhlIFRSQkUgZGV2aWNlcyBhcHBlYXIgb24gdGhlIGV4aXN0aW5nIGNvcmVzaWdodCBi dXMgYWxvbmdzaWRlIHRoZSBvdGhlcgo+PiArY29yZXNpZ2h0IGRldmljZXM6Ogo+PiArCj4+ICvC oMKgwqAgPiQgbHMgL3N5cy9idXMvY29yZXNpZ2h0L2RldmljZXMKPj4gK8KgwqDCoCB0cmJlMMKg IHRyYmUxwqAgdHJiZTIgdHJiZTMKPj4gKwo+PiArVGhlIGBgdHJiZTxOPmBgIG5hbWVkIFRSQkVz IGFyZSBhc3NvY2lhdGVkIHdpdGggYSBDUFUuOjoKPj4gKwo+PiArwqDCoMKgID4kIGxzIC9zeXMv YnVzL2NvcmVzaWdodC9kZXZpY2VzL3RyYmUwLwo+PiArwqDCoMKgIGlycSBhbGlnbiBkYm0KPiAK PiBZb3UgbWF5IHdhbnQgdG8gcmVtb3ZlIGlycSBoZXJlLgoKU3VyZSwgd2lsbCBkby4KCj4gCj4+ ICsKPj4gKypLZXkgZmlsZSBpdGVtcyBhcmU6LSoKPj4gK8KgwqAgKiBgYGFsaWduYGA6IFRSQkUg d3JpdGUgcG9pbnRlciBhbGlnbm1lbnQKPj4gK8KgwqAgKiBgYGRibWBgOiBUUkJFIHVwZGF0ZXMg bWVtb3J5IHdpdGggYWNjZXNzIGFuZCBkaXJ0eSBmbGFncwo+PiArCj4+IGRpZmYgLS1naXQgYS9h cmNoL2FybTY0L2luY2x1ZGUvYXNtL3N5c3JlZy5oIGIvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9z eXNyZWcuaAo+PiBpbmRleCBlNjk2MmIxLi4yYTliZmI3IDEwMDY0NAo+PiAtLS0gYS9hcmNoL2Fy bTY0L2luY2x1ZGUvYXNtL3N5c3JlZy5oCj4+ICsrKyBiL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20v c3lzcmVnLmgKPj4gQEAgLTk3LDYgKzk3LDcgQEAKPj4gwqAgI2RlZmluZSBTRVRfUFNUQVRFX1VB Tyh4KcKgwqDCoMKgwqDCoMKgIF9fZW1pdF9pbnN0KDB4ZDUwMDQwMWYgfCBQU1RBVEVfVUFPIHwg KCghIXgpIDw8IFBTVEFURV9JbW1fc2hpZnQpKQo+PiDCoCAjZGVmaW5lIFNFVF9QU1RBVEVfU1NC Uyh4KcKgwqDCoMKgwqDCoMKgIF9fZW1pdF9pbnN0KDB4ZDUwMDQwMWYgfCBQU1RBVEVfU1NCUyB8 ICgoISF4KSA8PCBQU1RBVEVfSW1tX3NoaWZ0KSkKPj4gwqAgI2RlZmluZSBTRVRfUFNUQVRFX1RD Tyh4KcKgwqDCoMKgwqDCoMKgIF9fZW1pdF9pbnN0KDB4ZDUwMDQwMWYgfCBQU1RBVEVfVENPIHwg KCghIXgpIDw8IFBTVEFURV9JbW1fc2hpZnQpKQo+PiArI2RlZmluZSBUU0JfQ1NZTkPCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIF9fZW1pdF9pbnN0KDB4ZDUwMzIyNWYpCj4+IMKgIMKgICNkZWZpbmUg X19TWVNfQkFSUklFUl9JTlNOKENSbSwgb3AyLCBSdCkgXAo+PiDCoMKgwqDCoMKgIF9fZW1pdF9p bnN0KDB4ZDUwMDAwMDAgfCBzeXNfaW5zbigwLCAzLCAzLCAoQ1JtKSwgKG9wMikpIHwgKChSdCkg JiAweDFmKSkKPj4gQEAgLTg2OSw2ICs4NzAsNyBAQAo+PiDCoCAjZGVmaW5lIElEX0FBNjRNTUZS Ml9DTlBfU0hJRlTCoMKgwqDCoMKgwqDCoCAwCj4+IMKgIMKgIC8qIGlkX2FhNjRkZnIwICovCj4+ ICsjZGVmaW5lIElEX0FBNjRERlIwX1RSQkVfU0hJRlTCoMKgwqDCoMKgwqDCoCA0NAo+PiDCoCAj ZGVmaW5lIElEX0FBNjRERlIwX1RSQUNFX0ZJTFRfU0hJRlTCoMKgwqAgNDAKPj4gwqAgI2RlZmlu ZSBJRF9BQTY0REZSMF9ET1VCTEVMT0NLX1NISUZUwqDCoMKgIDM2Cj4+IMKgICNkZWZpbmUgSURf QUE2NERGUjBfUE1TVkVSX1NISUZUwqDCoMKgIDMyCj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3 dHJhY2luZy9jb3Jlc2lnaHQvS2NvbmZpZyBiL2RyaXZlcnMvaHd0cmFjaW5nL2NvcmVzaWdodC9L Y29uZmlnCj4+IGluZGV4IGMxMTk4MjQuLjBmNWUxMDEgMTAwNjQ0Cj4+IC0tLSBhL2RyaXZlcnMv aHd0cmFjaW5nL2NvcmVzaWdodC9LY29uZmlnCj4+ICsrKyBiL2RyaXZlcnMvaHd0cmFjaW5nL2Nv cmVzaWdodC9LY29uZmlnCj4+IEBAIC0xNTYsNiArMTU2LDE3IEBAIGNvbmZpZyBDT1JFU0lHSFRf Q1RJCj4+IMKgwqDCoMKgwqDCoMKgIFRvIGNvbXBpbGUgdGhpcyBkcml2ZXIgYXMgYSBtb2R1bGUs IGNob29zZSBNIGhlcmU6IHRoZQo+PiDCoMKgwqDCoMKgwqDCoCBtb2R1bGUgd2lsbCBiZSBjYWxs ZWQgY29yZXNpZ2h0LWN0aS4KPj4gwqAgK2NvbmZpZyBDT1JFU0lHSFRfVFJCRQo+PiArwqDCoMKg IGJvb2wgIlRyYWNlIEJ1ZmZlciBFeHRlbnNpb24gKFRSQkUpIGRyaXZlciIKPj4gK8KgwqDCoCBk ZXBlbmRzIG9uIEFSTTY0Cj4+ICvCoMKgwqAgaGVscAo+PiArwqDCoMKgwqDCoCBUaGlzIGRyaXZl ciBwcm92aWRlcyBzdXBwb3J0IGZvciBwZXJjcHUgVHJhY2UgQnVmZmVyIEV4dGVuc2lvbiAoVFJC RSkuCj4+ICvCoMKgwqDCoMKgIFRSQkUgYWx3YXlzIG5lZWRzIHRvIGJlIHVzZWQgYWxvbmcgd2l0 aCBpdCdzIGNvcnJlc3BvbmRpbmcgcGVyY3B1IEVURQo+PiArwqDCoMKgwqDCoCBjb21wb25lbnQu IEVURSBnZW5lcmF0ZXMgdHJhY2UgZGF0YSB3aGljaCBpcyB0aGVuIGNhcHR1cmVkIHdpdGggVFJC RS4KPj4gK8KgwqDCoMKgwqAgVW5saWtlIHRyYWRpdGlvbmFsIHNpbmsgZGV2aWNlcywgVFJCRSBp cyBhIENQVSBmZWF0dXJlIGFjY2Vzc2libGUgdmlhCj4+ICvCoMKgwqDCoMKgIHN5c3RlbSByZWdp c3RlcnMuIEJ1dCBpdCdzIGV4cGxpY2l0IGRlcGVuZGVuY3kgd2l0aCB0cmFjZSB1bml0IChFVEUp Cj4+ICvCoMKgwqDCoMKgIHJlcXVpcmVzIGl0IHRvIGJlIHBsdWdnZWQgaW4gYXMgYSBjb3Jlc2ln aHQgc2luayBkZXZpY2UuCj4+ICsKPj4gwqAgY29uZmlnIENPUkVTSUdIVF9DVElfSU5URUdSQVRJ T05fUkVHUwo+PiDCoMKgwqDCoMKgIGJvb2wgIkFjY2VzcyBDVEkgQ29yZVNpZ2h0IEludGVncmF0 aW9uIFJlZ2lzdGVycyIKPj4gwqDCoMKgwqDCoCBkZXBlbmRzIG9uIENPUkVTSUdIVF9DVEkKPj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHd0cmFjaW5nL2NvcmVzaWdodC9NYWtlZmlsZSBiL2RyaXZl cnMvaHd0cmFjaW5nL2NvcmVzaWdodC9NYWtlZmlsZQo+PiBpbmRleCBmMjBlMzU3Li5kNjA4MTY1 IDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvTWFrZWZpbGUKPj4g KysrIGIvZHJpdmVycy9od3RyYWNpbmcvY29yZXNpZ2h0L01ha2VmaWxlCj4+IEBAIC0yMSw1ICsy MSw2IEBAIG9iai0kKENPTkZJR19DT1JFU0lHSFRfU1RNKSArPSBjb3Jlc2lnaHQtc3RtLm8KPj4g wqAgb2JqLSQoQ09ORklHX0NPUkVTSUdIVF9DUFVfREVCVUcpICs9IGNvcmVzaWdodC1jcHUtZGVi dWcubwo+PiDCoCBvYmotJChDT05GSUdfQ09SRVNJR0hUX0NBVFUpICs9IGNvcmVzaWdodC1jYXR1 Lm8KPj4gwqAgb2JqLSQoQ09ORklHX0NPUkVTSUdIVF9DVEkpICs9IGNvcmVzaWdodC1jdGkubwo+ PiArb2JqLSQoQ09ORklHX0NPUkVTSUdIVF9UUkJFKSArPSBjb3Jlc2lnaHQtdHJiZS5vCj4+IMKg IGNvcmVzaWdodC1jdGkteSA6PSBjb3Jlc2lnaHQtY3RpLWNvcmUub8KgwqDCoCBjb3Jlc2lnaHQt Y3RpLXBsYXRmb3JtLm8gXAo+PiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgY29yZXNpZ2h0LWN0 aS1zeXNmcy5vCj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvY29y ZXNpZ2h0LXRyYmUuYyBiL2RyaXZlcnMvaHd0cmFjaW5nL2NvcmVzaWdodC9jb3Jlc2lnaHQtdHJi ZS5jCj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+IGluZGV4IDAwMDAwMDAuLmJhMjgwZTYKPj4g LS0tIC9kZXYvbnVsbAo+PiArKysgYi9kcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvY29yZXNp Z2h0LXRyYmUuYwo+PiBAQCAtMCwwICsxLDkyNSBAQAo+PiArLy8gU1BEWC1MaWNlbnNlLUlkZW50 aWZpZXI6IEdQTC0yLjAKPj4gKy8qCj4+ICsgKiBUaGlzIGRyaXZlciBlbmFibGVzIFRyYWNlIEJ1 ZmZlciBFeHRlbnNpb24gKFRSQkUpIGFzIGEgcGVyLWNwdSBjb3Jlc2lnaHQKPj4gKyAqIHNpbmsg ZGV2aWNlIGNvdWxkIHRoZW4gcGFpciB3aXRoIGFuIGFwcHJvcHJpYXRlIHBlci1jcHUgY29yZXNp Z2h0IHNvdXJjZQo+PiArICogZGV2aWNlIChFVEUpIHRodXMgZ2VuZXJhdGluZyByZXF1aXJlZCB0 cmFjZSBkYXRhLiBUcmFjZSBjYW4gYmUgZW5hYmxlZAo+PiArICogdmlhIHRoZSBwZXJmIGZyYW1l d29yay4KPj4gKyAqCj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjAgQVJNIEx0ZC4KPj4gKyAqCj4+ ICsgKiBBdXRob3I6IEFuc2h1bWFuIEtoYW5kdWFsIDxhbnNodW1hbi5raGFuZHVhbEBhcm0uY29t Pgo+PiArICovCj4+ICsjZGVmaW5lIERSVk5BTUUgImFybV90cmJlIgo+PiArCj4+ICsjZGVmaW5l IHByX2ZtdChmbXQpIERSVk5BTUUgIjogIiBmbXQKPj4gKwo+PiArI2luY2x1ZGUgImNvcmVzaWdo dC10cmJlLmgiCj4+ICsKPj4gKyNkZWZpbmUgUEVSRl9JRFgyT0ZGKGlkeCwgYnVmKSAoKGlkeCkg JSAoKGJ1ZiktPm5yX3BhZ2VzIDw8IFBBR0VfU0hJRlQpKQo+PiArCj4+ICsvKgo+PiArICogQSBw YWRkaW5nIHBhY2tldCB0aGF0IHdpbGwgaGVscCB0aGUgdXNlciBzcGFjZSB0b29scwo+PiArICog aW4gc2tpcHBpbmcgcmVsZXZhbnQgc2VjdGlvbnMgaW4gdGhlIGNhcHR1cmVkIHRyYWNlCj4+ICsg KiBkYXRhIHdoaWNoIGNvdWxkIG5vdCBiZSBkZWNvZGVkLgo+IAo+IFlvdSBtYXkgd2FudCB0byBh ZGQgOgo+IAo+IFRSQkUgZG9lc24ndCBzdXBwb3J0IGZvcm1hdHRpbmcgdGhlIHRyYWNlIGRhdGEs IHVubGlrZSB0aGUgbGVnYWN5IENvcmVTaWdodCBzaW5rcwo+IGFuZCB0aHVzIHdlIHVzZSBFVEUg dHJhY2UgcGFja2V0cyB0byBwYWQgdGhlIHNlY3Rpb25zIG9mIGJ1ZmZlci4KClN1cmUsIHdpbGwg YWRkLgoKPiAKPiAKPj4gKyAqLwo+PiArI2RlZmluZSBFVEVfSUdOT1JFX1BBQ0tFVCAweDcwCj4+ ICsKPj4gK2VudW0gdHJiZV9mYXVsdF9hY3Rpb24gewo+PiArwqDCoMKgIFRSQkVfRkFVTFRfQUNU X1dSQVAsCj4+ICvCoMKgwqAgVFJCRV9GQVVMVF9BQ1RfU1BVUklPVVMsCj4+ICvCoMKgwqAgVFJC RV9GQVVMVF9BQ1RfRkFUQUwsCj4+ICt9Owo+PiArCj4+ICtzdHJ1Y3QgdHJiZV9idWYgewo+PiAr wqDCoMKgIHVuc2lnbmVkIGxvbmcgdHJiZV9iYXNlOwo+PiArwqDCoMKgIHVuc2lnbmVkIGxvbmcg dHJiZV9saW1pdDsKPj4gK8KgwqDCoCB1bnNpZ25lZCBsb25nIHRyYmVfd3JpdGU7Cj4+ICvCoMKg wqAgaW50IG5yX3BhZ2VzOwo+PiArwqDCoMKgIHZvaWQgKipwYWdlczsKPj4gK8KgwqDCoCBib29s IHNuYXBzaG90Owo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNwdWRhdGE7Cj4+ICt9 Owo+PiArCj4+ICtzdHJ1Y3QgdHJiZV9jcHVkYXRhIHsKPj4gK8KgwqDCoCBib29sIHRyYmVfZGJt Owo+PiArwqDCoMKgIHU2NCB0cmJlX2FsaWduOwo+PiArwqDCoMKgIGludCBjcHU7Cj4+ICvCoMKg wqAgZW51bSBjc19tb2RlIG1vZGU7Cj4+ICvCoMKgwqAgc3RydWN0IHRyYmVfYnVmICpidWY7Cj4+ ICvCoMKgwqAgc3RydWN0IHRyYmVfZHJ2ZGF0YSAqZHJ2ZGF0YTsKPj4gK307Cj4+ICsKPj4gK3N0 cnVjdCB0cmJlX2RydmRhdGEgewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgX19wZXJj cHUgKmNwdWRhdGE7Cj4+ICvCoMKgwqAgc3RydWN0IHBlcmZfb3V0cHV0X2hhbmRsZSBfX3BlcmNw dSAqKmhhbmRsZTsKPj4gK8KgwqDCoCBzdHJ1Y3QgaGxpc3Rfbm9kZSBob3RwbHVnX25vZGU7Cj4+ ICvCoMKgwqAgaW50IGlycTsKPj4gK8KgwqDCoCBjcHVtYXNrX3Qgc3VwcG9ydGVkX2NwdXM7Cj4+ ICvCoMKgwqAgZW51bSBjcHVocF9zdGF0ZSB0cmJlX29ubGluZTsKPj4gK8KgwqDCoCBzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2Owo+PiArfTsKPj4gKwo+PiArc3RhdGljIGludCB0cmJlX2Fs bG9jX25vZGUoc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50KQo+PiArewo+PiArwqDCoMKgIGlmIChl dmVudC0+Y3B1ID09IC0xKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIE5VTUFfTk9fTk9ERTsK Pj4gK8KgwqDCoCByZXR1cm4gY3B1X3RvX25vZGUoZXZlbnQtPmNwdSk7Cj4+ICt9Cj4+ICsKPj4g K3N0YXRpYyB2b2lkIHNldF90cmJlX2ZsdXNoKHZvaWQpCj4+ICt7Cj4+ICvCoMKgwqAgYXNtKFRT Ql9DU1lOQyk7Cj4+ICvCoMKgwqAgZHNiKGlzaCk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyB2b2lk IHRyYmVfZGlzYWJsZV9hbmRfZHJhaW5fbG9jYWwodm9pZCkKPj4gK3sKPj4gK8KgwqDCoCB3cml0 ZV9zeXNyZWdfcygwLCBTWVNfVFJCTElNSVRSX0VMMSk7Cj4+ICvCoMKgwqAgaXNiKCk7Cj4+ICvC oMKgwqAgc2V0X3RyYmVfZmx1c2goKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgdHJiZV9y ZXNldF9sb2NhbCh2b2lkKQo+PiArewo+PiArwqDCoMKgIHRyYmVfZGlzYWJsZV9hbmRfZHJhaW5f bG9jYWwoKTsKPj4gK8KgwqDCoCB3cml0ZV9zeXNyZWdfcygwLCBTWVNfVFJCUFRSX0VMMSk7Cj4+ ICvCoMKgwqAgd3JpdGVfc3lzcmVnX3MoMCwgU1lTX1RSQkJBU0VSX0VMMSk7Cj4+ICvCoMKgwqAg d3JpdGVfc3lzcmVnX3MoMCwgU1lTX1RSQlNSX0VMMSk7Cj4+ICvCoMKgwqAgaXNiKCk7Cj4+ICt9 Cj4+ICsKPj4gKy8qCj4+ICsgKiBUUkJFIEJ1ZmZlciBNYW5hZ2VtZW50Cj4+ICsgKgo+PiArICog VGhlIFRSQkUgYnVmZmVyIHNwYW5zIGZyb20gdGhlIGJhc2UgcG9pbnRlciB0aWxsIHRoZSBsaW1p dCBwb2ludGVyLiBXaGVuIGVuYWJsZWQsCj4+ICsgKiBpdCBzdGFydHMgd3JpdGluZyB0cmFjZSBk YXRhIGZyb20gdGhlIHdyaXRlIHBvaW50ZXIgb253YXJkIHRpbGwgdGhlIGxpbWl0IHBvaW50ZXIu Cj4+ICsgKiBXaGVuIHRoZSB3cml0ZSBwb2ludGVyIHJlYWNoZXMgdGhlIGFkZHJlc3MganVzdCBi ZWZvcmUgdGhlIGxpbWl0IHBvaW50ZXIsIGl0IGdldHMKPj4gKyAqIHdyYXBwZWQgYXJvdW5kIGFn YWluIHRvIHRoZSBiYXNlIHBvaW50ZXIuIFRoaXMgaXMgY2FsbGVkIGEgVFJCRSB3cmFwIGV2ZW50 IHdoaWNoCj4+ICsgKiBpcyBhY2NvbXBhbmllZCBieSBhbiBJUlEuCj4gCj4gVGhpcyBpcyB0cnVl IGZvciBvbmUgb2YgdGhlIG1vZGVzIG9mIG9wZXJhdGlvbiwgdGhlIFdSQVAgbW9kZSwgd2hpY2gg Y291bGQgYmUgc3BlY2lmaWVkCj4gaW4gdGhlIGNvbW1lbnQuIGUuZywKPiAKPiBUaGlzIGlzIGNh bGxlZCBhIFRSQkUgd3JhcCBldmVudCwgd2hpY2ggZ2VuZXJhdGVzIGEgbWFpbnRlbmFuY2UgaW50 ZXJydXB0IHdoZW4gb3BlcmF0ZWQKPiBpbiBXUkFQIG1vZGUuCgpTdXJlLCB3aWxsIGNoYW5nZS4K Cj4gCj4gCj4gwqBUaGUgd3JpdGUgcG9pbnRlciBhZ2FpbiBzdGFydHMgd3JpdGluZyB0cmFjZSBk YXRhIGZyb20KPj4gKyAqIHRoZSBiYXNlIHBvaW50ZXIgdW50aWwganVzdCBiZWZvcmUgdGhlIGxp bWl0IHBvaW50ZXIgYmVmb3JlIGdldHRpbmcgd3JhcHBlZCBhZ2Fpbgo+PiArICogd2l0aCBhbiBJ UlEgYW5kIHRoaXMgcHJvY2VzcyBqdXN0IGdvZXMgb24gYXMgbG9uZyBhcyB0aGUgVFJCRSBpcyBl bmFibGVkLgo+PiArICoKPj4gKyAqwqDCoMKgIFdyYXAgYXJvdW5kIHdpdGggYW4gSVJRCj4+ICsg KsKgwqDCoCAtLS0tLS0gPCAtLS0tLS0gPCAtLS0tLS0tIDwgLS0tLS0gPCAtLS0tLQo+PiArICrC oMKgwqAgfMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHwKPj4gKyAqwqDC oMKgIC0tLS0tLSA+IC0tLS0tLSA+IC0tLS0tLS0gPiAtLS0tLSA+IC0tLS0tCj4+ICsgKgo+PiAr ICrCoMKgwqAgKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKPj4gKyAq wqDCoMKgIHzCoMKgwqDCoMKgwqDCoCB8wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCB8Cj4+ICsgKsKg wqDCoCArLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwo+PiArICrCoMKg wqAgQmFzZSBQb2ludGVywqDCoMKgIFdyaXRlIFBvaW50ZXLCoMKgwqDCoMKgwqDCoCBMaW1pdCBQ b2ludGVyCj4+ICsgKgo+PiArICogVGhlIGJhc2UgYW5kIGxpbWl0IHBvaW50ZXJzIGFsd2F5cyBu ZWVkcyB0byBiZSBQQUdFX1NJWkUgYWxpZ25lZC4gQnV0IHRoZSB3cml0ZQo+PiArICogcG9pbnRl ciBjYW4gYmUgYWxpZ25lZCB0byB0aGUgaW1wbGVtZW50YXRpb24gZGVmaW5lZCBUUkJFIHRyYWNl IGJ1ZmZlciBhbGlnbm1lbnQKPj4gKyAqIGFzIGNhcHR1cmVkIGluIHRyYmVfY3B1ZGF0YS0+dHJi ZV9hbGlnbi4KPj4gKyAqCj4+ICsgKgo+PiArICrCoMKgwqDCoMKgwqDCoCBoZWFkwqDCoMKgwqDC oMKgwqAgdGFpbMKgwqDCoMKgwqDCoMKgIHdha2V1cAo+PiArICrCoMKgwqAgKy0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLSB+IH4gLS0tLS0tCj4+ICsgKsKgwqDC oCB8JCQkJCQkJHwjIyMjIyMjIyMjIyMjIyMjfCQkJCQkJCQkJCQkJCQkfMKgwqDCoMKgwqDCoMKg IHwKPj4gKyAqwqDCoMKgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0r LS0tLS0gfiB+IC0tLS0tLQo+PiArICrCoMKgwqAgQmFzZSBQb2ludGVywqDCoMKgIFdyaXRlIFBv aW50ZXLCoMKgwqDCoMKgwqDCoCBMaW1pdCBQb2ludGVyCj4+ICsgKgo+PiArICogVGhlIHBlcmZf b3V0cHV0X2hhbmRsZSBpbmRpY2VzIChoZWFkLCB0YWlsLCB3YWtldXApIGFyZSBtb25vdG9uaWNh bGx5IGluY3JlYXNpbmcKPj4gKyAqIHZhbHVlcyB3aGljaCB0cmFja3MgYWxsIHRoZSBkcml2ZXIg d3JpdGVzIGFuZCB1c2VyIHJlYWRzIGZyb20gdGhlIHBlcmYgYXV4aWxpYXJ5Cj4+ICsgKiBidWZm ZXIuIEdlbmVyYWxseSBbaGVhZC4udGFpbF0gaXMgdGhlIGFyZWEgd2hlcmUgdGhlIGRyaXZlciBj YW4gd3JpdGUgaW50byB1bmxlc3MKPj4gKyAqIHRoZSB3YWtldXAgaXMgYmVoaW5kIHRoZSB0YWls LiBFbmFibGVkIFRSQkUgYnVmZmVyIHNwYW4gbmVlZHMgdG8gYmUgYWRqdXN0ZWQgYW5kCj4+ICsg KiBjb25maWd1cmVkIGRlcGVuZGluZyBvbiB0aGUgcGVyZl9vdXRwdXRfaGFuZGxlIGluZGljZXMs IHNvIHRoYXQgdGhlIGRyaXZlciBkb2VzCj4+ICsgKiBub3Qgb3ZlcnJpZGUgaW50byBhcmVhcyBp biB0aGUgcGVyZiBhdXhpbGlhcnkgYnVmZmVyIHdoaWNoIGlzIGJlaW5nIG9yIHlldCB0byBiZQo+ PiArICogY29uc3VtZWQgZnJvbSB0aGUgdXNlciBzcGFjZS4gVGhlIGVuYWJsZWQgVFJCRSBidWZm ZXIgYXJlYSBpcyBhIG1vdmluZyBzdWJzZXQgb2YKPj4gKyAqIHRoZSBhbGxvY2F0ZWQgcGVyZiBh dXhpbGlhcnkgYnVmZmVyLgo+PiArICovCj4+ICtzdGF0aWMgdm9pZCB0cmJlX3BhZF9idWYoc3Ry dWN0IHBlcmZfb3V0cHV0X2hhbmRsZSAqaGFuZGxlLCBpbnQgbGVuKQo+PiArewo+PiArwqDCoMKg IHN0cnVjdCB0cmJlX2J1ZiAqYnVmID0gZXRtX3BlcmZfc2lua19jb25maWcoaGFuZGxlKTsKPj4g K8KgwqDCoCB1NjQgaGVhZCA9IFBFUkZfSURYMk9GRihoYW5kbGUtPmhlYWQsIGJ1Zik7Cj4+ICsK Pj4gK8KgwqDCoCBtZW1zZXQoKHZvaWQgKikgYnVmLT50cmJlX2Jhc2UgKyBoZWFkLCBFVEVfSUdO T1JFX1BBQ0tFVCwgbGVuKTsKPj4gK8KgwqDCoCBpZiAoIWJ1Zi0+c25hcHNob3QpCj4+ICvCoMKg wqDCoMKgwqDCoCBwZXJmX2F1eF9vdXRwdXRfc2tpcChoYW5kbGUsIGxlbik7Cj4+ICt9Cj4+ICsK Pj4gK3N0YXRpYyB1bnNpZ25lZCBsb25nIHRyYmVfc25hcHNob3Rfb2Zmc2V0KHN0cnVjdCBwZXJm X291dHB1dF9oYW5kbGUgKmhhbmRsZSkKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3QgdHJiZV9idWYg KmJ1ZiA9IGV0bV9wZXJmX3NpbmtfY29uZmlnKGhhbmRsZSk7Cj4+ICvCoMKgwqAgdTY0IGhlYWQg PSBQRVJGX0lEWDJPRkYoaGFuZGxlLT5oZWFkLCBidWYpOwo+PiArwqDCoMKgIHU2NCBsaW1pdCA9 IGJ1Zi0+bnJfcGFnZXMgKiBQQUdFX1NJWkU7Cj4+ICsKPj4gK8KgwqDCoCAvKgo+PiArwqDCoMKg wqAgKiBUaGUgdHJhY2UgZm9ybWF0IGlzbid0IHBhcnNlYWJsZSBpbiByZXZlcnNlLCBzbyBjbGFt cCB0aGUgbGltaXQKPj4gK8KgwqDCoMKgICogdG8gaGFsZiBvZiB0aGUgYnVmZmVyIHNpemUgaW4g c25hcHNob3QgbW9kZSBzbyB0aGF0IHRoZSB3b3JzdAo+PiArwqDCoMKgwqAgKiBjYXNlIGlzIGhh bGYgYSBidWZmZXIgb2YgcmVjb3JkcywgYXMgb3Bwb3NlZCB0byBhIHNpbmdsZSByZWNvcmQuCj4+ ICvCoMKgwqDCoCAqLwo+IAo+IFRoYXQgaXMgbm90IHRydWUuIFdlIGNhbiBwYWQgdGhlIGJ1ZmZl ciB3aXRoIElnbm9yZSBwYWNrZXRzIGFuZCB0aGUgZGVjb2RlciBjb3VsZAo+IHNraXAgZm9yd2Fy ZCB1bnRpbCBpdCBmaW5kcyBhbiBhbGlnbm1lbnQgc3luY2hyb25pemF0aW9uIHBhY2tldC4gU28s IHdlIGNvdWxkIHVzZQo+IHRoZSBmdWxsIHNpemUgb2YgdGhlIGJ1ZmZlciwgdW5saWtlIHRoZSBT UEUuCgpXaWxsIHJld29yayB0aGlzIGFuZCB1cGRhdGUuCgo+IAo+PiArwqDCoMKgIGlmIChoZWFk IDwgbGltaXQgPj4gMSkKPj4gK8KgwqDCoMKgwqDCoMKgIGxpbWl0ID4+PSAxOwo+PiArCj4+ICvC oMKgwqAgcmV0dXJuIGxpbWl0Owo+PiArfQo+PiArCj4+ICsvKgo+PiArICogVFJCRSBMaW1pdCBD YWxjdWxhdGlvbgo+PiArICoKPj4gKyAqIFRoZSBmb2xsb3dpbmcgbWFya2VycyBhcmUgdXNlZCB0 byBpbGx1c3RyYXRlIHZhcmlvdXMgVFJCRSBidWZmZXIgc2l0dWF0aW9ucy4KPj4gKyAqCj4+ICsg KiAkJCQkIC0gRGF0YSBhcmVhLCB1bmNvbnN1bWVkIGNhcHR1cmVkIHRyYWNlIGRhdGEsIG5vdCB0 byBiZSBvdmVycmlkZGVuCj4+ICsgKiAjIyMjIC0gRnJlZSBhcmVhLCBlbmFibGVkLCB0cmFjZSB3 aWxsIGJlIHdyaXR0ZW4KPj4gKyAqICUlJSUgLSBGcmVlIGFyZWEsIGRpc2FibGVkLCB0cmFjZSB3 aWxsIG5vdCBiZSB3cml0dGVuCj4+ICsgKiA9PT09IC0gRnJlZSBhcmVhLCBwYWRkZWQgd2l0aCBF VEVfSUdOT1JFX1BBQ0tFVCwgdHJhY2Ugd2lsbCBiZSBza2lwcGVkCj4+ICsgKi8KPiAKPiBUaGFu a3MgZm9yIHRoZSBuaWNlIEFTQ0lJIGFydCwgaXQgcmVhbGx5IGhlbHBzIHRvIHVuZGVyc3RhbmQg dGhlIHNjZW5hcmlvcy4KPiAKPj4gK3N0YXRpYyB1bnNpZ25lZCBsb25nIHRyYmVfbm9ybWFsX29m ZnNldChzdHJ1Y3QgcGVyZl9vdXRwdXRfaGFuZGxlICpoYW5kbGUpCj4+ICt7Cj4+ICvCoMKgwqAg c3RydWN0IHRyYmVfYnVmICpidWYgPSBldG1fcGVyZl9zaW5rX2NvbmZpZyhoYW5kbGUpOwo+PiAr wqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNwdWRhdGEgPSBidWYtPmNwdWRhdGE7Cj4+ICvC oMKgwqAgY29uc3QgdTY0IGJ1ZnNpemUgPSBidWYtPm5yX3BhZ2VzICogUEFHRV9TSVpFOwo+PiAr wqDCoMKgIHU2NCBsaW1pdCA9IGJ1ZnNpemU7Cj4+ICvCoMKgwqAgdTY0IGhlYWQsIHRhaWwsIHdh a2V1cDsKPj4gKwo+PiArwqDCoMKgIGhlYWQgPSBQRVJGX0lEWDJPRkYoaGFuZGxlLT5oZWFkLCBi dWYpOwo+PiArCj4+ICvCoMKgwqAgLyoKPj4gK8KgwqDCoMKgICrCoMKgwqDCoMKgwqDCoCBoZWFk Cj4+ICvCoMKgwqDCoCAqwqDCoMKgIC0tLS0tLS0+fAo+PiArwqDCoMKgwqAgKsKgwqDCoCB8Cj4+ ICvCoMKgwqDCoCAqwqDCoMKgIGhlYWTCoMKgwqAgVFJCRSBhbGlnbsKgwqDCoCB0YWlsCj4+ICvC oMKgwqDCoCAqICstLS0tfC0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0rCj4+ICvCoMKg wqDCoCAqIHwkJCQkfD09PT09PT18IyMjIyMjIyMjIyMjIyMjfCQkJCQkJCR8Cj4+ICvCoMKgwqDC oCAqICstLS0tfC0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0rCj4+ICvCoMKgwqDCoCAq IHRyYmVfYmFzZcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCB0cmJlX2Jhc2UgKyBucl9w YWdlcwo+PiArwqDCoMKgwqAgKgo+PiArwqDCoMKgwqAgKiBQZXJmIGF1eCBidWZmZXIgb3V0cHV0 IGhlYWQgcG9zaXRpb24gY2FuIGJlIG1pc2FsaWduZWQgZGVwZW5kaW5nIG9uCj4+ICvCoMKgwqDC oCAqIHZhcmlvdXMgZmFjdG9ycyBpbmNsdWRpbmcgdXNlciBzcGFjZSByZWFkcy4gSW4gY2FzZSBt aXNhbGlnbmVkLCBoZWFkCj4+ICvCoMKgwqDCoCAqIG5lZWRzIHRvIGJlIGFsaWduZWQgYmVmb3Jl IFRSQkUgY2FuIGJlIGNvbmZpZ3VyZWQuIFBhZCB0aGUgYWxpZ25tZW50Cj4+ICvCoMKgwqDCoCAq IGdhcCB3aXRoIEVURV9JR05PUkVfUEFDS0VUIGJ5dGVzIHRoYXQgd2lsbCBiZSBpZ25vcmVkIGJ5 IHVzZXIgdG9vbHMKPj4gK8KgwqDCoMKgICogYW5kIHNraXAgdGhpcyBzZWN0aW9uIHRodXMgYWR2 YW5jaW5nIHRoZSBoZWFkLgo+PiArwqDCoMKgwqAgKi8KPj4gK8KgwqDCoCBpZiAoIUlTX0FMSUdO RUQoaGVhZCwgY3B1ZGF0YS0+dHJiZV9hbGlnbikpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIHVuc2ln bmVkIGxvbmcgZGVsdGEgPSByb3VuZHVwKGhlYWQsIGNwdWRhdGEtPnRyYmVfYWxpZ24pIC0gaGVh ZDsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgZGVsdGEgPSBtaW4oZGVsdGEsIGhhbmRsZS0+c2l6 ZSk7Cj4+ICvCoMKgwqDCoMKgwqDCoCB0cmJlX3BhZF9idWYoaGFuZGxlLCBkZWx0YSk7Cj4+ICvC oMKgwqDCoMKgwqDCoCBoZWFkID0gUEVSRl9JRFgyT0ZGKGhhbmRsZS0+aGVhZCwgYnVmKTsKPj4g K8KgwqDCoCB9Cj4+ICsKPj4gK8KgwqDCoCAvKgo+PiArwqDCoMKgwqAgKsKgwqDCoCBoZWFkID0g dGFpbCAoc2l6ZSA9IDApCj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0rCj4+ICvCoMKgwqDCoCAqIHwkJCQkfCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQk JCQkJCQkJMKgwqDCoCB8Cj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0rCj4+ICvCoMKgwqDCoCAqIHRyYmVfYmFzZcKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCB0cmJlX2Jhc2UgKyBucl9wYWdlcwo+PiArwqDCoMKgwqAgKgo+PiArwqDCoMKg wqAgKiBQZXJmIGF1eCBidWZmZXIgZG9lcyBub3QgaGF2ZSBhbnkgc3BhY2UgZm9yIHRoZSBkcml2 ZXIgdG8gd3JpdGUgaW50by4KPj4gK8KgwqDCoMKgICogSnVzdCBjb21tdW5pY2F0ZSB0cmFjZSB0 cnVuY2F0aW9uIGV2ZW50IHRvIHRoZSB1c2VyIHNwYWNlIGJ5IG1hcmtpbmcKPj4gK8KgwqDCoMKg ICogaXQgd2l0aCBQRVJGX0FVWF9GTEFHX1RSVU5DQVRFRC4KPj4gK8KgwqDCoMKgICovCj4+ICvC oMKgwqAgaWYgKCFoYW5kbGUtPnNpemUpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIHBlcmZfYXV4X291 dHB1dF9mbGFnKGhhbmRsZSwgUEVSRl9BVVhfRkxBR19UUlVOQ0FURUQpOwo+PiArwqDCoMKgwqDC oMKgwqAgcmV0dXJuIDA7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgLyogQ29tcHV0ZSB0 aGUgdGFpbCBhbmQgd2FrZXVwIGluZGljZXMgbm93IHRoYXQgd2UndmUgYWxpZ25lZCBoZWFkICov Cj4+ICvCoMKgwqAgdGFpbCA9IFBFUkZfSURYMk9GRihoYW5kbGUtPmhlYWQgKyBoYW5kbGUtPnNp emUsIGJ1Zik7Cj4+ICvCoMKgwqAgd2FrZXVwID0gUEVSRl9JRFgyT0ZGKGhhbmRsZS0+d2FrZXVw LCBidWYpOwo+PiArCj4+ICvCoMKgwqAgLyoKPj4gK8KgwqDCoMKgICogTGV0cyBjYWxjdWxhdGUg dGhlIGJ1ZmZlciBhcmVhIHdoaWNoIFRSQkUgY291bGQgd3JpdGUgaW50by4gVGhlcmUKPj4gK8Kg wqDCoMKgICogYXJlIHRocmVlIHBvc3NpYmxlIHNjZW5hcmlvcyBoZXJlLiBMaW1pdCBuZWVkcyB0 byBiZSBhbGlnbmVkIHdpdGgKPj4gK8KgwqDCoMKgICogUEFHRV9TSVpFIHBlciB0aGUgVFJCRSBy ZXF1aXJlbWVudC4gQWx3YXlzIGF2b2lkIGNsb2JiZXJpbmcgdGhlCj4+ICvCoMKgwqDCoCAqIHVu Y29uc3VtZWQgZGF0YS4KPj4gK8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICogMSkgaGVhZCA8IHRh aWwKPj4gK8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICrCoMKgwqAgaGVhZMKgwqDCoMKgwqDCoMKg wqDCoMKgwqAgdGFpbAo+PiArwqDCoMKgwqAgKiArLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0t LXwtLS0tLS0tKwo+PiArwqDCoMKgwqAgKiB8JCQkJHwjIyMjIyMjIyMjIyMjIyMjIyMjIyMjI3wk JCQkJCQkfAo+PiArwqDCoMKgwqAgKiArLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0t LS0tKwo+PiArwqDCoMKgwqAgKiB0cmJlX2Jhc2XCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGxpbWl0 wqDCoMKgIHRyYmVfYmFzZSArIG5yX3BhZ2VzCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAq IFRSQkUgY291bGQgd3JpdGUgaW50byBbaGVhZC4udGFpbF0gYXJlYS4gVW5sZXNzIHRoZSB0YWls IGlzIHJpZ2h0IGF0Cj4+ICvCoMKgwqDCoCAqIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlciwgbmVpdGhl ciBhbiB3cmFwIGFyb3VuZCBub3IgYW4gSVJRIGlzIGV4cGVjdGVkCj4+ICvCoMKgwqDCoCAqIHdo aWxlIGJlaW5nIGVuYWJsZWQuCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAqIDIpIGhlYWQg PT0gdGFpbAo+PiArwqDCoMKgwqAgKgo+PiArwqDCoMKgwqAgKsKgwqDCoCBoZWFkID0gdGFpbCAo c2l6ZSA+IDApCj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0rCj4+ICvCoMKgwqDCoCAqIHwlJSUlfCMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyN8Cj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0r Cj4+ICvCoMKgwqDCoCAqIHRyYmVfYmFzZcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBs aW1pdCA9IHRyYmVfYmFzZSArIG5yX3BhZ2VzCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAq IFRSQkUgc2hvdWxkIGp1c3Qgd3JpdGUgaW50byBbaGVhZC4uYmFzZSArIG5yX3BhZ2VzXSBhcmVh IGV2ZW4gdGhvdWdoCj4+ICvCoMKgwqDCoCAqIHRoZSBlbnRpcmUgYnVmZmVyIGlzIGVtcHR5LiBS ZWFzb24gYmVpbmcsIHdoZW4gdGhlIHRyYWNlIHJlYWNoZXMgdGhlCj4+ICvCoMKgwqDCoCAqIGVu ZCBvZiB0aGUgYnVmZmVyLCBpdCB3aWxsIGp1c3Qgd3JhcCBhcm91bmQgd2l0aCBhbiBJUlEgZ2l2 aW5nIGFuCj4+ICvCoMKgwqDCoCAqIG9wcG9ydHVuaXR5IHRvIHJlY29uZmlndXJlIHRoZSBidWZm ZXIuCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAqIDMpIHRhaWwgPCBoZWFkCj4+ICvCoMKg wqDCoCAqCj4+ICvCoMKgwqDCoCAqwqDCoMKgIHRhaWzCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGhl YWQKPj4gK8KgwqDCoMKgICogKy0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLSsK Pj4gK8KgwqDCoMKgICogfCUlJSV8JCQkJCQkJCQkJCQkJCQkJCQkJCQkJCR8IyMjIyMjI3wKPj4g K8KgwqDCoMKgICogKy0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLSsKPj4gK8Kg wqDCoMKgICogdHJiZV9iYXNlwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGxpbWl0ID0g dHJiZV9iYXNlICsgbnJfcGFnZXMKPj4gK8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICogVFJCRSBz aG91bGQganVzdCB3cml0ZSBpbnRvIFtoZWFkLi5iYXNlICsgbnJfcGFnZXNdIGFyZWEgZXZlbiB0 aG91Z2gKPj4gK8KgwqDCoMKgICogdGhlIFt0cmJlX2Jhc2UuLnRhaWxdIGlzIGFsc28gZW1wdHku IFJlYXNvbiBiZWluZywgd2hlbiB0aGUgdHJhY2UKPj4gK8KgwqDCoMKgICogcmVhY2hlcyB0aGUg ZW5kIG9mIHRoZSBidWZmZXIsIGl0IHdpbGwganVzdCB3cmFwIGFyb3VuZCB3aXRoIGFuIElSUQo+ PiArwqDCoMKgwqAgKiBnaXZpbmcgYW4gb3Bwb3J0dW5pdHkgdG8gcmVjb25maWd1cmUgdGhlIGJ1 ZmZlci4KPj4gK8KgwqDCoMKgICovCj4+ICvCoMKgwqAgaWYgKGhlYWQgPCB0YWlsKQo+PiArwqDC oMKgwqDCoMKgwqAgbGltaXQgPSByb3VuZF9kb3duKHRhaWwsIFBBR0VfU0laRSk7Cj4+ICsKPj4g K8KgwqDCoCAvKgo+PiArwqDCoMKgwqAgKiBXYWtldXAgbWF5IGJlIGFyYml0cmFyaWx5IGZhciBp bnRvIHRoZSBmdXR1cmUuIElmIGl0J3Mgbm90IGluIHRoZQo+PiArwqDCoMKgwqAgKiBjdXJyZW50 IGdlbmVyYXRpb24sIGVpdGhlciB3ZSdsbCB3cmFwIGJlZm9yZSBoaXR0aW5nIGl0LCBvciBpdCdz Cj4+ICvCoMKgwqDCoCAqIGluIHRoZSBwYXN0IGFuZCBoYXMgYmVlbiBoYW5kbGVkIGFscmVhZHku Cj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAqIElmIHRoZXJlJ3MgYSB3YWtldXAgYmVmb3Jl IHdlIHdyYXAsIGFycmFuZ2UgdG8gYmUgd29rZW4gdXAgYnkgdGhlCj4+ICvCoMKgwqDCoCAqIHBh Z2UgYm91bmRhcnkgZm9sbG93aW5nIGl0LiBLZWVwIHRoZSB0YWlsIGJvdW5kYXJ5IGlmIHRoYXQn cyBsb3dlci4KPj4gK8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICrCoMKgwqAgaGVhZMKgwqDCoMKg wqDCoMKgIHdha2V1cMKgwqDCoCB0YWlsCj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0t LS0tLXwtLS0tLS0tfC0tLS0tLS0rCj4+ICvCoMKgwqDCoCAqIHwkJCQkfCMjIyMjIyMjIyMjIyMj I3wlJSUlJSUlfCQkJCQkJCR8Cj4+ICvCoMKgwqDCoCAqICstLS0tfC0tLS0tLS0tLS0tLS0tLXwt LS0tLS0tfC0tLS0tLS0rCj4+ICvCoMKgwqDCoCAqIHRyYmVfYmFzZcKgwqDCoMKgwqDCoMKgIGxp bWl0wqDCoMKgwqDCoMKgwqAgdHJiZV9iYXNlICsgbnJfcGFnZXMKPj4gK8KgwqDCoMKgICovCj4+ ICvCoMKgwqAgaWYgKGhhbmRsZS0+d2FrZXVwIDwgKGhhbmRsZS0+aGVhZCArIGhhbmRsZS0+c2l6 ZSkgJiYgaGVhZCA8PSB3YWtldXApCj4+ICvCoMKgwqDCoMKgwqDCoCBsaW1pdCA9IG1pbihsaW1p dCwgcm91bmRfdXAod2FrZXVwLCBQQUdFX1NJWkUpKTsKPj4gKwo+PiArwqDCoMKgIC8qCj4+ICvC oMKgwqDCoCAqIFRoZXJlIGFyZSB0d28gc2l0dWF0aW9uIHdoZW4gdGhpcyBjYW4gaGFwcGVuIGku ZSBsaW1pdCBpcyBiZWZvcmUKPj4gK8KgwqDCoMKgICogdGhlIGhlYWQgYW5kIGhlbmNlIFRSQkUg Y2Fubm90IGJlIGNvbmZpZ3VyZWQuCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAqIDEpIGhl YWQgPCB0YWlsIChhbGlnbmVkIGRvd24gd2l0aCBQQUdFX1NJWkUpIGFuZCBhbHNvIHRoZXkgYXJl IGJvdGgKPj4gK8KgwqDCoMKgICogd2l0aGluIHRoZSBzYW1lIFBBR0Ugc2l6ZSByYW5nZS4KPj4g K8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICrCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIFBBR0VfU0la RQo+PiArwqDCoMKgwqAgKsKgwqDCoMKgwqDCoMKgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAo+ PiArwqDCoMKgwqAgKgo+PiArwqDCoMKgwqAgKsKgwqDCoMKgwqDCoMKgIGxpbWl0wqDCoMKgIGhl YWTCoMKgwqAgdGFpbAo+PiArwqDCoMKgwqAgKiArLS0tLS0tLS0tLS0tfC0tLS0tLXwtLS0tLS0t LXwtLS0tLS0tKwo+PiArwqDCoMKgwqAgKiB8JCQkJCQkJCQkJCQkJCQkJCQkJHw9PT09PT09PXwk JCQkJCQkfAo+PiArwqDCoMKgwqAgKiArLS0tLS0tLS0tLS0tfC0tLS0tLXwtLS0tLS0tLXwtLS0t LS0tKwo+PiArwqDCoMKgwqAgKiB0cmJlX2Jhc2XCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqAgdHJiZV9iYXNlICsgbnJfcGFnZXMKPj4gK8KgwqDCoMKgICoKPj4gK8KgwqDCoMKgICogMikg aGVhZCA8IHdha2V1cCAoYWxpZ25lZCB1cCB3aXRoIFBBR0VfU0laRSkgPCB0YWlsIGFuZCBhbHNv IGJvdGgKPj4gK8KgwqDCoMKgICogaGVhZCBhbmQgd2FrZXVwIGFyZSB3aXRoaW4gc2FtZSBQQUdF IHNpemUgcmFuZ2UuCj4+ICvCoMKgwqDCoCAqCj4+ICvCoMKgwqDCoCAqwqDCoMKgwqDCoMKgwqAg UEFHRV9TSVpFCj4+ICvCoMKgwqDCoCAqwqDCoMKgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAo+ PiArwqDCoMKgwqAgKgo+PiArwqDCoMKgwqAgKsKgwqDCoCBsaW1pdMKgwqDCoCBoZWFkwqDCoMKg IHdha2V1cMKgIHRhaWwKPj4gK8KgwqDCoMKgICogKy0tLS18LS0tLS0tfC0tLS0tLS18LS0tLS0t LS18LS0tLS0tLSsKPj4gK8KgwqDCoMKgICogfCQkJCQkJCQkJCQkfD09PT09PT18PT09PT09PT18 JCQkJCQkJHwKPj4gK8KgwqDCoMKgICogKy0tLS18LS0tLS0tfC0tLS0tLS18LS0tLS0tLS18LS0t LS0tLSsKPj4gK8KgwqDCoMKgICogdHJiZV9iYXNlwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgIHRyYmVfYmFzZSArIG5yX3BhZ2VzCj4+ICvCoMKgwqDCoCAqLwo+PiArwqDCoMKgIGlmIChs aW1pdCA+IGhlYWQpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gbGltaXQ7Cj4+ICsKPj4gK8Kg wqDCoCB0cmJlX3BhZF9idWYoaGFuZGxlLCBoYW5kbGUtPnNpemUpOwo+PiArwqDCoMKgIHBlcmZf YXV4X291dHB1dF9mbGFnKGhhbmRsZSwgUEVSRl9BVVhfRkxBR19UUlVOQ0FURUQpOwo+PiArwqDC oMKgIHJldHVybiAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdW5zaWduZWQgbG9uZyBnZXRfdHJi ZV9saW1pdChzdHJ1Y3QgcGVyZl9vdXRwdXRfaGFuZGxlICpoYW5kbGUpCj4gCj4gbml0OiBUaGUg bmFtaW5nIGlzIGEgYml0IGNvbmZ1c2luZyB3aXRoIGdldF90cmJlX2xpbWl0KCkgYW5kIGdldF90 cmJlX2xpbWl0X3BvaW50ZXIoKS4KPiBPbmUgY29tcHV0ZXMgdGhlIFRSQkUgYnVmZmVyIGxpbWl0 IGFuZCB0aGUgb3RoZXIgcmVhZHMgdGhlIGhhcmR3YXJlIExpbWl0IHBvaW50ZXIuCj4gSXQgd291 bGQgYmUgZ29vZCBpZiBmb2xsb3cgYSBzY2hlbWUgZm9yIHRoZSBuYW1pbmdzLgo+IAo+IGUuZywg dHJiZV9saW1pdF9wb2ludGVyKCkgLCB0cmJlX2Jhc2VfcG9pbnRlcigpLCB0cmJlXzxyZWdpc3Rl cj5fPG5hbWU+IGZvciBhbnl0aGluZwo+IHRoYXQgcmVhZHMgdGhlIGhhcmR3YXJlIHJlZ2lzdGVy LgoKVGhlIGN1cnJlbnQgc2NoZW1lIGlzIGluIHRoZSBmb3JtIGdldF90cmJlX1hYWCgpIHdoZXJl IFhYWAppcyBhIFRSQkUgaGFyZHdhcmUgY29tcG9uZW50IGUuZy4KCmdldF90cmJlX2Jhc2VfcG9p bnRlcigpCmdldF90cmJlX2xpbWl0X3BvaW50ZXIoKQpnZXRfdHJiZV93cml0ZV9wb2ludGVyKCkK Z2V0X3RyYmVfZWMoKQpnZXRfdHJiZV9ic2MoKQpnZXRfdHJiZV9hZGRyZXNzX2FsaWduKCkKZ2V0 X3RyYmVfZmxhZ191cGRhdGUoKQoKPiAKPiBPciBtYXkgYmUgcmVuYW1lIHRoZSBnZXRfdHJiZV9s aW1pdCgpIHRvIGNvbXB1dGVfdHJiZV9idWZmZXJfbGltaXQoKQoKVGhpcyBtYWtlcyBpdCBjbGVh ciwgd2lsbCBjaGFuZ2UuCgo+IAo+PiArewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2J1ZiAqYnVm ID0gZXRtX3BlcmZfc2lua19jb25maWcoaGFuZGxlKTsKPj4gK8KgwqDCoCB1bnNpZ25lZCBsb25n IG9mZnNldDsKPj4gKwo+PiArwqDCoMKgIGlmIChidWYtPnNuYXBzaG90KQo+PiArwqDCoMKgwqDC oMKgwqAgb2Zmc2V0ID0gdHJiZV9zbmFwc2hvdF9vZmZzZXQoaGFuZGxlKTsKPj4gK8KgwqDCoCBl bHNlCj4+ICvCoMKgwqDCoMKgwqDCoCBvZmZzZXQgPSB0cmJlX25vcm1hbF9vZmZzZXQoaGFuZGxl KTsKPj4gK8KgwqDCoCByZXR1cm4gYnVmLT50cmJlX2Jhc2UgKyBvZmZzZXQ7Cj4+ICt9Cj4+ICsK Pj4gK3N0YXRpYyB2b2lkIGNsZWFyX3RyYmVfc3RhdGUodm9pZCkKPiAKPiBuaXQ6IFRoZSBuYW1l IGRvZXNuJ3QgZ2l2ZSBtdWNoIGNsdWUgYWJvdXQgd2hhdCBpdCBpcyBkb2luZywgZXNwZWNpYWxs eSwgZ2l2ZW4KPiB0aGUgZm9sbG93aW5nICJzZXRfdHJiZV9zdGF0ZSgpIiB3aGljaCBkb2VzIGNv bXBsZXRlbHkgZGlmZmVyZW50IGZyb20gdGhpcyAiY2xlYXIiCj4gb3BlcmF0aW9uLgoKSSBhZ3Jl ZSB0aGF0IHRoZXNlIG5hbWVzIGNvdWxkIGhhdmUgYmVlbiBiZXR0ZXIuCgpzL2NsZWFyX3RyYmVf c3RhdGUvdHJiZV9yZXNldF9wZXJmX3N0YXRlICAtIENsZWFycyBUUkJFIGZyb20gY3VycmVudCBw ZXJmIGNvbmZpZwpzL3NldF90cmJlX3N0YXRlL3RyYmVfcHJlcGFyZV9wZXJmX3N0YXRlICAtIFBy ZXBhcmVzIFRSQkUgZm9yIHRoZSBuZXh0IHBlcmYgY29uZmlnCgoKPiAKPiBJIHdvdWxkIHJhdGhl ciBvcGVuIGNvZGUgdGhpcyB3aXRoIGEgd3JpdGUgb2YgMCB0byB0cmJzciBpbiB0aGUgY2FsbGVy Lgo+IAo+PiArewo+PiArwqDCoMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQlNS X0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCBXQVJOX09OKGlzX3RyYmVfZW5hYmxlZCgpKTsKPj4gK8Kg wqDCoCB0cmJzciAmPSB+VFJCU1JfSVJROwo+PiArwqDCoMKgIHRyYnNyICY9IH5UUkJTUl9UUkc7 Cj4+ICvCoMKgwqAgdHJic3IgJj0gflRSQlNSX1dSQVA7Cj4+ICvCoMKgwqAgdHJic3IgJj0gfihU UkJTUl9FQ19NQVNLIDw8IFRSQlNSX0VDX1NISUZUKTsKPj4gK8KgwqDCoCB0cmJzciAmPSB+KFRS QlNSX0JTQ19NQVNLIDw8IFRSQlNSX0JTQ19TSElGVCk7Cj4+ICvCoMKgwqAgdHJic3IgJj0gfihU UkJTUl9GU0NfTUFTSyA8PCBUUkJTUl9GU0NfU0hJRlQpOwo+IAo+IEJTQyBhbmQgRlNDIGFyZSB0 aGUgc2FtZSBmaWVsZHMgdW5kZXIgTVNTLCB3aXRoIHRoZWlyIG1lYW5pbmdzIGRldGVybWluZWQg YnkgdGhlIEVDIGZpZWxkLgoKQ291bGQganVzdCBkcm9wIHRoZSBGU0MgcGFydCBpZiByZXF1aXJl ZC4KCj4gCj4gQ291bGQgd2Ugc2ltcGx5IHdyaXRlIDAgdG8gdGhlIHJlZ2lzdGVyID8KCkkgd291 bGQgcmVhbGx5IGxpa2UgdG8gYXZvaWQgdGhhdC4gVGhpcyBmdW5jdGlvbiBjbGVhcmx5IGVudW1l cmF0ZXMgYWxsCmluZGl2aWR1YWwgYml0IGZpZWxkcyBiZWluZyBjbGVhcmVkIGZvciByZXNldHRp bmcgYXMgd2VsbCBhcyBwcmVwYXJpbmcKdGhlIFRSQkUgZm9yIHRoZSBuZXh0IHBlcmYgc2Vzc2lv bi4gQ29udmVydGluZyB0aGlzIGludG8gYSAwIHdyaXRlIGZvcgpTWVNfVFJCU1JfRUwxIHNvdW5k cyBleGNlc3NpdmUgYW5kIHRoZSBvbmx5IHRoaW5nIGl0IHdvdWxkIHNhdmUgaXMgdGhlCnJlZ2lz dGVyIHJlYWQuCgo+IAo+PiArwqDCoMKgIHdyaXRlX3N5c3JlZ19zKHRyYnNyLCBTWVNfVFJCU1Jf RUwxKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgc2V0X3RyYmVfc3RhdGUodm9pZCkKPj4g K3sKPj4gK8KgwqDCoCB1NjQgdHJibGltaXRyID0gcmVhZF9zeXNyZWdfcyhTWVNfVFJCTElNSVRS X0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCB0cmJsaW1pdHIgJj0gflRSQkxJTUlUUl9OVk07Cj4+ICvC oMKgwqAgdHJibGltaXRyICY9IH4oVFJCTElNSVRSX0ZJTExfTU9ERV9NQVNLIDw8IFRSQkxJTUlU Ul9GSUxMX01PREVfU0hJRlQpOwo+PiArwqDCoMKgIHRyYmxpbWl0ciAmPSB+KFRSQkxJTUlUUl9U UklHX01PREVfTUFTSyA8PCBUUkJMSU1JVFJfVFJJR19NT0RFX1NISUZUKTsKPj4gK8KgwqDCoCB0 cmJsaW1pdHIgfD0gKFRSQkVfRklMTF9TVE9QICYgVFJCTElNSVRSX0ZJTExfTU9ERV9NQVNLKSA8 PCBUUkJMSU1JVFJfRklMTF9NT0RFX1NISUZUOwo+PiArwqDCoMKgIHRyYmxpbWl0ciB8PSAoVFJC RV9UUklHR0VSX0lHTk9SRSAmIFRSQkxJTUlUUl9UUklHX01PREVfTUFTSykgPDwgVFJCTElNSVRS X1RSSUdfTU9ERV9TSElGVDsKPj4gK8KgwqDCoCB3cml0ZV9zeXNyZWdfcyh0cmJsaW1pdHIsIFNZ U19UUkJMSU1JVFJfRUwxKTsKPiAKPiBEbyB3ZSBuZWVkIHRvIHJlYWQtY29weS11cGRhdGUgaGVy ZSA/IENvdWxkIHdlIHNpbXBseSB3cml0ZSAwID8KPiBTYW1lIGFzIGFib3ZlIGNvbW1lbnQsIGNv dWxkIHdlIG5vdCBzaW1wbHkgb3BlbmNvZGUgaXQgYXQgdGhlIGNhbGxlciA/Cj4gQ2xlYXJseSB0 aGUgbmFtZXMgZG9uJ3QgaGVscC4KCldpbGwgY2hhbmdlIHRoZSBuYW1lcyBhcyBwcm9wb3NlZCBv ciBzb21ldGhpbmcgYmV0dGVyLiBCdXQgbGV0cyBsZWF2ZQp0aGVzZSBmdW5jdGlvbnMgYXMgaXMu IEJlc2lkZXMgVFJCRV9UUklHR0VSX0lHTk9SRSBhbHNvIGhhcyBhIHBvc2l0aXZlCnZhbHVlIChp LmUgMyksIHdyaXRpbmcgYWxsIDBzIGludG8gU1lTX1RSQkxJTUlUUl9FTDEgd2lsbCBub3QgYmUg aWRlYWwuCgo+IAo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCB0cmJlX2VuYWJsZV9odyhzdHJ1 Y3QgdHJiZV9idWYgKmJ1ZikKPj4gK3sKPj4gK8KgwqDCoCBXQVJOX09OKGJ1Zi0+dHJiZV93cml0 ZSA8IGJ1Zi0+dHJiZV9iYXNlKTsKPj4gK8KgwqDCoCBXQVJOX09OKGJ1Zi0+dHJiZV93cml0ZSA+ PSBidWYtPnRyYmVfbGltaXQpOwo+PiArwqDCoMKgIHNldF90cmJlX2Rpc2FibGVkKCk7Cj4+ICvC oMKgwqAgY2xlYXJfdHJiZV9zdGF0ZSgpOwo+PiArwqDCoMKgIHNldF90cmJlX3N0YXRlKCk7Cj4+ ICvCoMKgwqAgaXNiKCk7Cj4+ICvCoMKgwqAgc2V0X3RyYmVfYmFzZV9wb2ludGVyKGJ1Zi0+dHJi ZV9iYXNlKTsKPj4gK8KgwqDCoCBzZXRfdHJiZV9saW1pdF9wb2ludGVyKGJ1Zi0+dHJiZV9saW1p dCk7Cj4+ICvCoMKgwqAgc2V0X3RyYmVfd3JpdGVfcG9pbnRlcihidWYtPnRyYmVfd3JpdGUpOwo+ IAo+IFdoZXJlIGRvIHdlIHNldCB0aGUgZmlsbCBtb2RlID8KClRSQkVfRklMTF9TVE9QIGhhcyBh bHJlYWR5IGJlZW4gY29uZmlndXJlZCBpbiBzZXRfdHJiZV9zdGF0ZSgpLgoKPiAKPj4gK8KgwqDC oCBpc2IoKTsKPj4gK8KgwqDCoCBzZXRfdHJiZV9ydW5uaW5nKCk7Cj4+ICvCoMKgwqAgc2V0X3Ry YmVfZW5hYmxlZCgpOwo+PiArwqDCoMKgIHNldF90cmJlX2ZsdXNoKCk7Cj4+ICt9Cj4+ICsKPj4g K3N0YXRpYyB2b2lkICphcm1fdHJiZV9hbGxvY19idWZmZXIoc3RydWN0IGNvcmVzaWdodF9kZXZp Y2UgKmNzZGV2LAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHN0cnVj dCBwZXJmX2V2ZW50ICpldmVudCwgdm9pZCAqKnBhZ2VzLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIGludCBucl9wYWdlcywgYm9vbCBzbmFwc2hvdCkKPj4gK3sKPj4g K8KgwqDCoCBzdHJ1Y3QgdHJiZV9idWYgKmJ1ZjsKPj4gK8KgwqDCoCBzdHJ1Y3QgcGFnZSAqKnBn bGlzdDsKPj4gK8KgwqDCoCBpbnQgaTsKPj4gKwo+PiArwqDCoMKgIGlmICgobnJfcGFnZXMgPCAy KSB8fCAoc25hcHNob3QgJiYgKG5yX3BhZ2VzICYgMSkpKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0 dXJuIE5VTEw7Cj4+ICsKPj4gK8KgwqDCoCBidWYgPSBremFsbG9jX25vZGUoc2l6ZW9mKCpidWYp LCBHRlBfS0VSTkVMLCB0cmJlX2FsbG9jX25vZGUoZXZlbnQpKTsKPj4gK8KgwqDCoCBpZiAoSVNf RVJSKGJ1ZikpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPj4g Kwo+PiArwqDCoMKgIHBnbGlzdCA9IGtjYWxsb2MobnJfcGFnZXMsIHNpemVvZigqcGdsaXN0KSwg R0ZQX0tFUk5FTCk7Cj4+ICvCoMKgwqAgaWYgKElTX0VSUihwZ2xpc3QpKSB7Cj4+ICvCoMKgwqDC oMKgwqDCoCBrZnJlZShidWYpOwo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIEVSUl9QVFIoLUVO T01FTSk7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgZm9yIChpID0gMDsgaSA8IG5yX3Bh Z2VzOyBpKyspCj4+ICvCoMKgwqDCoMKgwqDCoCBwZ2xpc3RbaV0gPSB2aXJ0X3RvX3BhZ2UocGFn ZXNbaV0pOwo+PiArCj4+ICvCoMKgwqAgYnVmLT50cmJlX2Jhc2UgPSAodW5zaWduZWQgbG9uZykg dm1hcChwZ2xpc3QsIG5yX3BhZ2VzLCBWTV9NQVAsIFBBR0VfS0VSTkVMKTsKPj4gK8KgwqDCoCBp ZiAoSVNfRVJSKCh2b2lkICopIGJ1Zi0+dHJiZV9iYXNlKSkgewo+PiArwqDCoMKgwqDCoMKgwqAg a2ZyZWUocGdsaXN0KTsKPj4gK8KgwqDCoMKgwqDCoMKgIGtmcmVlKGJ1Zik7Cj4+ICvCoMKgwqDC oMKgwqDCoCByZXR1cm4gRVJSX1BUUihidWYtPnRyYmVfYmFzZSk7Cj4+ICvCoMKgwqAgfQo+PiAr wqDCoMKgIGJ1Zi0+dHJiZV9saW1pdCA9IGJ1Zi0+dHJiZV9iYXNlICsgbnJfcGFnZXMgKiBQQUdF X1NJWkU7Cj4+ICvCoMKgwqAgYnVmLT50cmJlX3dyaXRlID0gYnVmLT50cmJlX2Jhc2U7Cj4+ICvC oMKgwqAgYnVmLT5zbmFwc2hvdCA9IHNuYXBzaG90Owo+PiArwqDCoMKgIGJ1Zi0+bnJfcGFnZXMg PSBucl9wYWdlczsKPj4gK8KgwqDCoCBidWYtPnBhZ2VzID0gcGFnZXM7Cj4+ICvCoMKgwqAga2Zy ZWUocGdsaXN0KTsKPj4gK8KgwqDCoCByZXR1cm4gYnVmOwo+PiArfQo+PiArCj4+ICt2b2lkIGFy bV90cmJlX2ZyZWVfYnVmZmVyKHZvaWQgKmNvbmZpZykKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3Qg dHJiZV9idWYgKmJ1ZiA9IGNvbmZpZzsKPj4gKwo+PiArwqDCoMKgIHZ1bm1hcCgodm9pZCAqKSBi dWYtPnRyYmVfYmFzZSk7Cj4+ICvCoMKgwqAga2ZyZWUoYnVmKTsKPj4gK30KPj4gKwo+PiArc3Rh dGljIHVuc2lnbmVkIGxvbmcgYXJtX3RyYmVfdXBkYXRlX2J1ZmZlcihzdHJ1Y3QgY29yZXNpZ2h0 X2RldmljZSAqY3NkZXYsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgIHN0cnVjdCBwZXJmX291dHB1dF9oYW5kbGUgKmhhbmRsZSwKPj4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgdm9pZCAqY29uZmlnKQo+PiAr ewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2RydmRhdGEgKmRydmRhdGEgPSBkZXZfZ2V0X2RydmRh dGEoY3NkZXYtPmRldi5wYXJlbnQpOwo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNw dWRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoJmNzZGV2LT5kZXYpOwo+PiArwqDCoMKgIHN0cnVjdCB0 cmJlX2J1ZiAqYnVmID0gY29uZmlnOwo+PiArwqDCoMKgIHVuc2lnbmVkIGxvbmcgc2l6ZSwgb2Zm c2V0Owo+PiArCj4+ICvCoMKgwqAgV0FSTl9PTihidWYtPmNwdWRhdGEgIT0gY3B1ZGF0YSk7Cj4+ ICvCoMKgwqAgV0FSTl9PTihjcHVkYXRhLT5jcHUgIT0gc21wX3Byb2Nlc3Nvcl9pZCgpKTsKPj4g K8KgwqDCoCBXQVJOX09OKGNwdWRhdGEtPmRydmRhdGEgIT0gZHJ2ZGF0YSk7Cj4+ICvCoMKgwqAg aWYgKGNwdWRhdGEtPm1vZGUgIT0gQ1NfTU9ERV9QRVJGKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0 dXJuIC1FSU5WQUw7Cj4+ICsKPj4gK8KgwqDCoCBvZmZzZXQgPSBnZXRfdHJiZV93cml0ZV9wb2lu dGVyKCkgLSBnZXRfdHJiZV9iYXNlX3BvaW50ZXIoKTsKPj4gK8KgwqDCoCBzaXplID0gb2Zmc2V0 IC0gUEVSRl9JRFgyT0ZGKGhhbmRsZS0+aGVhZCwgYnVmKTsKPj4gK8KgwqDCoCBpZiAoYnVmLT5z bmFwc2hvdCkKPj4gK8KgwqDCoMKgwqDCoMKgIGhhbmRsZS0+aGVhZCArPSBzaXplOwo+IAo+IFlv dSBtYXkgd2FudCB0byBhZGQgaW4gYSBjb21tZW50IHdoeSB3ZSBrZWVwIHRoZSBUUkJFIGRpc2Fi bGVkIGhlcmUuCgpHb29kIHBvaW50LCB3aWxsIGFkZC4KCj4gCj4+ICvCoMKgwqAgdHJiZV9yZXNl dF9sb2NhbCgpOwo+PiArwqDCoMKgIHJldHVybiBzaXplOwo+PiArfQo+PiArCj4+ICtzdGF0aWMg aW50IGFybV90cmJlX2VuYWJsZShzdHJ1Y3QgY29yZXNpZ2h0X2RldmljZSAqY3NkZXYsIHUzMiBt b2RlLCB2b2lkICpkYXRhKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2RydmRhdGEgKmRy dmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoY3NkZXYtPmRldi5wYXJlbnQpOwo+PiArwqDCoMKgIHN0 cnVjdCB0cmJlX2NwdWRhdGEgKmNwdWRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoJmNzZGV2LT5kZXYp Owo+PiArwqDCoMKgIHN0cnVjdCBwZXJmX291dHB1dF9oYW5kbGUgKmhhbmRsZSA9IGRhdGE7Cj4+ ICvCoMKgwqAgc3RydWN0IHRyYmVfYnVmICpidWYgPSBldG1fcGVyZl9zaW5rX2NvbmZpZyhoYW5k bGUpOwo+PiArCj4+ICvCoMKgwqAgV0FSTl9PTihjcHVkYXRhLT5jcHUgIT0gc21wX3Byb2Nlc3Nv cl9pZCgpKTsKPj4gK8KgwqDCoCBXQVJOX09OKGNwdWRhdGEtPmRydmRhdGEgIT0gZHJ2ZGF0YSk7 Cj4+ICvCoMKgwqAgaWYgKG1vZGUgIT0gQ1NfTU9ERV9QRVJGKQo+PiArwqDCoMKgwqDCoMKgwqAg cmV0dXJuIC1FSU5WQUw7Cj4+ICsKPj4gK8KgwqDCoCAqdGhpc19jcHVfcHRyKGRydmRhdGEtPmhh bmRsZSkgPSBoYW5kbGU7Cj4+ICvCoMKgwqAgY3B1ZGF0YS0+YnVmID0gYnVmOwo+PiArwqDCoMKg IGNwdWRhdGEtPm1vZGUgPSBtb2RlOwo+PiArwqDCoMKgIGJ1Zi0+Y3B1ZGF0YSA9IGNwdWRhdGE7 Cj4+ICvCoMKgwqAgYnVmLT50cmJlX3dyaXRlID0gYnVmLT50cmJlX2Jhc2UgKyBQRVJGX0lEWDJP RkYoaGFuZGxlLT5oZWFkLCBidWYpOwo+PiArwqDCoMKgIGJ1Zi0+dHJiZV9saW1pdCA9IGdldF90 cmJlX2xpbWl0KGhhbmRsZSk7Cj4+ICvCoMKgwqAgaWYgKGJ1Zi0+dHJiZV9saW1pdCA9PSBidWYt PnRyYmVfYmFzZSkgewo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9kaXNhYmxlX2FuZF9kcmFpbl9s b2NhbCgpOwo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIDA7Cj4+ICvCoMKgwqAgfQo+PiArwqDC oMKgIHRyYmVfZW5hYmxlX2h3KGJ1Zik7Cj4+ICvCoMKgwqAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsK Pj4gK3N0YXRpYyBpbnQgYXJtX3RyYmVfZGlzYWJsZShzdHJ1Y3QgY29yZXNpZ2h0X2RldmljZSAq Y3NkZXYpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IHRyYmVfZHJ2ZGF0YSAqZHJ2ZGF0YSA9IGRl dl9nZXRfZHJ2ZGF0YShjc2Rldi0+ZGV2LnBhcmVudCk7Cj4+ICvCoMKgwqAgc3RydWN0IHRyYmVf Y3B1ZGF0YSAqY3B1ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YSgmY3NkZXYtPmRldik7Cj4+ICvCoMKg wqAgc3RydWN0IHRyYmVfYnVmICpidWYgPSBjcHVkYXRhLT5idWY7Cj4+ICsKPj4gK8KgwqDCoCBX QVJOX09OKGJ1Zi0+Y3B1ZGF0YSAhPSBjcHVkYXRhKTsKPj4gK8KgwqDCoCBXQVJOX09OKGNwdWRh dGEtPmNwdSAhPSBzbXBfcHJvY2Vzc29yX2lkKCkpOwo+PiArwqDCoMKgIFdBUk5fT04oY3B1ZGF0 YS0+ZHJ2ZGF0YSAhPSBkcnZkYXRhKTsKPj4gK8KgwqDCoCBpZiAoY3B1ZGF0YS0+bW9kZSAhPSBD U19NT0RFX1BFUkYpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPj4gKwo+PiAr wqDCoMKgIHRyYmVfZGlzYWJsZV9hbmRfZHJhaW5fbG9jYWwoKTsKPj4gK8KgwqDCoCBidWYtPmNw dWRhdGEgPSBOVUxMOwo+PiArwqDCoMKgIGNwdWRhdGEtPmJ1ZiA9IE5VTEw7Cj4+ICvCoMKgwqAg Y3B1ZGF0YS0+bW9kZSA9IENTX01PREVfRElTQUJMRUQ7Cj4+ICvCoMKgwqAgcmV0dXJuIDA7Cj4+ ICt9Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIHRyYmVfaGFuZGxlX2ZhdGFsKHN0cnVjdCBwZXJmX291 dHB1dF9oYW5kbGUgKmhhbmRsZSkKPj4gK3sKPj4gK8KgwqDCoCBwZXJmX2F1eF9vdXRwdXRfZmxh ZyhoYW5kbGUsIFBFUkZfQVVYX0ZMQUdfVFJVTkNBVEVEKTsKPj4gK8KgwqDCoCBwZXJmX2F1eF9v dXRwdXRfZW5kKGhhbmRsZSwgMCk7Cj4+ICvCoMKgwqAgdHJiZV9kaXNhYmxlX2FuZF9kcmFpbl9s b2NhbCgpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCB0cmJlX2hhbmRsZV9zcHVyaW91cyhz dHJ1Y3QgcGVyZl9vdXRwdXRfaGFuZGxlICpoYW5kbGUpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0 IHRyYmVfYnVmICpidWYgPSBldG1fcGVyZl9zaW5rX2NvbmZpZyhoYW5kbGUpOwo+PiArCj4+ICvC oMKgwqAgYnVmLT50cmJlX3dyaXRlID0gYnVmLT50cmJlX2Jhc2UgKyBQRVJGX0lEWDJPRkYoaGFu ZGxlLT5oZWFkLCBidWYpOwo+PiArwqDCoMKgIGJ1Zi0+dHJiZV9saW1pdCA9IGdldF90cmJlX2xp bWl0KGhhbmRsZSk7Cj4+ICvCoMKgwqAgaWYgKGJ1Zi0+dHJiZV9saW1pdCA9PSBidWYtPnRyYmVf YmFzZSkgewo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9kaXNhYmxlX2FuZF9kcmFpbl9sb2NhbCgp Owo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuOwo+PiArwqDCoMKgIH0KPj4gK8KgwqDCoCB0cmJl X2VuYWJsZV9odyhidWYpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCB0cmJlX2hhbmRsZV9v dmVyZmxvdyhzdHJ1Y3QgcGVyZl9vdXRwdXRfaGFuZGxlICpoYW5kbGUpCj4+ICt7Cj4+ICvCoMKg wqAgc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50ID0gaGFuZGxlLT5ldmVudDsKPj4gK8KgwqDCoCBz dHJ1Y3QgdHJiZV9idWYgKmJ1ZiA9IGV0bV9wZXJmX3NpbmtfY29uZmlnKGhhbmRsZSk7Cj4+ICvC oMKgwqAgdW5zaWduZWQgbG9uZyBvZmZzZXQsIHNpemU7Cj4+ICvCoMKgwqAgc3RydWN0IGV0bV9l dmVudF9kYXRhICpldmVudF9kYXRhOwo+PiArCj4+ICvCoMKgwqAgb2Zmc2V0ID0gZ2V0X3RyYmVf bGltaXRfcG9pbnRlcigpIC0gZ2V0X3RyYmVfYmFzZV9wb2ludGVyKCk7Cj4+ICvCoMKgwqAgc2l6 ZSA9IG9mZnNldCAtIFBFUkZfSURYMk9GRihoYW5kbGUtPmhlYWQsIGJ1Zik7Cj4+ICvCoMKgwqAg aWYgKGJ1Zi0+c25hcHNob3QpCj4+ICvCoMKgwqDCoMKgwqDCoCBoYW5kbGUtPmhlYWQgPSBvZmZz ZXQ7Cj4+ICvCoMKgwqAgcGVyZl9hdXhfb3V0cHV0X2VuZChoYW5kbGUsIHNpemUpOwo+PiArCj4+ ICvCoMKgwqAgZXZlbnRfZGF0YSA9IHBlcmZfYXV4X291dHB1dF9iZWdpbihoYW5kbGUsIGV2ZW50 KTsKPj4gK8KgwqDCoCBpZiAoIWV2ZW50X2RhdGEpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGV2ZW50 LT5ody5zdGF0ZSB8PSBQRVJGX0hFU19TVE9QUEVEOwo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9k aXNhYmxlX2FuZF9kcmFpbl9sb2NhbCgpOwo+PiArwqDCoMKgwqDCoMKgwqAgcGVyZl9hdXhfb3V0 cHV0X2ZsYWcoaGFuZGxlLCBQRVJGX0FVWF9GTEFHX1RSVU5DQVRFRCk7Cj4+ICvCoMKgwqDCoMKg wqDCoCByZXR1cm47Cj4+ICvCoMKgwqAgfQo+PiArwqDCoMKgIGJ1Zi0+dHJiZV93cml0ZSA9IGJ1 Zi0+dHJiZV9iYXNlOwo+PiArwqDCoMKgIGJ1Zi0+dHJiZV9saW1pdCA9IGdldF90cmJlX2xpbWl0 KGhhbmRsZSk7Cj4+ICvCoMKgwqAgaWYgKGJ1Zi0+dHJiZV9saW1pdCA9PSBidWYtPnRyYmVfYmFz ZSkgewo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9kaXNhYmxlX2FuZF9kcmFpbl9sb2NhbCgpOwo+ PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuOwo+PiArwqDCoMKgIH0KPj4gK8KgwqDCoCAqdGhpc19j cHVfcHRyKGJ1Zi0+Y3B1ZGF0YS0+ZHJ2ZGF0YS0+aGFuZGxlKSA9IGhhbmRsZTsKPj4gK8KgwqDC oCB0cmJlX2VuYWJsZV9odyhidWYpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgYm9vbCBpc19wZXJm X3RyYmUoc3RydWN0IHBlcmZfb3V0cHV0X2hhbmRsZSAqaGFuZGxlKQo+PiArewo+PiArwqDCoMKg IHN0cnVjdCB0cmJlX2J1ZiAqYnVmID0gZXRtX3BlcmZfc2lua19jb25maWcoaGFuZGxlKTsKPj4g K8KgwqDCoCBzdHJ1Y3QgdHJiZV9jcHVkYXRhICpjcHVkYXRhID0gYnVmLT5jcHVkYXRhOwo+PiAr wqDCoMKgIHN0cnVjdCB0cmJlX2RydmRhdGEgKmRydmRhdGEgPSBjcHVkYXRhLT5kcnZkYXRhOwo+ PiArwqDCoMKgIGludCBjcHUgPSBzbXBfcHJvY2Vzc29yX2lkKCk7Cj4+ICsKPj4gK8KgwqDCoCBX QVJOX09OKGJ1Zi0+dHJiZV9iYXNlICE9IGdldF90cmJlX2Jhc2VfcG9pbnRlcigpKTsKPj4gK8Kg wqDCoCBXQVJOX09OKGJ1Zi0+dHJiZV9saW1pdCAhPSBnZXRfdHJiZV9saW1pdF9wb2ludGVyKCkp Owo+PiArCj4+ICvCoMKgwqAgaWYgKGNwdWRhdGEtPm1vZGUgIT0gQ1NfTU9ERV9QRVJGKQo+PiAr wqDCoMKgwqDCoMKgwqAgcmV0dXJuIGZhbHNlOwo+PiArCj4+ICvCoMKgwqAgaWYgKGNwdWRhdGEt PmNwdSAhPSBjcHUpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gZmFsc2U7Cj4+ICsKPj4gK8Kg wqDCoCBpZiAoIWNwdW1hc2tfdGVzdF9jcHUoY3B1LCAmZHJ2ZGF0YS0+c3VwcG9ydGVkX2NwdXMp KQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIGZhbHNlOwo+PiArCj4+ICvCoMKgwqAgcmV0dXJu IHRydWU7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBlbnVtIHRyYmVfZmF1bHRfYWN0aW9uIHRyYmVf Z2V0X2ZhdWx0X2FjdChzdHJ1Y3QgcGVyZl9vdXRwdXRfaGFuZGxlICpoYW5kbGUpCj4+ICt7Cj4+ ICvCoMKgwqAgaW50IGVjID0gZ2V0X3RyYmVfZWMoKTsKPj4gK8KgwqDCoCBpbnQgYnNjID0gZ2V0 X3RyYmVfYnNjKCk7Cj4+ICsKPj4gK8KgwqDCoCBXQVJOX09OKGlzX3RyYmVfcnVubmluZygpKTsK Pj4gK8KgwqDCoCBpZiAoaXNfdHJiZV90cmcoKSB8fCBpc190cmJlX2Fib3J0KCkpCj4+ICvCoMKg wqDCoMKgwqDCoCByZXR1cm4gVFJCRV9GQVVMVF9BQ1RfRkFUQUw7Cj4+ICsKPj4gK8KgwqDCoCBp ZiAoKGVjID09IFRSQkVfRUNfU1RBR0UxX0FCT1JUKSB8fCAoZWMgPT0gVFJCRV9FQ19TVEFHRTJf QUJPUlQpKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIFRSQkVfRkFVTFRfQUNUX0ZBVEFMOwo+ PiArCj4+ICvCoMKgwqAgaWYgKGlzX3RyYmVfd3JhcCgpICYmIChlYyA9PSBUUkJFX0VDX09USEVS UykgJiYgKGJzYyA9PSBUUkJFX0JTQ19GSUxMRUQpKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAo Z2V0X3RyYmVfd3JpdGVfcG9pbnRlcigpID09IGdldF90cmJlX2Jhc2VfcG9pbnRlcigpKQo+PiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCByZXR1cm4gVFJCRV9GQVVMVF9BQ1RfV1JBUDsKPj4gK8Kg wqDCoCB9Cj4+ICvCoMKgwqAgcmV0dXJuIFRSQkVfRkFVTFRfQUNUX1NQVVJJT1VTOwo+PiArfQo+ PiArCj4+ICtzdGF0aWMgaXJxcmV0dXJuX3QgYXJtX3RyYmVfaXJxX2hhbmRsZXIoaW50IGlycSwg dm9pZCAqZGV2KQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCBwZXJmX291dHB1dF9oYW5kbGUgKipo YW5kbGVfcHRyID0gZGV2Owo+PiArwqDCoMKgIHN0cnVjdCBwZXJmX291dHB1dF9oYW5kbGUgKmhh bmRsZSA9ICpoYW5kbGVfcHRyOwo+PiArwqDCoMKgIGVudW0gdHJiZV9mYXVsdF9hY3Rpb24gYWN0 Owo+PiArCj4+ICvCoMKgwqAgV0FSTl9PTighaXNfdHJiZV9pcnEoKSk7Cj4+ICvCoMKgwqAgY2xy X3RyYmVfaXJxKCk7Cj4+ICsKPj4gK8KgwqDCoCBpZiAoIXBlcmZfZ2V0X2F1eChoYW5kbGUpKQo+ PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIElSUV9OT05FOwo+PiArCj4+ICvCoMKgwqAgaWYgKCFp c19wZXJmX3RyYmUoaGFuZGxlKSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiBJUlFfTk9ORTsK Pj4gKwo+PiArwqDCoMKgIGlycV93b3JrX3J1bigpOwo+PiArCj4+ICvCoMKgwqAgYWN0ID0gdHJi ZV9nZXRfZmF1bHRfYWN0KGhhbmRsZSk7Cj4+ICvCoMKgwqAgc3dpdGNoIChhY3QpIHsKPj4gK8Kg wqDCoCBjYXNlIFRSQkVfRkFVTFRfQUNUX1dSQVA6Cj4+ICvCoMKgwqDCoMKgwqDCoCB0cmJlX2hh bmRsZV9vdmVyZmxvdyhoYW5kbGUpOwo+PiArwqDCoMKgwqDCoMKgwqAgYnJlYWs7Cj4+ICvCoMKg wqAgY2FzZSBUUkJFX0ZBVUxUX0FDVF9TUFVSSU9VUzoKPj4gK8KgwqDCoMKgwqDCoMKgIHRyYmVf aGFuZGxlX3NwdXJpb3VzKGhhbmRsZSk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBicmVhazsKPj4gK8Kg wqDCoCBjYXNlIFRSQkVfRkFVTFRfQUNUX0ZBVEFMOgo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9o YW5kbGVfZmF0YWwoaGFuZGxlKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGJyZWFrOwo+PiArwqDCoMKg IH0KPj4gK8KgwqDCoCByZXR1cm4gSVJRX0hBTkRMRUQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgY29yZXNpZ2h0X29wc19zaW5rIGFybV90cmJlX3Npbmtfb3BzID0gewo+PiAr wqDCoMKgIC5lbmFibGXCoMKgwqDCoMKgwqDCoCA9IGFybV90cmJlX2VuYWJsZSwKPj4gK8KgwqDC oCAuZGlzYWJsZcKgwqDCoCA9IGFybV90cmJlX2Rpc2FibGUsCj4+ICvCoMKgwqAgLmFsbG9jX2J1 ZmZlcsKgwqDCoCA9IGFybV90cmJlX2FsbG9jX2J1ZmZlciwKPj4gK8KgwqDCoCAuZnJlZV9idWZm ZXLCoMKgwqAgPSBhcm1fdHJiZV9mcmVlX2J1ZmZlciwKPj4gK8KgwqDCoCAudXBkYXRlX2J1ZmZl csKgwqDCoCA9IGFybV90cmJlX3VwZGF0ZV9idWZmZXIsCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMg Y29uc3Qgc3RydWN0IGNvcmVzaWdodF9vcHMgYXJtX3RyYmVfY3Nfb3BzID0gewo+PiArwqDCoMKg IC5zaW5rX29wc8KgwqDCoCA9ICZhcm1fdHJiZV9zaW5rX29wcywKPj4gK307Cj4+ICsKPj4gK3N0 YXRpYyBzc2l6ZV90IGFsaWduX3Nob3coc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNl X2F0dHJpYnV0ZSAqYXR0ciwgY2hhciAqYnVmKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCB0cmJl X2NwdWRhdGEgKmNwdWRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPj4gKwo+PiArwqDCoMKg IHJldHVybiBzcHJpbnRmKGJ1ZiwgIiVsbHhcbiIsIGNwdWRhdGEtPnRyYmVfYWxpZ24pOwo+PiAr fQo+PiArc3RhdGljIERFVklDRV9BVFRSX1JPKGFsaWduKTsKPj4gKwo+PiArc3RhdGljIHNzaXpl X3QgZGJtX3Nob3coc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAq YXR0ciwgY2hhciAqYnVmKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNw dWRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiBzcHJp bnRmKGJ1ZiwgIiVkXG4iLCBjcHVkYXRhLT50cmJlX2RibSk7Cj4+ICt9Cj4+ICtzdGF0aWMgREVW SUNFX0FUVFJfUk8oZGJtKTsKPj4gKwo+PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmFybV90 cmJlX2F0dHJzW10gPSB7Cj4+ICvCoMKgwqAgJmRldl9hdHRyX2FsaWduLmF0dHIsCj4+ICvCoMKg wqAgJmRldl9hdHRyX2RibS5hdHRyLAo+PiArwqDCoMKgIE5VTEwsCj4+ICt9Owo+PiArCj4+ICtz dGF0aWMgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBhcm1fdHJiZV9ncm91cCA9IHsKPj4g K8KgwqDCoCAuYXR0cnMgPSBhcm1fdHJiZV9hdHRycywKPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwICphcm1fdHJiZV9ncm91cHNbXSA9IHsKPj4gK8Kg wqDCoCAmYXJtX3RyYmVfZ3JvdXAsCj4+ICvCoMKgwqAgTlVMTCwKPj4gK307Cj4+ICsKPj4gK3N0 YXRpYyB2b2lkIGFybV90cmJlX3Byb2JlX2NvcmVzaWdodF9jcHUodm9pZCAqaW5mbykKPj4gK3sK Pj4gK8KgwqDCoCBzdHJ1Y3QgdHJiZV9kcnZkYXRhICpkcnZkYXRhID0gaW5mbzsKPj4gK8KgwqDC oCBzdHJ1Y3QgY29yZXNpZ2h0X2Rlc2MgZGVzYyA9IHsgMCB9Owo+PiArwqDCoMKgIGludCBjcHUg PSBzbXBfcHJvY2Vzc29yX2lkKCk7Cj4+ICvCoMKgwqAgc3RydWN0IHRyYmVfY3B1ZGF0YSAqY3B1 ZGF0YSA9IHBlcl9jcHVfcHRyKGRydmRhdGEtPmNwdWRhdGEsIGNwdSk7Cj4+ICvCoMKgwqAgc3Ry dWN0IGNvcmVzaWdodF9kZXZpY2UgKnRyYmVfY3NkZXYgPSBwZXJfY3B1KGNzZGV2X3NpbmssIGNw dSk7Cj4+ICvCoMKgwqAgc3RydWN0IGRldmljZSAqZGV2Owo+PiArCj4+ICvCoMKgwqAgaWYgKFdB Uk5fT04oIWNwdWRhdGEpKQo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBjcHVfY2xlYXI7Cj4+ICsK Pj4gK8KgwqDCoCBpZiAodHJiZV9jc2RldikKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybjsKPj4g Kwo+PiArwqDCoMKgIGNwdWRhdGEtPmNwdSA9IHNtcF9wcm9jZXNzb3JfaWQoKTsKPj4gK8KgwqDC oCBjcHVkYXRhLT5kcnZkYXRhID0gZHJ2ZGF0YTsKPj4gK8KgwqDCoCBkZXYgPSAmY3B1ZGF0YS0+ ZHJ2ZGF0YS0+cGRldi0+ZGV2Owo+PiArCj4+ICvCoMKgwqAgaWYgKCFpc190cmJlX2F2YWlsYWJs ZSgpKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBwcl9lcnIoIlRSQkUgaXMgbm90IGltcGxlbWVudGVk IG9uIGNwdSAlZFxuIiwgY3B1ZGF0YS0+Y3B1KTsKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gY3B1 X2NsZWFyOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGlmICghaXNfdHJiZV9wcm9ncmFt bWFibGUoKSkgewo+PiArwqDCoMKgwqDCoMKgwqAgcHJfZXJyKCJUUkJFIGlzIG93bmVkIGluIGhp Z2hlciBleGNlcHRpb24gbGV2ZWwgb24gY3B1ICVkXG4iLCBjcHVkYXRhLT5jcHUpOwo+PiArwqDC oMKgwqDCoMKgwqAgZ290byBjcHVfY2xlYXI7Cj4+ICvCoMKgwqAgfQo+PiArwqDCoMKgIGRlc2Mu bmFtZSA9IGRldm1fa2FzcHJpbnRmKGRldiwgR0ZQX0tFUk5FTCwgIiVzJWQiLCBEUlZOQU1FLCBz bXBfcHJvY2Vzc29yX2lkKCkpOwo+PiArwqDCoMKgIGlmIChJU19FUlIoZGVzYy5uYW1lKSkKPj4g K8KgwqDCoMKgwqDCoMKgIGdvdG8gY3B1X2NsZWFyOwo+PiArCj4+ICvCoMKgwqAgZGVzYy50eXBl ID0gQ09SRVNJR0hUX0RFVl9UWVBFX1NJTks7Cj4+ICvCoMKgwqAgZGVzYy5zdWJ0eXBlLnNpbmtf c3VidHlwZSA9IENPUkVTSUdIVF9ERVZfU1VCVFlQRV9TSU5LX1BFUkNQVV9TWVNNRU07Cj4+ICvC oMKgwqAgZGVzYy5vcHMgPSAmYXJtX3RyYmVfY3Nfb3BzOwo+PiArwqDCoMKgIGRlc2MucGRhdGEg PSBkZXZfZ2V0X3BsYXRkYXRhKGRldik7Cj4+ICvCoMKgwqAgZGVzYy5ncm91cHMgPSBhcm1fdHJi ZV9ncm91cHM7Cj4+ICvCoMKgwqAgZGVzYy5kZXYgPSBkZXY7Cj4+ICvCoMKgwqAgdHJiZV9jc2Rl diA9IGNvcmVzaWdodF9yZWdpc3RlcigmZGVzYyk7Cj4+ICvCoMKgwqAgaWYgKElTX0VSUih0cmJl X2NzZGV2KSkKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gY3B1X2NsZWFyOwo+PiArCj4+ICvCoMKg wqAgZGV2X3NldF9kcnZkYXRhKCZ0cmJlX2NzZGV2LT5kZXYsIGNwdWRhdGEpOwo+PiArwqDCoMKg IGNwdWRhdGEtPnRyYmVfZGJtID0gZ2V0X3RyYmVfZmxhZ191cGRhdGUoKTsKPj4gK8KgwqDCoCBj cHVkYXRhLT50cmJlX2FsaWduID0gMVVMTCA8PCBnZXRfdHJiZV9hZGRyZXNzX2FsaWduKCk7Cj4+ ICvCoMKgwqAgaWYgKGNwdWRhdGEtPnRyYmVfYWxpZ24gPiBTWl8ySykgewo+PiArwqDCoMKgwqDC oMKgwqAgcHJfZXJyKCJVbnN1cHBvcnRlZCBhbGlnbm1lbnQgb24gY3B1ICVkXG4iLCBjcHVkYXRh LT5jcHUpOwo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBjcHVfY2xlYXI7Cj4+ICvCoMKgwqAgfQo+ PiArwqDCoMKgIHBlcl9jcHUoY3NkZXZfc2luaywgY3B1KSA9IHRyYmVfY3NkZXY7Cj4+ICvCoMKg wqAgdHJiZV9yZXNldF9sb2NhbCgpOwo+PiArwqDCoMKgIGVuYWJsZV9wZXJjcHVfaXJxKGRydmRh dGEtPmlycSwgSVJRX1RZUEVfTk9ORSk7Cj4+ICvCoMKgwqAgcmV0dXJuOwo+PiArY3B1X2NsZWFy Ogo+PiArwqDCoMKgIGNwdW1hc2tfY2xlYXJfY3B1KGNwdWRhdGEtPmNwdSwgJmNwdWRhdGEtPmRy dmRhdGEtPnN1cHBvcnRlZF9jcHVzKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgYXJtX3Ry YmVfcmVtb3ZlX2NvcmVzaWdodF9jcHUodm9pZCAqaW5mbykKPj4gK3sKPj4gK8KgwqDCoCBpbnQg Y3B1ID0gc21wX3Byb2Nlc3Nvcl9pZCgpOwo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2RydmRhdGEg KmRydmRhdGEgPSBpbmZvOwo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2NwdWRhdGEgKmNwdWRhdGEg PSBwZXJfY3B1X3B0cihkcnZkYXRhLT5jcHVkYXRhLCBjcHUpOwo+PiArwqDCoMKgIHN0cnVjdCBj b3Jlc2lnaHRfZGV2aWNlICp0cmJlX2NzZGV2ID0gcGVyX2NwdShjc2Rldl9zaW5rLCBjcHUpOwo+ PiArCj4+ICvCoMKgwqAgaWYgKHRyYmVfY3NkZXYpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGNvcmVz aWdodF91bnJlZ2lzdGVyKHRyYmVfY3NkZXYpOwo+PiArwqDCoMKgwqDCoMKgwqAgY3B1ZGF0YS0+ ZHJ2ZGF0YSA9IE5VTEw7Cj4+ICvCoMKgwqDCoMKgwqDCoCBwZXJfY3B1KGNzZGV2X3NpbmssIGNw dSkgPSBOVUxMOwo+PiArwqDCoMKgIH0KPj4gK8KgwqDCoCBkaXNhYmxlX3BlcmNwdV9pcnEoZHJ2 ZGF0YS0+aXJxKTsKPj4gK8KgwqDCoCB0cmJlX3Jlc2V0X2xvY2FsKCk7Cj4+ICt9Cj4+ICsKPj4g K3N0YXRpYyBpbnQgYXJtX3RyYmVfcHJvYmVfY29yZXNpZ2h0KHN0cnVjdCB0cmJlX2RydmRhdGEg KmRydmRhdGEpCj4+ICt7Cj4+ICvCoMKgwqAgZHJ2ZGF0YS0+Y3B1ZGF0YSA9IGFsbG9jX3BlcmNw dSh0eXBlb2YoKmRydmRhdGEtPmNwdWRhdGEpKTsKPj4gK8KgwqDCoCBpZiAoSVNfRVJSKGRydmRh dGEtPmNwdWRhdGEpKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIFBUUl9FUlIoZHJ2ZGF0YS0+ Y3B1ZGF0YSk7Cj4+ICsKPj4gK8KgwqDCoCBhcm1fdHJiZV9wcm9iZV9jb3Jlc2lnaHRfY3B1KGRy dmRhdGEpOwo+PiArwqDCoMKgIHNtcF9jYWxsX2Z1bmN0aW9uX21hbnkoJmRydmRhdGEtPnN1cHBv cnRlZF9jcHVzLCBhcm1fdHJiZV9wcm9iZV9jb3Jlc2lnaHRfY3B1LCBkcnZkYXRhLCAxKTsKPj4g K8KgwqDCoCByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBhcm1fdHJiZV9yZW1v dmVfY29yZXNpZ2h0KHN0cnVjdCB0cmJlX2RydmRhdGEgKmRydmRhdGEpCj4+ICt7Cj4+ICvCoMKg wqAgYXJtX3RyYmVfcmVtb3ZlX2NvcmVzaWdodF9jcHUoZHJ2ZGF0YSk7Cj4+ICvCoMKgwqAgc21w X2NhbGxfZnVuY3Rpb25fbWFueSgmZHJ2ZGF0YS0+c3VwcG9ydGVkX2NwdXMsIGFybV90cmJlX3Jl bW92ZV9jb3Jlc2lnaHRfY3B1LCBkcnZkYXRhLCAxKTsKPj4gK8KgwqDCoCBmcmVlX3BlcmNwdShk cnZkYXRhLT5jcHVkYXRhKTsKPj4gK8KgwqDCoCByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3Rh dGljIGludCBhcm1fdHJiZV9jcHVfc3RhcnR1cCh1bnNpZ25lZCBpbnQgY3B1LCBzdHJ1Y3QgaGxp c3Rfbm9kZSAqbm9kZSkKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3QgdHJiZV9kcnZkYXRhICpkcnZk YXRhID0gaGxpc3RfZW50cnlfc2FmZShub2RlLCBzdHJ1Y3QgdHJiZV9kcnZkYXRhLCBob3RwbHVn X25vZGUpOwo+PiArCj4+ICvCoMKgwqAgaWYgKGNwdW1hc2tfdGVzdF9jcHUoY3B1LCAmZHJ2ZGF0 YS0+c3VwcG9ydGVkX2NwdXMpKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAoIXBlcl9jcHUoY3Nk ZXZfc2luaywgY3B1KSAmJiAoc3lzdGVtX3N0YXRlID09IFNZU1RFTV9SVU5OSU5HKSkgewo+IAo+ IFdoeSBpcyB0aGUgc3lzdGVtX3N0YXRlIGNoZWNrIHJlbGV2YW50IGhlcmUgPwoKSSBoYWQgYSBj b25jZXJuIHJlZ2FyZGluZyB3aGV0aGVyIGFybV90cmJlX3Byb2JlX2NvcmVzaWdodF9jcHUoKSBp bnZvY2F0aW9ucwpmcm9tIGFybV90cmJlX2NwdV9zdGFydHVwKCkgbWlnaHQgcmFjZSB3aXRoIGl0 cyBpbnZvY2F0aW9ucyBkdXJpbmcgYm9vdCBmcm9tCmFybV90cmJlX2RldmljZV9wcm9iZSgpLiBD aGVja2luZyBmb3IgcnVudGltZSBzeXN0ZW1fc3RhdGUgd291bGQgZW5zdXJlIHRoYXQKYSBjb21w bGV0ZSBUUkJFIHByb2JlIG9uIGEgZ2l2ZW4gY3B1IGlzIGNhbGxlZCBvbmx5IGFmdGVyIHRoZSBi b290IGlzIGNvbXBsZXRlLgpCdXQgaWYgdGhlIHJhY2UgY29uZGl0aW9uIGlzIHJlYWxseSBuZXZl ciBwb3NzaWJsZSwgY2FuIGp1c3QgZHJvcCB0aGlzIGNoZWNrLgoKPiAKPj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqAgYXJtX3RyYmVfcHJvYmVfY29yZXNpZ2h0X2NwdShkcnZkYXRhKTsKPj4gK8Kg wqDCoMKgwqDCoMKgIH0gZWxzZSB7Cj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHRyYmVfcmVz ZXRfbG9jYWwoKTsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZW5hYmxlX3BlcmNwdV9pcnEo ZHJ2ZGF0YS0+aXJxLCBJUlFfVFlQRV9OT05FKTsKPj4gK8KgwqDCoMKgwqDCoMKgIH0KPj4gK8Kg wqDCoCB9Cj4+ICvCoMKgwqAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgYXJt X3RyYmVfY3B1X3RlYXJkb3duKHVuc2lnbmVkIGludCBjcHUsIHN0cnVjdCBobGlzdF9ub2RlICpu b2RlKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCB0cmJlX2RydmRhdGEgKmRydmRhdGEgPSBobGlz dF9lbnRyeV9zYWZlKG5vZGUsIHN0cnVjdCB0cmJlX2RydmRhdGEsIGhvdHBsdWdfbm9kZSk7Cj4+ ICsKPj4gK8KgwqDCoCBpZiAoY3B1bWFza190ZXN0X2NwdShjcHUsICZkcnZkYXRhLT5zdXBwb3J0 ZWRfY3B1cykpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGRpc2FibGVfcGVyY3B1X2lycShkcnZkYXRh LT5pcnEpOwo+PiArwqDCoMKgwqDCoMKgwqAgdHJiZV9yZXNldF9sb2NhbCgpOwo+PiArwqDCoMKg IH0KPj4gK8KgwqDCoCByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBhcm1fdHJi ZV9wcm9iZV9jcHVocChzdHJ1Y3QgdHJiZV9kcnZkYXRhICpkcnZkYXRhKQo+PiArewo+PiArwqDC oMKgIGVudW0gY3B1aHBfc3RhdGUgdHJiZV9vbmxpbmU7Cj4+ICsKPj4gK8KgwqDCoCB0cmJlX29u bGluZSA9IGNwdWhwX3NldHVwX3N0YXRlX211bHRpKENQVUhQX0FQX09OTElORV9EWU4sIERSVk5B TUUsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBhcm1fdHJiZV9j cHVfc3RhcnR1cCwgYXJtX3RyYmVfY3B1X3RlYXJkb3duKTsKPj4gK8KgwqDCoCBpZiAodHJiZV9v bmxpbmUgPCAwKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FSU5WQUw7Cj4+ICsKPj4gK8Kg wqDCoCBpZiAoY3B1aHBfc3RhdGVfYWRkX2luc3RhbmNlKHRyYmVfb25saW5lLCAmZHJ2ZGF0YS0+ aG90cGx1Z19ub2RlKSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRUlOVkFMOwo+PiArCj4+ ICvCoMKgwqAgZHJ2ZGF0YS0+dHJiZV9vbmxpbmUgPSB0cmJlX29ubGluZTsKPj4gK8KgwqDCoCBy ZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgYXJtX3RyYmVfcmVtb3ZlX2NwdWhw KHN0cnVjdCB0cmJlX2RydmRhdGEgKmRydmRhdGEpCj4+ICt7Cj4+ICvCoMKgwqAgY3B1aHBfcmVt b3ZlX211bHRpX3N0YXRlKGRydmRhdGEtPnRyYmVfb25saW5lKTsKPj4gK30KPj4gKwo+PiArc3Rh dGljIGludCBhcm1fdHJiZV9wcm9iZV9pcnEoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwK Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgc3RydWN0IHRyYmVfZHJ2ZGF0 YSAqZHJ2ZGF0YSkKPj4gK3sKPj4gK8KgwqDCoCBkcnZkYXRhLT5pcnEgPSBwbGF0Zm9ybV9nZXRf aXJxKHBkZXYsIDApOwo+PiArwqDCoMKgIGlmICghZHJ2ZGF0YS0+aXJxKSB7Cj4+ICvCoMKgwqDC oMKgwqDCoCBwcl9lcnIoIklSUSBub3QgZm91bmQgZm9yIHRoZSBwbGF0Zm9ybSBkZXZpY2VcbiIp Owo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FTlhJTzsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4g K8KgwqDCoCBpZiAoIWlycV9pc19wZXJjcHUoZHJ2ZGF0YS0+aXJxKSkgewo+PiArwqDCoMKgwqDC oMKgwqAgcHJfZXJyKCJJUlEgaXMgbm90IGEgUFBJXG4iKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHJl dHVybiAtRUlOVkFMOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGlmIChpcnFfZ2V0X3Bl cmNwdV9kZXZpZF9wYXJ0aXRpb24oZHJ2ZGF0YS0+aXJxLCAmZHJ2ZGF0YS0+c3VwcG9ydGVkX2Nw dXMpKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FSU5WQUw7Cj4+ICsKPj4gK8KgwqDCoCBk cnZkYXRhLT5oYW5kbGUgPSBhbGxvY19wZXJjcHUodHlwZW9mKCpkcnZkYXRhLT5oYW5kbGUpKTsK Pj4gK8KgwqDCoCBpZiAoIWRydmRhdGEtPmhhbmRsZSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVy biAtRU5PTUVNOwo+PiArCj4+ICvCoMKgwqAgaWYgKHJlcXVlc3RfcGVyY3B1X2lycShkcnZkYXRh LT5pcnEsIGFybV90cmJlX2lycV9oYW5kbGVyLCBEUlZOQU1FLCBkcnZkYXRhLT5oYW5kbGUpKSB7 Cj4+ICvCoMKgwqDCoMKgwqDCoCBmcmVlX3BlcmNwdShkcnZkYXRhLT5oYW5kbGUpOwo+PiArwqDC oMKgwqDCoMKgwqAgcmV0dXJuIC1FSU5WQUw7Cj4+ICvCoMKgwqAgfQo+PiArwqDCoMKgIHJldHVy biAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBhcm1fdHJiZV9yZW1vdmVfaXJxKHN0cnVj dCB0cmJlX2RydmRhdGEgKmRydmRhdGEpCj4+ICt7Cj4+ICvCoMKgwqAgZnJlZV9wZXJjcHVfaXJx KGRydmRhdGEtPmlycSwgZHJ2ZGF0YS0+aGFuZGxlKTsKPj4gK8KgwqDCoCBmcmVlX3BlcmNwdShk cnZkYXRhLT5oYW5kbGUpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IGFybV90cmJlX2Rldmlj ZV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+PiArewo+PiArwqDCoMKgIHN0 cnVjdCBjb3Jlc2lnaHRfcGxhdGZvcm1fZGF0YSAqcGRhdGE7Cj4+ICvCoMKgwqAgc3RydWN0IHRy YmVfZHJ2ZGF0YSAqZHJ2ZGF0YTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRl di0+ZGV2Owo+PiArwqDCoMKgIGludCByZXQ7Cj4+ICsKPj4gK8KgwqDCoCBkcnZkYXRhID0gZGV2 bV9remFsbG9jKGRldiwgc2l6ZW9mKCpkcnZkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4+ICvCoMKgwqAg aWYgKElTX0VSUihkcnZkYXRhKSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRU5PTUVNOwo+ PiArCj4+ICvCoMKgwqAgcGRhdGEgPSBjb3Jlc2lnaHRfZ2V0X3BsYXRmb3JtX2RhdGEoZGV2KTsK Pj4gK8KgwqDCoCBpZiAoSVNfRVJSKHBkYXRhKSkgewo+PiArwqDCoMKgwqDCoMKgwqAga2ZyZWUo ZHJ2ZGF0YSk7Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVOT01FTTsKPj4gK8KgwqDCoCB9 Cj4+ICsKPj4gK8KgwqDCoCBkZXZfc2V0X2RydmRhdGEoZGV2LCBkcnZkYXRhKTsKPj4gK8KgwqDC oCBkZXYtPnBsYXRmb3JtX2RhdGEgPSBwZGF0YTsKPj4gK8KgwqDCoCBkcnZkYXRhLT5wZGV2ID0g cGRldjsKPj4gK8KgwqDCoCByZXQgPSBhcm1fdHJiZV9wcm9iZV9pcnEocGRldiwgZHJ2ZGF0YSk7 Cj4+ICvCoMKgwqAgaWYgKHJldCkKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gaXJxX2ZhaWxlZDsK Pj4gKwo+PiArwqDCoMKgIHJldCA9IGFybV90cmJlX3Byb2JlX2NvcmVzaWdodChkcnZkYXRhKTsK Pj4gK8KgwqDCoCBpZiAocmV0KQo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBwcm9iZV9mYWlsZWQ7 Cj4+ICsKPj4gK8KgwqDCoCByZXQgPSBhcm1fdHJiZV9wcm9iZV9jcHVocChkcnZkYXRhKTsKPj4g K8KgwqDCoCBpZiAocmV0KQo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBjcHVocF9mYWlsZWQ7Cj4+ ICsKPj4gK8KgwqDCoCByZXR1cm4gMDsKPj4gK2NwdWhwX2ZhaWxlZDoKPj4gK8KgwqDCoCBhcm1f dHJiZV9yZW1vdmVfY29yZXNpZ2h0KGRydmRhdGEpOwo+PiArcHJvYmVfZmFpbGVkOgo+PiArwqDC oMKgIGFybV90cmJlX3JlbW92ZV9pcnEoZHJ2ZGF0YSk7Cj4+ICtpcnFfZmFpbGVkOgo+PiArwqDC oMKgIGtmcmVlKHBkYXRhKTsKPj4gK8KgwqDCoCBrZnJlZShkcnZkYXRhKTsKPj4gK8KgwqDCoCBy ZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IGFybV90cmJlX2RldmljZV9yZW1v dmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3Qg Y29yZXNpZ2h0X3BsYXRmb3JtX2RhdGEgKnBkYXRhID0gZGV2X2dldF9wbGF0ZGF0YSgmcGRldi0+ ZGV2KTsKPj4gK8KgwqDCoCBzdHJ1Y3QgdHJiZV9kcnZkYXRhICpkcnZkYXRhID0gcGxhdGZvcm1f Z2V0X2RydmRhdGEocGRldik7Cj4+ICsKPj4gK8KgwqDCoCBhcm1fdHJiZV9yZW1vdmVfY29yZXNp Z2h0KGRydmRhdGEpOwo+PiArwqDCoMKgIGFybV90cmJlX3JlbW92ZV9jcHVocChkcnZkYXRhKTsK Pj4gK8KgwqDCoCBhcm1fdHJiZV9yZW1vdmVfaXJxKGRydmRhdGEpOwo+PiArwqDCoMKgIGtmcmVl KHBkYXRhKTsKPj4gK8KgwqDCoCBrZnJlZShkcnZkYXRhKTsKPj4gK8KgwqDCoCByZXR1cm4gMDsK Pj4gK30KPj4gKwo+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgYXJtX3RyYmVf b2ZfbWF0Y2hbXSA9IHsKPj4gK8KgwqDCoCB7IC5jb21wYXRpYmxlID0gImFybSx0cmFjZS1idWZm ZXItZXh0ZW5zaW9uIizCoMKgwqAgLmRhdGEgPSAodm9pZCAqKTEgfSwKPiAKPiBXaGF0IGlzIHRo ZSBzaWduaWZpY2FuY2Ugb2YgLmRhdGEgPSAxID8KCkkgZ3Vlc3MgdGhpcyBjYW4gYWxzbyBiZSBk cm9wcGVkLgoKPiAKPj4gK8KgwqDCoCB7fSwKPj4gK307Cj4+ICtNT0RVTEVfREVWSUNFX1RBQkxF KG9mLCBhcm1fdHJiZV9vZl9tYXRjaCk7Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1f ZHJpdmVyIGFybV90cmJlX2RyaXZlciA9IHsKPj4gK8KgwqDCoCAuZHJpdmVywqDCoMKgID0gewo+ PiArwqDCoMKgwqDCoMKgwqAgLm5hbWUgPSBEUlZOQU1FLAo+PiArwqDCoMKgwqDCoMKgwqAgLm9m X21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKGFybV90cmJlX29mX21hdGNoKSwKPj4gK8KgwqDC oMKgwqDCoMKgIC5zdXBwcmVzc19iaW5kX2F0dHJzID0gdHJ1ZSwKPj4gK8KgwqDCoCB9LAo+PiAr wqDCoMKgIC5wcm9iZcKgwqDCoCA9IGFybV90cmJlX2RldmljZV9wcm9iZSwKPj4gK8KgwqDCoCAu cmVtb3ZlwqDCoMKgID0gYXJtX3RyYmVfZGV2aWNlX3JlbW92ZSwKPj4gK307Cj4+ICsKPj4gK3N0 YXRpYyBpbnQgX19pbml0IGFybV90cmJlX2luaXQodm9pZCkKPj4gK3sKPj4gK8KgwqDCoCBpbnQg cmV0Owo+PiArCj4+ICvCoMKgwqAgcmV0ID0gcGxhdGZvcm1fZHJpdmVyX3JlZ2lzdGVyKCZhcm1f dHJiZV9kcml2ZXIpOwo+PiArwqDCoMKgIGlmICghcmV0KQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0 dXJuIDA7Cj4+ICsKPj4gK8KgwqDCoCBwcl9lcnIoIkVycm9yIHJlZ2lzdGVyaW5nICVzIHBsYXRm b3JtIGRyaXZlclxuIiwgRFJWTkFNRSk7Cj4+ICvCoMKgwqAgcmV0dXJuIHJldDsKPj4gK30KPj4g Kwo+PiArc3RhdGljIHZvaWQgX19leGl0IGFybV90cmJlX2V4aXQodm9pZCkKPj4gK3sKPj4gK8Kg wqDCoCBwbGF0Zm9ybV9kcml2ZXJfdW5yZWdpc3RlcigmYXJtX3RyYmVfZHJpdmVyKTsKPj4gK30K Pj4gK21vZHVsZV9pbml0KGFybV90cmJlX2luaXQpOwo+PiArbW9kdWxlX2V4aXQoYXJtX3RyYmVf ZXhpdCk7Cj4+ICsKPj4gK01PRFVMRV9BVVRIT1IoIkFuc2h1bWFuIEtoYW5kdWFsIDxhbnNodW1h bi5raGFuZHVhbEBhcm0uY29tPiIpOwo+PiArTU9EVUxFX0RFU0NSSVBUSU9OKCJBcm0gVHJhY2Ug QnVmZmVyIEV4dGVuc2lvbiAoVFJCRSkgZHJpdmVyIik7Cj4+ICtNT0RVTEVfTElDRU5TRSgiR1BM IHYyIik7Cj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvY29yZXNp Z2h0LXRyYmUuaCBiL2RyaXZlcnMvaHd0cmFjaW5nL2NvcmVzaWdodC9jb3Jlc2lnaHQtdHJiZS5o Cj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+IGluZGV4IDAwMDAwMDAuLmU5NTY0MzkKPj4gLS0t IC9kZXYvbnVsbAo+PiArKysgYi9kcml2ZXJzL2h3dHJhY2luZy9jb3Jlc2lnaHQvY29yZXNpZ2h0 LXRyYmUuaAo+PiBAQCAtMCwwICsxLDI0OCBAQAo+PiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IEdQTC0yLjAgKi8KPj4gKy8qCj4+ICsgKiBUaGlzIGNvbnRhaW5zIGFsbCByZXF1aXJlZCBo YXJkd2FyZSByZWxhdGVkIGhlbHBlciBmdW5jdGlvbnMgZm9yCj4+ICsgKiBUcmFjZSBCdWZmZXIg RXh0ZW5zaW9uIChUUkJFKSBkcml2ZXIgaW4gdGhlIGNvcmVzaWdodCBmcmFtZXdvcmsuCj4+ICsg Kgo+PiArICogQ29weXJpZ2h0IChDKSAyMDIwIEFSTSBMdGQuCj4+ICsgKgo+PiArICogQXV0aG9y OiBBbnNodW1hbiBLaGFuZHVhbCA8YW5zaHVtYW4ua2hhbmR1YWxAYXJtLmNvbT4KPj4gKyAqLwo+ PiArI2luY2x1ZGUgPGxpbnV4L2NvcmVzaWdodC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2Rldmlj ZS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2lycS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2tlcm5l bC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L29mLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZv cm1fZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvc21wLmg+Cj4+ICsKPj4gKyNpbmNsdWRl ICJjb3Jlc2lnaHQtZXRtLXBlcmYuaCIKPj4gKwo+PiArREVDTEFSRV9QRVJfQ1BVKHN0cnVjdCBj b3Jlc2lnaHRfZGV2aWNlICosIGNzZGV2X3NpbmspOwo+PiArCj4+ICtzdGF0aWMgaW5saW5lIGJv b2wgaXNfdHJiZV9hdmFpbGFibGUodm9pZCkKPj4gK3sKPj4gK8KgwqDCoCB1NjQgYWE2NGRmcjAg PSByZWFkX3N5c3JlZ19zKFNZU19JRF9BQTY0REZSMF9FTDEpOwo+PiArwqDCoMKgIGludCB0cmJl ID0gY3B1aWRfZmVhdHVyZV9leHRyYWN0X3Vuc2lnbmVkX2ZpZWxkKGFhNjRkZnIwLCBJRF9BQTY0 REZSMF9UUkJFX1NISUZUKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiB0cmJlID49IDBiMDAwMTsK Pj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSBib29sIGlzX3RyYmVfZW5hYmxlZCh2b2lkKQo+ PiArewo+PiArwqDCoMKgIHU2NCB0cmJsaW1pdHIgPSByZWFkX3N5c3JlZ19zKFNZU19UUkJMSU1J VFJfRUwxKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiB0cmJsaW1pdHIgJiBUUkJMSU1JVFJfRU5B QkxFOwo+PiArfQo+PiArCj4+ICsjZGVmaW5lIFRSQkVfRUNfT1RIRVJTwqDCoMKgwqDCoMKgwqAg MAo+PiArI2RlZmluZSBUUkJFX0VDX1NUQUdFMV9BQk9SVMKgwqDCoCAzNgo+PiArI2RlZmluZSBU UkJFX0VDX1NUQUdFMl9BQk9SVMKgwqDCoCAzNwo+PiArCj4+ICtzdGF0aWMgaW5saW5lIGludCBn ZXRfdHJiZV9lYyh2b2lkKQo+PiArewo+PiArwqDCoMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVn X3MoU1lTX1RSQlNSX0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gKHRyYnNyID4+IFRSQlNS X0VDX1NISUZUKSAmIFRSQlNSX0VDX01BU0s7Cj4+ICt9Cj4+ICsKPj4gKyNkZWZpbmUgVFJCRV9C U0NfTk9UX1NUT1BQRUTCoMKgwqAgMAo+PiArI2RlZmluZcKgwqDCoCBUUkJFX0JTQ19GSUxMRUTC oMKgwqDCoMKgwqDCoCAxCj4+ICsjZGVmaW5lIFRSQkVfQlNDX1RSSUdHRVJFRMKgwqDCoCAyCj4+ ICsKPj4gK3N0YXRpYyBpbmxpbmUgaW50IGdldF90cmJlX2JzYyh2b2lkKQo+PiArewo+PiArwqDC oMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQlNSX0VMMSk7Cj4+ICsKPj4gK8Kg wqDCoCByZXR1cm4gKHRyYnNyID4+IFRSQlNSX0JTQ19TSElGVCkgJiBUUkJTUl9CU0NfTUFTSzsK Pj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSB2b2lkIGNscl90cmJlX2lycSh2b2lkKQo+PiAr ewo+PiArwqDCoMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQlNSX0VMMSk7Cj4+ ICsKPj4gK8KgwqDCoCB0cmJzciAmPSB+VFJCU1JfSVJROwo+PiArwqDCoMKgIHdyaXRlX3N5c3Jl Z19zKHRyYnNyLCBTWVNfVFJCU1JfRUwxKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSBi b29sIGlzX3RyYmVfaXJxKHZvaWQpCj4+ICt7Cj4+ICvCoMKgwqAgdTY0IHRyYnNyID0gcmVhZF9z eXNyZWdfcyhTWVNfVFJCU1JfRUwxKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiB0cmJzciAmIFRS QlNSX0lSUTsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSBib29sIGlzX3RyYmVfdHJnKHZv aWQpCj4+ICt7Cj4+ICvCoMKgwqAgdTY0IHRyYnNyID0gcmVhZF9zeXNyZWdfcyhTWVNfVFJCU1Jf RUwxKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiB0cmJzciAmIFRSQlNSX1RSRzsKPj4gK30KPj4g Kwo+PiArc3RhdGljIGlubGluZSBib29sIGlzX3RyYmVfd3JhcCh2b2lkKQo+PiArewo+PiArwqDC oMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQlNSX0VMMSk7Cj4+ICsKPj4gK8Kg wqDCoCByZXR1cm4gdHJic3IgJiBUUkJTUl9XUkFQOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW5s aW5lIGJvb2wgaXNfdHJiZV9hYm9ydCh2b2lkKQo+PiArewo+PiArwqDCoMKgIHU2NCB0cmJzciA9 IHJlYWRfc3lzcmVnX3MoU1lTX1RSQlNSX0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gdHJi c3IgJiBUUkJTUl9BQk9SVDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSBib29sIGlzX3Ry YmVfcnVubmluZyh2b2lkKQo+PiArewo+PiArwqDCoMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVn X3MoU1lTX1RSQlNSX0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gISh0cmJzciAmIFRSQlNS X1NUT1ApOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW5saW5lIHZvaWQgc2V0X3RyYmVfcnVubmlu Zyh2b2lkKQo+PiArewo+PiArwqDCoMKgIHU2NCB0cmJzciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RS QlNSX0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCB0cmJzciAmPSB+VFJCU1JfU1RPUDsKPj4gK8KgwqDC oCB3cml0ZV9zeXNyZWdfcyh0cmJzciwgU1lTX1RSQlNSX0VMMSk7Cj4+ICt9Cj4+ICsKPj4gK3N0 YXRpYyBpbmxpbmUgdm9pZCBzZXRfdHJiZV92aXJ0dWFsX21vZGUodm9pZCkKPj4gK3sKPj4gK8Kg wqDCoCB1NjQgdHJibGltaXRyID0gcmVhZF9zeXNyZWdfcyhTWVNfVFJCTElNSVRSX0VMMSk7Cj4+ ICsKPj4gK8KgwqDCoCB0cmJsaW1pdHIgJj0gflRSQkxJTUlUUl9OVk07Cj4+ICvCoMKgwqAgd3Jp dGVfc3lzcmVnX3ModHJibGltaXRyLCBTWVNfVFJCTElNSVRSX0VMMSk7Cj4+ICt9Cj4+ICsKPj4g KyNkZWZpbmUgVFJCRV9UUklHR0VSX1NUT1DCoMKgwqAgMAo+PiArI2RlZmluZSBUUkJFX1RSSUdH RVJfSVJRwqDCoMKgIDEKPj4gKyNkZWZpbmUgVFJCRV9UUklHR0VSX0lHTk9SRcKgwqDCoCAzCj4+ ICsKPj4gK3N0YXRpYyBpbmxpbmUgaW50IGdldF90cmJlX3RyaWdfbW9kZSh2b2lkKQo+PiArewo+ PiArwqDCoMKgIHU2NCB0cmJsaW1pdHIgPSByZWFkX3N5c3JlZ19zKFNZU19UUkJMSU1JVFJfRUwx KTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiAodHJibGltaXRyID4+IFRSQkxJTUlUUl9UUklHX01P REVfU0hJRlQpICYgVFJCTElNSVRSX1RSSUdfTU9ERV9NQVNLOwo+PiArfQo+PiArCj4+ICtzdGF0 aWMgaW5saW5lIHZvaWQgc2V0X3RyYmVfdHJpZ19tb2RlKGludCBtb2RlKQo+PiArewo+PiArwqDC oMKgIHU2NCB0cmJsaW1pdHIgPSByZWFkX3N5c3JlZ19zKFNZU19UUkJMSU1JVFJfRUwxKTsKPj4g Kwo+PiArwqDCoMKgIHRyYmxpbWl0ciAmPSB+KFRSQkxJTUlUUl9UUklHX01PREVfTUFTSyA8PCBU UkJMSU1JVFJfVFJJR19NT0RFX1NISUZUKTsKPj4gK8KgwqDCoCB0cmJsaW1pdHIgfD0gKChtb2Rl ICYgVFJCTElNSVRSX1RSSUdfTU9ERV9NQVNLKSA8PCBUUkJMSU1JVFJfVFJJR19NT0RFX1NISUZU KTsKPj4gK8KgwqDCoCB3cml0ZV9zeXNyZWdfcyh0cmJsaW1pdHIsIFNZU19UUkJMSU1JVFJfRUwx KTsKPj4gK30KPj4gKwo+PiArI2RlZmluZSBUUkJFX0ZJTExfU1RPUMKgwqDCoMKgwqDCoMKgIDAK Pj4gKyNkZWZpbmUgVFJCRV9GSUxMX1dSQVDCoMKgwqDCoMKgwqDCoCAxCj4+ICsjZGVmaW5lIFRS QkVfRklMTF9DSVJDVUxBUsKgwqDCoCAzCj4+ICsKPiAKPiAtLS04Pi0tLQo+IAo+PiArc3RhdGlj IGlubGluZSBpbnQgZ2V0X3RyYmVfZmlsbF9tb2RlKHZvaWQpCj4+ICt7Cj4+ICvCoMKgwqAgdTY0 IHRyYmxpbWl0ciA9IHJlYWRfc3lzcmVnX3MoU1lTX1RSQkxJTUlUUl9FTDEpOwo+PiArCj4+ICvC oMKgwqAgcmV0dXJuICh0cmJsaW1pdHIgPj4gVFJCTElNSVRSX0ZJTExfTU9ERV9TSElGVCkgJiBU UkJMSU1JVFJfRklMTF9NT0RFX01BU0s7Cj4+ICt9ID4gKwo+PiArc3RhdGljIGlubGluZSB2b2lk IHNldF90cmJlX2ZpbGxfbW9kZShpbnQgbW9kZSkKPj4gK3sKPj4gK8KgwqDCoCB1NjQgdHJibGlt aXRyID0gcmVhZF9zeXNyZWdfcyhTWVNfVFJCTElNSVRSX0VMMSk7Cj4+ICsKPj4gK8KgwqDCoCB0 cmJsaW1pdHIgJj0gfihUUkJMSU1JVFJfRklMTF9NT0RFX01BU0sgPDwgVFJCTElNSVRSX0ZJTExf TU9ERV9TSElGVCk7Cj4+ICvCoMKgwqAgdHJibGltaXRyIHw9ICgobW9kZSAmIFRSQkxJTUlUUl9G SUxMX01PREVfTUFTSykgPDwgVFJCTElNSVRSX0ZJTExfTU9ERV9TSElGVCk7Cj4+ICvCoMKgwqAg d3JpdGVfc3lzcmVnX3ModHJibGltaXRyLCBTWVNfVFJCTElNSVRSX0VMMSk7Cj4+ICt9Cj4+ICsK PiAKPiBXaGVyZSBkbyB3ZSB1c2UgdGhlc2UgPyBJIGNvdWxkbid0IGZpbmQgYW55IHVzZXJzLgoK QWZ0ZXIgZGlyZWN0bHkgY29uZmlndXJpbmcgdGhlIFRSQkUgc3RhdGUgdmlhIFtzZXR8Y2xlYXJd X3RyYmVfc3RhdGUoKQpmdW5jdGlvbnMsIHRoZXNlIHRyaWcvZmlsbCBtb2RlIHJlbGF0ZWQgaGVs cGVycyBhcmUgbm90IHVzZWQgYW55IG1vcmUuCkhlbmNlIHdpbGwganVzdCBkcm9wIHRoZXNlLgoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJt LWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3Jn Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtl cm5lbAo=