From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5542C64EC7 for ; Wed, 22 Feb 2023 23:18:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231737AbjBVXS4 (ORCPT ); Wed, 22 Feb 2023 18:18:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232110AbjBVXSw (ORCPT ); Wed, 22 Feb 2023 18:18:52 -0500 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF7CD1B314; Wed, 22 Feb 2023 15:18:49 -0800 (PST) Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 31MN2PxC032018; Wed, 22 Feb 2023 23:18:34 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=message-id : date : mime-version : subject : to : cc : references : from : in-reply-to : content-type : content-transfer-encoding; s=qcppdkim1; bh=kLp6Y2SwLfvdNEEx+KlRLVuK23xsbKShI7drVCOpPjI=; b=KeVcOukVog1gQWIjT6mo5/eAqjncIqPognZua9aNyC1dt3P+6ZmmwDvQSET1gGoOqlBv 4HfvL9qy3dp1aPv0LoH9XJwodaEBhNILs/mQCDwg+pH45zwdQVbPjWXh0NvJVgDjk7J8 iKe1QvaTzkm2qW43MI14NYqU4963JRj889SO3jySoIR5CdjyUsoWB3bgMXN0uqF8IGd3 IztXcDoNIWe6aZ2j/1f1cGaAvhTe4SmqRrSixmprC8loLCYK817LCrcJhqds6LiCBYvC xkxIHwax8eWOeW5SmDhGOyR1floA7p25Fu1pxibhYn8l/04CF5OP2fJNlph7vG0RC8eF tA== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nwn389778-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 Feb 2023 23:18:34 +0000 Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 31MNIXHa007425 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 Feb 2023 23:18:33 GMT Received: from [10.134.67.48] (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Wed, 22 Feb 2023 15:18:33 -0800 Message-ID: <94ebe2f0-0baf-21c0-45d5-c5bc4df9ad94@quicinc.com> Date: Wed, 22 Feb 2023 15:18:32 -0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Subject: Re: [PATCH v10 08/26] gunyah: rsc_mgr: Add resource manager RPC core Content-Language: en-US To: Srinivas Kandagatla , Alex Elder , Prakruthi Deepak Heragu CC: Murali Nalajala , Trilok Soni , Srivatsa Vaddagiri , Carl van Schaik , Dmitry Baryshkov , Bjorn Andersson , "Konrad Dybcio" , Arnd Bergmann , "Greg Kroah-Hartman" , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet , Bagas Sanjaya , Catalin Marinas , Jassi Brar , , , , , References: <20230214211229.3239350-1-quic_eberman@quicinc.com> <20230214212327.3310128-1-quic_eberman@quicinc.com> From: Elliot Berman In-Reply-To: Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: epDXlmXZriZeLsP3EnT4PS9K2nrF5jdU X-Proofpoint-ORIG-GUID: epDXlmXZriZeLsP3EnT4PS9K2nrF5jdU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.170.22 definitions=2023-02-22_10,2023-02-22_02,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 clxscore=1015 malwarescore=0 bulkscore=0 phishscore=0 spamscore=0 priorityscore=1501 mlxlogscore=999 adultscore=0 suspectscore=0 lowpriorityscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2302220201 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org On 2/20/2023 10:10 AM, Srinivas Kandagatla wrote: > > > On 14/02/2023 21:23, Elliot Berman wrote: >> >> The resource manager is a special virtual machine which is always >> running on a Gunyah system. It provides APIs for creating and destroying >> VMs, secure memory management, sharing/lending of memory between VMs, >> and setup of inter-VM communication. Calls to the resource manager are >> made via message queues. >> >> This patch implements the basic probing and RPC mechanism to make those >> API calls. Request/response calls can be made with gh_rm_call. >> Drivers can also register to notifications pushed by RM via >> gh_rm_register_notifier >> >> Specific API calls that resource manager supports will be implemented in >> subsequent patches. >> >> Signed-off-by: Elliot Berman >> --- >>   drivers/virt/gunyah/Makefile   |   3 + >>   drivers/virt/gunyah/rsc_mgr.c  | 604 +++++++++++++++++++++++++++++++++ >>   drivers/virt/gunyah/rsc_mgr.h  |  77 +++++ >>   include/linux/gunyah_rsc_mgr.h |  24 ++ >>   4 files changed, 708 insertions(+) >>   create mode 100644 drivers/virt/gunyah/rsc_mgr.c >>   create mode 100644 drivers/virt/gunyah/rsc_mgr.h >>   create mode 100644 include/linux/gunyah_rsc_mgr.h >> >> diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile >> index 34f32110faf9..cc864ff5abbb 100644 >> --- a/drivers/virt/gunyah/Makefile >> +++ b/drivers/virt/gunyah/Makefile >> @@ -1,3 +1,6 @@ >>   # SPDX-License-Identifier: GPL-2.0 >>   obj-$(CONFIG_GUNYAH) += gunyah.o >> + >> +gunyah_rsc_mgr-y += rsc_mgr.o >> +obj-$(CONFIG_GUNYAH) += gunyah_rsc_mgr.o >> diff --git a/drivers/virt/gunyah/rsc_mgr.c >> b/drivers/virt/gunyah/rsc_mgr.c >> new file mode 100644 >> index 000000000000..2a47139873a8 >> --- /dev/null >> +++ b/drivers/virt/gunyah/rsc_mgr.c >> @@ -0,0 +1,604 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All >> rights reserved. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include > why do we need this? > >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "rsc_mgr.h" >> + > > ... > >> +struct gh_rm { >> +    struct device *dev; >> +    struct gunyah_resource tx_ghrsc, rx_ghrsc; >> +    struct gh_msgq msgq; >> +    struct mbox_client msgq_client; >> +    struct gh_rm_connection *active_rx_connection; >> +    int last_tx_ret; >> + > >> +    struct idr call_idr; >> +    struct mutex call_idr_lock; > > IDR interface is deprecated you should use Xarrays instead here, > > Other good thing about Xarrays is that you need not worry about locking > it uses RCU and internal spinlock, that should simiply code a bit here. > > more info at > Documentation/core-api/xarray.rst > Done. >> + >> +    struct kmem_cache *cache; >> +    struct mutex send_lock; >> +    struct blocking_notifier_head nh; >> +}; >> + >> +static struct gh_rm_connection *gh_rm_alloc_connection(__le32 msg_id, >> u8 type) >> +{ >> +    struct gh_rm_connection *connection; >> + >> +    connection = kzalloc(sizeof(*connection), GFP_KERNEL); >> +    if (!connection) >> +        return ERR_PTR(-ENOMEM); >> + >> +    connection->type = type; >> +    connection->msg_id = msg_id; >> + >> +    return connection; >> +} >> + >> +static int gh_rm_init_connection_payload(struct gh_rm_connection >> *connection, void *msg, >> +                    size_t hdr_size, size_t msg_size) >> +{ >> +    size_t max_buf_size, payload_size; >> +    struct gh_rm_rpc_hdr *hdr = msg; >> + >> +    if (hdr_size > msg_size) >> +        return -EINVAL; >> + >> +    payload_size = msg_size - hdr_size; >> + >> +    connection->num_fragments = FIELD_GET(RM_RPC_FRAGMENTS_MASK, >> hdr->type); >> +    connection->fragments_received = 0; >> + >> +    /* There's not going to be any payload, no need to allocate >> buffer. */ >> +    if (!payload_size && !connection->num_fragments) >> +        return 0; >> + >> +    if (connection->num_fragments > GH_RM_MAX_NUM_FRAGMENTS) >> +        return -EINVAL; >> + >> +    max_buf_size = payload_size + (connection->num_fragments * >> GH_RM_MAX_MSG_SIZE); >> + >> +    connection->payload = kzalloc(max_buf_size, GFP_KERNEL); >> +    if (!connection->payload) >> +        return -ENOMEM; >> + >> +    memcpy(connection->payload, msg + hdr_size, payload_size); >> +    connection->size = payload_size; >> +    return 0; >> +} >> + >> +static void gh_rm_notif_work(struct work_struct *work) >> +{ >> +    struct gh_rm_connection *connection = container_of(work, struct >> gh_rm_connection, >> +                                notification.work); >> +    struct gh_rm *rm = connection->notification.rm; >> + >> +    blocking_notifier_call_chain(&rm->nh, connection->msg_id, >> connection->payload); >> + >> +    put_gh_rm(rm); >> +    kfree(connection->payload); > if (connection->size) >     kfree(connection->payload); > > should we check for payload size before freeing this, Normally kfree > NULL should be safe, unless connection object is allocated uninitialized. > connection object is kzalloc'd, so it's always allocated initialized. >> +    kfree(connection); >> +} >> + >> +static struct gh_rm_connection *gh_rm_process_notif(struct gh_rm *rm, >> void *msg, size_t msg_size) >> +{ >> +    struct gh_rm_connection *connection; >> +    struct gh_rm_rpc_hdr *hdr = msg; >> +    int ret; >> + >> +    connection = gh_rm_alloc_connection(hdr->msg_id, RM_RPC_TYPE_NOTIF); >> +    if (IS_ERR(connection)) { >> +        dev_err(rm->dev, "Failed to alloc connection for >> notification: %ld, dropping.\n", >> +            PTR_ERR(connection)); >> +        return NULL; >> +    } >> + >> +    get_gh_rm(rm); >> +    connection->notification.rm = rm; >> +    INIT_WORK(&connection->notification.work, gh_rm_notif_work); >> + >> +    ret = gh_rm_init_connection_payload(connection, msg, >> sizeof(*hdr), msg_size); >> +    if (ret) { >> +        dev_err(rm->dev, "Failed to initialize connection buffer for >> notification: %d\n", >> +            ret); > put_gh_rm(rm); > > is missing. > or move the get and other lines after this check > Done. >> +        kfree(connection); >> +        return NULL; >> +    } >> + >> +    return connection; >> +} >> + > >> +static int gh_rm_send_request(struct gh_rm *rm, u32 message_id, >> +                  const void *req_buff, size_t req_buff_size, >> +                  struct gh_rm_connection *connection) >> +{ >> +    u8 msg_type = FIELD_PREP(RM_RPC_TYPE_MASK, RM_RPC_TYPE_REQUEST); >> +    size_t buff_size_remaining = req_buff_size; >> +    const void *req_buff_curr = req_buff; >> +    struct gh_msgq_tx_data *msg; >> +    struct gh_rm_rpc_hdr *hdr; >> +    u32 cont_fragments = 0; >> +    size_t payload_size; >> +    void *payload; >> +    int ret; >> + >> +    if (req_buff_size) >> +        cont_fragments = (req_buff_size - 1) / GH_RM_MAX_MSG_SIZE; >> + >> +    if (req_buff_size > GH_RM_MAX_NUM_FRAGMENTS * GH_RM_MAX_MSG_SIZE) { >> +        pr_warn("Limit exceeded for the number of fragments: %u\n", >> cont_fragments); >> +        dump_stack(); >> +        return -E2BIG; >> +    } >> + >> +    ret = mutex_lock_interruptible(&rm->send_lock); >> +    if (ret) >> +        return ret; >> + >> +    /* Consider also the 'request' packet for the loop count */ >> +    do { >> +        msg = kmem_cache_zalloc(rm->cache, GFP_KERNEL); >> +        if (!msg) { >> +            ret = -ENOMEM; >> +            goto out; >> +        } >> + >> +        /* Fill header */ >> +        hdr = (struct gh_rm_rpc_hdr *)msg->data; >> +        hdr->api = RM_RPC_API; >> +        hdr->type = msg_type | FIELD_PREP(RM_RPC_FRAGMENTS_MASK, >> cont_fragments); >> +        hdr->seq = cpu_to_le16(connection->reply.seq); >> +        hdr->msg_id = cpu_to_le32(message_id); >> + >> +        /* Copy payload */ >> +        payload = hdr + 1; >> +        payload_size = min(buff_size_remaining, GH_RM_MAX_MSG_SIZE); >> +        memcpy(payload, req_buff_curr, payload_size); >> +        req_buff_curr += payload_size; >> +        buff_size_remaining -= payload_size; >> + >> +        /* Force the last fragment to immediately alert the receiver */ >> +        msg->push = !buff_size_remaining; >> +        msg->length = sizeof(*hdr) + payload_size; >> + >> +        ret = mbox_send_message(gh_msgq_chan(&rm->msgq), msg); >> +        if (ret < 0) { >> +            kmem_cache_free(rm->cache, msg); >> +            break; >> +        } >> + >> +        if (rm->last_tx_ret) { >> +            ret = rm->last_tx_ret; >> +            break; >> +        } >> + >> +        msg_type = FIELD_PREP(RM_RPC_TYPE_MASK, >> RM_RPC_TYPE_CONTINUATION); >> +    } while (buff_size_remaining); >> + >> +out: >> +    mutex_unlock(&rm->send_lock); >> +    return ret < 0 ? ret : 0; >> +} >> + >> +/** >> + * gh_rm_call: Achieve request-response type communication with RPC >> + * @rm: Pointer to Gunyah resource manager internal data >> + * @message_id: The RM RPC message-id >> + * @req_buff: Request buffer that contains the payload >> + * @req_buff_size: Total size of the payload >> + * @resp_buf: Pointer to a response buffer >> + * @resp_buff_size: Size of the response buffer >> + * >> + * Make a request to the RM-VM and wait for reply back. For a successful >> + * response, the function returns the payload. The size of the >> payload is set in >> + * resp_buff_size. The resp_buf should be freed by the caller. >> + * >> + * req_buff should be not NULL for req_buff_size >0. If req_buff_size >> == 0, >> + * req_buff *can* be NULL and no additional payload is sent. >> + * >> + * Context: Process context. Will sleep waiting for reply. >> + * Return: 0 on success. <0 if error. >> + */ >> +int gh_rm_call(struct gh_rm *rm, u32 message_id, void *req_buff, >> size_t req_buff_size, >> +        void **resp_buf, size_t *resp_buff_size) >> +{ >> +    struct gh_rm_connection *connection; >> +    int ret; >> + >> +    /* message_id 0 is reserved. req_buff_size implies req_buf is not >> NULL */ >> +    if (!message_id || (!req_buff && req_buff_size) || !rm) >> +        return -EINVAL; >> + >> +    connection = gh_rm_alloc_connection(cpu_to_le32(message_id), >> RM_RPC_TYPE_REPLY); >> +    if (IS_ERR(connection)) >> +        return PTR_ERR(connection); >> + >> +    init_completion(&connection->reply.seq_done); >> + >> +    /* Allocate a new seq number for this connection */ >> +    mutex_lock(&rm->call_idr_lock); >> +    ret = idr_alloc_cyclic(&rm->call_idr, connection, 0, U16_MAX, >> +                        GFP_KERNEL); >> +    mutex_unlock(&rm->call_idr_lock); >> +    if (ret < 0) >> +        goto out; > > new line. > >> +    connection->reply.seq = ret; >> + >> +    /* Send the request to the Resource Manager */ >> +    ret = gh_rm_send_request(rm, message_id, req_buff, req_buff_size, >> connection); >> +    if (ret < 0) >> +        goto out; >> + >> +    /* Wait for response */ >> +    ret = >> wait_for_completion_interruptible(&connection->reply.seq_done); >> +    if (ret) >> +        goto out; >> + >> +    /* Check for internal (kernel) error waiting for the response */ >> +    if (connection->reply.ret) { >> +        ret = connection->reply.ret; >> +        if (ret != -ENOMEM) >> +            kfree(connection->payload); >> +        goto out; >> +    } >> + >> +    /* Got a response, did resource manager give us an error? */ >> +    if (connection->reply.rm_error != GH_RM_ERROR_OK) { >> +        pr_warn("RM rejected message %08x. Error: %d\n", message_id, >> +            connection->reply.rm_error); >> +        dump_stack(); >> +        ret = gh_rm_remap_error(connection->reply.rm_error); >> +        kfree(connection->payload); >> +        goto out; >> +    } >> + >> +    /* Everything looks good, return the payload */ >> +    *resp_buff_size = connection->size; >> +    if (connection->size) >> +        *resp_buf = connection->payload; >> +    else { >> +        /* kfree in case RM sent us multiple fragments but never any >> data in >> +         * those fragments. We would've allocated memory for it, but >> connection->size == 0 >> +         */ >> +        kfree(connection->payload); >> +    } >> + >> +out: >> +    mutex_lock(&rm->call_idr_lock); >> +    idr_remove(&rm->call_idr, connection->reply.seq); >> +    mutex_unlock(&rm->call_idr_lock); >> +    kfree(connection); >> +    return ret; >> +} >> + >> + >> +int gh_rm_notifier_register(struct gh_rm *rm, struct notifier_block *nb) >> +{ >> +    return blocking_notifier_chain_register(&rm->nh, nb); >> +} >> +EXPORT_SYMBOL_GPL(gh_rm_notifier_register); >> + >> +int gh_rm_notifier_unregister(struct gh_rm *rm, struct notifier_block >> *nb) >> +{ >> +    return blocking_notifier_chain_unregister(&rm->nh, nb); >> +} >> +EXPORT_SYMBOL_GPL(gh_rm_notifier_unregister); >> + >> +void get_gh_rm(struct gh_rm *rm) >> +{ >> +    get_device(rm->dev); >> +} >> +EXPORT_SYMBOL_GPL(get_gh_rm); > > Can we have some consistency in the exported symbol naming, > we have two combinations now. > > EXPORT_SYMBOL_GPL(gh_rm_notifier_register); > EXPORT_SYMBOL_GPL(get_gh_rm); > > lets stick to one. done. >> + >> +void put_gh_rm(struct gh_rm *rm) >> +{ >> +    put_device(rm->dev); >> +} >> +EXPORT_SYMBOL_GPL(put_gh_rm); >> > ... > >> + >> +static int gh_rm_drv_probe(struct platform_device *pdev) >> +{ >> +    struct gh_msgq_tx_data *msg; >> +    struct gh_rm *rm; >> +    int ret; >> + > How are we ensuring that gunyah driver is probed before this driver? > > Which driver? >> +    rm = devm_kzalloc(&pdev->dev, sizeof(*rm), GFP_KERNEL); >> +    if (!rm) >> +        return -ENOMEM; >> + >> +    platform_set_drvdata(pdev, rm); >> +    rm->dev = &pdev->dev; >> + >> +    mutex_init(&rm->call_idr_lock); >> +    idr_init(&rm->call_idr); >> +    rm->cache = kmem_cache_create("gh_rm", struct_size(msg, data, >> GH_MSGQ_MAX_MSG_SIZE), 0, >> +        SLAB_HWCACHE_ALIGN, NULL); >> +    if (!rm->cache) >> +        return -ENOMEM; > new line here would be nice. > done. >> +    mutex_init(&rm->send_lock); >> +    BLOCKING_INIT_NOTIFIER_HEAD(&rm->nh); >> + >> +    ret = gh_msgq_platform_probe_direction(pdev, true, 0, >> &rm->tx_ghrsc); >> +    if (ret) >> +        goto err_cache; >> + >> +    ret = gh_msgq_platform_probe_direction(pdev, false, 1, >> &rm->rx_ghrsc); >> +    if (ret) >> +        goto err_cache; >> + >> +    rm->msgq_client.dev = &pdev->dev; >> +    rm->msgq_client.tx_block = true; >> +    rm->msgq_client.rx_callback = gh_rm_msgq_rx_data; >> +    rm->msgq_client.tx_done = gh_rm_msgq_tx_done; >> + >> +    return gh_msgq_init(&pdev->dev, &rm->msgq, &rm->msgq_client, >> &rm->tx_ghrsc, &rm->rx_ghrsc); >> +err_cache: >> +    kmem_cache_destroy(rm->cache); >> +    return ret; >> +} >> + >> +static int gh_rm_drv_remove(struct platform_device *pdev) >> +{ >> +    struct gh_rm *rm = platform_get_drvdata(pdev); >> + >> +    mbox_free_channel(gh_msgq_chan(&rm->msgq)); >> +    gh_msgq_remove(&rm->msgq); >> +    kmem_cache_destroy(rm->cache); >> + >> +    return 0; >> +} >> + >> +static const struct of_device_id gh_rm_of_match[] = { >> +    { .compatible = "gunyah-resource-manager" }, >> +    {} >> +}; >> +MODULE_DEVICE_TABLE(of, gh_rm_of_match); >> + >> +static struct platform_driver gh_rm_driver = { >> +    .probe = gh_rm_drv_probe, >> +    .remove = gh_rm_drv_remove, >> +    .driver = { >> +        .name = "gh_rsc_mgr", >> +        .of_match_table = gh_rm_of_match, >> +    }, >> +}; >> +module_platform_driver(gh_rm_driver); >> + >> +MODULE_LICENSE("GPL"); >> +MODULE_DESCRIPTION("Gunyah Resource Manager Driver"); >> diff --git a/drivers/virt/gunyah/rsc_mgr.h >> b/drivers/virt/gunyah/rsc_mgr.h >> new file mode 100644 >> index 000000000000..d4e799a7526f >> --- /dev/null >> +++ b/drivers/virt/gunyah/rsc_mgr.h >> @@ -0,0 +1,77 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* >> + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All >> rights reserved. >> + */ >> +#ifndef __GH_RSC_MGR_PRIV_H >> +#define __GH_RSC_MGR_PRIV_H >> + >> +#include >> +#include >> +#include >> + > <------------------ >> +/* RM Error codes */ >> +enum gh_rm_error { >> +    GH_RM_ERROR_OK            = 0x0, >> +    GH_RM_ERROR_UNIMPLEMENTED    = 0xFFFFFFFF, >> +    GH_RM_ERROR_NOMEM        = 0x1, >> +    GH_RM_ERROR_NORESOURCE        = 0x2, >> +    GH_RM_ERROR_DENIED        = 0x3, >> +    GH_RM_ERROR_INVALID        = 0x4, >> +    GH_RM_ERROR_BUSY        = 0x5, >> +    GH_RM_ERROR_ARGUMENT_INVALID    = 0x6, >> +    GH_RM_ERROR_HANDLE_INVALID    = 0x7, >> +    GH_RM_ERROR_VALIDATE_FAILED    = 0x8, >> +    GH_RM_ERROR_MAP_FAILED        = 0x9, >> +    GH_RM_ERROR_MEM_INVALID        = 0xA, >> +    GH_RM_ERROR_MEM_INUSE        = 0xB, >> +    GH_RM_ERROR_MEM_RELEASED    = 0xC, >> +    GH_RM_ERROR_VMID_INVALID    = 0xD, >> +    GH_RM_ERROR_LOOKUP_FAILED    = 0xE, >> +    GH_RM_ERROR_IRQ_INVALID        = 0xF, >> +    GH_RM_ERROR_IRQ_INUSE        = 0x10, >> +    GH_RM_ERROR_IRQ_RELEASED    = 0x11, >> +}; >> + >> +/** >> + * gh_rm_remap_error() - Remap Gunyah resource manager errors into a >> Linux error code >> + * @gh_error: "Standard" return value from Gunyah resource manager >> + */ >> +static inline int gh_rm_remap_error(enum gh_rm_error rm_error) >> +{ >> +    switch (rm_error) { >> +    case GH_RM_ERROR_OK: >> +        return 0; >> +    case GH_RM_ERROR_UNIMPLEMENTED: >> +        return -EOPNOTSUPP; >> +    case GH_RM_ERROR_NOMEM: >> +        return -ENOMEM; >> +    case GH_RM_ERROR_NORESOURCE: >> +        return -ENODEV; >> +    case GH_RM_ERROR_DENIED: >> +        return -EPERM; >> +    case GH_RM_ERROR_BUSY: >> +        return -EBUSY; >> +    case GH_RM_ERROR_INVALID: >> +    case GH_RM_ERROR_ARGUMENT_INVALID: >> +    case GH_RM_ERROR_HANDLE_INVALID: >> +    case GH_RM_ERROR_VALIDATE_FAILED: >> +    case GH_RM_ERROR_MAP_FAILED: >> +    case GH_RM_ERROR_MEM_INVALID: >> +    case GH_RM_ERROR_MEM_INUSE: >> +    case GH_RM_ERROR_MEM_RELEASED: >> +    case GH_RM_ERROR_VMID_INVALID: >> +    case GH_RM_ERROR_LOOKUP_FAILED: >> +    case GH_RM_ERROR_IRQ_INVALID: >> +    case GH_RM_ERROR_IRQ_INUSE: >> +    case GH_RM_ERROR_IRQ_RELEASED: >> +        return -EINVAL; >> +    default: >> +        return -EBADMSG; >> +    } >> +} >> + > ----------------> > > Only user for the error code coversion is within the rm driver, you > should just move this to the .c file, I see no value of this in .h > unless there are some other users for this. > > Done. > >> +struct gh_rm; >> +int gh_rm_call(struct gh_rm *rsc_mgr, u32 message_id, void *req_buff, >> size_t req_buff_size, >> +        void **resp_buf, size_t *resp_buff_size); >> + >> +#endif >> diff --git a/include/linux/gunyah_rsc_mgr.h >> b/include/linux/gunyah_rsc_mgr.h >> new file mode 100644 >> index 000000000000..c992b3188c8d >> --- /dev/null >> +++ b/include/linux/gunyah_rsc_mgr.h >> @@ -0,0 +1,24 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* >> + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All >> rights reserved. >> + */ >> + >> +#ifndef _GUNYAH_RSC_MGR_H >> +#define _GUNYAH_RSC_MGR_H >> + >> +#include >> +#include >> +#include >> + >> +#define GH_VMID_INVAL    U16_MAX >> + >> +/* Gunyah recognizes VMID0 as an alias to the current VM's ID */ >> +#define GH_VMID_SELF            0 >> + >> +struct gh_rm; >> +int gh_rm_notifier_register(struct gh_rm *rm, struct notifier_block >> *nb); >> +int gh_rm_notifier_unregister(struct gh_rm *rm, struct notifier_block >> *nb); >> +void get_gh_rm(struct gh_rm *rm); >> +void put_gh_rm(struct gh_rm *rm); >> + >> +#endif From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B13B7C636D6 for ; Wed, 22 Feb 2023 23:19:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:From:References:CC:To:Subject: MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rWqmbWg31qykcpGjwnrJOuZWSJ1QIjKh51w7iC1B7NY=; b=eqz2J+auUfX1li zbWlvI/ai2muO/NlDbP9g3TFXC624MYGKIyQoJpTJwMdjP5wyWhJrFbXJvJSgzFCkolrlR9QigcSo BXdL8gP62jftEU4PhIzIRjvQznPjxy8D0ZEIWCoepl/zsetyIzFRXldpdLvGtbwhmUzJCZhPpH3F/ MOP/9a27tH5VWSxLvza77fO7p/KcP0Ou7YnFKtvIfL+M/2AYPAwic4nxsywYOurshnqMTrszbY7t8 lD3PDYsFI2uTegNxLM8QSC9QxRE0Qod7pzyGDoun2uwXrOCYR+1skd12a+fVKcjLU++ew7lsvDICt Bod0ji+eyc5ugpxvHPLw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pUyNt-00EPNW-VK; Wed, 22 Feb 2023 23:18:50 +0000 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pUyNp-00EPMC-2A for linux-arm-kernel@lists.infradead.org; Wed, 22 Feb 2023 23:18:48 +0000 Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 31MN2PxC032018; Wed, 22 Feb 2023 23:18:34 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=message-id : date : mime-version : subject : to : cc : references : from : in-reply-to : content-type : content-transfer-encoding; s=qcppdkim1; bh=kLp6Y2SwLfvdNEEx+KlRLVuK23xsbKShI7drVCOpPjI=; b=KeVcOukVog1gQWIjT6mo5/eAqjncIqPognZua9aNyC1dt3P+6ZmmwDvQSET1gGoOqlBv 4HfvL9qy3dp1aPv0LoH9XJwodaEBhNILs/mQCDwg+pH45zwdQVbPjWXh0NvJVgDjk7J8 iKe1QvaTzkm2qW43MI14NYqU4963JRj889SO3jySoIR5CdjyUsoWB3bgMXN0uqF8IGd3 IztXcDoNIWe6aZ2j/1f1cGaAvhTe4SmqRrSixmprC8loLCYK817LCrcJhqds6LiCBYvC xkxIHwax8eWOeW5SmDhGOyR1floA7p25Fu1pxibhYn8l/04CF5OP2fJNlph7vG0RC8eF tA== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nwn389778-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 Feb 2023 23:18:34 +0000 Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 31MNIXHa007425 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 Feb 2023 23:18:33 GMT Received: from [10.134.67.48] (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.41; Wed, 22 Feb 2023 15:18:33 -0800 Message-ID: <94ebe2f0-0baf-21c0-45d5-c5bc4df9ad94@quicinc.com> Date: Wed, 22 Feb 2023 15:18:32 -0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1 Subject: Re: [PATCH v10 08/26] gunyah: rsc_mgr: Add resource manager RPC core Content-Language: en-US To: Srinivas Kandagatla , Alex Elder , Prakruthi Deepak Heragu CC: Murali Nalajala , Trilok Soni , Srivatsa Vaddagiri , Carl van Schaik , Dmitry Baryshkov , Bjorn Andersson , "Konrad Dybcio" , Arnd Bergmann , "Greg Kroah-Hartman" , Rob Herring , Krzysztof Kozlowski , Jonathan Corbet , Bagas Sanjaya , Catalin Marinas , Jassi Brar , , , , , References: <20230214211229.3239350-1-quic_eberman@quicinc.com> <20230214212327.3310128-1-quic_eberman@quicinc.com> From: Elliot Berman In-Reply-To: X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: epDXlmXZriZeLsP3EnT4PS9K2nrF5jdU X-Proofpoint-ORIG-GUID: epDXlmXZriZeLsP3EnT4PS9K2nrF5jdU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.170.22 definitions=2023-02-22_10,2023-02-22_02,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 clxscore=1015 malwarescore=0 bulkscore=0 phishscore=0 spamscore=0 priorityscore=1501 mlxlogscore=999 adultscore=0 suspectscore=0 lowpriorityscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2302220201 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230222_151845_256337_9F5105FA X-CRM114-Status: GOOD ( 38.84 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org CgpPbiAyLzIwLzIwMjMgMTA6MTAgQU0sIFNyaW5pdmFzIEthbmRhZ2F0bGEgd3JvdGU6Cj4gCj4g Cj4gT24gMTQvMDIvMjAyMyAyMToyMywgRWxsaW90IEJlcm1hbiB3cm90ZToKPj4KPj4gVGhlIHJl c291cmNlIG1hbmFnZXIgaXMgYSBzcGVjaWFsIHZpcnR1YWwgbWFjaGluZSB3aGljaCBpcyBhbHdh eXMKPj4gcnVubmluZyBvbiBhIEd1bnlhaCBzeXN0ZW0uIEl0IHByb3ZpZGVzIEFQSXMgZm9yIGNy ZWF0aW5nIGFuZCBkZXN0cm95aW5nCj4+IFZNcywgc2VjdXJlIG1lbW9yeSBtYW5hZ2VtZW50LCBz aGFyaW5nL2xlbmRpbmcgb2YgbWVtb3J5IGJldHdlZW4gVk1zLAo+PiBhbmQgc2V0dXAgb2YgaW50 ZXItVk0gY29tbXVuaWNhdGlvbi4gQ2FsbHMgdG8gdGhlIHJlc291cmNlIG1hbmFnZXIgYXJlCj4+ IG1hZGUgdmlhIG1lc3NhZ2UgcXVldWVzLgo+Pgo+PiBUaGlzIHBhdGNoIGltcGxlbWVudHMgdGhl IGJhc2ljIHByb2JpbmcgYW5kIFJQQyBtZWNoYW5pc20gdG8gbWFrZSB0aG9zZQo+PiBBUEkgY2Fs bHMuIFJlcXVlc3QvcmVzcG9uc2UgY2FsbHMgY2FuIGJlIG1hZGUgd2l0aCBnaF9ybV9jYWxsLgo+ PiBEcml2ZXJzIGNhbiBhbHNvIHJlZ2lzdGVyIHRvIG5vdGlmaWNhdGlvbnMgcHVzaGVkIGJ5IFJN IHZpYQo+PiBnaF9ybV9yZWdpc3Rlcl9ub3RpZmllcgo+Pgo+PiBTcGVjaWZpYyBBUEkgY2FsbHMg dGhhdCByZXNvdXJjZSBtYW5hZ2VyIHN1cHBvcnRzIHdpbGwgYmUgaW1wbGVtZW50ZWQgaW4KPj4g c3Vic2VxdWVudCBwYXRjaGVzLgo+Pgo+PiBTaWduZWQtb2ZmLWJ5OiBFbGxpb3QgQmVybWFuIDxx dWljX2ViZXJtYW5AcXVpY2luYy5jb20+Cj4+IC0tLQo+PiDCoCBkcml2ZXJzL3ZpcnQvZ3VueWFo L01ha2VmaWxlwqDCoCB8wqDCoCAzICsKPj4gwqAgZHJpdmVycy92aXJ0L2d1bnlhaC9yc2NfbWdy LmPCoCB8IDYwNCArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPj4gwqAgZHJpdmVy cy92aXJ0L2d1bnlhaC9yc2NfbWdyLmjCoCB8wqAgNzcgKysrKysKPj4gwqAgaW5jbHVkZS9saW51 eC9ndW55YWhfcnNjX21nci5oIHzCoCAyNCArKwo+PiDCoCA0IGZpbGVzIGNoYW5nZWQsIDcwOCBp bnNlcnRpb25zKCspCj4+IMKgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3ZpcnQvZ3VueWFo L3JzY19tZ3IuYwo+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy92aXJ0L2d1bnlhaC9y c2NfbWdyLmgKPj4gwqAgY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUvbGludXgvZ3VueWFoX3Jz Y19tZ3IuaAo+Pgo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy92aXJ0L2d1bnlhaC9NYWtlZmlsZSBi L2RyaXZlcnMvdmlydC9ndW55YWgvTWFrZWZpbGUKPj4gaW5kZXggMzRmMzIxMTBmYWY5Li5jYzg2 NGZmNWFiYmIgMTAwNjQ0Cj4+IC0tLSBhL2RyaXZlcnMvdmlydC9ndW55YWgvTWFrZWZpbGUKPj4g KysrIGIvZHJpdmVycy92aXJ0L2d1bnlhaC9NYWtlZmlsZQo+PiBAQCAtMSwzICsxLDYgQEAKPj4g wqAgIyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+PiDCoCBvYmotJChDT05GSUdf R1VOWUFIKSArPSBndW55YWgubwo+PiArCj4+ICtndW55YWhfcnNjX21nci15ICs9IHJzY19tZ3Iu bwo+PiArb2JqLSQoQ09ORklHX0dVTllBSCkgKz0gZ3VueWFoX3JzY19tZ3Iubwo+PiBkaWZmIC0t Z2l0IGEvZHJpdmVycy92aXJ0L2d1bnlhaC9yc2NfbWdyLmMgCj4+IGIvZHJpdmVycy92aXJ0L2d1 bnlhaC9yc2NfbWdyLmMKPj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAwMDAwMDAw MDAwLi4yYTQ3MTM5ODczYTgKPj4gLS0tIC9kZXYvbnVsbAo+PiArKysgYi9kcml2ZXJzL3ZpcnQv Z3VueWFoL3JzY19tZ3IuYwo+PiBAQCAtMCwwICsxLDYwNCBAQAo+PiArLy8gU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAtb25seQo+PiArLyoKPj4gKyAqIENvcHlyaWdodCAoYykgMjAy Mi0yMDIzIFF1YWxjb21tIElubm92YXRpb24gQ2VudGVyLCBJbmMuIEFsbCAKPj4gcmlnaHRzIHJl c2VydmVkLgo+PiArICovCj4+ICsKPj4gKyNpbmNsdWRlIDxsaW51eC9vZi5oPgo+PiArI2luY2x1 ZGUgPGxpbnV4L3NsYWIuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPgo+PiArI2luY2x1 ZGUgPGxpbnV4L3NjaGVkLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvZ3VueWFoLmg+Cj4+ICsjaW5j bHVkZSA8bGludXgvbW9kdWxlLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvb2ZfaXJxLmg+Cj4+ICsj aW5jbHVkZSA8bGludXgva3RocmVhZC5oPgo+IHdoeSBkbyB3ZSBuZWVkIHRoaXM/Cj4gCj4+ICsj aW5jbHVkZSA8bGludXgvbm90aWZpZXIuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC93b3JrcXVldWUu aD4KPj4gKyNpbmNsdWRlIDxsaW51eC9jb21wbGV0aW9uLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgv Z3VueWFoX3JzY19tZ3IuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4K Pj4gKwo+PiArI2luY2x1ZGUgInJzY19tZ3IuaCIKPj4gKwo+IAo+IC4uLgo+IAo+PiArc3RydWN0 IGdoX3JtIHsKPj4gK8KgwqDCoCBzdHJ1Y3QgZGV2aWNlICpkZXY7Cj4+ICvCoMKgwqAgc3RydWN0 IGd1bnlhaF9yZXNvdXJjZSB0eF9naHJzYywgcnhfZ2hyc2M7Cj4+ICvCoMKgwqAgc3RydWN0IGdo X21zZ3EgbXNncTsKPj4gK8KgwqDCoCBzdHJ1Y3QgbWJveF9jbGllbnQgbXNncV9jbGllbnQ7Cj4+ ICvCoMKgwqAgc3RydWN0IGdoX3JtX2Nvbm5lY3Rpb24gKmFjdGl2ZV9yeF9jb25uZWN0aW9uOwo+ PiArwqDCoMKgIGludCBsYXN0X3R4X3JldDsKPj4gKwo+IAo+PiArwqDCoMKgIHN0cnVjdCBpZHIg Y2FsbF9pZHI7Cj4+ICvCoMKgwqAgc3RydWN0IG11dGV4IGNhbGxfaWRyX2xvY2s7Cj4gCj4gSURS IGludGVyZmFjZSBpcyBkZXByZWNhdGVkIHlvdSBzaG91bGQgdXNlIFhhcnJheXMgaW5zdGVhZCBo ZXJlLAo+IAo+IE90aGVyIGdvb2QgdGhpbmcgYWJvdXQgWGFycmF5cyBpcyB0aGF0IHlvdSBuZWVk IG5vdCB3b3JyeSBhYm91dCBsb2NraW5nIAo+IGl0IHVzZXMgUkNVIGFuZCBpbnRlcm5hbCBzcGlu bG9jaywgdGhhdCBzaG91bGQgc2ltaXBseSBjb2RlIGEgYml0IGhlcmUuCj4gCj4gbW9yZSBpbmZv IGF0Cj4gRG9jdW1lbnRhdGlvbi9jb3JlLWFwaS94YXJyYXkucnN0Cj4gCgpEb25lLgoKPj4gKwo+ PiArwqDCoMKgIHN0cnVjdCBrbWVtX2NhY2hlICpjYWNoZTsKPj4gK8KgwqDCoCBzdHJ1Y3QgbXV0 ZXggc2VuZF9sb2NrOwo+PiArwqDCoMKgIHN0cnVjdCBibG9ja2luZ19ub3RpZmllcl9oZWFkIG5o Owo+PiArfTsKPj4gKwo+PiArc3RhdGljIHN0cnVjdCBnaF9ybV9jb25uZWN0aW9uICpnaF9ybV9h bGxvY19jb25uZWN0aW9uKF9fbGUzMiBtc2dfaWQsIAo+PiB1OCB0eXBlKQo+PiArewo+PiArwqDC oMKgIHN0cnVjdCBnaF9ybV9jb25uZWN0aW9uICpjb25uZWN0aW9uOwo+PiArCj4+ICvCoMKgwqAg Y29ubmVjdGlvbiA9IGt6YWxsb2Moc2l6ZW9mKCpjb25uZWN0aW9uKSwgR0ZQX0tFUk5FTCk7Cj4+ ICvCoMKgwqAgaWYgKCFjb25uZWN0aW9uKQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIEVSUl9Q VFIoLUVOT01FTSk7Cj4+ICsKPj4gK8KgwqDCoCBjb25uZWN0aW9uLT50eXBlID0gdHlwZTsKPj4g K8KgwqDCoCBjb25uZWN0aW9uLT5tc2dfaWQgPSBtc2dfaWQ7Cj4+ICsKPj4gK8KgwqDCoCByZXR1 cm4gY29ubmVjdGlvbjsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBnaF9ybV9pbml0X2Nvbm5l Y3Rpb25fcGF5bG9hZChzdHJ1Y3QgZ2hfcm1fY29ubmVjdGlvbiAKPj4gKmNvbm5lY3Rpb24sIHZv aWQgKm1zZywKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHNpemVf dCBoZHJfc2l6ZSwgc2l6ZV90IG1zZ19zaXplKQo+PiArewo+PiArwqDCoMKgIHNpemVfdCBtYXhf YnVmX3NpemUsIHBheWxvYWRfc2l6ZTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfcm1fcnBjX2hkciAq aGRyID0gbXNnOwo+PiArCj4+ICvCoMKgwqAgaWYgKGhkcl9zaXplID4gbXNnX3NpemUpCj4+ICvC oMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPj4gKwo+PiArwqDCoMKgIHBheWxvYWRfc2l6 ZSA9IG1zZ19zaXplIC0gaGRyX3NpemU7Cj4+ICsKPj4gK8KgwqDCoCBjb25uZWN0aW9uLT5udW1f ZnJhZ21lbnRzID0gRklFTERfR0VUKFJNX1JQQ19GUkFHTUVOVFNfTUFTSywgCj4+IGhkci0+dHlw ZSk7Cj4+ICvCoMKgwqAgY29ubmVjdGlvbi0+ZnJhZ21lbnRzX3JlY2VpdmVkID0gMDsKPj4gKwo+ PiArwqDCoMKgIC8qIFRoZXJlJ3Mgbm90IGdvaW5nIHRvIGJlIGFueSBwYXlsb2FkLCBubyBuZWVk IHRvIGFsbG9jYXRlIAo+PiBidWZmZXIuICovCj4+ICvCoMKgwqAgaWYgKCFwYXlsb2FkX3NpemUg JiYgIWNvbm5lY3Rpb24tPm51bV9mcmFnbWVudHMpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4g MDsKPj4gKwo+PiArwqDCoMKgIGlmIChjb25uZWN0aW9uLT5udW1fZnJhZ21lbnRzID4gR0hfUk1f TUFYX05VTV9GUkFHTUVOVFMpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPj4g Kwo+PiArwqDCoMKgIG1heF9idWZfc2l6ZSA9IHBheWxvYWRfc2l6ZSArIChjb25uZWN0aW9uLT5u dW1fZnJhZ21lbnRzICogCj4+IEdIX1JNX01BWF9NU0dfU0laRSk7Cj4+ICsKPj4gK8KgwqDCoCBj b25uZWN0aW9uLT5wYXlsb2FkID0ga3phbGxvYyhtYXhfYnVmX3NpemUsIEdGUF9LRVJORUwpOwo+ PiArwqDCoMKgIGlmICghY29ubmVjdGlvbi0+cGF5bG9hZCkKPj4gK8KgwqDCoMKgwqDCoMKgIHJl dHVybiAtRU5PTUVNOwo+PiArCj4+ICvCoMKgwqAgbWVtY3B5KGNvbm5lY3Rpb24tPnBheWxvYWQs IG1zZyArIGhkcl9zaXplLCBwYXlsb2FkX3NpemUpOwo+PiArwqDCoMKgIGNvbm5lY3Rpb24tPnNp emUgPSBwYXlsb2FkX3NpemU7Cj4+ICvCoMKgwqAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0 YXRpYyB2b2lkIGdoX3JtX25vdGlmX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQo+PiAr ewo+PiArwqDCoMKgIHN0cnVjdCBnaF9ybV9jb25uZWN0aW9uICpjb25uZWN0aW9uID0gY29udGFp bmVyX29mKHdvcmssIHN0cnVjdCAKPj4gZ2hfcm1fY29ubmVjdGlvbiwKPj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG5vdGlm aWNhdGlvbi53b3JrKTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfcm0gKnJtID0gY29ubmVjdGlvbi0+ bm90aWZpY2F0aW9uLnJtOwo+PiArCj4+ICvCoMKgwqAgYmxvY2tpbmdfbm90aWZpZXJfY2FsbF9j aGFpbigmcm0tPm5oLCBjb25uZWN0aW9uLT5tc2dfaWQsIAo+PiBjb25uZWN0aW9uLT5wYXlsb2Fk KTsKPj4gKwo+PiArwqDCoMKgIHB1dF9naF9ybShybSk7Cj4+ICvCoMKgwqAga2ZyZWUoY29ubmVj dGlvbi0+cGF5bG9hZCk7Cj4gaWYgKGNvbm5lY3Rpb24tPnNpemUpCj4gIMKgwqDCoMKga2ZyZWUo Y29ubmVjdGlvbi0+cGF5bG9hZCk7Cj4gCj4gc2hvdWxkIHdlIGNoZWNrIGZvciBwYXlsb2FkIHNp emUgYmVmb3JlIGZyZWVpbmcgdGhpcywgTm9ybWFsbHkga2ZyZWUgCj4gTlVMTCBzaG91bGQgYmUg c2FmZSwgdW5sZXNzIGNvbm5lY3Rpb24gb2JqZWN0IGlzIGFsbG9jYXRlZCB1bmluaXRpYWxpemVk Lgo+IAoKY29ubmVjdGlvbiBvYmplY3QgaXMga3phbGxvYydkLCBzbyBpdCdzIGFsd2F5cyBhbGxv Y2F0ZWQgaW5pdGlhbGl6ZWQuCgo+PiArwqDCoMKgIGtmcmVlKGNvbm5lY3Rpb24pOwo+PiArfQo+ PiArCj4+ICtzdGF0aWMgc3RydWN0IGdoX3JtX2Nvbm5lY3Rpb24gKmdoX3JtX3Byb2Nlc3Nfbm90 aWYoc3RydWN0IGdoX3JtICpybSwgCj4+IHZvaWQgKm1zZywgc2l6ZV90IG1zZ19zaXplKQo+PiAr ewo+PiArwqDCoMKgIHN0cnVjdCBnaF9ybV9jb25uZWN0aW9uICpjb25uZWN0aW9uOwo+PiArwqDC oMKgIHN0cnVjdCBnaF9ybV9ycGNfaGRyICpoZHIgPSBtc2c7Cj4+ICvCoMKgwqAgaW50IHJldDsK Pj4gKwo+PiArwqDCoMKgIGNvbm5lY3Rpb24gPSBnaF9ybV9hbGxvY19jb25uZWN0aW9uKGhkci0+ bXNnX2lkLCBSTV9SUENfVFlQRV9OT1RJRik7Cj4+ICvCoMKgwqAgaWYgKElTX0VSUihjb25uZWN0 aW9uKSkgewo+PiArwqDCoMKgwqDCoMKgwqAgZGV2X2VycihybS0+ZGV2LCAiRmFpbGVkIHRvIGFs bG9jIGNvbm5lY3Rpb24gZm9yIAo+PiBub3RpZmljYXRpb246ICVsZCwgZHJvcHBpbmcuXG4iLAo+ PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBQVFJfRVJSKGNvbm5lY3Rpb24pKTsKPj4gK8KgwqDC oMKgwqDCoMKgIHJldHVybiBOVUxMOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGdldF9n aF9ybShybSk7Cj4+ICvCoMKgwqAgY29ubmVjdGlvbi0+bm90aWZpY2F0aW9uLnJtID0gcm07Cj4+ ICvCoMKgwqAgSU5JVF9XT1JLKCZjb25uZWN0aW9uLT5ub3RpZmljYXRpb24ud29yaywgZ2hfcm1f bm90aWZfd29yayk7Cj4+ICsKPj4gK8KgwqDCoCByZXQgPSBnaF9ybV9pbml0X2Nvbm5lY3Rpb25f cGF5bG9hZChjb25uZWN0aW9uLCBtc2csIAo+PiBzaXplb2YoKmhkciksIG1zZ19zaXplKTsKPj4g K8KgwqDCoCBpZiAocmV0KSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfZXJyKHJtLT5kZXYsICJG YWlsZWQgdG8gaW5pdGlhbGl6ZSBjb25uZWN0aW9uIGJ1ZmZlciBmb3IgCj4+IG5vdGlmaWNhdGlv bjogJWRcbiIsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHJldCk7Cj4gcHV0X2doX3JtKHJt KTsKPiAKPiBpcyBtaXNzaW5nLgo+IG9yIG1vdmUgdGhlIGdldCBhbmQgb3RoZXIgbGluZXMgYWZ0 ZXIgdGhpcyBjaGVjawo+IAoKRG9uZS4KCj4+ICvCoMKgwqDCoMKgwqDCoCBrZnJlZShjb25uZWN0 aW9uKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiBOVUxMOwo+PiArwqDCoMKgIH0KPj4gKwo+ PiArwqDCoMKgIHJldHVybiBjb25uZWN0aW9uOwo+PiArfQo+PiArCj4gCj4+ICtzdGF0aWMgaW50 IGdoX3JtX3NlbmRfcmVxdWVzdChzdHJ1Y3QgZ2hfcm0gKnJtLCB1MzIgbWVzc2FnZV9pZCwKPj4g K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgY29uc3Qgdm9pZCAqcmVxX2J1ZmYs IHNpemVfdCByZXFfYnVmZl9zaXplLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCBzdHJ1Y3QgZ2hfcm1fY29ubmVjdGlvbiAqY29ubmVjdGlvbikKPj4gK3sKPj4gK8KgwqDC oCB1OCBtc2dfdHlwZSA9IEZJRUxEX1BSRVAoUk1fUlBDX1RZUEVfTUFTSywgUk1fUlBDX1RZUEVf UkVRVUVTVCk7Cj4+ICvCoMKgwqAgc2l6ZV90IGJ1ZmZfc2l6ZV9yZW1haW5pbmcgPSByZXFfYnVm Zl9zaXplOwo+PiArwqDCoMKgIGNvbnN0IHZvaWQgKnJlcV9idWZmX2N1cnIgPSByZXFfYnVmZjsK Pj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfbXNncV90eF9kYXRhICptc2c7Cj4+ICvCoMKgwqAgc3RydWN0 IGdoX3JtX3JwY19oZHIgKmhkcjsKPj4gK8KgwqDCoCB1MzIgY29udF9mcmFnbWVudHMgPSAwOwo+ PiArwqDCoMKgIHNpemVfdCBwYXlsb2FkX3NpemU7Cj4+ICvCoMKgwqAgdm9pZCAqcGF5bG9hZDsK Pj4gK8KgwqDCoCBpbnQgcmV0Owo+PiArCj4+ICvCoMKgwqAgaWYgKHJlcV9idWZmX3NpemUpCj4+ ICvCoMKgwqDCoMKgwqDCoCBjb250X2ZyYWdtZW50cyA9IChyZXFfYnVmZl9zaXplIC0gMSkgLyBH SF9STV9NQVhfTVNHX1NJWkU7Cj4+ICsKPj4gK8KgwqDCoCBpZiAocmVxX2J1ZmZfc2l6ZSA+IEdI X1JNX01BWF9OVU1fRlJBR01FTlRTICogR0hfUk1fTUFYX01TR19TSVpFKSB7Cj4+ICvCoMKgwqDC oMKgwqDCoCBwcl93YXJuKCJMaW1pdCBleGNlZWRlZCBmb3IgdGhlIG51bWJlciBvZiBmcmFnbWVu dHM6ICV1XG4iLCAKPj4gY29udF9mcmFnbWVudHMpOwo+PiArwqDCoMKgwqDCoMKgwqAgZHVtcF9z dGFjaygpOwo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FMkJJRzsKPj4gK8KgwqDCoCB9Cj4+ ICsKPj4gK8KgwqDCoCByZXQgPSBtdXRleF9sb2NrX2ludGVycnVwdGlibGUoJnJtLT5zZW5kX2xv Y2spOwo+PiArwqDCoMKgIGlmIChyZXQpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gcmV0Owo+ PiArCj4+ICvCoMKgwqAgLyogQ29uc2lkZXIgYWxzbyB0aGUgJ3JlcXVlc3QnIHBhY2tldCBmb3Ig dGhlIGxvb3AgY291bnQgKi8KPj4gK8KgwqDCoCBkbyB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBtc2cg PSBrbWVtX2NhY2hlX3phbGxvYyhybS0+Y2FjaGUsIEdGUF9LRVJORUwpOwo+PiArwqDCoMKgwqDC oMKgwqAgaWYgKCFtc2cpIHsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcmV0ID0gLUVOT01F TTsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZ290byBvdXQ7Cj4+ICvCoMKgwqDCoMKgwqDC oCB9Cj4+ICsKPj4gK8KgwqDCoMKgwqDCoMKgIC8qIEZpbGwgaGVhZGVyICovCj4+ICvCoMKgwqDC oMKgwqDCoCBoZHIgPSAoc3RydWN0IGdoX3JtX3JwY19oZHIgKiltc2ctPmRhdGE7Cj4+ICvCoMKg wqDCoMKgwqDCoCBoZHItPmFwaSA9IFJNX1JQQ19BUEk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBoZHIt PnR5cGUgPSBtc2dfdHlwZSB8IEZJRUxEX1BSRVAoUk1fUlBDX0ZSQUdNRU5UU19NQVNLLCAKPj4g Y29udF9mcmFnbWVudHMpOwo+PiArwqDCoMKgwqDCoMKgwqAgaGRyLT5zZXEgPSBjcHVfdG9fbGUx Nihjb25uZWN0aW9uLT5yZXBseS5zZXEpOwo+PiArwqDCoMKgwqDCoMKgwqAgaGRyLT5tc2dfaWQg PSBjcHVfdG9fbGUzMihtZXNzYWdlX2lkKTsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgLyogQ29w eSBwYXlsb2FkICovCj4+ICvCoMKgwqDCoMKgwqDCoCBwYXlsb2FkID0gaGRyICsgMTsKPj4gK8Kg wqDCoMKgwqDCoMKgIHBheWxvYWRfc2l6ZSA9IG1pbihidWZmX3NpemVfcmVtYWluaW5nLCBHSF9S TV9NQVhfTVNHX1NJWkUpOwo+PiArwqDCoMKgwqDCoMKgwqAgbWVtY3B5KHBheWxvYWQsIHJlcV9i dWZmX2N1cnIsIHBheWxvYWRfc2l6ZSk7Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXFfYnVmZl9jdXJy ICs9IHBheWxvYWRfc2l6ZTsKPj4gK8KgwqDCoMKgwqDCoMKgIGJ1ZmZfc2l6ZV9yZW1haW5pbmcg LT0gcGF5bG9hZF9zaXplOwo+PiArCj4+ICvCoMKgwqDCoMKgwqDCoCAvKiBGb3JjZSB0aGUgbGFz dCBmcmFnbWVudCB0byBpbW1lZGlhdGVseSBhbGVydCB0aGUgcmVjZWl2ZXIgKi8KPj4gK8KgwqDC oMKgwqDCoMKgIG1zZy0+cHVzaCA9ICFidWZmX3NpemVfcmVtYWluaW5nOwo+PiArwqDCoMKgwqDC oMKgwqAgbXNnLT5sZW5ndGggPSBzaXplb2YoKmhkcikgKyBwYXlsb2FkX3NpemU7Cj4+ICsKPj4g K8KgwqDCoMKgwqDCoMKgIHJldCA9IG1ib3hfc2VuZF9tZXNzYWdlKGdoX21zZ3FfY2hhbigmcm0t Pm1zZ3EpLCBtc2cpOwo+PiArwqDCoMKgwqDCoMKgwqAgaWYgKHJldCA8IDApIHsKPj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAga21lbV9jYWNoZV9mcmVlKHJtLT5jYWNoZSwgbXNnKTsKPj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgYnJlYWs7Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+ICsKPj4g K8KgwqDCoMKgwqDCoMKgIGlmIChybS0+bGFzdF90eF9yZXQpIHsKPj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqAgcmV0ID0gcm0tPmxhc3RfdHhfcmV0Owo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCBicmVhazsKPj4gK8KgwqDCoMKgwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgbXNn X3R5cGUgPSBGSUVMRF9QUkVQKFJNX1JQQ19UWVBFX01BU0ssIAo+PiBSTV9SUENfVFlQRV9DT05U SU5VQVRJT04pOwo+PiArwqDCoMKgIH0gd2hpbGUgKGJ1ZmZfc2l6ZV9yZW1haW5pbmcpOwo+PiAr Cj4+ICtvdXQ6Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2NrKCZybS0+c2VuZF9sb2NrKTsKPj4gK8Kg wqDCoCByZXR1cm4gcmV0IDwgMCA/IHJldCA6IDA7Cj4+ICt9Cj4+ICsKPj4gKy8qKgo+PiArICog Z2hfcm1fY2FsbDogQWNoaWV2ZSByZXF1ZXN0LXJlc3BvbnNlIHR5cGUgY29tbXVuaWNhdGlvbiB3 aXRoIFJQQwo+PiArICogQHJtOiBQb2ludGVyIHRvIEd1bnlhaCByZXNvdXJjZSBtYW5hZ2VyIGlu dGVybmFsIGRhdGEKPj4gKyAqIEBtZXNzYWdlX2lkOiBUaGUgUk0gUlBDIG1lc3NhZ2UtaWQKPj4g KyAqIEByZXFfYnVmZjogUmVxdWVzdCBidWZmZXIgdGhhdCBjb250YWlucyB0aGUgcGF5bG9hZAo+ PiArICogQHJlcV9idWZmX3NpemU6IFRvdGFsIHNpemUgb2YgdGhlIHBheWxvYWQKPj4gKyAqIEBy ZXNwX2J1ZjogUG9pbnRlciB0byBhIHJlc3BvbnNlIGJ1ZmZlcgo+PiArICogQHJlc3BfYnVmZl9z aXplOiBTaXplIG9mIHRoZSByZXNwb25zZSBidWZmZXIKPj4gKyAqCj4+ICsgKiBNYWtlIGEgcmVx dWVzdCB0byB0aGUgUk0tVk0gYW5kIHdhaXQgZm9yIHJlcGx5IGJhY2suIEZvciBhIHN1Y2Nlc3Nm dWwKPj4gKyAqIHJlc3BvbnNlLCB0aGUgZnVuY3Rpb24gcmV0dXJucyB0aGUgcGF5bG9hZC4gVGhl IHNpemUgb2YgdGhlIAo+PiBwYXlsb2FkIGlzIHNldCBpbgo+PiArICogcmVzcF9idWZmX3NpemUu IFRoZSByZXNwX2J1ZiBzaG91bGQgYmUgZnJlZWQgYnkgdGhlIGNhbGxlci4KPj4gKyAqCj4+ICsg KiByZXFfYnVmZiBzaG91bGQgYmUgbm90IE5VTEwgZm9yIHJlcV9idWZmX3NpemUgPjAuIElmIHJl cV9idWZmX3NpemUgCj4+ID09IDAsCj4+ICsgKiByZXFfYnVmZiAqY2FuKiBiZSBOVUxMIGFuZCBu byBhZGRpdGlvbmFsIHBheWxvYWQgaXMgc2VudC4KPj4gKyAqCj4+ICsgKiBDb250ZXh0OiBQcm9j ZXNzIGNvbnRleHQuIFdpbGwgc2xlZXAgd2FpdGluZyBmb3IgcmVwbHkuCj4+ICsgKiBSZXR1cm46 IDAgb24gc3VjY2Vzcy4gPDAgaWYgZXJyb3IuCj4+ICsgKi8KPj4gK2ludCBnaF9ybV9jYWxsKHN0 cnVjdCBnaF9ybSAqcm0sIHUzMiBtZXNzYWdlX2lkLCB2b2lkICpyZXFfYnVmZiwgCj4+IHNpemVf dCByZXFfYnVmZl9zaXplLAo+PiArwqDCoMKgwqDCoMKgwqAgdm9pZCAqKnJlc3BfYnVmLCBzaXpl X3QgKnJlc3BfYnVmZl9zaXplKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCBnaF9ybV9jb25uZWN0 aW9uICpjb25uZWN0aW9uOwo+PiArwqDCoMKgIGludCByZXQ7Cj4+ICsKPj4gK8KgwqDCoCAvKiBt ZXNzYWdlX2lkIDAgaXMgcmVzZXJ2ZWQuIHJlcV9idWZmX3NpemUgaW1wbGllcyByZXFfYnVmIGlz IG5vdCAKPj4gTlVMTCAqLwo+PiArwqDCoMKgIGlmICghbWVzc2FnZV9pZCB8fCAoIXJlcV9idWZm ICYmIHJlcV9idWZmX3NpemUpIHx8ICFybSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRUlO VkFMOwo+PiArCj4+ICvCoMKgwqAgY29ubmVjdGlvbiA9IGdoX3JtX2FsbG9jX2Nvbm5lY3Rpb24o Y3B1X3RvX2xlMzIobWVzc2FnZV9pZCksIAo+PiBSTV9SUENfVFlQRV9SRVBMWSk7Cj4+ICvCoMKg wqAgaWYgKElTX0VSUihjb25uZWN0aW9uKSkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiBQVFJf RVJSKGNvbm5lY3Rpb24pOwo+PiArCj4+ICvCoMKgwqAgaW5pdF9jb21wbGV0aW9uKCZjb25uZWN0 aW9uLT5yZXBseS5zZXFfZG9uZSk7Cj4+ICsKPj4gK8KgwqDCoCAvKiBBbGxvY2F0ZSBhIG5ldyBz ZXEgbnVtYmVyIGZvciB0aGlzIGNvbm5lY3Rpb24gKi8KPj4gK8KgwqDCoCBtdXRleF9sb2NrKCZy bS0+Y2FsbF9pZHJfbG9jayk7Cj4+ICvCoMKgwqAgcmV0ID0gaWRyX2FsbG9jX2N5Y2xpYygmcm0t PmNhbGxfaWRyLCBjb25uZWN0aW9uLCAwLCBVMTZfTUFYLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBHRlBfS0VSTkVMKTsKPj4gK8KgwqDCoCBtdXRl eF91bmxvY2soJnJtLT5jYWxsX2lkcl9sb2NrKTsKPj4gK8KgwqDCoCBpZiAocmV0IDwgMCkKPj4g K8KgwqDCoMKgwqDCoMKgIGdvdG8gb3V0Owo+IAo+IG5ldyBsaW5lLgo+IAo+PiArwqDCoMKgIGNv bm5lY3Rpb24tPnJlcGx5LnNlcSA9IHJldDsKPj4gKwo+PiArwqDCoMKgIC8qIFNlbmQgdGhlIHJl cXVlc3QgdG8gdGhlIFJlc291cmNlIE1hbmFnZXIgKi8KPj4gK8KgwqDCoCByZXQgPSBnaF9ybV9z ZW5kX3JlcXVlc3Qocm0sIG1lc3NhZ2VfaWQsIHJlcV9idWZmLCByZXFfYnVmZl9zaXplLCAKPj4g Y29ubmVjdGlvbik7Cj4+ICvCoMKgwqAgaWYgKHJldCA8IDApCj4+ICvCoMKgwqDCoMKgwqDCoCBn b3RvIG91dDsKPj4gKwo+PiArwqDCoMKgIC8qIFdhaXQgZm9yIHJlc3BvbnNlICovCj4+ICvCoMKg wqAgcmV0ID0gCj4+IHdhaXRfZm9yX2NvbXBsZXRpb25faW50ZXJydXB0aWJsZSgmY29ubmVjdGlv bi0+cmVwbHkuc2VxX2RvbmUpOwo+PiArwqDCoMKgIGlmIChyZXQpCj4+ICvCoMKgwqDCoMKgwqDC oCBnb3RvIG91dDsKPj4gKwo+PiArwqDCoMKgIC8qIENoZWNrIGZvciBpbnRlcm5hbCAoa2VybmVs KSBlcnJvciB3YWl0aW5nIGZvciB0aGUgcmVzcG9uc2UgKi8KPj4gK8KgwqDCoCBpZiAoY29ubmVj dGlvbi0+cmVwbHkucmV0KSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXQgPSBjb25uZWN0aW9uLT5y ZXBseS5yZXQ7Cj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAocmV0ICE9IC1FTk9NRU0pCj4+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIGtmcmVlKGNvbm5lY3Rpb24tPnBheWxvYWQpOwo+PiArwqDCoMKg wqDCoMKgwqAgZ290byBvdXQ7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgLyogR290IGEg cmVzcG9uc2UsIGRpZCByZXNvdXJjZSBtYW5hZ2VyIGdpdmUgdXMgYW4gZXJyb3I/ICovCj4+ICvC oMKgwqAgaWYgKGNvbm5lY3Rpb24tPnJlcGx5LnJtX2Vycm9yICE9IEdIX1JNX0VSUk9SX09LKSB7 Cj4+ICvCoMKgwqDCoMKgwqDCoCBwcl93YXJuKCJSTSByZWplY3RlZCBtZXNzYWdlICUwOHguIEVy cm9yOiAlZFxuIiwgbWVzc2FnZV9pZCwKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgY29ubmVj dGlvbi0+cmVwbHkucm1fZXJyb3IpOwo+PiArwqDCoMKgwqDCoMKgwqAgZHVtcF9zdGFjaygpOwo+ PiArwqDCoMKgwqDCoMKgwqAgcmV0ID0gZ2hfcm1fcmVtYXBfZXJyb3IoY29ubmVjdGlvbi0+cmVw bHkucm1fZXJyb3IpOwo+PiArwqDCoMKgwqDCoMKgwqAga2ZyZWUoY29ubmVjdGlvbi0+cGF5bG9h ZCk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIG91dDsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4gK8Kg wqDCoCAvKiBFdmVyeXRoaW5nIGxvb2tzIGdvb2QsIHJldHVybiB0aGUgcGF5bG9hZCAqLwo+PiAr wqDCoMKgICpyZXNwX2J1ZmZfc2l6ZSA9IGNvbm5lY3Rpb24tPnNpemU7Cj4+ICvCoMKgwqAgaWYg KGNvbm5lY3Rpb24tPnNpemUpCj4+ICvCoMKgwqDCoMKgwqDCoCAqcmVzcF9idWYgPSBjb25uZWN0 aW9uLT5wYXlsb2FkOwo+PiArwqDCoMKgIGVsc2Ugewo+PiArwqDCoMKgwqDCoMKgwqAgLyoga2Zy ZWUgaW4gY2FzZSBSTSBzZW50IHVzIG11bHRpcGxlIGZyYWdtZW50cyBidXQgbmV2ZXIgYW55IAo+ PiBkYXRhIGluCj4+ICvCoMKgwqDCoMKgwqDCoMKgICogdGhvc2UgZnJhZ21lbnRzLiBXZSB3b3Vs ZCd2ZSBhbGxvY2F0ZWQgbWVtb3J5IGZvciBpdCwgYnV0IAo+PiBjb25uZWN0aW9uLT5zaXplID09 IDAKPj4gK8KgwqDCoMKgwqDCoMKgwqAgKi8KPj4gK8KgwqDCoMKgwqDCoMKgIGtmcmVlKGNvbm5l Y3Rpb24tPnBheWxvYWQpOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArb3V0Ogo+PiArwqDCoMKgIG11 dGV4X2xvY2soJnJtLT5jYWxsX2lkcl9sb2NrKTsKPj4gK8KgwqDCoCBpZHJfcmVtb3ZlKCZybS0+ Y2FsbF9pZHIsIGNvbm5lY3Rpb24tPnJlcGx5LnNlcSk7Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2Nr KCZybS0+Y2FsbF9pZHJfbG9jayk7Cj4+ICvCoMKgwqAga2ZyZWUoY29ubmVjdGlvbik7Cj4+ICvC oMKgwqAgcmV0dXJuIHJldDsKPj4gK30KPj4gKwo+PiArCj4+ICtpbnQgZ2hfcm1fbm90aWZpZXJf cmVnaXN0ZXIoc3RydWN0IGdoX3JtICpybSwgc3RydWN0IG5vdGlmaWVyX2Jsb2NrICpuYikKPj4g K3sKPj4gK8KgwqDCoCByZXR1cm4gYmxvY2tpbmdfbm90aWZpZXJfY2hhaW5fcmVnaXN0ZXIoJnJt LT5uaCwgbmIpOwo+PiArfQo+PiArRVhQT1JUX1NZTUJPTF9HUEwoZ2hfcm1fbm90aWZpZXJfcmVn aXN0ZXIpOwo+PiArCj4+ICtpbnQgZ2hfcm1fbm90aWZpZXJfdW5yZWdpc3RlcihzdHJ1Y3QgZ2hf cm0gKnJtLCBzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgCj4+ICpuYikKPj4gK3sKPj4gK8KgwqDCoCBy ZXR1cm4gYmxvY2tpbmdfbm90aWZpZXJfY2hhaW5fdW5yZWdpc3Rlcigmcm0tPm5oLCBuYik7Cj4+ ICt9Cj4+ICtFWFBPUlRfU1lNQk9MX0dQTChnaF9ybV9ub3RpZmllcl91bnJlZ2lzdGVyKTsKPj4g Kwo+PiArdm9pZCBnZXRfZ2hfcm0oc3RydWN0IGdoX3JtICpybSkKPj4gK3sKPj4gK8KgwqDCoCBn ZXRfZGV2aWNlKHJtLT5kZXYpOwo+PiArfQo+PiArRVhQT1JUX1NZTUJPTF9HUEwoZ2V0X2doX3Jt KTsKPiAKPiBDYW4gd2UgaGF2ZSBzb21lIGNvbnNpc3RlbmN5IGluIHRoZSBleHBvcnRlZCBzeW1i b2wgbmFtaW5nLAo+IHdlIGhhdmUgdHdvIGNvbWJpbmF0aW9ucyBub3cuCj4gCj4gRVhQT1JUX1NZ TUJPTF9HUEwoZ2hfcm1fbm90aWZpZXJfcmVnaXN0ZXIpOwo+IEVYUE9SVF9TWU1CT0xfR1BMKGdl dF9naF9ybSk7Cj4gCj4gbGV0cyBzdGljayB0byBvbmUuCgpkb25lLgoKPj4gKwo+PiArdm9pZCBw dXRfZ2hfcm0oc3RydWN0IGdoX3JtICpybSkKPj4gK3sKPj4gK8KgwqDCoCBwdXRfZGV2aWNlKHJt LT5kZXYpOwo+PiArfQo+PiArRVhQT1JUX1NZTUJPTF9HUEwocHV0X2doX3JtKTsKPj4KPiAuLi4K PiAKPj4gKwo+PiArc3RhdGljIGludCBnaF9ybV9kcnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rl dmljZSAqcGRldikKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfbXNncV90eF9kYXRhICptc2c7 Cj4+ICvCoMKgwqAgc3RydWN0IGdoX3JtICpybTsKPj4gK8KgwqDCoCBpbnQgcmV0Owo+PiArCj4g SG93IGFyZSB3ZSBlbnN1cmluZyB0aGF0IGd1bnlhaCBkcml2ZXIgaXMgcHJvYmVkIGJlZm9yZSB0 aGlzIGRyaXZlcj8KPiAKPiAKCldoaWNoIGRyaXZlcj8KCj4+ICvCoMKgwqAgcm0gPSBkZXZtX2t6 YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCpybSksIEdGUF9LRVJORUwpOwo+PiArwqDCoMKgIGlm ICghcm0pCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArwqDCoMKg IHBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHJtKTsKPj4gK8KgwqDCoCBybS0+ZGV2ID0gJnBk ZXYtPmRldjsKPj4gKwo+PiArwqDCoMKgIG11dGV4X2luaXQoJnJtLT5jYWxsX2lkcl9sb2NrKTsK Pj4gK8KgwqDCoCBpZHJfaW5pdCgmcm0tPmNhbGxfaWRyKTsKPj4gK8KgwqDCoCBybS0+Y2FjaGUg PSBrbWVtX2NhY2hlX2NyZWF0ZSgiZ2hfcm0iLCBzdHJ1Y3Rfc2l6ZShtc2csIGRhdGEsIAo+PiBH SF9NU0dRX01BWF9NU0dfU0laRSksIDAsCj4+ICvCoMKgwqDCoMKgwqDCoCBTTEFCX0hXQ0FDSEVf QUxJR04sIE5VTEwpOwo+PiArwqDCoMKgIGlmICghcm0tPmNhY2hlKQo+PiArwqDCoMKgwqDCoMKg wqAgcmV0dXJuIC1FTk9NRU07Cj4gbmV3IGxpbmUgaGVyZSB3b3VsZCBiZSBuaWNlLgo+IAoKZG9u ZS4KCj4+ICvCoMKgwqAgbXV0ZXhfaW5pdCgmcm0tPnNlbmRfbG9jayk7Cj4+ICvCoMKgwqAgQkxP Q0tJTkdfSU5JVF9OT1RJRklFUl9IRUFEKCZybS0+bmgpOwo+PiArCj4+ICvCoMKgwqAgcmV0ID0g Z2hfbXNncV9wbGF0Zm9ybV9wcm9iZV9kaXJlY3Rpb24ocGRldiwgdHJ1ZSwgMCwgCj4+ICZybS0+ dHhfZ2hyc2MpOwo+PiArwqDCoMKgIGlmIChyZXQpCj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIGVy cl9jYWNoZTsKPj4gKwo+PiArwqDCoMKgIHJldCA9IGdoX21zZ3FfcGxhdGZvcm1fcHJvYmVfZGly ZWN0aW9uKHBkZXYsIGZhbHNlLCAxLCAKPj4gJnJtLT5yeF9naHJzYyk7Cj4+ICvCoMKgwqAgaWYg KHJldCkKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZXJyX2NhY2hlOwo+PiArCj4+ICvCoMKgwqAg cm0tPm1zZ3FfY2xpZW50LmRldiA9ICZwZGV2LT5kZXY7Cj4+ICvCoMKgwqAgcm0tPm1zZ3FfY2xp ZW50LnR4X2Jsb2NrID0gdHJ1ZTsKPj4gK8KgwqDCoCBybS0+bXNncV9jbGllbnQucnhfY2FsbGJh Y2sgPSBnaF9ybV9tc2dxX3J4X2RhdGE7Cj4+ICvCoMKgwqAgcm0tPm1zZ3FfY2xpZW50LnR4X2Rv bmUgPSBnaF9ybV9tc2dxX3R4X2RvbmU7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gZ2hfbXNncV9p bml0KCZwZGV2LT5kZXYsICZybS0+bXNncSwgJnJtLT5tc2dxX2NsaWVudCwgCj4+ICZybS0+dHhf Z2hyc2MsICZybS0+cnhfZ2hyc2MpOwo+PiArZXJyX2NhY2hlOgo+PiArwqDCoMKgIGttZW1fY2Fj aGVfZGVzdHJveShybS0+Y2FjaGUpOwo+PiArwqDCoMKgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsK Pj4gK3N0YXRpYyBpbnQgZ2hfcm1fZHJ2X3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpw ZGV2KQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCBnaF9ybSAqcm0gPSBwbGF0Zm9ybV9nZXRfZHJ2 ZGF0YShwZGV2KTsKPj4gKwo+PiArwqDCoMKgIG1ib3hfZnJlZV9jaGFubmVsKGdoX21zZ3FfY2hh bigmcm0tPm1zZ3EpKTsKPj4gK8KgwqDCoCBnaF9tc2dxX3JlbW92ZSgmcm0tPm1zZ3EpOwo+PiAr wqDCoMKgIGttZW1fY2FjaGVfZGVzdHJveShybS0+Y2FjaGUpOwo+PiArCj4+ICvCoMKgwqAgcmV0 dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIGdo X3JtX29mX21hdGNoW10gPSB7Cj4+ICvCoMKgwqAgeyAuY29tcGF0aWJsZSA9ICJndW55YWgtcmVz b3VyY2UtbWFuYWdlciIgfSwKPj4gK8KgwqDCoCB7fQo+PiArfTsKPj4gK01PRFVMRV9ERVZJQ0Vf VEFCTEUob2YsIGdoX3JtX29mX21hdGNoKTsKPj4gKwo+PiArc3RhdGljIHN0cnVjdCBwbGF0Zm9y bV9kcml2ZXIgZ2hfcm1fZHJpdmVyID0gewo+PiArwqDCoMKgIC5wcm9iZSA9IGdoX3JtX2Rydl9w cm9iZSwKPj4gK8KgwqDCoCAucmVtb3ZlID0gZ2hfcm1fZHJ2X3JlbW92ZSwKPj4gK8KgwqDCoCAu ZHJpdmVyID0gewo+PiArwqDCoMKgwqDCoMKgwqAgLm5hbWUgPSAiZ2hfcnNjX21nciIsCj4+ICvC oMKgwqDCoMKgwqDCoCAub2ZfbWF0Y2hfdGFibGUgPSBnaF9ybV9vZl9tYXRjaCwKPj4gK8KgwqDC oCB9LAo+PiArfTsKPj4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIoZ2hfcm1fZHJpdmVyKTsKPj4g Kwo+PiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+PiArTU9EVUxFX0RFU0NSSVBUSU9OKCJHdW55 YWggUmVzb3VyY2UgTWFuYWdlciBEcml2ZXIiKTsKPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmly dC9ndW55YWgvcnNjX21nci5oIAo+PiBiL2RyaXZlcnMvdmlydC9ndW55YWgvcnNjX21nci5oCj4+ IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+IGluZGV4IDAwMDAwMDAwMDAwMC4uZDRlNzk5YTc1MjZm Cj4+IC0tLSAvZGV2L251bGwKPj4gKysrIGIvZHJpdmVycy92aXJ0L2d1bnlhaC9yc2NfbWdyLmgK Pj4gQEAgLTAsMCArMSw3NyBAQAo+PiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0y LjAtb25seSAqLwo+PiArLyoKPj4gKyAqIENvcHlyaWdodCAoYykgMjAyMi0yMDIzIFF1YWxjb21t IElubm92YXRpb24gQ2VudGVyLCBJbmMuIEFsbCAKPj4gcmlnaHRzIHJlc2VydmVkLgo+PiArICov Cj4+ICsjaWZuZGVmIF9fR0hfUlNDX01HUl9QUklWX0gKPj4gKyNkZWZpbmUgX19HSF9SU0NfTUdS X1BSSVZfSAo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgvZ3VueWFoLmg+Cj4+ICsjaW5jbHVkZSA8 bGludXgvZ3VueWFoX3JzY19tZ3IuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC90eXBlcy5oPgo+PiAr Cj4gPC0tLS0tLS0tLS0tLS0tLS0tLQo+PiArLyogUk0gRXJyb3IgY29kZXMgKi8KPj4gK2VudW0g Z2hfcm1fZXJyb3Igewo+PiArwqDCoMKgIEdIX1JNX0VSUk9SX09LwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCA9IDB4MCwKPj4gK8KgwqDCoCBHSF9STV9FUlJPUl9VTklNUExFTUVOVEVEwqDCoMKgID0g MHhGRkZGRkZGRiwKPj4gK8KgwqDCoCBHSF9STV9FUlJPUl9OT01FTcKgwqDCoMKgwqDCoMKgID0g MHgxLAo+PiArwqDCoMKgIEdIX1JNX0VSUk9SX05PUkVTT1VSQ0XCoMKgwqDCoMKgwqDCoCA9IDB4 MiwKPj4gK8KgwqDCoCBHSF9STV9FUlJPUl9ERU5JRUTCoMKgwqDCoMKgwqDCoCA9IDB4MywKPj4g K8KgwqDCoCBHSF9STV9FUlJPUl9JTlZBTElEwqDCoMKgwqDCoMKgwqAgPSAweDQsCj4+ICvCoMKg wqAgR0hfUk1fRVJST1JfQlVTWcKgwqDCoMKgwqDCoMKgID0gMHg1LAo+PiArwqDCoMKgIEdIX1JN X0VSUk9SX0FSR1VNRU5UX0lOVkFMSUTCoMKgwqAgPSAweDYsCj4+ICvCoMKgwqAgR0hfUk1fRVJS T1JfSEFORExFX0lOVkFMSUTCoMKgwqAgPSAweDcsCj4+ICvCoMKgwqAgR0hfUk1fRVJST1JfVkFM SURBVEVfRkFJTEVEwqDCoMKgID0gMHg4LAo+PiArwqDCoMKgIEdIX1JNX0VSUk9SX01BUF9GQUlM RUTCoMKgwqDCoMKgwqDCoCA9IDB4OSwKPj4gK8KgwqDCoCBHSF9STV9FUlJPUl9NRU1fSU5WQUxJ RMKgwqDCoMKgwqDCoMKgID0gMHhBLAo+PiArwqDCoMKgIEdIX1JNX0VSUk9SX01FTV9JTlVTRcKg wqDCoMKgwqDCoMKgID0gMHhCLAo+PiArwqDCoMKgIEdIX1JNX0VSUk9SX01FTV9SRUxFQVNFRMKg wqDCoCA9IDB4QywKPj4gK8KgwqDCoCBHSF9STV9FUlJPUl9WTUlEX0lOVkFMSUTCoMKgwqAgPSAw eEQsCj4+ICvCoMKgwqAgR0hfUk1fRVJST1JfTE9PS1VQX0ZBSUxFRMKgwqDCoCA9IDB4RSwKPj4g K8KgwqDCoCBHSF9STV9FUlJPUl9JUlFfSU5WQUxJRMKgwqDCoMKgwqDCoMKgID0gMHhGLAo+PiAr wqDCoMKgIEdIX1JNX0VSUk9SX0lSUV9JTlVTRcKgwqDCoMKgwqDCoMKgID0gMHgxMCwKPj4gK8Kg wqDCoCBHSF9STV9FUlJPUl9JUlFfUkVMRUFTRUTCoMKgwqAgPSAweDExLAo+PiArfTsKPj4gKwo+ PiArLyoqCj4+ICsgKiBnaF9ybV9yZW1hcF9lcnJvcigpIC0gUmVtYXAgR3VueWFoIHJlc291cmNl IG1hbmFnZXIgZXJyb3JzIGludG8gYSAKPj4gTGludXggZXJyb3IgY29kZQo+PiArICogQGdoX2Vy cm9yOiAiU3RhbmRhcmQiIHJldHVybiB2YWx1ZSBmcm9tIEd1bnlhaCByZXNvdXJjZSBtYW5hZ2Vy Cj4+ICsgKi8KPj4gK3N0YXRpYyBpbmxpbmUgaW50IGdoX3JtX3JlbWFwX2Vycm9yKGVudW0gZ2hf cm1fZXJyb3Igcm1fZXJyb3IpCj4+ICt7Cj4+ICvCoMKgwqAgc3dpdGNoIChybV9lcnJvcikgewo+ PiArwqDCoMKgIGNhc2UgR0hfUk1fRVJST1JfT0s6Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4g MDsKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX1VOSU1QTEVNRU5URUQ6Cj4+ICvCoMKgwqDC oMKgwqDCoCByZXR1cm4gLUVPUE5PVFNVUFA7Cj4+ICvCoMKgwqAgY2FzZSBHSF9STV9FUlJPUl9O T01FTToKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRU5PTUVNOwo+PiArwqDCoMKgIGNhc2Ug R0hfUk1fRVJST1JfTk9SRVNPVVJDRToKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRU5PREVW Owo+PiArwqDCoMKgIGNhc2UgR0hfUk1fRVJST1JfREVOSUVEOgo+PiArwqDCoMKgwqDCoMKgwqAg cmV0dXJuIC1FUEVSTTsKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX0JVU1k6Cj4+ICvCoMKg wqDCoMKgwqDCoCByZXR1cm4gLUVCVVNZOwo+PiArwqDCoMKgIGNhc2UgR0hfUk1fRVJST1JfSU5W QUxJRDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX0FSR1VNRU5UX0lOVkFMSUQ6Cj4+ICvC oMKgwqAgY2FzZSBHSF9STV9FUlJPUl9IQU5ETEVfSU5WQUxJRDoKPj4gK8KgwqDCoCBjYXNlIEdI X1JNX0VSUk9SX1ZBTElEQVRFX0ZBSUxFRDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX01B UF9GQUlMRUQ6Cj4+ICvCoMKgwqAgY2FzZSBHSF9STV9FUlJPUl9NRU1fSU5WQUxJRDoKPj4gK8Kg wqDCoCBjYXNlIEdIX1JNX0VSUk9SX01FTV9JTlVTRToKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VS Uk9SX01FTV9SRUxFQVNFRDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX1ZNSURfSU5WQUxJ RDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX0xPT0tVUF9GQUlMRUQ6Cj4+ICvCoMKgwqAg Y2FzZSBHSF9STV9FUlJPUl9JUlFfSU5WQUxJRDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9S X0lSUV9JTlVTRToKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX0VSUk9SX0lSUV9SRUxFQVNFRDoKPj4g K8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRUlOVkFMOwo+PiArwqDCoMKgIGRlZmF1bHQ6Cj4+ICvC oMKgwqDCoMKgwqDCoCByZXR1cm4gLUVCQURNU0c7Cj4+ICvCoMKgwqAgfQo+PiArfQo+PiArCj4g LS0tLS0tLS0tLS0tLS0tLT4KPiAKPiBPbmx5IHVzZXIgZm9yIHRoZSBlcnJvciBjb2RlIGNvdmVy c2lvbiBpcyB3aXRoaW4gdGhlIHJtIGRyaXZlciwgeW91IAo+IHNob3VsZCBqdXN0IG1vdmUgdGhp cyB0byB0aGUgLmMgZmlsZSwgSSBzZWUgbm8gdmFsdWUgb2YgdGhpcyBpbiAuaCAKPiB1bmxlc3Mg dGhlcmUgYXJlIHNvbWUgb3RoZXIgdXNlcnMgZm9yIHRoaXMuCj4gCj4gCgpEb25lLgoKPiAKPj4g K3N0cnVjdCBnaF9ybTsKPj4gK2ludCBnaF9ybV9jYWxsKHN0cnVjdCBnaF9ybSAqcnNjX21nciwg dTMyIG1lc3NhZ2VfaWQsIHZvaWQgKnJlcV9idWZmLCAKPj4gc2l6ZV90IHJlcV9idWZmX3NpemUs Cj4+ICvCoMKgwqDCoMKgwqDCoCB2b2lkICoqcmVzcF9idWYsIHNpemVfdCAqcmVzcF9idWZmX3Np emUpOwo+PiArCj4+ICsjZW5kaWYKPj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvZ3VueWFo X3JzY19tZ3IuaCAKPj4gYi9pbmNsdWRlL2xpbnV4L2d1bnlhaF9yc2NfbWdyLmgKPj4gbmV3IGZp bGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAwMDAwMDAwMDAwLi5jOTkyYjMxODhjOGQKPj4gLS0t IC9kZXYvbnVsbAo+PiArKysgYi9pbmNsdWRlL2xpbnV4L2d1bnlhaF9yc2NfbWdyLmgKPj4gQEAg LTAsMCArMSwyNCBAQAo+PiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAtb25s eSAqLwo+PiArLyoKPj4gKyAqIENvcHlyaWdodCAoYykgMjAyMi0yMDIzIFF1YWxjb21tIElubm92 YXRpb24gQ2VudGVyLCBJbmMuIEFsbCAKPj4gcmlnaHRzIHJlc2VydmVkLgo+PiArICovCj4+ICsK Pj4gKyNpZm5kZWYgX0dVTllBSF9SU0NfTUdSX0gKPj4gKyNkZWZpbmUgX0dVTllBSF9SU0NfTUdS X0gKPj4gKwo+PiArI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9u b3RpZmllci5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2d1bnlhaC5oPgo+PiArCj4+ICsjZGVmaW5l IEdIX1ZNSURfSU5WQUzCoMKgwqAgVTE2X01BWAo+PiArCj4+ICsvKiBHdW55YWggcmVjb2duaXpl cyBWTUlEMCBhcyBhbiBhbGlhcyB0byB0aGUgY3VycmVudCBWTSdzIElEICovCj4+ICsjZGVmaW5l IEdIX1ZNSURfU0VMRsKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgMAo+PiArCj4+ICtzdHJ1Y3QgZ2hf cm07Cj4+ICtpbnQgZ2hfcm1fbm90aWZpZXJfcmVnaXN0ZXIoc3RydWN0IGdoX3JtICpybSwgc3Ry dWN0IG5vdGlmaWVyX2Jsb2NrIAo+PiAqbmIpOwo+PiAraW50IGdoX3JtX25vdGlmaWVyX3VucmVn aXN0ZXIoc3RydWN0IGdoX3JtICpybSwgc3RydWN0IG5vdGlmaWVyX2Jsb2NrIAo+PiAqbmIpOwo+ PiArdm9pZCBnZXRfZ2hfcm0oc3RydWN0IGdoX3JtICpybSk7Cj4+ICt2b2lkIHB1dF9naF9ybShz dHJ1Y3QgZ2hfcm0gKnJtKTsKPj4gKwo+PiArI2VuZGlmCgpfX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdAps aW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVh ZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==