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=-5.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE, SPF_PASS,USER_AGENT_SANE_1 autolearn=no 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 4C914C4167B for ; Fri, 4 Dec 2020 09:39:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E697722838 for ; Fri, 4 Dec 2020 09:39:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729615AbgLDJjo (ORCPT ); Fri, 4 Dec 2020 04:39:44 -0500 Received: from mout.kundenserver.de ([212.227.17.13]:41131 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727518AbgLDJjo (ORCPT ); Fri, 4 Dec 2020 04:39:44 -0500 Received: from [192.168.1.155] ([95.114.158.118]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MTigN-1kbbwT2HDJ-00U5aG; Fri, 04 Dec 2020 10:36:56 +0100 Subject: Re: [PATCH v2 2/2] drivers: gpio: add virtio-gpio guest driver To: Jason Wang , linux-kernel@vger.kernel.org Cc: corbet@lwn.net, linus.walleij@linaro.org, bgolaszewski@baylibre.com, mst@redhat.com, linux-doc@vger.kernel.org, linux-gpio@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-riscv@lists.infradead.org References: <20201203191135.21576-1-info@metux.net> <20201203191135.21576-2-info@metux.net> <8209ce55-a4aa-f256-b9b9-f7eb3cac877b@redhat.com> From: "Enrico Weigelt, metux IT consult" Message-ID: <43f1ee89-89f3-95a3-58f1-7a0a12c2b92f@metux.net> Date: Fri, 4 Dec 2020 10:36:53 +0100 User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0 MIME-Version: 1.0 In-Reply-To: <8209ce55-a4aa-f256-b9b9-f7eb3cac877b@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Language: tl Content-Transfer-Encoding: 8bit X-Provags-ID: V03:K1:mOFd+JW7LQb94sy2J5a6Zrm6GQyrCzOe1foidRfS2Sdq5ZJFDNr c9yXWiDh78oST49XU5yOT2hkWmi+sHBEeoCthMcDLadIjN7f33OyR95JbbbWC81VZvkKsJ2 CyEL1bcP6HGIcQKMdx+26NZtYVdXg7Tmeoc3QjBu3oN58zjc3+CyfltBuq0Ay50wvkv6a5l qfTjbCjDluCwMRQUxcNqg== X-UI-Out-Filterresults: notjunk:1;V03:K0:qtpKIGiM1QU=:9HXPFi4Z0pQrtpSEQjPRtZ JtGyl92IC0eeKKCWknd9gvTWDpN+lXZQKRBaJ+lBRKjFApBrEvqRmswQ1aAhRYb2w+eejfugo eC7B3VI6W6sRYKGQQMrDDzkH6ZXjoirbr+q28PGbRyY+bzodAnvWs1EGx2M/aqG69gdvjLTRX 6IMYsUTKWhk4usvsgW11YbdKH1e/y31rqbdHNMpVFr4Ti4gWYsVgEegiUoLuYuKdqdU+TkU5n x5yzzR3+5yAODcNZy9zjHJBRGxLg8AxpAcX69/elxA+GjkIbMvPMeytzQDiMEocj2QpfQVGMq 86j47f6GvwRDPf/me9+9BhZfqUTplqzJ5Sc4MFXJirhwcP2QgerCKlvMiwJgq9yetG/xUIeIW u8O9OjFfy3L6ZFMNe2TJMvNljme/73qPxwpWAKQ9DrqGX7uqhJ/PC2MDHpPGO Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org On 04.12.20 04:35, Jason Wang wrote: Hi, > Is the plan to keep this doc synced with the one in the virtio > specification? Yes, of course. I'm still in progress of doing the beaurocratic stuff w/ virtio-tc folks (ID registration, ...) - yet have to see whether they wanna add it to their spec documents ... BTW: if you feel, sometings not good w/ the current spec, please raise your voice now. > I think it's better to use u8 ot uint8_t here.Git grep told me the > former is more popular under Documentation/. thx, I'll fix that >> +- for version field currently only value 1 supported. >> +- the line names block holds a stream of zero-terminated strings, >> +  holding the individual line names. > > I'm not sure but does this mean we don't have a fixed length of config > space? Need to check whether it can bring any trouble to > migration(compatibility). Yes, it depends on how many gpio lines are present and how much space their names take up. A fixed size would either put unpleasent limits on the max number of lines or waste a lot space when only few lines present. Not that virtio-gpio is also meant for small embedded workloads running under some hypervisor. >> +- unspecified fields are reserved for future use and should be zero. >> + >> +------------------------ >> +Virtqueues and messages: >> +------------------------ >> + >> +- Queue #0: transmission from host to guest >> +- Queue #1: transmission from guest to host > > > Virtio became more a popular in the area without virtualization. So I > think it's better to use "device/driver" instead of "host/guest" here. Good point. But I'd prefer "cpu" instead of "driver" in that case. > Not a native speaker but event sounds like something driver read from > device. Looking at the below lists, most of them except for > VIRTIO_GPIO_EV_HOST_LEVEL looks more like a command. okay, shall I name it "message" ? > Another question is, what's the benefit of unifying the message format > of the two queues. E.g VIRTIO_GPIO_EV_HOST_LEVEL can only works fro rxq. Simplicity. Those fields that aren't really relevant (eg. replies also carry the line id), can just be ignored. > Not familiar with GPIO but I wonder the value of a standalone > VIRTIO_GPIO_EV_GUEST_DIRECTION_INPUT/OUTPUT. Can we simply imply them in > SET/GET_VALUE? Would introduce more complexity. Somewhere I'd have to fit in some extra bit for differenciating between line state and line direction. The direction tells whether the line currently acts as input or output. The "value" (hmm, maybe I should rethink terminology here) is the current line level (high/low or active/inactive). >> +---------------------- >> +Data flow: >> +---------------------- >> + >> +- all operations, except ``VIRTIO_GPIO_EV_HOST_LEVEL``, are >> guest-initiated >> +- host replies ``VIRTIO_GPIO_EV_HOST_LEVEL`` OR'ed to the ``type`` field >> +- ``VIRTIO_GPIO_EV_HOST_LEVEL`` is only sent asynchronically from >> host to guest >> +- in replies, a negative ``value`` field denotes an unix-style errno >> code > > > Virtio is in a different scope, so we need to define the error code on > our own. > > E.g for virtio-net we define: > > > #define VIRTIO_NET_OK     0 > #define VIRTIO_NET_ERR    1 hmm, so I'd need to define all the error codes that possibly could happen ? >>   +config GPIO_VIRTIO >> +    tristate "VirtIO GPIO support" >> +    depends on VIRTIO > > > Let's use select, since there's no prompt for VIRTIO and it doesn't have > any dependencies. Ok. I just was under the impression that subsystems and busses should not be select'ed, but depends on (eg. some time ago tried that w/ gpio subsys and failed). >> +    help >> +      Say Y here to enable guest support for virtio-based GPIOs. >> + >> +      These virtual GPIOs can be routed to real GPIOs or attached to >> +      simulators on the host (qemu). > > > It's better to avoid talking host and qemu here for new virtio devices. Ok, dropped that line. >> +static int virtio_gpio_xmit(struct virtio_gpio_priv *priv, int type, >> +                int pin, int value, struct virtio_gpio_event *ev) >> +{ >> +    struct scatterlist sg[1]; >> +    int ret; >> +    unsigned long flags; >> + >> +    WARN_ON(!ev); >> + >> +    ev->type = type; >> +    ev->pin = pin; >> +    ev->value = value; >> + >> +    sg_init_table(sg, 1); >> +    sg_set_buf(&sg[0], ev, sizeof(struct virtio_gpio_event)); >> + >> +    spin_lock_irqsave(&priv->vq_lock, flags); >> +    ret = virtqueue_add_outbuf(priv->vq_tx, sg, ARRAY_SIZE(sg), >> +                   priv, GFP_KERNEL); >> +    if (ret < 0) { >> +        dev_err(&priv->vdev->dev, >> +            "virtqueue_add_outbuf() failed: %d\n", ret); >> +        goto out; > > > So except for the error log, the failure is silently ignored by the > caller. Is this intended? ups, I've forgotten the error handling in the caller. fixed in v3. >> +static int virtio_gpio_req(struct virtio_gpio_priv *priv, int type, >> +               int pin, int value) >> +{ >> +    struct virtio_gpio_event *ev >> +        = kzalloc(&priv->vdev->dev, sizeof(struct virtio_gpio_event), >> +              GFP_KERNEL); >> + >> +    if (!ev) >> +        return -ENOMEM; >> + >> +    clear_event(priv, type); >> +    virtio_gpio_xmit(priv, type, pin, value, ev); >> +    wait_event_interruptible(priv->waitq, check_event(priv, type)); > > > If I read the code correctly, this expects there will be at most a > single type of event that can be processed at the same time. E.g can > upper layer want to read from different lines in parallel? If yes, we > need to deal with that. @Linus @Bartosz: can that happen or does gpio subsys already serialize requests ? Initially, I tried to protect it by spinlock (so, only one request may run at a time, other calls just wait until the first is finished), but it crashed when gpio cdev registration calls into the driver (fetches the status) while still in bootup. Don't recall the exact error anymore, but something like an inconsistency in the spinlock calls. Did I just use the wrong type of lock ? >> +static void virtio_gpio_data_rx(struct virtqueue *vq) >> +{ >> +    struct virtio_gpio_priv *priv = vq->vdev->priv; >> +    void *data; >> +    unsigned int len; >> +    struct virtio_gpio_event *ev; >> + >> +    data = virtqueue_get_buf(priv->vq_rx, &len); >> +    if (!data || !len) { >> +        dev_warn(&vq->vdev->dev, "RX received no data ! %d\n", len); >> +        return; >> +    } >> + >> +    ev = data; >> +    WARN_ON(data != &priv->rcv_buf); >> + >> +    memcpy(&priv->last, &priv->rcv_buf, sizeof(struct >> virtio_gpio_event)); >> + >> +    switch (ev->type) { >> +    case VIRTIO_GPIO_EV_HOST_LEVEL: >> +        virtio_gpio_signal(priv, ev->type, ev->pin, ev->value); >> +        break; >> +    default: >> +        wakeup_event(priv, ev->type & ~VIRTIO_GPIO_EV_REPLY); > > > This looks suspicious, it looks to me what is done here is, consider we > want to do VIRTIO_GPIO_EV_GUEST_SET_VALUE > > 1) put the event in txq, wait > 2) the result is returned from rxq, wakeup > > It looks to me this is racy since the device should be able to process a > batch of descriptors and there's no guarantee that the descriptor is > processed in order from the virtio level. Not sure whether we're on the same page, but: VIRTIO_GPIO_EV_HOST_LEVEL is kinda interrupt - it tells cpu when the input has changed level. We can receive this async event, it shouldn't matter whether somebody else (another thread) is doing a regular call, thus waiting for reply at the same time. The reply will be next in queue. What could go wrong here ? > I wonder why not introduce two virtqueues: > > 1) command vq > 2) event vq > > All commands were sent via command vq and then device can write back to > the command buffer as other virtio device did. Then there's no worries > of batching or out of order completion. I've been under the impression that queues only work in only one direction. (at least that's what my web research was telling). Could you please give an example how bi-directional transmission within the same queue could look like ? >> +        break; >> +    } >> +    virtio_gpio_prepare_inbuf(priv); > > > This assumes at most one event could be generated, is this how GPIO > device expect to behave? I think level could change several times. Should I add more buffers ? Maybe add one new buffer per request and one new per received async signal ? >> +static int virtio_gpio_probe(struct virtio_device *vdev) >> +{ >> +    struct virtio_gpio_priv *priv; >> +    struct virtio_gpio_config cf = {}; >> +    char *name_buffer; >> +    const char **gpio_names = NULL; >> +    struct device *dev = &vdev->dev; >> + >> +    priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); >> +    if (!priv) >> +        return -ENOMEM; > > > Is devres guaranteed to be enabled here? How should it not ? Could virtio probing so early that even devm isn't working yet ? --mtx -- --- Hinweis: unverschlüsselte E-Mails können leicht abgehört und manipuliert werden ! Für eine vertrauliche Kommunikation senden Sie bitte ihren GPG/PGP-Schlüssel zu. --- Enrico Weigelt, metux IT consult Free software and Linux embedded engineering info@metux.net -- +49-151-27565287 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=-6.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=no 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 EE0D1C4361A for ; Fri, 4 Dec 2020 09:37:22 +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 610D0225AC for ; Fri, 4 Dec 2020 09:37:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 610D0225AC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=metux.net Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-riscv-bounces+linux-riscv=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=8yd4p/UsnuicJowd3SEgW8Kbg25eXhmUbAHzWqrhe0M=; b=vE7e5DlNabsHJiUcsgkTaNeur 8/C7uXSWWOPZf2U1FndmhIrVdd0QnuO5d7zj8tBbNuwbAr8TYFOtkqwQZWrhE5HoQu++u9vPezNK2 fXUGPCypfspYS4Sa6D4fZBOTNv2Zfp0XwbE6ByisYC0CMjftkIVq5yzsmJE8UmeHfdF7s2AWY9Bq3 jrxBrQUM/XuCDCl2Q8bFUZBC93f25inT5r92fa1BxKGcobitGfVF7Q7BymyWxTLv7caaTp89Xgobz Pjyg8TdnPT6zf44cRo0+epq9mcwhvocB4V+kPb7XOzIrrUNcaI4KhqfwyNuYLDSweQz1BiAKuWEcx 10U3RLYNQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kl7WZ-0007Kk-UL; Fri, 04 Dec 2020 09:37:12 +0000 Received: from mout.kundenserver.de ([212.227.17.13]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kl7WW-0007K1-Pz for linux-riscv@lists.infradead.org; Fri, 04 Dec 2020 09:37:10 +0000 Received: from [192.168.1.155] ([95.114.158.118]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MTigN-1kbbwT2HDJ-00U5aG; Fri, 04 Dec 2020 10:36:56 +0100 Subject: Re: [PATCH v2 2/2] drivers: gpio: add virtio-gpio guest driver To: Jason Wang , linux-kernel@vger.kernel.org References: <20201203191135.21576-1-info@metux.net> <20201203191135.21576-2-info@metux.net> <8209ce55-a4aa-f256-b9b9-f7eb3cac877b@redhat.com> From: "Enrico Weigelt, metux IT consult" Message-ID: <43f1ee89-89f3-95a3-58f1-7a0a12c2b92f@metux.net> Date: Fri, 4 Dec 2020 10:36:53 +0100 User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0 MIME-Version: 1.0 In-Reply-To: <8209ce55-a4aa-f256-b9b9-f7eb3cac877b@redhat.com> Content-Language: tl X-Provags-ID: V03:K1:mOFd+JW7LQb94sy2J5a6Zrm6GQyrCzOe1foidRfS2Sdq5ZJFDNr c9yXWiDh78oST49XU5yOT2hkWmi+sHBEeoCthMcDLadIjN7f33OyR95JbbbWC81VZvkKsJ2 CyEL1bcP6HGIcQKMdx+26NZtYVdXg7Tmeoc3QjBu3oN58zjc3+CyfltBuq0Ay50wvkv6a5l qfTjbCjDluCwMRQUxcNqg== X-UI-Out-Filterresults: notjunk:1;V03:K0:qtpKIGiM1QU=:9HXPFi4Z0pQrtpSEQjPRtZ JtGyl92IC0eeKKCWknd9gvTWDpN+lXZQKRBaJ+lBRKjFApBrEvqRmswQ1aAhRYb2w+eejfugo eC7B3VI6W6sRYKGQQMrDDzkH6ZXjoirbr+q28PGbRyY+bzodAnvWs1EGx2M/aqG69gdvjLTRX 6IMYsUTKWhk4usvsgW11YbdKH1e/y31rqbdHNMpVFr4Ti4gWYsVgEegiUoLuYuKdqdU+TkU5n x5yzzR3+5yAODcNZy9zjHJBRGxLg8AxpAcX69/elxA+GjkIbMvPMeytzQDiMEocj2QpfQVGMq 86j47f6GvwRDPf/me9+9BhZfqUTplqzJ5Sc4MFXJirhwcP2QgerCKlvMiwJgq9yetG/xUIeIW u8O9OjFfy3L6ZFMNe2TJMvNljme/73qPxwpWAKQ9DrqGX7uqhJ/PC2MDHpPGO X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201204_043709_079167_803DB1D8 X-CRM114-Status: GOOD ( 46.19 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: corbet@lwn.net, mst@redhat.com, linus.walleij@linaro.org, linux-doc@vger.kernel.org, virtualization@lists.linux-foundation.org, bgolaszewski@baylibre.com, linux-gpio@vger.kernel.org, linux-riscv@lists.infradead.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org T24gMDQuMTIuMjAgMDQ6MzUsIEphc29uIFdhbmcgd3JvdGU6CgpIaSwKCj4gSXMgdGhlIHBsYW4g dG8ga2VlcCB0aGlzIGRvYyBzeW5jZWQgd2l0aCB0aGUgb25lIGluIHRoZSB2aXJ0aW8KPiBzcGVj aWZpY2F0aW9uPwoKWWVzLCBvZiBjb3Vyc2UuIEknbSBzdGlsbCBpbiBwcm9ncmVzcyBvZiBkb2lu ZyB0aGUgYmVhdXJvY3JhdGljIHN0dWZmIHcvCnZpcnRpby10YyBmb2xrcyAoSUQgcmVnaXN0cmF0 aW9uLCAuLi4pIC0geWV0IGhhdmUgdG8gc2VlIHdoZXRoZXIgdGhleQp3YW5uYSBhZGQgaXQgdG8g dGhlaXIgc3BlYyBkb2N1bWVudHMgLi4uCgpCVFc6IGlmIHlvdSBmZWVsLCBzb21ldGluZ3Mgbm90 IGdvb2Qgdy8gdGhlIGN1cnJlbnQgc3BlYywgcGxlYXNlIHJhaXNlCnlvdXIgdm9pY2Ugbm93LgoK PiBJIHRoaW5rIGl0J3MgYmV0dGVyIHRvIHVzZSB1OCBvdCB1aW50OF90IGhlcmUuR2l0IGdyZXAg dG9sZCBtZSB0aGUKPiBmb3JtZXIgaXMgbW9yZSBwb3B1bGFyIHVuZGVyIERvY3VtZW50YXRpb24v LgoKdGh4LCBJJ2xsIGZpeCB0aGF0Cgo+PiArLSBmb3IgdmVyc2lvbiBmaWVsZCBjdXJyZW50bHkg b25seSB2YWx1ZSAxIHN1cHBvcnRlZC4KPj4gKy0gdGhlIGxpbmUgbmFtZXMgYmxvY2sgaG9sZHMg YSBzdHJlYW0gb2YgemVyby10ZXJtaW5hdGVkIHN0cmluZ3MsCj4+ICvCoCBob2xkaW5nIHRoZSBp bmRpdmlkdWFsIGxpbmUgbmFtZXMuCj4gCj4gSSdtIG5vdCBzdXJlIGJ1dCBkb2VzIHRoaXMgbWVh biB3ZSBkb24ndCBoYXZlIGEgZml4ZWQgbGVuZ3RoIG9mIGNvbmZpZwo+IHNwYWNlPyBOZWVkIHRv IGNoZWNrIHdoZXRoZXIgaXQgY2FuIGJyaW5nIGFueSB0cm91YmxlIHRvCj4gbWlncmF0aW9uKGNv bXBhdGliaWxpdHkpLgoKWWVzLCBpdCBkZXBlbmRzIG9uIGhvdyBtYW55IGdwaW8gbGluZXMgYXJl IHByZXNlbnQgYW5kIGhvdyBtdWNoIHNwYWNlCnRoZWlyIG5hbWVzIHRha2UgdXAuCgpBIGZpeGVk IHNpemUgd291bGQgZWl0aGVyIHB1dCB1bnBsZWFzZW50IGxpbWl0cyBvbiB0aGUgbWF4IG51bWJl ciBvZgpsaW5lcyBvciB3YXN0ZSBhIGxvdCBzcGFjZSB3aGVuIG9ubHkgZmV3IGxpbmVzIHByZXNl bnQuCgpOb3QgdGhhdCB2aXJ0aW8tZ3BpbyBpcyBhbHNvIG1lYW50IGZvciBzbWFsbCBlbWJlZGRl ZCB3b3JrbG9hZHMgcnVubmluZwp1bmRlciBzb21lIGh5cGVydmlzb3IuCgo+PiArLSB1bnNwZWNp ZmllZCBmaWVsZHMgYXJlIHJlc2VydmVkIGZvciBmdXR1cmUgdXNlIGFuZCBzaG91bGQgYmUgemVy by4KPj4gKwo+PiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4+ICtWaXJ0cXVldWVzIGFuZCBt ZXNzYWdlczoKPj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+PiArCj4+ICstIFF1ZXVlICMw OiB0cmFuc21pc3Npb24gZnJvbSBob3N0IHRvIGd1ZXN0Cj4+ICstIFF1ZXVlICMxOiB0cmFuc21p c3Npb24gZnJvbSBndWVzdCB0byBob3N0Cj4gCj4gCj4gVmlydGlvIGJlY2FtZSBtb3JlIGEgcG9w dWxhciBpbiB0aGUgYXJlYSB3aXRob3V0IHZpcnR1YWxpemF0aW9uLiBTbyBJCj4gdGhpbmsgaXQn cyBiZXR0ZXIgdG8gdXNlICJkZXZpY2UvZHJpdmVyIiBpbnN0ZWFkIG9mICJob3N0L2d1ZXN0IiBo ZXJlLgoKR29vZCBwb2ludC4gQnV0IEknZCBwcmVmZXIgImNwdSIgaW5zdGVhZCBvZiAiZHJpdmVy IiBpbiB0aGF0IGNhc2UuCgo+IE5vdCBhIG5hdGl2ZSBzcGVha2VyIGJ1dCBldmVudCBzb3VuZHMg bGlrZSBzb21ldGhpbmcgZHJpdmVyIHJlYWQgZnJvbQo+IGRldmljZS4gTG9va2luZyBhdCB0aGUg YmVsb3cgbGlzdHMsIG1vc3Qgb2YgdGhlbSBleGNlcHQgZm9yCj4gVklSVElPX0dQSU9fRVZfSE9T VF9MRVZFTCBsb29rcyBtb3JlIGxpa2UgYSBjb21tYW5kLgoKb2theSwgc2hhbGwgSSBuYW1lIGl0 ICJtZXNzYWdlIiA/Cgo+IEFub3RoZXIgcXVlc3Rpb24gaXMsIHdoYXQncyB0aGUgYmVuZWZpdCBv ZiB1bmlmeWluZyB0aGUgbWVzc2FnZSBmb3JtYXQKPiBvZiB0aGUgdHdvIHF1ZXVlcy4gRS5nIFZJ UlRJT19HUElPX0VWX0hPU1RfTEVWRUwgY2FuIG9ubHkgd29ya3MgZnJvIHJ4cS4KClNpbXBsaWNp dHkuIFRob3NlIGZpZWxkcyB0aGF0IGFyZW4ndCByZWFsbHkgcmVsZXZhbnQgKGVnLiByZXBsaWVz IGFsc28KY2FycnkgdGhlIGxpbmUgaWQpLCBjYW4ganVzdCBiZSBpZ25vcmVkLgoKPiBOb3QgZmFt aWxpYXIgd2l0aCBHUElPIGJ1dCBJIHdvbmRlciB0aGUgdmFsdWUgb2YgYSBzdGFuZGFsb25lCj4g VklSVElPX0dQSU9fRVZfR1VFU1RfRElSRUNUSU9OX0lOUFVUL09VVFBVVC4gQ2FuIHdlIHNpbXBs eSBpbXBseSB0aGVtIGluCj4gU0VUL0dFVF9WQUxVRT8KCldvdWxkIGludHJvZHVjZSBtb3JlIGNv bXBsZXhpdHkuIFNvbWV3aGVyZSBJJ2QgaGF2ZSB0byBmaXQgaW4gc29tZSBleHRyYQpiaXQgZm9y IGRpZmZlcmVuY2lhdGluZyBiZXR3ZWVuIGxpbmUgc3RhdGUgYW5kIGxpbmUgZGlyZWN0aW9uLiBU aGUKZGlyZWN0aW9uIHRlbGxzIHdoZXRoZXIgdGhlIGxpbmUgY3VycmVudGx5IGFjdHMgYXMgaW5w dXQgb3Igb3V0cHV0LiBUaGUKInZhbHVlIiAoaG1tLCBtYXliZSBJIHNob3VsZCByZXRoaW5rIHRl cm1pbm9sb2d5IGhlcmUpIGlzIHRoZSBjdXJyZW50CmxpbmUgbGV2ZWwgKGhpZ2gvbG93IG9yIGFj dGl2ZS9pbmFjdGl2ZSkuCgo+PiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+PiArRGF0YSBmbG93 Ogo+PiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+PiArCj4+ICstIGFsbCBvcGVyYXRpb25zLCBl eGNlcHQgYGBWSVJUSU9fR1BJT19FVl9IT1NUX0xFVkVMYGAsIGFyZQo+PiBndWVzdC1pbml0aWF0 ZWQKPj4gKy0gaG9zdCByZXBsaWVzIGBgVklSVElPX0dQSU9fRVZfSE9TVF9MRVZFTGBgIE9SJ2Vk IHRvIHRoZSBgYHR5cGVgYCBmaWVsZAo+PiArLSBgYFZJUlRJT19HUElPX0VWX0hPU1RfTEVWRUxg YCBpcyBvbmx5IHNlbnQgYXN5bmNocm9uaWNhbGx5IGZyb20KPj4gaG9zdCB0byBndWVzdAo+PiAr LSBpbiByZXBsaWVzLCBhIG5lZ2F0aXZlIGBgdmFsdWVgYCBmaWVsZCBkZW5vdGVzIGFuIHVuaXgt c3R5bGUgZXJybm8KPj4gY29kZQo+IAo+IAo+IFZpcnRpbyBpcyBpbiBhIGRpZmZlcmVudCBzY29w ZSwgc28gd2UgbmVlZCB0byBkZWZpbmUgdGhlIGVycm9yIGNvZGUgb24KPiBvdXIgb3duLgo+IAo+ IEUuZyBmb3IgdmlydGlvLW5ldCB3ZSBkZWZpbmU6Cj4gCj4gCj4gI2RlZmluZSBWSVJUSU9fTkVU X09LwqDCoMKgwqAgMAo+ICNkZWZpbmUgVklSVElPX05FVF9FUlLCoMKgwqAgMQoKaG1tLCBzbyBJ J2QgbmVlZCB0byBkZWZpbmUgYWxsIHRoZSBlcnJvciBjb2RlcyB0aGF0IHBvc3NpYmx5IGNvdWxk IGhhcHBlbiA/Cgo+PiDCoCArY29uZmlnIEdQSU9fVklSVElPCj4+ICvCoMKgwqAgdHJpc3RhdGUg IlZpcnRJTyBHUElPIHN1cHBvcnQiCj4+ICvCoMKgwqAgZGVwZW5kcyBvbiBWSVJUSU8KPiAKPiAK PiBMZXQncyB1c2Ugc2VsZWN0LCBzaW5jZSB0aGVyZSdzIG5vIHByb21wdCBmb3IgVklSVElPIGFu ZCBpdCBkb2Vzbid0IGhhdmUKPiBhbnkgZGVwZW5kZW5jaWVzLgoKT2suIEkganVzdCB3YXMgdW5k ZXIgdGhlIGltcHJlc3Npb24gdGhhdCBzdWJzeXN0ZW1zIGFuZCBidXNzZXMgc2hvdWxkCm5vdCBi ZSBzZWxlY3QnZWQsIGJ1dCBkZXBlbmRzIG9uIChlZy4gc29tZSB0aW1lIGFnbyB0cmllZCB0aGF0 IHcvIGdwaW8Kc3Vic3lzIGFuZCBmYWlsZWQpLgoKPj4gK8KgwqDCoCBoZWxwCj4+ICvCoMKgwqDC oMKgIFNheSBZIGhlcmUgdG8gZW5hYmxlIGd1ZXN0IHN1cHBvcnQgZm9yIHZpcnRpby1iYXNlZCBH UElPcy4KPj4gKwo+PiArwqDCoMKgwqDCoCBUaGVzZSB2aXJ0dWFsIEdQSU9zIGNhbiBiZSByb3V0 ZWQgdG8gcmVhbCBHUElPcyBvciBhdHRhY2hlZCB0bwo+PiArwqDCoMKgwqDCoCBzaW11bGF0b3Jz IG9uIHRoZSBob3N0IChxZW11KS4KPiAKPiAKPiBJdCdzIGJldHRlciB0byBhdm9pZCB0YWxraW5n IGhvc3QgYW5kIHFlbXUgaGVyZSBmb3IgbmV3IHZpcnRpbyBkZXZpY2VzLgoKT2ssIGRyb3BwZWQg dGhhdCBsaW5lLgoKPj4gK3N0YXRpYyBpbnQgdmlydGlvX2dwaW9feG1pdChzdHJ1Y3QgdmlydGlv X2dwaW9fcHJpdiAqcHJpdiwgaW50IHR5cGUsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqAgaW50IHBpbiwgaW50IHZhbHVlLCBzdHJ1Y3QgdmlydGlvX2dwaW9fZXZlbnQgKmV2KQo+ PiArewo+PiArwqDCoMKgIHN0cnVjdCBzY2F0dGVybGlzdCBzZ1sxXTsKPj4gK8KgwqDCoCBpbnQg cmV0Owo+PiArwqDCoMKgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4+ICsKPj4gK8KgwqDCoCBXQVJO X09OKCFldik7Cj4+ICsKPj4gK8KgwqDCoCBldi0+dHlwZSA9IHR5cGU7Cj4+ICvCoMKgwqAgZXYt PnBpbiA9IHBpbjsKPj4gK8KgwqDCoCBldi0+dmFsdWUgPSB2YWx1ZTsKPj4gKwo+PiArwqDCoMKg IHNnX2luaXRfdGFibGUoc2csIDEpOwo+PiArwqDCoMKgIHNnX3NldF9idWYoJnNnWzBdLCBldiwg c2l6ZW9mKHN0cnVjdCB2aXJ0aW9fZ3Bpb19ldmVudCkpOwo+PiArCj4+ICvCoMKgwqAgc3Bpbl9s b2NrX2lycXNhdmUoJnByaXYtPnZxX2xvY2ssIGZsYWdzKTsKPj4gK8KgwqDCoCByZXQgPSB2aXJ0 cXVldWVfYWRkX291dGJ1Zihwcml2LT52cV90eCwgc2csIEFSUkFZX1NJWkUoc2cpLAo+PiArwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHByaXYsIEdGUF9LRVJORUwpOwo+PiAr wqDCoMKgIGlmIChyZXQgPCAwKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfZXJyKCZwcml2LT52 ZGV2LT5kZXYsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgICJ2aXJ0cXVldWVfYWRkX291dGJ1 ZigpIGZhaWxlZDogJWRcbiIsIHJldCk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIG91dDsKPiAK PiAKPiBTbyBleGNlcHQgZm9yIHRoZSBlcnJvciBsb2csIHRoZSBmYWlsdXJlIGlzIHNpbGVudGx5 IGlnbm9yZWQgYnkgdGhlCj4gY2FsbGVyLiBJcyB0aGlzIGludGVuZGVkPwoKdXBzLCBJJ3ZlIGZv cmdvdHRlbiB0aGUgZXJyb3IgaGFuZGxpbmcgaW4gdGhlIGNhbGxlci4gZml4ZWQgaW4gdjMuCgo+ PiArc3RhdGljIGludCB2aXJ0aW9fZ3Bpb19yZXEoc3RydWN0IHZpcnRpb19ncGlvX3ByaXYgKnBy aXYsIGludCB0eXBlLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpbnQgcGluLCBp bnQgdmFsdWUpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IHZpcnRpb19ncGlvX2V2ZW50ICpldgo+ PiArwqDCoMKgwqDCoMKgwqAgPSBremFsbG9jKCZwcml2LT52ZGV2LT5kZXYsIHNpemVvZihzdHJ1 Y3QgdmlydGlvX2dwaW9fZXZlbnQpLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgR0ZQ X0tFUk5FTCk7Cj4+ICsKPj4gK8KgwqDCoCBpZiAoIWV2KQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0 dXJuIC1FTk9NRU07Cj4+ICsKPj4gK8KgwqDCoCBjbGVhcl9ldmVudChwcml2LCB0eXBlKTsKPj4g K8KgwqDCoCB2aXJ0aW9fZ3Bpb194bWl0KHByaXYsIHR5cGUsIHBpbiwgdmFsdWUsIGV2KTsKPj4g K8KgwqDCoCB3YWl0X2V2ZW50X2ludGVycnVwdGlibGUocHJpdi0+d2FpdHEsIGNoZWNrX2V2ZW50 KHByaXYsIHR5cGUpKTsKPiAKPiAKPiBJZiBJIHJlYWQgdGhlIGNvZGUgY29ycmVjdGx5LCB0aGlz IGV4cGVjdHMgdGhlcmUgd2lsbCBiZSBhdCBtb3N0IGEKPiBzaW5nbGUgdHlwZSBvZiBldmVudCB0 aGF0IGNhbiBiZSBwcm9jZXNzZWQgYXQgdGhlIHNhbWUgdGltZS4gRS5nIGNhbgo+IHVwcGVyIGxh eWVyIHdhbnQgdG8gcmVhZCBmcm9tIGRpZmZlcmVudCBsaW5lcyBpbiBwYXJhbGxlbD8gSWYgeWVz LCB3ZQo+IG5lZWQgdG8gZGVhbCB3aXRoIHRoYXQuCgpATGludXMgQEJhcnRvc3o6IGNhbiB0aGF0 IGhhcHBlbiBvciBkb2VzIGdwaW8gc3Vic3lzIGFscmVhZHkgc2VyaWFsaXplCnJlcXVlc3RzID8K CkluaXRpYWxseSwgSSB0cmllZCB0byBwcm90ZWN0IGl0IGJ5IHNwaW5sb2NrIChzbywgb25seSBv bmUgcmVxdWVzdCBtYXkKcnVuIGF0IGEgdGltZSwgb3RoZXIgY2FsbHMganVzdCB3YWl0IHVudGls IHRoZSBmaXJzdCBpcyBmaW5pc2hlZCksIGJ1dAppdCBjcmFzaGVkIHdoZW4gZ3BpbyBjZGV2IHJl Z2lzdHJhdGlvbiBjYWxscyBpbnRvIHRoZSBkcml2ZXIgKGZldGNoZXMKdGhlIHN0YXR1cykgd2hp bGUgc3RpbGwgaW4gYm9vdHVwLgoKRG9uJ3QgcmVjYWxsIHRoZSBleGFjdCBlcnJvciBhbnltb3Jl LCBidXQgc29tZXRoaW5nIGxpa2UgYW4KaW5jb25zaXN0ZW5jeSBpbiB0aGUgc3BpbmxvY2sgY2Fs bHMuCgpEaWQgSSBqdXN0IHVzZSB0aGUgd3JvbmcgdHlwZSBvZiBsb2NrID8KCj4+ICtzdGF0aWMg dm9pZCB2aXJ0aW9fZ3Bpb19kYXRhX3J4KHN0cnVjdCB2aXJ0cXVldWUgKnZxKQo+PiArewo+PiAr wqDCoMKgIHN0cnVjdCB2aXJ0aW9fZ3Bpb19wcml2ICpwcml2ID0gdnEtPnZkZXYtPnByaXY7Cj4+ ICvCoMKgwqAgdm9pZCAqZGF0YTsKPj4gK8KgwqDCoCB1bnNpZ25lZCBpbnQgbGVuOwo+PiArwqDC oMKgIHN0cnVjdCB2aXJ0aW9fZ3Bpb19ldmVudCAqZXY7Cj4+ICsKPj4gK8KgwqDCoCBkYXRhID0g dmlydHF1ZXVlX2dldF9idWYocHJpdi0+dnFfcngsICZsZW4pOwo+PiArwqDCoMKgIGlmICghZGF0 YSB8fCAhbGVuKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfd2FybigmdnEtPnZkZXYtPmRldiwg IlJYIHJlY2VpdmVkIG5vIGRhdGEgISAlZFxuIiwgbGVuKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHJl dHVybjsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4gK8KgwqDCoCBldiA9IGRhdGE7Cj4+ICvCoMKgwqAg V0FSTl9PTihkYXRhICE9ICZwcml2LT5yY3ZfYnVmKTsKPj4gKwo+PiArwqDCoMKgIG1lbWNweSgm cHJpdi0+bGFzdCwgJnByaXYtPnJjdl9idWYsIHNpemVvZihzdHJ1Y3QKPj4gdmlydGlvX2dwaW9f ZXZlbnQpKTsKPj4gKwo+PiArwqDCoMKgIHN3aXRjaCAoZXYtPnR5cGUpIHsKPj4gK8KgwqDCoCBj YXNlIFZJUlRJT19HUElPX0VWX0hPU1RfTEVWRUw6Cj4+ICvCoMKgwqDCoMKgwqDCoCB2aXJ0aW9f Z3Bpb19zaWduYWwocHJpdiwgZXYtPnR5cGUsIGV2LT5waW4sIGV2LT52YWx1ZSk7Cj4+ICvCoMKg wqDCoMKgwqDCoCBicmVhazsKPj4gK8KgwqDCoCBkZWZhdWx0Ogo+PiArwqDCoMKgwqDCoMKgwqAg d2FrZXVwX2V2ZW50KHByaXYsIGV2LT50eXBlICYgflZJUlRJT19HUElPX0VWX1JFUExZKTsKPiAK PiAKPiBUaGlzIGxvb2tzIHN1c3BpY2lvdXMsIGl0IGxvb2tzIHRvIG1lIHdoYXQgaXMgZG9uZSBo ZXJlIGlzLCBjb25zaWRlciB3ZQo+IHdhbnQgdG8gZG8gVklSVElPX0dQSU9fRVZfR1VFU1RfU0VU X1ZBTFVFCj4gCj4gMSkgcHV0IHRoZSBldmVudCBpbiB0eHEsIHdhaXQKPiAyKSB0aGUgcmVzdWx0 IGlzIHJldHVybmVkIGZyb20gcnhxLCB3YWtldXAKPiAKPiBJdCBsb29rcyB0byBtZSB0aGlzIGlz IHJhY3kgc2luY2UgdGhlIGRldmljZSBzaG91bGQgYmUgYWJsZSB0byBwcm9jZXNzIGEKPiBiYXRj aCBvZiBkZXNjcmlwdG9ycyBhbmQgdGhlcmUncyBubyBndWFyYW50ZWUgdGhhdCB0aGUgZGVzY3Jp cHRvciBpcwo+IHByb2Nlc3NlZCBpbiBvcmRlciBmcm9tIHRoZSB2aXJ0aW8gbGV2ZWwuCgpOb3Qg c3VyZSB3aGV0aGVyIHdlJ3JlIG9uIHRoZSBzYW1lIHBhZ2UsIGJ1dDoKClZJUlRJT19HUElPX0VW X0hPU1RfTEVWRUwgaXMga2luZGEgaW50ZXJydXB0IC0gaXQgdGVsbHMgY3B1IHdoZW4gdGhlCmlu cHV0IGhhcyBjaGFuZ2VkIGxldmVsLiBXZSBjYW4gcmVjZWl2ZSB0aGlzIGFzeW5jIGV2ZW50LCBp dCBzaG91bGRuJ3QKbWF0dGVyIHdoZXRoZXIgc29tZWJvZHkgZWxzZSAoYW5vdGhlciB0aHJlYWQp IGlzIGRvaW5nIGEgcmVndWxhciBjYWxsLAp0aHVzIHdhaXRpbmcgZm9yIHJlcGx5IGF0IHRoZSBz YW1lIHRpbWUuIFRoZSByZXBseSB3aWxsIGJlIG5leHQgaW4KcXVldWUuCgpXaGF0IGNvdWxkIGdv IHdyb25nIGhlcmUgPwoKCj4gSSB3b25kZXIgd2h5IG5vdCBpbnRyb2R1Y2UgdHdvIHZpcnRxdWV1 ZXM6Cj4gCj4gMSkgY29tbWFuZCB2cQo+IDIpIGV2ZW50IHZxCj4gCj4gQWxsIGNvbW1hbmRzIHdl cmUgc2VudCB2aWEgY29tbWFuZCB2cSBhbmQgdGhlbiBkZXZpY2UgY2FuIHdyaXRlIGJhY2sgdG8K PiB0aGUgY29tbWFuZCBidWZmZXIgYXMgb3RoZXIgdmlydGlvIGRldmljZSBkaWQuIFRoZW4gdGhl cmUncyBubyB3b3JyaWVzCj4gb2YgYmF0Y2hpbmcgb3Igb3V0IG9mIG9yZGVyIGNvbXBsZXRpb24u CgpJJ3ZlIGJlZW4gdW5kZXIgdGhlIGltcHJlc3Npb24gdGhhdCBxdWV1ZXMgb25seSB3b3JrIGlu IG9ubHkgb25lCmRpcmVjdGlvbi4gKGF0IGxlYXN0IHRoYXQncyB3aGF0IG15IHdlYiByZXNlYXJj aCB3YXMgdGVsbGluZykuCgpDb3VsZCB5b3UgcGxlYXNlIGdpdmUgYW4gZXhhbXBsZSBob3cgYmkt ZGlyZWN0aW9uYWwgdHJhbnNtaXNzaW9uIHdpdGhpbgp0aGUgc2FtZSBxdWV1ZSBjb3VsZCBsb29r IGxpa2UgPwoKPj4gK8KgwqDCoMKgwqDCoMKgIGJyZWFrOwo+PiArwqDCoMKgIH0KPj4gK8KgwqDC oCB2aXJ0aW9fZ3Bpb19wcmVwYXJlX2luYnVmKHByaXYpOwo+IAo+IAo+IFRoaXMgYXNzdW1lcyBh dCBtb3N0IG9uZSBldmVudCBjb3VsZCBiZSBnZW5lcmF0ZWQsIGlzIHRoaXMgaG93IEdQSU8KPiBk ZXZpY2UgZXhwZWN0IHRvIGJlaGF2ZT8gSSB0aGluayBsZXZlbCBjb3VsZCBjaGFuZ2Ugc2V2ZXJh bCB0aW1lcy4KClNob3VsZCBJIGFkZCBtb3JlIGJ1ZmZlcnMgPwoKTWF5YmUgYWRkIG9uZSBuZXcg YnVmZmVyIHBlciByZXF1ZXN0IGFuZCBvbmUgbmV3IHBlciByZWNlaXZlZCBhc3luYwpzaWduYWwg PwoKPj4gK3N0YXRpYyBpbnQgdmlydGlvX2dwaW9fcHJvYmUoc3RydWN0IHZpcnRpb19kZXZpY2Ug KnZkZXYpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IHZpcnRpb19ncGlvX3ByaXYgKnByaXY7Cj4+ ICvCoMKgwqAgc3RydWN0IHZpcnRpb19ncGlvX2NvbmZpZyBjZiA9IHt9Owo+PiArwqDCoMKgIGNo YXIgKm5hbWVfYnVmZmVyOwo+PiArwqDCoMKgIGNvbnN0IGNoYXIgKipncGlvX25hbWVzID0gTlVM TDsKPj4gK8KgwqDCoCBzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmdmRldi0+ZGV2Owo+PiArCj4+ICvC oMKgwqAgcHJpdiA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcHJpdiksIEdGUF9LRVJORUwp Owo+PiArwqDCoMKgIGlmICghcHJpdikKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRU5PTUVN Owo+IAo+IAo+IElzIGRldnJlcyBndWFyYW50ZWVkIHRvIGJlIGVuYWJsZWQgaGVyZT8KCkhvdyBz aG91bGQgaXQgbm90ID8gQ291bGQgdmlydGlvIHByb2Jpbmcgc28gZWFybHkgdGhhdCBldmVuIGRl dm0KaXNuJ3Qgd29ya2luZyB5ZXQgPwoKCi0tbXR4CgotLSAKLS0tCkhpbndlaXM6IHVudmVyc2No bMO8c3NlbHRlIEUtTWFpbHMga8O2bm5lbiBsZWljaHQgYWJnZWjDtnJ0IHVuZCBtYW5pcHVsaWVy dAp3ZXJkZW4gISBGw7xyIGVpbmUgdmVydHJhdWxpY2hlIEtvbW11bmlrYXRpb24gc2VuZGVuIFNp ZSBiaXR0ZSBpaHJlbgpHUEcvUEdQLVNjaGzDvHNzZWwgenUuCi0tLQpFbnJpY28gV2VpZ2VsdCwg bWV0dXggSVQgY29uc3VsdApGcmVlIHNvZnR3YXJlIGFuZCBMaW51eCBlbWJlZGRlZCBlbmdpbmVl cmluZwppbmZvQG1ldHV4Lm5ldCAtLSArNDktMTUxLTI3NTY1Mjg3CgpfX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1yaXNjdiBtYWlsaW5nIGxpc3QK bGludXgtcmlzY3ZAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9y Zy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LXJpc2N2Cg==