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 11F13C7EE2F for ; Fri, 24 Feb 2023 23:45:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229454AbjBXXo7 (ORCPT ); Fri, 24 Feb 2023 18:44:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229446AbjBXXo7 (ORCPT ); Fri, 24 Feb 2023 18:44:59 -0500 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8DC439CF7; Fri, 24 Feb 2023 15:44:55 -0800 (PST) Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 31OLS0KR009914; Fri, 24 Feb 2023 23:44:32 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=message-id : date : mime-version : from : subject : to : cc : references : in-reply-to : content-type : content-transfer-encoding; s=qcppdkim1; bh=LyAFSt8ovm7kNNn40sLG7l2+9PseoG3munN0NNC+q98=; b=DWSt7nnjKCf9jZ4NFvyC/alEJQznMk61Znc8vSckgmW+CEJgA6bBNrBYBZUggTF8PsUT TylqABiyV9c0RySSLAPdPgEiAtA7jy3JdRTilAW+cR+ctrslKrY4JUyVrXOdKZVusph0 QJ/rIOKHD+2ZO7J0lWcd8ZseiKWNOLhVAiO4aFtWl19dFYZP5LYR1Cjg+x8W6nXlo5fb H7mRn+16vJneqCZSNkH+G7yNkH7Py9g2qJBwyPCFABFUfVRAr813OxO/R5cXtmho9V+i mW1217qkhBFwxn8PMtKA49mJqh3LzvemY/ZyaHCw+5xJiGoDZtkueXYoGhF/eaVdkx3o og== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nxwb7sp6m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 24 Feb 2023 23:44:31 +0000 Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 31ONiVdD013327 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 24 Feb 2023 23:44:31 GMT Received: from [10.110.9.108] (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; Fri, 24 Feb 2023 15:44:29 -0800 Message-ID: <87a34969-5c19-6a2d-e708-399411823c0b@quicinc.com> Date: Fri, 24 Feb 2023 15:44:29 -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 From: Elliot Berman Subject: Re: [PATCH v10 19/26] gunyah: vm_mgr: Add framework to add VM Functions To: Srinivas Kandagatla , Alex Elder , Prakruthi Deepak Heragu , Jonathan Corbet 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 , Bagas Sanjaya , Catalin Marinas , Jassi Brar , , , , , References: <20230214211229.3239350-1-quic_eberman@quicinc.com> <20230214212531.3323284-1-quic_eberman@quicinc.com> <2cd83439-8518-f2a1-42b5-c5936f3e4548@linaro.org> Content-Language: en-US In-Reply-To: <2cd83439-8518-f2a1-42b5-c5936f3e4548@linaro.org> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) 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: VyzzYgdLyTCCFPhmlNeYQXGgPCCgH9-d X-Proofpoint-ORIG-GUID: VyzzYgdLyTCCFPhmlNeYQXGgPCCgH9-d 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-24_17,2023-02-24_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 suspectscore=0 phishscore=0 clxscore=1015 priorityscore=1501 mlxscore=0 spamscore=0 bulkscore=0 adultscore=0 impostorscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2302240192 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org On 2/22/2023 6:08 AM, Srinivas Kandagatla wrote: > > > On 14/02/2023 21:25, Elliot Berman wrote: >> >> Introduce a framework for Gunyah userspace to install VM functions. VM >> functions are optional interfaces to the virtual machine. vCPUs, >> ioeventfs, and irqfds are examples of such VM functions and are >> implemented in subsequent patches. >> >> A generic framework is implemented instead of individual ioctls to >> create vCPUs, irqfds, etc., in order to simplify the VM manager core >> implementation and allow dynamic loading of VM function modules. >> >> Signed-off-by: Elliot Berman >> --- >>   Documentation/virt/gunyah/vm-manager.rst |  18 ++ >>   drivers/virt/gunyah/vm_mgr.c             | 240 ++++++++++++++++++++++- >>   drivers/virt/gunyah/vm_mgr.h             |   3 + >>   include/linux/gunyah_vm_mgr.h            |  80 ++++++++ >>   include/uapi/linux/gunyah.h              |  17 ++ >>   5 files changed, 353 insertions(+), 5 deletions(-) >>   create mode 100644 include/linux/gunyah_vm_mgr.h >> >> diff --git a/Documentation/virt/gunyah/vm-manager.rst >> b/Documentation/virt/gunyah/vm-manager.rst >> index c0126cfeadc7..5272a6e9145c 100644 >> --- a/Documentation/virt/gunyah/vm-manager.rst >> +++ b/Documentation/virt/gunyah/vm-manager.rst >> @@ -17,6 +17,24 @@ sharing userspace memory with a VM is done via the >> GH_VM_SET_USER_MEM_REGION >>   ioctl. The VM itself is configured to use the memory region via the >>   devicetree. >> +Gunyah Functions >> +================ >> + >> +Components of a Gunyah VM's configuration that need kernel >> configuration are >> +called "functions" and are built on top of a framework. Functions are >> identified >> +by a string and have some argument(s) to configure them. They are >> typically >> +created by the `GH_VM_ADD_FUNCTION` ioctl. >> + >> +Functions typically will always do at least one of these operations: >> + >> +1. Create resource ticket(s). Resource tickets allow a function to >> register >> +   itself as the client for a Gunyah resource (e.g. doorbell or vCPU) >> and >> +   the function is given the pointer to the `struct gunyah_resource` >> when the >> +   VM is starting. >> + >> +2. Register IO handler(s). IO handlers allow a function to handle >> stage-2 faults >> +   from the virtual machine. >> + >>   Sample Userspace VMM >>   ==================== >> diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c >> index fa324385ade5..e9c55e7dd1b3 100644 >> --- a/drivers/virt/gunyah/vm_mgr.c >> +++ b/drivers/virt/gunyah/vm_mgr.c >> @@ -6,8 +6,10 @@ >>   #define pr_fmt(fmt) "gh_vm_mgr: " fmt >>   #include >> +#include >>   #include >>   #include >> +#include >>   #include >>   #include >>   #include >> @@ -16,6 +18,177 @@ >>   #include "vm_mgr.h" >> +static DEFINE_MUTEX(functions_lock); >> +static DEFINE_IDR(functions); > Why are these global? Can these be not part of struc gh_rm? If I make the list part of gh_rm, the core gunyah framework would need to know and be dependent on all possible VM functions. This prevents CONFIG_GUNYAH=y and CONFIG_GUNYAH_IRQFD=m (or any other function from being enabled as a module). I also see a 2-way dependency when enabled all enabled as modules. This approach seems vastly simpler. > Not to mention please move idr to xarrays. > Done. >> + >> +int gh_vm_function_register(struct gh_vm_function *drv) >> +{ >> +    int ret = 0; >> + >> +    if (!drv->bind || !drv->unbind) >> +        return -EINVAL; >> + >> +    mutex_lock(&functions_lock); >> +    if (idr_find(&functions, drv->type)) { >> +        ret = -EEXIST; >> +        goto out; >> +    } >> + >> +    INIT_LIST_HEAD(&drv->instances); >> +    ret = idr_alloc(&functions, drv, drv->type, drv->type + 1, >> GFP_KERNEL); >> +    if (ret > 0) >> +        ret = 0; >> +out: >> +    mutex_unlock(&functions_lock); >> +    return ret; >> +} >> +EXPORT_SYMBOL_GPL(gh_vm_function_register); >> + >> +static void gh_vm_remove_function_instance(struct >> gh_vm_function_instance *inst) >> +    __must_hold(functions_lock) >> +{ >> +    inst->fn->unbind(inst); >> +    list_del(&inst->vm_list); >> +    list_del(&inst->fn_list); >> +    module_put(inst->fn->mod); >> +    if (inst->arg_size) >> +        kfree(inst->argp); >> +    kfree(inst); >> +} >> + >> +void gh_vm_function_unregister(struct gh_vm_function *fn) >> +{ >> +    struct gh_vm_function_instance *inst, *iter; >> + >> +    mutex_lock(&functions_lock); >> +    list_for_each_entry_safe(inst, iter, &fn->instances,fn_list) >> +        gh_vm_remove_function_instance(inst); > > We should never have any instances as we have refcounted the module. > > If there are any instances then its clearly a bug, as this will pull out > function under the hood while userspace is using it. > > Done. >> +    idr_remove(&functions, fn->type); >> +    mutex_unlock(&functions_lock); >> +} >> +EXPORT_SYMBOL_GPL(gh_vm_function_unregister); >> + >> +static long gh_vm_add_function(struct gh_vm *ghvm, struct gh_fn_desc *f) >> +{ >> +    struct gh_vm_function_instance *inst; >> +    void __user *argp; >> +    long r = 0; >> + >> +    if (f->arg_size > GH_FN_MAX_ARG_SIZE) > > lets print some useful error message to user. > >> +        return -EINVAL; >> + >> +    inst = kzalloc(sizeof(*inst), GFP_KERNEL); >> +    if (!inst) >> +        return -ENOMEM; >> + >> +    inst->arg_size = f->arg_size; >> +    if (inst->arg_size) { >> +        inst->argp = kzalloc(inst->arg_size, GFP_KERNEL); >> +        if (!inst->arg) { >> +            r = -ENOMEM; >> +            gotofree; >> +        } >> + >> +        argp = is_compat_task() ? compat_ptr(f->arg) : (void __user >> *) f->arg; > > hmm, arg is not a data pointer it is a fixed size variable (__u64 arg), > so why are using compat_ptr() here? > > you should be able to do > > argp = u64_to_user_ptr(f->arg); > Done. >> +        if (copy_from_user(inst->argp, argp, f->arg_size)) { >> +            r = -EFAULT; >> +            gotofree_arg; >> +        } >> +    } else { >> +        inst->arg = f->arg; > bit lost here, so, we treat the arg as both pointer and value in cases > where size is zero. > That's correct -- arg is value in cases where size is zero. It might be a bit too strange, and I'm not opposed to always treating arg as pointer when size >= 0 and none of the "arg is value". In vCPU and several other possible functions we have (presently) downstream, the only argument a only a 32-bit integer label. I thought it would be good to optimize this path. >> +    } >> + > <--- >> +    mutex_lock(&functions_lock); >> +    inst->fn = idr_find(&functions, f->type); >> +    if (!inst->fn) { >> +        mutex_unlock(&functions_lock); >> +        r = request_module("ghfunc:%d", f->type); >> +        if (r) >> +            gotounlock_free; >> + >> +        mutex_lock(&functions_lock); >> +        inst->fn = idr_find(&functions, f->type); >> +    } >> + >> +    if (!inst->fn) { >> +        r = -ENOENT; >> +        goto unlock_free; >> +    } >> + >> +    if (!try_module_get(inst->fn->mod)) { >> +        r = -ENOENT; >> +        inst->fn = NULL; >> +        goto unlock_free; >> +    } >> + > ---> > can we do this snippet as a gh_vm_get_function() and corresponding > gh_vm_put_function(). that should make the code more cleaner. > Done. > >> +    inst->ghvm = ghvm; >> +    inst->rm = ghvm->rm; >> + >> +    r = inst->fn->bind(inst); >> +    if (r < 0) { >> +        module_put(inst->fn->mod); >> +        goto unlock_free; >> +    } >> + >> +    list_add(&inst->vm_list, &ghvm->functions); > > I guess its possible to add same functions with same argumentso to this > list, how are we preventing this to happen? > > Is it a valid usecase? > I'm not able to think of a function where this is valid. This is handled today because the ->bind() callback returns an error. This happens if the resource ticket was already created, e.g. same vCPU is requested twice. This should be handled at function level because two arguments could be different but request the same resource. For instance, two GH_VM_ADD_FUNCTION to create irqfd with same doorbell. One call is with LEVEL flag and the other doesn't have the flag set. Only once we try to register the doorbell resource ticket do we realize that 2nd GH_VM_ADD_FUNCTION should fail. >> +    list_add(&inst->fn_list, &inst->fn->instances); >> +    mutex_unlock(&functions_lock); >> +    return r; >> +unlock_free: >> +    mutex_unlock(&functions_lock); >> +free_arg: >> +    if (inst->arg_size) >> +        kfree(inst->argp); >> +free: >> +    kfree(inst); >> +    return r; >> +} >> + >> +static long gh_vm_rm_function(struct gh_vm *ghvm, struct gh_fn_desc *f) >> +{ >> +    struct gh_vm_function_instance *inst, *iter; >> +    void __user *user_argp; >> +    void *argp; >> +    long r = 0; >> + >> +    r = mutex_lock_interruptible(&functions_lock); >> +    if (r) >> +        return r; >> + >> +    if (f->arg_size) { >> +        argp = kzalloc(f->arg_size, GFP_KERNEL); >> +        if (!argp) { >> +            r = -ENOMEM; >> +            gotoout; >> +        } >> + >> +        user_argp = is_compat_task() ? compat_ptr(f->arg) : (void >> __user *) f->arg; > > same comment as add; > >> +        if (copy_from_user(argp, user_argp, f->arg_size)) { >> +            r = -EFAULT; >> +            kfree(argp); >> +            gotoout; >> +        } >> + >> +        list_for_each_entry_safe(inst, iter, &ghvm->functions, >> vm_list) { >> +            if (inst->fn->type == f->type && >> +                f->arg_size == inst->arg_size && >> +                !memcmp(argp, inst->argp, f->arg_size)) >> +                gh_vm_remove_function_instance(inst); >> +        } > > leaking argp; > Done. >> +    } else { >> +        list_for_each_entry_safe(inst, iter, &ghvm->functions, >> vm_list) { >> +            if (inst->fn->type == f->type && >> +                f->arg_size == inst->arg_size && >> +                inst->arg == f->arg) >> +                gh_vm_remove_function_instance(inst); >> +        } >> +    } >> + >> +out: >> +    mutex_unlock(&functions_lock); >> +    return r; >> +} >> + >>   static int gh_vm_rm_notification_status(struct gh_vm *ghvm, void *data) >>   { >>       struct gh_rm_vm_status_payload *payload = data; >> @@ -80,6 +253,7 @@ static void gh_vm_stop(struct gh_vm *ghvm) >>   static void gh_vm_free(struct work_struct *work) >>   { >>       struct gh_vm *ghvm = container_of(work,struct gh_vm, free_work); >> +    struct gh_vm_function_instance *inst, *iiter; >>       struct gh_vm_mem *mapping, *tmp; >>       int ret; >> @@ -90,7 +264,13 @@ static void gh_vm_free(struct work_struct *work) >>           fallthrough; >>       case GH_RM_VM_STATUS_INIT_FAILED: >>       case GH_RM_VM_STATUS_LOAD: >> -    case GH_RM_VM_STATUS_LOAD_FAILED: >> +    case GH_RM_VM_STATUS_EXITED: >> +        mutex_lock(&functions_lock); >> +        list_for_each_entry_safe(inst, iiter, &ghvm->functions, >> vm_list) { >> +            gh_vm_remove_function_instance(inst); >> +        } >> +        mutex_unlock(&functions_lock); >> + >>           mutex_lock(&ghvm->mm_lock); >>           list_for_each_entry_safe(mapping, tmp, >> &ghvm->memory_mappings, list) { >>               gh_vm_mem_reclaim(ghvm, mapping); >> @@ -113,6 +293,28 @@ static void gh_vm_free(struct work_struct *work) >>       } >>   } >> +static void _gh_vm_put(struct kref *kref) >> +{ >> +    struct gh_vm *ghvm = container_of(kref, struct gh_vm, kref); >> + >> +    /* VM will be reset and make RM calls which can interruptible sleep. >> +     * Defer to a work so this thread can receive signal. >> +     */ >> +    schedule_work(&ghvm->free_work); >> +} >> + >> +int __must_check gh_vm_get(struct gh_vm *ghvm) >> +{ >> +    return kref_get_unless_zero(&ghvm->kref); >> +} >> +EXPORT_SYMBOL_GPL(gh_vm_get); >> + >> +void gh_vm_put(struct gh_vm *ghvm) >> +{ >> +    kref_put(&ghvm->kref, _gh_vm_put); >> +} >> +EXPORT_SYMBOL_GPL(gh_vm_put); >> + >>   static __must_check struct gh_vm *gh_vm_alloc(struct gh_rm *rm) >>   { >>       struct gh_vm *ghvm; >> @@ -147,6 +349,8 @@ static __must_check struct gh_vm >> *gh_vm_alloc(struct gh_rm *rm) >>       INIT_LIST_HEAD(&ghvm->memory_mappings); >>       init_rwsem(&ghvm->status_lock); >>       INIT_WORK(&ghvm->free_work, gh_vm_free); >> +    kref_init(&ghvm->kref); >> +    INIT_LIST_HEAD(&ghvm->functions); >>       ghvm->vm_status = GH_RM_VM_STATUS_LOAD; >>       return ghvm; >> @@ -291,6 +495,35 @@ static long gh_vm_ioctl(struct file *filp, >> unsigned int cmd, unsigned long arg) >>           r = gh_vm_ensure_started(ghvm); >>           break; >>       } >> +    case GH_VM_ADD_FUNCTION: { >> +        struct gh_fn_desc *f; >> + >> +        f = kzalloc(sizeof(*f), GFP_KERNEL); >> +        if (!f) >> +            return -ENOMEM; >> + >> +        if (copy_from_user(f, argp, sizeof(*f))) >> +            return -EFAULT; >> + >> +        r = gh_vm_add_function(ghvm, f); >> +        if (r < 0) >> +            kfree(f); > > > we are memory leaking f here, we should free it irrespective of return > value. or I see no reason not to use this small struct from stack. > I can copy to stack directly. > >> +        break; >> +    } >> +    case GH_VM_REMOVE_FUNCTION: { >> +        struct gh_fn_desc *f; >> + >> +        f = kzalloc(sizeof(*f), GFP_KERNEL); >> +        if (!f) >> +            return -ENOMEM; >> + >> +        if (copy_from_user(f, argp, sizeof(*f))) >> +            return -EFAULT; >> + >> +        r = gh_vm_rm_function(ghvm, f); >> +        kfree(f); >> +        break; >> +    } >>       default: >>           r = -ENOTTY; >>           break; >> @@ -303,10 +536,7 @@ static int gh_vm_release(struct inode *inode, >> struct file *filp) >>   { >>       struct gh_vm *ghvm = filp->private_data; >> -    /* VM will be reset and make RM calls which can interruptible sleep. >> -     * Defer to a work so this thread can receive signal. >> -     */ >> -    schedule_work(&ghvm->free_work); >> +    gh_vm_put(ghvm); >>       return 0; >>   } >> diff --git a/drivers/virt/gunyah/vm_mgr.h b/drivers/virt/gunyah/vm_mgr.h >> index e9cf56647cc2..4750d56c1297 100644 >> --- a/drivers/virt/gunyah/vm_mgr.h >> +++ b/drivers/virt/gunyah/vm_mgr.h >> @@ -8,6 +8,7 @@ >>   #include >>   #include >> +#include >>   #include >>   #include >>   #include >> @@ -44,8 +45,10 @@ struct gh_vm { >>       struct rw_semaphore status_lock; >>       struct work_struct free_work; >> +    struct kref kref; >>       struct mutex mm_lock; >>       struct list_head memory_mappings; >> +    struct list_head functions; >>   }; >>   int gh_vm_mem_alloc(struct gh_vm *ghvm, struct >> gh_userspace_memory_region *region); >> diff --git a/include/linux/gunyah_vm_mgr.h >> b/include/linux/gunyah_vm_mgr.h >> new file mode 100644 >> index 000000000000..f0a95af50b2e >> --- /dev/null >> +++ b/include/linux/gunyah_vm_mgr.h >> @@ -0,0 +1,80 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* >> + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All >> rights reserved. >> + */ >> + >> +#ifndef _GUNYAH_VM_MGR_H >> +#define _GUNYAH_VM_MGR_H >> + >> +#include >> +#include >> +#include >> +#include >> +#include > ?? > >> +#include > > ?? > >> + >> +#include >> + >> +struct gh_vm; >> + >> +int __must_check gh_vm_get(struct gh_vm *ghvm); >> +void gh_vm_put(struct gh_vm *ghvm); >> + >> +struct gh_vm_function_instance; >> +struct gh_vm_function { >> +    u32 type; > +    const char *name; >> +    struct module *mod; >> +    long (*bind)(struct gh_vm_function_instance *f); >> +    void (*unbind)(struct gh_vm_function_instance *f); >> +    struct mutex instances_lock; >> +    struct list_head instances; >> +}; >> + >> +/** >> + * struct gh_vm_function_instance - Represents one function instance >> + * @arg_size: size of user argument >> + * @arg: user argument to describe the function instance; arg_size is 0 >> + * @argp: pointer to user argument >> + * @ghvm: Pointer to VM instance >> + * @rm: Pointer to resource manager for the VM instance >> + * @fn: The ops for the function >> + * @data: Private data for function >> + * @vm_list: for gh_vm's functions list >> + * @fn_list: for gh_vm_function's instances list >> + */ >> +struct gh_vm_function_instance { >> +    size_t arg_size; >> +    union { >> +        u64 arg; >> +        void *argp; >> +    }; >> +    struct gh_vm *ghvm; >> +    struct gh_rm *rm; >> +    struct gh_vm_function *fn; >> +    void *data; >> +    struct list_head vm_list; >> +    struct list_head fn_list; > Am not seeing any advantage of storing the instance in two different > list, they look redundant to me. storing the function instances in vm > should be good IMO. > I was concerned about removal of function outside of module_removal, but we don't have reason/ability to do it. > >> +}; >> + >> +int gh_vm_function_register(struct gh_vm_function *f); >> +void gh_vm_function_unregister(struct gh_vm_function *f); >> + >> +#define DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind)    \ >> +    static struct gh_vm_function _name = {        \ >> +        .type = _type,                        \ >> +        .name = __stringify(_name),                \ >> +        .mod = THIS_MODULE,                    \ >> +        .bind = _bind,                        \ >> +        .unbind = _unbind,                    \ >> +    };                                \ >> +    MODULE_ALIAS("ghfunc:"__stringify(_type)) >> + >> +#define module_gunyah_vm_function(__gf)                    \ >> +    module_driver(__gf, gh_vm_function_register, >> gh_vm_function_unregister) >> + >> +#define DECLARE_GUNYAH_VM_FUNCTION_INIT(_name, _type, _bind, >> _unbind)    \ >> +    DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind);    \ >> +    module_gunyah_vm_function(_name) >> + >> +#endif >> diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h >> index d899bba6a4c6..8df455a2a293 100644 >> --- a/include/uapi/linux/gunyah.h >> +++ b/include/uapi/linux/gunyah.h >> @@ -66,4 +66,21 @@ struct gh_vm_dtb_config { >>   #define GH_VM_START        _IO(GH_IOCTL_TYPE, 0x3) >> +#define GH_FN_MAX_ARG_SIZE        256 >> + >> +/** >> + * struct gh_fn_desc - Arguments to create a VM function >> + * @type: Type of the function. See GH_FN_* macro for supported types >> + * @arg_size: Size of argument to pass to the function > > a note on max arg size  of 256 bytes would be useful. > >> + * @arg: Value or pointer to argument given to the function > > Treating this as value when arg_size == 0 is really confusing abi. > how about just use as arg as ptr to data along with arg_size; > > --srini >> + */ >> +struct gh_fn_desc { >> +    __u32 type; >> +    __u32 arg_size; >> +    __u64 arg; >> +}; >> + >> +#define GH_VM_ADD_FUNCTION    _IOW(GH_IOCTL_TYPE, 0x4, struct >> gh_fn_desc) >> +#define GH_VM_REMOVE_FUNCTION    _IOW(GH_IOCTL_TYPE, 0x7, struct >> gh_fn_desc) > > Do you have an example of how add and rm ioctls are used w.r.t to arg, i > see that we check correcteness of arg in between add and remove. > > --srini >> + >>   #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 78BE6C6FA8E for ; Fri, 24 Feb 2023 23:46:00 +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:References:CC:To:Subject:From: 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=x93z2B32vmpCdHH2AJgVPbvEWiXH56CrxFCLMks5brk=; b=Rk9HFJIifKbNnt pKVkx0ShzVbDS4RswwDMFrQn83ZnUyDAHXNriiOWl049aIBKlNC2/z6AnyU98MzMBYm/cPHssPylT bAsH7yjf4gBDGs+oG+g5r3yxtXbXMqQhvAUQT33PnaaJb8c4RwYvFLTOAS8opQvsMYUN/gOE6tmaj zEHA5efKwdmRUDlLLbEtmzd5tiB5xIpvaf3Hvsu6W1KWoDWStPRY+emj6tCY24ABph0h9NMfIug3f 69eMQvsfJVljDQlfDcGEpNJdD9FZhlQOjOl6TriGX2ddkhDSruIWYb7r0JCWYNsy7hE1EY2D84/ia /DVoPH5ZeVtv54s6kR+w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pVhkG-004KGi-W5; Fri, 24 Feb 2023 23:44:57 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pVhkC-004KEg-Cv for linux-arm-kernel@lists.infradead.org; Fri, 24 Feb 2023 23:44:55 +0000 Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 31OLS0KR009914; Fri, 24 Feb 2023 23:44:32 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=message-id : date : mime-version : from : subject : to : cc : references : in-reply-to : content-type : content-transfer-encoding; s=qcppdkim1; bh=LyAFSt8ovm7kNNn40sLG7l2+9PseoG3munN0NNC+q98=; b=DWSt7nnjKCf9jZ4NFvyC/alEJQznMk61Znc8vSckgmW+CEJgA6bBNrBYBZUggTF8PsUT TylqABiyV9c0RySSLAPdPgEiAtA7jy3JdRTilAW+cR+ctrslKrY4JUyVrXOdKZVusph0 QJ/rIOKHD+2ZO7J0lWcd8ZseiKWNOLhVAiO4aFtWl19dFYZP5LYR1Cjg+x8W6nXlo5fb H7mRn+16vJneqCZSNkH+G7yNkH7Py9g2qJBwyPCFABFUfVRAr813OxO/R5cXtmho9V+i mW1217qkhBFwxn8PMtKA49mJqh3LzvemY/ZyaHCw+5xJiGoDZtkueXYoGhF/eaVdkx3o og== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3nxwb7sp6m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 24 Feb 2023 23:44:31 +0000 Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 31ONiVdD013327 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 24 Feb 2023 23:44:31 GMT Received: from [10.110.9.108] (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; Fri, 24 Feb 2023 15:44:29 -0800 Message-ID: <87a34969-5c19-6a2d-e708-399411823c0b@quicinc.com> Date: Fri, 24 Feb 2023 15:44:29 -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 From: Elliot Berman Subject: Re: [PATCH v10 19/26] gunyah: vm_mgr: Add framework to add VM Functions To: Srinivas Kandagatla , Alex Elder , Prakruthi Deepak Heragu , Jonathan Corbet 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 , Bagas Sanjaya , Catalin Marinas , Jassi Brar , , , , , References: <20230214211229.3239350-1-quic_eberman@quicinc.com> <20230214212531.3323284-1-quic_eberman@quicinc.com> <2cd83439-8518-f2a1-42b5-c5936f3e4548@linaro.org> Content-Language: en-US In-Reply-To: <2cd83439-8518-f2a1-42b5-c5936f3e4548@linaro.org> X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) 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: VyzzYgdLyTCCFPhmlNeYQXGgPCCgH9-d X-Proofpoint-ORIG-GUID: VyzzYgdLyTCCFPhmlNeYQXGgPCCgH9-d 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-24_17,2023-02-24_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 suspectscore=0 phishscore=0 clxscore=1015 priorityscore=1501 mlxscore=0 spamscore=0 bulkscore=0 adultscore=0 impostorscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2302240192 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230224_154452_511944_F1CF9ABC X-CRM114-Status: GOOD ( 50.87 ) 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 CgpPbiAyLzIyLzIwMjMgNjowOCBBTSwgU3Jpbml2YXMgS2FuZGFnYXRsYSB3cm90ZToKPiAKPiAK PiBPbiAxNC8wMi8yMDIzIDIxOjI1LCBFbGxpb3QgQmVybWFuIHdyb3RlOgo+Pgo+PiBJbnRyb2R1 Y2UgYSBmcmFtZXdvcmsgZm9yIEd1bnlhaCB1c2Vyc3BhY2UgdG8gaW5zdGFsbCBWTSBmdW5jdGlv bnMuIFZNCj4+IGZ1bmN0aW9ucyBhcmUgb3B0aW9uYWwgaW50ZXJmYWNlcyB0byB0aGUgdmlydHVh bCBtYWNoaW5lLiB2Q1BVcywKPj4gaW9ldmVudGZzLCBhbmQgaXJxZmRzIGFyZSBleGFtcGxlcyBv ZiBzdWNoIFZNIGZ1bmN0aW9ucyBhbmQgYXJlCj4+IGltcGxlbWVudGVkIGluIHN1YnNlcXVlbnQg cGF0Y2hlcy4KPj4KPj4gQSBnZW5lcmljIGZyYW1ld29yayBpcyBpbXBsZW1lbnRlZCBpbnN0ZWFk IG9mIGluZGl2aWR1YWwgaW9jdGxzIHRvCj4+IGNyZWF0ZSB2Q1BVcywgaXJxZmRzLCBldGMuLCBp biBvcmRlciB0byBzaW1wbGlmeSB0aGUgVk0gbWFuYWdlciBjb3JlCj4+IGltcGxlbWVudGF0aW9u IGFuZCBhbGxvdyBkeW5hbWljIGxvYWRpbmcgb2YgVk0gZnVuY3Rpb24gbW9kdWxlcy4KPj4KPj4g U2lnbmVkLW9mZi1ieTogRWxsaW90IEJlcm1hbiA8cXVpY19lYmVybWFuQHF1aWNpbmMuY29tPgo+ PiAtLS0KPj4gwqAgRG9jdW1lbnRhdGlvbi92aXJ0L2d1bnlhaC92bS1tYW5hZ2VyLnJzdCB8wqAg MTggKysKPj4gwqAgZHJpdmVycy92aXJ0L2d1bnlhaC92bV9tZ3IuY8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCB8IDI0MCArKysrKysrKysrKysrKysrKysrKysrLQo+PiDCoCBkcml2ZXJzL3ZpcnQv Z3VueWFoL3ZtX21nci5owqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHzCoMKgIDMgKwo+PiDCoCBp bmNsdWRlL2xpbnV4L2d1bnlhaF92bV9tZ3IuaMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgfMKgIDgw ICsrKysrKysrCj4+IMKgIGluY2x1ZGUvdWFwaS9saW51eC9ndW55YWguaMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgIHzCoCAxNyArKwo+PiDCoCA1IGZpbGVzIGNoYW5nZWQsIDM1MyBpbnNlcnRp b25zKCspLCA1IGRlbGV0aW9ucygtKQo+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS9s aW51eC9ndW55YWhfdm1fbWdyLmgKPj4KPj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vdmly dC9ndW55YWgvdm0tbWFuYWdlci5yc3QgCj4+IGIvRG9jdW1lbnRhdGlvbi92aXJ0L2d1bnlhaC92 bS1tYW5hZ2VyLnJzdAo+PiBpbmRleCBjMDEyNmNmZWFkYzcuLjUyNzJhNmU5MTQ1YyAxMDA2NDQK Pj4gLS0tIGEvRG9jdW1lbnRhdGlvbi92aXJ0L2d1bnlhaC92bS1tYW5hZ2VyLnJzdAo+PiArKysg Yi9Eb2N1bWVudGF0aW9uL3ZpcnQvZ3VueWFoL3ZtLW1hbmFnZXIucnN0Cj4+IEBAIC0xNyw2ICsx NywyNCBAQCBzaGFyaW5nIHVzZXJzcGFjZSBtZW1vcnkgd2l0aCBhIFZNIGlzIGRvbmUgdmlhIHRo ZSAKPj4gR0hfVk1fU0VUX1VTRVJfTUVNX1JFR0lPTgo+PiDCoCBpb2N0bC4gVGhlIFZNIGl0c2Vs ZiBpcyBjb25maWd1cmVkIHRvIHVzZSB0aGUgbWVtb3J5IHJlZ2lvbiB2aWEgdGhlCj4+IMKgIGRl dmljZXRyZWUuCj4+ICtHdW55YWggRnVuY3Rpb25zCj4+ICs9PT09PT09PT09PT09PT09Cj4+ICsK Pj4gK0NvbXBvbmVudHMgb2YgYSBHdW55YWggVk0ncyBjb25maWd1cmF0aW9uIHRoYXQgbmVlZCBr ZXJuZWwgCj4+IGNvbmZpZ3VyYXRpb24gYXJlCj4+ICtjYWxsZWQgImZ1bmN0aW9ucyIgYW5kIGFy ZSBidWlsdCBvbiB0b3Agb2YgYSBmcmFtZXdvcmsuIEZ1bmN0aW9ucyBhcmUgCj4+IGlkZW50aWZp ZWQKPj4gK2J5IGEgc3RyaW5nIGFuZCBoYXZlIHNvbWUgYXJndW1lbnQocykgdG8gY29uZmlndXJl IHRoZW0uIFRoZXkgYXJlIAo+PiB0eXBpY2FsbHkKPj4gK2NyZWF0ZWQgYnkgdGhlIGBHSF9WTV9B RERfRlVOQ1RJT05gIGlvY3RsLgo+PiArCj4+ICtGdW5jdGlvbnMgdHlwaWNhbGx5IHdpbGwgYWx3 YXlzIGRvIGF0IGxlYXN0IG9uZSBvZiB0aGVzZSBvcGVyYXRpb25zOgo+PiArCj4+ICsxLiBDcmVh dGUgcmVzb3VyY2UgdGlja2V0KHMpLiBSZXNvdXJjZSB0aWNrZXRzIGFsbG93IGEgZnVuY3Rpb24g dG8gCj4+IHJlZ2lzdGVyCj4+ICvCoMKgIGl0c2VsZiBhcyB0aGUgY2xpZW50IGZvciBhIEd1bnlh aCByZXNvdXJjZSAoZS5nLiBkb29yYmVsbCBvciB2Q1BVKSAKPj4gYW5kCj4+ICvCoMKgIHRoZSBm dW5jdGlvbiBpcyBnaXZlbiB0aGUgcG9pbnRlciB0byB0aGUgYHN0cnVjdCBndW55YWhfcmVzb3Vy Y2VgIAo+PiB3aGVuIHRoZQo+PiArwqDCoCBWTSBpcyBzdGFydGluZy4KPj4gKwo+PiArMi4gUmVn aXN0ZXIgSU8gaGFuZGxlcihzKS4gSU8gaGFuZGxlcnMgYWxsb3cgYSBmdW5jdGlvbiB0byBoYW5k bGUgCj4+IHN0YWdlLTIgZmF1bHRzCj4+ICvCoMKgIGZyb20gdGhlIHZpcnR1YWwgbWFjaGluZS4K Pj4gKwo+PiDCoCBTYW1wbGUgVXNlcnNwYWNlIFZNTQo+PiDCoCA9PT09PT09PT09PT09PT09PT09 PQo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy92aXJ0L2d1bnlhaC92bV9tZ3IuYyBiL2RyaXZlcnMv dmlydC9ndW55YWgvdm1fbWdyLmMKPj4gaW5kZXggZmEzMjQzODVhZGU1Li5lOWM1NWU3ZGQxYjMg MTAwNjQ0Cj4+IC0tLSBhL2RyaXZlcnMvdmlydC9ndW55YWgvdm1fbWdyLmMKPj4gKysrIGIvZHJp dmVycy92aXJ0L2d1bnlhaC92bV9tZ3IuYwo+PiBAQCAtNiw4ICs2LDEwIEBACj4+IMKgICNkZWZp bmUgcHJfZm10KGZtdCkgImdoX3ZtX21ncjogIiBmbXQKPj4gwqAgI2luY2x1ZGUgPGxpbnV4L2Fu b25faW5vZGVzLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvY29tcGF0Lmg+Cj4+IMKgICNpbmNsdWRl IDxsaW51eC9maWxlLmg+Cj4+IMKgICNpbmNsdWRlIDxsaW51eC9ndW55YWhfcnNjX21nci5oPgo+ PiArI2luY2x1ZGUgPGxpbnV4L2d1bnlhaF92bV9tZ3IuaD4KPj4gwqAgI2luY2x1ZGUgPGxpbnV4 L21pc2NkZXZpY2UuaD4KPj4gwqAgI2luY2x1ZGUgPGxpbnV4L21tLmg+Cj4+IMKgICNpbmNsdWRl IDxsaW51eC9tb2R1bGUuaD4KPj4gQEAgLTE2LDYgKzE4LDE3NyBAQAo+PiDCoCAjaW5jbHVkZSAi dm1fbWdyLmgiCj4+ICtzdGF0aWMgREVGSU5FX01VVEVYKGZ1bmN0aW9uc19sb2NrKTsKPj4gK3N0 YXRpYyBERUZJTkVfSURSKGZ1bmN0aW9ucyk7Cj4gV2h5IGFyZSB0aGVzZSBnbG9iYWw/IENhbiB0 aGVzZSBiZSBub3QgcGFydCBvZiBzdHJ1YyBnaF9ybT8KCklmIEkgbWFrZSB0aGUgbGlzdCBwYXJ0 IG9mIGdoX3JtLCB0aGUgY29yZSBndW55YWggZnJhbWV3b3JrIHdvdWxkIG5lZWQgCnRvIGtub3cg YW5kIGJlIGRlcGVuZGVudCBvbiBhbGwgcG9zc2libGUgVk0gZnVuY3Rpb25zLiBUaGlzIHByZXZl bnRzIApDT05GSUdfR1VOWUFIPXkgYW5kIENPTkZJR19HVU5ZQUhfSVJRRkQ9bSAob3IgYW55IG90 aGVyIGZ1bmN0aW9uIGZyb20gCmJlaW5nIGVuYWJsZWQgYXMgYSBtb2R1bGUpLiBJIGFsc28gc2Vl IGEgMi13YXkgZGVwZW5kZW5jeSB3aGVuIGVuYWJsZWQgCmFsbCBlbmFibGVkIGFzIG1vZHVsZXMu IFRoaXMgYXBwcm9hY2ggc2VlbXMgdmFzdGx5IHNpbXBsZXIuCgo+IE5vdCB0byBtZW50aW9uIHBs ZWFzZSBtb3ZlIGlkciB0byB4YXJyYXlzLgo+IAoKRG9uZS4KCj4+ICsKPj4gK2ludCBnaF92bV9m dW5jdGlvbl9yZWdpc3RlcihzdHJ1Y3QgZ2hfdm1fZnVuY3Rpb24gKmRydikKPj4gK3sKPj4gK8Kg wqDCoCBpbnQgcmV0ID0gMDsKPj4gKwo+PiArwqDCoMKgIGlmICghZHJ2LT5iaW5kIHx8ICFkcnYt PnVuYmluZCkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRUlOVkFMOwo+PiArCj4+ICvCoMKg wqAgbXV0ZXhfbG9jaygmZnVuY3Rpb25zX2xvY2spOwo+PiArwqDCoMKgIGlmIChpZHJfZmluZCgm ZnVuY3Rpb25zLCBkcnYtPnR5cGUpKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXQgPSAtRUVYSVNU Owo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBvdXQ7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKg wqAgSU5JVF9MSVNUX0hFQUQoJmRydi0+aW5zdGFuY2VzKTsKPj4gK8KgwqDCoCByZXQgPSBpZHJf YWxsb2MoJmZ1bmN0aW9ucywgZHJ2LCBkcnYtPnR5cGUsIGRydi0+dHlwZSArIDEsIAo+PiBHRlBf S0VSTkVMKTsKPj4gK8KgwqDCoCBpZiAocmV0ID4gMCkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldCA9 IDA7Cj4+ICtvdXQ6Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2NrKCZmdW5jdGlvbnNfbG9jayk7Cj4+ ICvCoMKgwqAgcmV0dXJuIHJldDsKPj4gK30KPj4gK0VYUE9SVF9TWU1CT0xfR1BMKGdoX3ZtX2Z1 bmN0aW9uX3JlZ2lzdGVyKTsKPj4gKwo+PiArc3RhdGljIHZvaWQgZ2hfdm1fcmVtb3ZlX2Z1bmN0 aW9uX2luc3RhbmNlKHN0cnVjdCAKPj4gZ2hfdm1fZnVuY3Rpb25faW5zdGFuY2UgKmluc3QpCj4+ ICvCoMKgwqAgX19tdXN0X2hvbGQoZnVuY3Rpb25zX2xvY2spCj4+ICt7Cj4+ICvCoMKgwqAgaW5z dC0+Zm4tPnVuYmluZChpbnN0KTsKPj4gK8KgwqDCoCBsaXN0X2RlbCgmaW5zdC0+dm1fbGlzdCk7 Cj4+ICvCoMKgwqAgbGlzdF9kZWwoJmluc3QtPmZuX2xpc3QpOwo+PiArwqDCoMKgIG1vZHVsZV9w dXQoaW5zdC0+Zm4tPm1vZCk7Cj4+ICvCoMKgwqAgaWYgKGluc3QtPmFyZ19zaXplKQo+PiArwqDC oMKgwqDCoMKgwqAga2ZyZWUoaW5zdC0+YXJncCk7Cj4+ICvCoMKgwqAga2ZyZWUoaW5zdCk7Cj4+ ICt9Cj4+ICsKPj4gK3ZvaWQgZ2hfdm1fZnVuY3Rpb25fdW5yZWdpc3RlcihzdHJ1Y3QgZ2hfdm1f ZnVuY3Rpb24gKmZuKQo+PiArewo+PiArwqDCoMKgIHN0cnVjdCBnaF92bV9mdW5jdGlvbl9pbnN0 YW5jZSAqaW5zdCwgKml0ZXI7Cj4+ICsKPj4gK8KgwqDCoCBtdXRleF9sb2NrKCZmdW5jdGlvbnNf bG9jayk7Cj4+ICvCoMKgwqAgbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGluc3QsIGl0ZXIsICZm bi0+aW5zdGFuY2VzLGZuX2xpc3QpCj4+ICvCoMKgwqDCoMKgwqDCoCBnaF92bV9yZW1vdmVfZnVu Y3Rpb25faW5zdGFuY2UoaW5zdCk7Cj4gCj4gV2Ugc2hvdWxkIG5ldmVyIGhhdmUgYW55IGluc3Rh bmNlcyBhcyB3ZSBoYXZlIHJlZmNvdW50ZWQgdGhlIG1vZHVsZS4KPiAKPiBJZiB0aGVyZSBhcmUg YW55IGluc3RhbmNlcyB0aGVuIGl0cyBjbGVhcmx5IGEgYnVnLCBhcyB0aGlzIHdpbGwgcHVsbCBv dXQgCj4gZnVuY3Rpb24gdW5kZXIgdGhlIGhvb2Qgd2hpbGUgdXNlcnNwYWNlIGlzIHVzaW5nIGl0 Lgo+IAo+IAoKRG9uZS4KCj4+ICvCoMKgwqAgaWRyX3JlbW92ZSgmZnVuY3Rpb25zLCBmbi0+dHlw ZSk7Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2NrKCZmdW5jdGlvbnNfbG9jayk7Cj4+ICt9Cj4+ICtF WFBPUlRfU1lNQk9MX0dQTChnaF92bV9mdW5jdGlvbl91bnJlZ2lzdGVyKTsKPj4gKwo+PiArc3Rh dGljIGxvbmcgZ2hfdm1fYWRkX2Z1bmN0aW9uKHN0cnVjdCBnaF92bSAqZ2h2bSwgc3RydWN0IGdo X2ZuX2Rlc2MgKmYpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2luc3Rh bmNlICppbnN0Owo+PiArwqDCoMKgIHZvaWQgX191c2VyICphcmdwOwo+PiArwqDCoMKgIGxvbmcg ciA9IDA7Cj4+ICsKPj4gK8KgwqDCoCBpZiAoZi0+YXJnX3NpemUgPiBHSF9GTl9NQVhfQVJHX1NJ WkUpCj4gCj4gbGV0cyBwcmludCBzb21lIHVzZWZ1bCBlcnJvciBtZXNzYWdlIHRvIHVzZXIuCj4g Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPj4gKwo+PiArwqDCoMKgIGluc3Qg PSBremFsbG9jKHNpemVvZigqaW5zdCksIEdGUF9LRVJORUwpOwo+PiArwqDCoMKgIGlmICghaW5z dCkKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRU5PTUVNOwo+PiArCj4+ICvCoMKgwqAgaW5z dC0+YXJnX3NpemUgPSBmLT5hcmdfc2l6ZTsKPj4gK8KgwqDCoCBpZiAoaW5zdC0+YXJnX3NpemUp IHsKPj4gK8KgwqDCoMKgwqDCoMKgIGluc3QtPmFyZ3AgPSBremFsbG9jKGluc3QtPmFyZ19zaXpl LCBHRlBfS0VSTkVMKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGlmICghaW5zdC0+YXJnKSB7Cj4+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIHIgPSAtRU5PTUVNOwo+PiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCBnb3RvZnJlZTsKPj4gK8KgwqDCoMKgwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgwqDCoMKg wqAgYXJncCA9IGlzX2NvbXBhdF90YXNrKCkgPyBjb21wYXRfcHRyKGYtPmFyZykgOiAodm9pZCBf X3VzZXIgCj4+ICopIGYtPmFyZzsKPiAKPiBobW0sIGFyZyBpcyBub3QgYSBkYXRhIHBvaW50ZXIg aXQgaXMgYSBmaXhlZCBzaXplIHZhcmlhYmxlIChfX3U2NCBhcmcpLCAKPiBzbyB3aHkgYXJlIHVz aW5nIGNvbXBhdF9wdHIoKSBoZXJlPwo+IAo+IHlvdSBzaG91bGQgYmUgYWJsZSB0byBkbwo+IAo+ IGFyZ3AgPSB1NjRfdG9fdXNlcl9wdHIoZi0+YXJnKTsKPiAKCkRvbmUuCgo+PiArwqDCoMKgwqDC oMKgwqAgaWYgKGNvcHlfZnJvbV91c2VyKGluc3QtPmFyZ3AsIGFyZ3AsIGYtPmFyZ19zaXplKSkg ewo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCByID0gLUVGQVVMVDsKPj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqAgZ290b2ZyZWVfYXJnOwo+PiArwqDCoMKgwqDCoMKgwqAgfQo+PiArwqDCoMKg IH0gZWxzZSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBpbnN0LT5hcmcgPSBmLT5hcmc7Cj4gYml0IGxv c3QgaGVyZSwgc28sIHdlIHRyZWF0IHRoZSBhcmcgYXMgYm90aCBwb2ludGVyIGFuZCB2YWx1ZSBp biBjYXNlcyAKPiB3aGVyZSBzaXplIGlzIHplcm8uCj4gCgpUaGF0J3MgY29ycmVjdCAtLSBhcmcg aXMgdmFsdWUgaW4gY2FzZXMgd2hlcmUgc2l6ZSBpcyB6ZXJvLiBJdCBtaWdodCBiZSAKYSBiaXQg dG9vIHN0cmFuZ2UsIGFuZCBJJ20gbm90IG9wcG9zZWQgdG8gYWx3YXlzIHRyZWF0aW5nIGFyZyBh cyBwb2ludGVyIAp3aGVuIHNpemUgPj0gMCBhbmQgbm9uZSBvZiB0aGUgImFyZyBpcyB2YWx1ZSIu IEluIHZDUFUgYW5kIHNldmVyYWwgb3RoZXIgCnBvc3NpYmxlIGZ1bmN0aW9ucyB3ZSBoYXZlIChw cmVzZW50bHkpIGRvd25zdHJlYW0sIHRoZSBvbmx5IGFyZ3VtZW50IGEgCm9ubHkgYSAzMi1iaXQg aW50ZWdlciBsYWJlbC4gSSB0aG91Z2h0IGl0IHdvdWxkIGJlIGdvb2QgdG8gb3B0aW1pemUgdGhp cyAKcGF0aC4KCj4+ICvCoMKgwqAgfQo+PiArCj4gPC0tLQo+PiArwqDCoMKgIG11dGV4X2xvY2so JmZ1bmN0aW9uc19sb2NrKTsKPj4gK8KgwqDCoCBpbnN0LT5mbiA9IGlkcl9maW5kKCZmdW5jdGlv bnMsIGYtPnR5cGUpOwo+PiArwqDCoMKgIGlmICghaW5zdC0+Zm4pIHsKPj4gK8KgwqDCoMKgwqDC oMKgIG11dGV4X3VubG9jaygmZnVuY3Rpb25zX2xvY2spOwo+PiArwqDCoMKgwqDCoMKgwqAgciA9 IHJlcXVlc3RfbW9kdWxlKCJnaGZ1bmM6JWQiLCBmLT50eXBlKTsKPj4gK8KgwqDCoMKgwqDCoMKg IGlmIChyKQo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBnb3RvdW5sb2NrX2ZyZWU7Cj4+ICsK Pj4gK8KgwqDCoMKgwqDCoMKgIG11dGV4X2xvY2soJmZ1bmN0aW9uc19sb2NrKTsKPj4gK8KgwqDC oMKgwqDCoMKgIGluc3QtPmZuID0gaWRyX2ZpbmQoJmZ1bmN0aW9ucywgZi0+dHlwZSk7Cj4+ICvC oMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgaWYgKCFpbnN0LT5mbikgewo+PiArwqDCoMKgwqDCoMKg wqAgciA9IC1FTk9FTlQ7Cj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIHVubG9ja19mcmVlOwo+PiAr wqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGlmICghdHJ5X21vZHVsZV9nZXQoaW5zdC0+Zm4tPm1v ZCkpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIHIgPSAtRU5PRU5UOwo+PiArwqDCoMKgwqDCoMKgwqAg aW5zdC0+Zm4gPSBOVUxMOwo+PiArwqDCoMKgwqDCoMKgwqAgZ290byB1bmxvY2tfZnJlZTsKPj4g K8KgwqDCoCB9Cj4+ICsKPiAtLS0+Cj4gY2FuIHdlIGRvIHRoaXMgc25pcHBldCBhcyBhIGdoX3Zt X2dldF9mdW5jdGlvbigpIGFuZCBjb3JyZXNwb25kaW5nIAo+IGdoX3ZtX3B1dF9mdW5jdGlvbigp LiB0aGF0IHNob3VsZCBtYWtlIHRoZSBjb2RlIG1vcmUgY2xlYW5lci4KPiAKCkRvbmUuCgo+IAo+ PiArwqDCoMKgIGluc3QtPmdodm0gPSBnaHZtOwo+PiArwqDCoMKgIGluc3QtPnJtID0gZ2h2bS0+ cm07Cj4+ICsKPj4gK8KgwqDCoCByID0gaW5zdC0+Zm4tPmJpbmQoaW5zdCk7Cj4+ICvCoMKgwqAg aWYgKHIgPCAwKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBtb2R1bGVfcHV0KGluc3QtPmZuLT5tb2Qp Owo+PiArwqDCoMKgwqDCoMKgwqAgZ290byB1bmxvY2tfZnJlZTsKPj4gK8KgwqDCoCB9Cj4+ICsK Pj4gK8KgwqDCoCBsaXN0X2FkZCgmaW5zdC0+dm1fbGlzdCwgJmdodm0tPmZ1bmN0aW9ucyk7Cj4g Cj4gSSBndWVzcyBpdHMgcG9zc2libGUgdG8gYWRkIHNhbWUgZnVuY3Rpb25zIHdpdGggc2FtZSBh cmd1bWVudHNvIHRvIHRoaXMgCj4gbGlzdCwgaG93IGFyZSB3ZSBwcmV2ZW50aW5nIHRoaXMgdG8g aGFwcGVuPwo+IAo+IElzIGl0IGEgdmFsaWQgdXNlY2FzZT8KPiAKCkknbSBub3QgYWJsZSB0byB0 aGluayBvZiBhIGZ1bmN0aW9uIHdoZXJlIHRoaXMgaXMgdmFsaWQuIFRoaXMgaXMgaGFuZGxlZCAK dG9kYXkgYmVjYXVzZSB0aGUgLT5iaW5kKCkgY2FsbGJhY2sgcmV0dXJucyBhbiBlcnJvci4gVGhp cyBoYXBwZW5zIGlmIAp0aGUgcmVzb3VyY2UgdGlja2V0IHdhcyBhbHJlYWR5IGNyZWF0ZWQsIGUu Zy4gc2FtZSB2Q1BVIGlzIHJlcXVlc3RlZCB0d2ljZS4KClRoaXMgc2hvdWxkIGJlIGhhbmRsZWQg YXQgZnVuY3Rpb24gbGV2ZWwgYmVjYXVzZSB0d28gYXJndW1lbnRzIGNvdWxkIGJlIApkaWZmZXJl bnQgYnV0IHJlcXVlc3QgdGhlIHNhbWUgcmVzb3VyY2UuIEZvciBpbnN0YW5jZSwgdHdvIApHSF9W TV9BRERfRlVOQ1RJT04gdG8gY3JlYXRlIGlycWZkIHdpdGggc2FtZSBkb29yYmVsbC4gT25lIGNh bGwgaXMgd2l0aCAKTEVWRUwgZmxhZyBhbmQgdGhlIG90aGVyIGRvZXNuJ3QgaGF2ZSB0aGUgZmxh ZyBzZXQuIE9ubHkgb25jZSB3ZSB0cnkgdG8gCnJlZ2lzdGVyIHRoZSBkb29yYmVsbCByZXNvdXJj ZSB0aWNrZXQgZG8gd2UgcmVhbGl6ZSB0aGF0IDJuZCAKR0hfVk1fQUREX0ZVTkNUSU9OIHNob3Vs ZCBmYWlsLgoKPj4gK8KgwqDCoCBsaXN0X2FkZCgmaW5zdC0+Zm5fbGlzdCwgJmluc3QtPmZuLT5p bnN0YW5jZXMpOwo+PiArwqDCoMKgIG11dGV4X3VubG9jaygmZnVuY3Rpb25zX2xvY2spOwo+PiAr wqDCoMKgIHJldHVybiByOwo+PiArdW5sb2NrX2ZyZWU6Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2Nr KCZmdW5jdGlvbnNfbG9jayk7Cj4+ICtmcmVlX2FyZzoKPj4gK8KgwqDCoCBpZiAoaW5zdC0+YXJn X3NpemUpCj4+ICvCoMKgwqDCoMKgwqDCoCBrZnJlZShpbnN0LT5hcmdwKTsKPj4gK2ZyZWU6Cj4+ ICvCoMKgwqAga2ZyZWUoaW5zdCk7Cj4+ICvCoMKgwqAgcmV0dXJuIHI7Cj4+ICt9Cj4+ICsKPj4g K3N0YXRpYyBsb25nIGdoX3ZtX3JtX2Z1bmN0aW9uKHN0cnVjdCBnaF92bSAqZ2h2bSwgc3RydWN0 IGdoX2ZuX2Rlc2MgKmYpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2lu c3RhbmNlICppbnN0LCAqaXRlcjsKPj4gK8KgwqDCoCB2b2lkIF9fdXNlciAqdXNlcl9hcmdwOwo+ PiArwqDCoMKgIHZvaWQgKmFyZ3A7Cj4+ICvCoMKgwqAgbG9uZyByID0gMDsKPj4gKwo+PiArwqDC oMKgIHIgPSBtdXRleF9sb2NrX2ludGVycnVwdGlibGUoJmZ1bmN0aW9uc19sb2NrKTsKPj4gK8Kg wqDCoCBpZiAocikKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiByOwo+PiArCj4+ICvCoMKgwqAg aWYgKGYtPmFyZ19zaXplKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCBhcmdwID0ga3phbGxvYyhmLT5h cmdfc2l6ZSwgR0ZQX0tFUk5FTCk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAoIWFyZ3ApIHsKPj4g K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgciA9IC1FTk9NRU07Cj4+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIGdvdG9vdXQ7Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+ICsKPj4gK8KgwqDCoMKgwqDC oMKgIHVzZXJfYXJncCA9IGlzX2NvbXBhdF90YXNrKCkgPyBjb21wYXRfcHRyKGYtPmFyZykgOiAo dm9pZCAKPj4gX191c2VyICopIGYtPmFyZzsKPiAKPiBzYW1lIGNvbW1lbnQgYXMgYWRkOwo+IAo+ PiArwqDCoMKgwqDCoMKgwqAgaWYgKGNvcHlfZnJvbV91c2VyKGFyZ3AsIHVzZXJfYXJncCwgZi0+ YXJnX3NpemUpKSB7Cj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHIgPSAtRUZBVUxUOwo+PiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBrZnJlZShhcmdwKTsKPj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqAgZ290b291dDsKPj4gK8KgwqDCoMKgwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgwqDCoMKg wqAgbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGluc3QsIGl0ZXIsICZnaHZtLT5mdW5jdGlvbnMs IAo+PiB2bV9saXN0KSB7Cj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGlmIChpbnN0LT5mbi0+ dHlwZSA9PSBmLT50eXBlICYmCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZi0+ YXJnX3NpemUgPT0gaW5zdC0+YXJnX3NpemUgJiYKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCAhbWVtY21wKGFyZ3AsIGluc3QtPmFyZ3AsIGYtPmFyZ19zaXplKSkKPj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBnaF92bV9yZW1vdmVfZnVuY3Rpb25faW5zdGFuY2Uo aW5zdCk7Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4gCj4gbGVha2luZyBhcmdwOwo+IAoKRG9uZS4K Cj4+ICvCoMKgwqAgfSBlbHNlIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGxpc3RfZm9yX2VhY2hfZW50 cnlfc2FmZShpbnN0LCBpdGVyLCAmZ2h2bS0+ZnVuY3Rpb25zLCAKPj4gdm1fbGlzdCkgewo+PiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpZiAoaW5zdC0+Zm4tPnR5cGUgPT0gZi0+dHlwZSAmJgo+ PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGYtPmFyZ19zaXplID09IGluc3QtPmFy Z19zaXplICYmCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgaW5zdC0+YXJnID09 IGYtPmFyZykKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBnaF92bV9yZW1vdmVf ZnVuY3Rpb25faW5zdGFuY2UoaW5zdCk7Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+ICvCoMKgwqAg fQo+PiArCj4+ICtvdXQ6Cj4+ICvCoMKgwqAgbXV0ZXhfdW5sb2NrKCZmdW5jdGlvbnNfbG9jayk7 Cj4+ICvCoMKgwqAgcmV0dXJuIHI7Cj4+ICt9Cj4+ICsKPj4gwqAgc3RhdGljIGludCBnaF92bV9y bV9ub3RpZmljYXRpb25fc3RhdHVzKHN0cnVjdCBnaF92bSAqZ2h2bSwgdm9pZCAqZGF0YSkKPj4g wqAgewo+PiDCoMKgwqDCoMKgIHN0cnVjdCBnaF9ybV92bV9zdGF0dXNfcGF5bG9hZCAqcGF5bG9h ZCA9IGRhdGE7Cj4+IEBAIC04MCw2ICsyNTMsNyBAQCBzdGF0aWMgdm9pZCBnaF92bV9zdG9wKHN0 cnVjdCBnaF92bSAqZ2h2bSkKPj4gwqAgc3RhdGljIHZvaWQgZ2hfdm1fZnJlZShzdHJ1Y3Qgd29y a19zdHJ1Y3QgKndvcmspCj4+IMKgIHsKPj4gwqDCoMKgwqDCoCBzdHJ1Y3QgZ2hfdm0gKmdodm0g PSBjb250YWluZXJfb2Yod29yayxzdHJ1Y3QgZ2hfdm0sIGZyZWVfd29yayk7Cj4+ICvCoMKgwqAg c3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2luc3RhbmNlICppbnN0LCAqaWl0ZXI7Cj4+IMKgwqDCoMKg wqAgc3RydWN0IGdoX3ZtX21lbSAqbWFwcGluZywgKnRtcDsKPj4gwqDCoMKgwqDCoCBpbnQgcmV0 Owo+PiBAQCAtOTAsNyArMjY0LDEzIEBAIHN0YXRpYyB2b2lkIGdoX3ZtX2ZyZWUoc3RydWN0IHdv cmtfc3RydWN0ICp3b3JrKQo+PiDCoMKgwqDCoMKgwqDCoMKgwqAgZmFsbHRocm91Z2g7Cj4+IMKg wqDCoMKgwqAgY2FzZSBHSF9STV9WTV9TVEFUVVNfSU5JVF9GQUlMRUQ6Cj4+IMKgwqDCoMKgwqAg Y2FzZSBHSF9STV9WTV9TVEFUVVNfTE9BRDoKPj4gLcKgwqDCoCBjYXNlIEdIX1JNX1ZNX1NUQVRV U19MT0FEX0ZBSUxFRDoKPj4gK8KgwqDCoCBjYXNlIEdIX1JNX1ZNX1NUQVRVU19FWElURUQ6Cj4+ ICvCoMKgwqDCoMKgwqDCoCBtdXRleF9sb2NrKCZmdW5jdGlvbnNfbG9jayk7Cj4+ICvCoMKgwqDC oMKgwqDCoCBsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoaW5zdCwgaWl0ZXIsICZnaHZtLT5mdW5j dGlvbnMsIAo+PiB2bV9saXN0KSB7Cj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGdoX3ZtX3Jl bW92ZV9mdW5jdGlvbl9pbnN0YW5jZShpbnN0KTsKPj4gK8KgwqDCoMKgwqDCoMKgIH0KPj4gK8Kg wqDCoMKgwqDCoMKgIG11dGV4X3VubG9jaygmZnVuY3Rpb25zX2xvY2spOwo+PiArCj4+IMKgwqDC oMKgwqDCoMKgwqDCoCBtdXRleF9sb2NrKCZnaHZtLT5tbV9sb2NrKTsKPj4gwqDCoMKgwqDCoMKg wqDCoMKgIGxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShtYXBwaW5nLCB0bXAsIAo+PiAmZ2h2bS0+ bWVtb3J5X21hcHBpbmdzLCBsaXN0KSB7Cj4+IMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGdo X3ZtX21lbV9yZWNsYWltKGdodm0sIG1hcHBpbmcpOwo+PiBAQCAtMTEzLDYgKzI5MywyOCBAQCBz dGF0aWMgdm9pZCBnaF92bV9mcmVlKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKPj4gwqDCoMKg wqDCoCB9Cj4+IMKgIH0KPj4gK3N0YXRpYyB2b2lkIF9naF92bV9wdXQoc3RydWN0IGtyZWYgKmty ZWYpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IGdoX3ZtICpnaHZtID0gY29udGFpbmVyX29mKGty ZWYsIHN0cnVjdCBnaF92bSwga3JlZik7Cj4+ICsKPj4gK8KgwqDCoCAvKiBWTSB3aWxsIGJlIHJl c2V0IGFuZCBtYWtlIFJNIGNhbGxzIHdoaWNoIGNhbiBpbnRlcnJ1cHRpYmxlIHNsZWVwLgo+PiAr wqDCoMKgwqAgKiBEZWZlciB0byBhIHdvcmsgc28gdGhpcyB0aHJlYWQgY2FuIHJlY2VpdmUgc2ln bmFsLgo+PiArwqDCoMKgwqAgKi8KPj4gK8KgwqDCoCBzY2hlZHVsZV93b3JrKCZnaHZtLT5mcmVl X3dvcmspOwo+PiArfQo+PiArCj4+ICtpbnQgX19tdXN0X2NoZWNrIGdoX3ZtX2dldChzdHJ1Y3Qg Z2hfdm0gKmdodm0pCj4+ICt7Cj4+ICvCoMKgwqAgcmV0dXJuIGtyZWZfZ2V0X3VubGVzc196ZXJv KCZnaHZtLT5rcmVmKTsKPj4gK30KPj4gK0VYUE9SVF9TWU1CT0xfR1BMKGdoX3ZtX2dldCk7Cj4+ ICsKPj4gK3ZvaWQgZ2hfdm1fcHV0KHN0cnVjdCBnaF92bSAqZ2h2bSkKPj4gK3sKPj4gK8KgwqDC oCBrcmVmX3B1dCgmZ2h2bS0+a3JlZiwgX2doX3ZtX3B1dCk7Cj4+ICt9Cj4+ICtFWFBPUlRfU1lN Qk9MX0dQTChnaF92bV9wdXQpOwo+PiArCj4+IMKgIHN0YXRpYyBfX211c3RfY2hlY2sgc3RydWN0 IGdoX3ZtICpnaF92bV9hbGxvYyhzdHJ1Y3QgZ2hfcm0gKnJtKQo+PiDCoCB7Cj4+IMKgwqDCoMKg wqAgc3RydWN0IGdoX3ZtICpnaHZtOwo+PiBAQCAtMTQ3LDYgKzM0OSw4IEBAIHN0YXRpYyBfX211 c3RfY2hlY2sgc3RydWN0IGdoX3ZtIAo+PiAqZ2hfdm1fYWxsb2Moc3RydWN0IGdoX3JtICpybSkK Pj4gwqDCoMKgwqDCoCBJTklUX0xJU1RfSEVBRCgmZ2h2bS0+bWVtb3J5X21hcHBpbmdzKTsKPj4g wqDCoMKgwqDCoCBpbml0X3J3c2VtKCZnaHZtLT5zdGF0dXNfbG9jayk7Cj4+IMKgwqDCoMKgwqAg SU5JVF9XT1JLKCZnaHZtLT5mcmVlX3dvcmssIGdoX3ZtX2ZyZWUpOwo+PiArwqDCoMKgIGtyZWZf aW5pdCgmZ2h2bS0+a3JlZik7Cj4+ICvCoMKgwqAgSU5JVF9MSVNUX0hFQUQoJmdodm0tPmZ1bmN0 aW9ucyk7Cj4+IMKgwqDCoMKgwqAgZ2h2bS0+dm1fc3RhdHVzID0gR0hfUk1fVk1fU1RBVFVTX0xP QUQ7Cj4+IMKgwqDCoMKgwqAgcmV0dXJuIGdodm07Cj4+IEBAIC0yOTEsNiArNDk1LDM1IEBAIHN0 YXRpYyBsb25nIGdoX3ZtX2lvY3RsKHN0cnVjdCBmaWxlICpmaWxwLCAKPj4gdW5zaWduZWQgaW50 IGNtZCwgdW5zaWduZWQgbG9uZyBhcmcpCj4+IMKgwqDCoMKgwqDCoMKgwqDCoCByID0gZ2hfdm1f ZW5zdXJlX3N0YXJ0ZWQoZ2h2bSk7Cj4+IMKgwqDCoMKgwqDCoMKgwqDCoCBicmVhazsKPj4gwqDC oMKgwqDCoCB9Cj4+ICvCoMKgwqAgY2FzZSBHSF9WTV9BRERfRlVOQ1RJT046IHsKPj4gK8KgwqDC oMKgwqDCoMKgIHN0cnVjdCBnaF9mbl9kZXNjICpmOwo+PiArCj4+ICvCoMKgwqDCoMKgwqDCoCBm ID0ga3phbGxvYyhzaXplb2YoKmYpLCBHRlBfS0VSTkVMKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGlm ICghZikKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FTk9NRU07Cj4+ICsKPj4g K8KgwqDCoMKgwqDCoMKgIGlmIChjb3B5X2Zyb21fdXNlcihmLCBhcmdwLCBzaXplb2YoKmYpKSkK Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FRkFVTFQ7Cj4+ICsKPj4gK8KgwqDC oMKgwqDCoMKgIHIgPSBnaF92bV9hZGRfZnVuY3Rpb24oZ2h2bSwgZik7Cj4+ICvCoMKgwqDCoMKg wqDCoCBpZiAociA8IDApCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGtmcmVlKGYpOwo+IAo+ IAo+IHdlIGFyZSBtZW1vcnkgbGVha2luZyBmIGhlcmUsIHdlIHNob3VsZCBmcmVlIGl0IGlycmVz cGVjdGl2ZSBvZiByZXR1cm4gCj4gdmFsdWUuIG9yIEkgc2VlIG5vIHJlYXNvbiBub3QgdG8gdXNl IHRoaXMgc21hbGwgc3RydWN0IGZyb20gc3RhY2suCj4gCgpJIGNhbiBjb3B5IHRvIHN0YWNrIGRp cmVjdGx5LgoKPiAKPj4gK8KgwqDCoMKgwqDCoMKgIGJyZWFrOwo+PiArwqDCoMKgIH0KPj4gK8Kg wqDCoCBjYXNlIEdIX1ZNX1JFTU9WRV9GVU5DVElPTjogewo+PiArwqDCoMKgwqDCoMKgwqAgc3Ry dWN0IGdoX2ZuX2Rlc2MgKmY7Cj4+ICsKPj4gK8KgwqDCoMKgwqDCoMKgIGYgPSBremFsbG9jKHNp emVvZigqZiksIEdGUF9LRVJORUwpOwo+PiArwqDCoMKgwqDCoMKgwqAgaWYgKCFmKQo+PiArwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArwqDCoMKgwqDCoMKg wqAgaWYgKGNvcHlfZnJvbV91c2VyKGYsIGFyZ3AsIHNpemVvZigqZikpKQo+PiArwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCByZXR1cm4gLUVGQVVMVDsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgciA9 IGdoX3ZtX3JtX2Z1bmN0aW9uKGdodm0sIGYpOwo+PiArwqDCoMKgwqDCoMKgwqAga2ZyZWUoZik7 Cj4+ICvCoMKgwqDCoMKgwqDCoCBicmVhazsKPj4gK8KgwqDCoCB9Cj4+IMKgwqDCoMKgwqAgZGVm YXVsdDoKPj4gwqDCoMKgwqDCoMKgwqDCoMKgIHIgPSAtRU5PVFRZOwo+PiDCoMKgwqDCoMKgwqDC oMKgwqAgYnJlYWs7Cj4+IEBAIC0zMDMsMTAgKzUzNiw3IEBAIHN0YXRpYyBpbnQgZ2hfdm1fcmVs ZWFzZShzdHJ1Y3QgaW5vZGUgKmlub2RlLCAKPj4gc3RydWN0IGZpbGUgKmZpbHApCj4+IMKgIHsK Pj4gwqDCoMKgwqDCoCBzdHJ1Y3QgZ2hfdm0gKmdodm0gPSBmaWxwLT5wcml2YXRlX2RhdGE7Cj4+ IC3CoMKgwqAgLyogVk0gd2lsbCBiZSByZXNldCBhbmQgbWFrZSBSTSBjYWxscyB3aGljaCBjYW4g aW50ZXJydXB0aWJsZSBzbGVlcC4KPj4gLcKgwqDCoMKgICogRGVmZXIgdG8gYSB3b3JrIHNvIHRo aXMgdGhyZWFkIGNhbiByZWNlaXZlIHNpZ25hbC4KPj4gLcKgwqDCoMKgICovCj4+IC3CoMKgwqAg c2NoZWR1bGVfd29yaygmZ2h2bS0+ZnJlZV93b3JrKTsKPj4gK8KgwqDCoCBnaF92bV9wdXQoZ2h2 bSk7Cj4+IMKgwqDCoMKgwqAgcmV0dXJuIDA7Cj4+IMKgIH0KPj4gZGlmZiAtLWdpdCBhL2RyaXZl cnMvdmlydC9ndW55YWgvdm1fbWdyLmggYi9kcml2ZXJzL3ZpcnQvZ3VueWFoL3ZtX21nci5oCj4+ IGluZGV4IGU5Y2Y1NjY0N2NjMi4uNDc1MGQ1NmMxMjk3IDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJz L3ZpcnQvZ3VueWFoL3ZtX21nci5oCj4+ICsrKyBiL2RyaXZlcnMvdmlydC9ndW55YWgvdm1fbWdy LmgKPj4gQEAgLTgsNiArOCw3IEBACj4+IMKgICNpbmNsdWRlIDxsaW51eC9ndW55YWhfcnNjX21n ci5oPgo+PiDCoCAjaW5jbHVkZSA8bGludXgvbGlzdC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2ty ZWYuaD4KPj4gwqAgI2luY2x1ZGUgPGxpbnV4L21pc2NkZXZpY2UuaD4KPj4gwqAgI2luY2x1ZGUg PGxpbnV4L211dGV4Lmg+Cj4+IMKgICNpbmNsdWRlIDxsaW51eC9yd3NlbS5oPgo+PiBAQCAtNDQs OCArNDUsMTAgQEAgc3RydWN0IGdoX3ZtIHsKPj4gwqDCoMKgwqDCoCBzdHJ1Y3Qgcndfc2VtYXBo b3JlIHN0YXR1c19sb2NrOwo+PiDCoMKgwqDCoMKgIHN0cnVjdCB3b3JrX3N0cnVjdCBmcmVlX3dv cms7Cj4+ICvCoMKgwqAgc3RydWN0IGtyZWYga3JlZjsKPj4gwqDCoMKgwqDCoCBzdHJ1Y3QgbXV0 ZXggbW1fbG9jazsKPj4gwqDCoMKgwqDCoCBzdHJ1Y3QgbGlzdF9oZWFkIG1lbW9yeV9tYXBwaW5n czsKPj4gK8KgwqDCoCBzdHJ1Y3QgbGlzdF9oZWFkIGZ1bmN0aW9uczsKPj4gwqAgfTsKPj4gwqAg aW50IGdoX3ZtX21lbV9hbGxvYyhzdHJ1Y3QgZ2hfdm0gKmdodm0sIHN0cnVjdCAKPj4gZ2hfdXNl cnNwYWNlX21lbW9yeV9yZWdpb24gKnJlZ2lvbik7Cj4+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xp bnV4L2d1bnlhaF92bV9tZ3IuaCAKPj4gYi9pbmNsdWRlL2xpbnV4L2d1bnlhaF92bV9tZ3IuaAo+ PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwMDAwMDAuLmYwYTk1YWY1MGIy ZQo+PiAtLS0gL2Rldi9udWxsCj4+ICsrKyBiL2luY2x1ZGUvbGludXgvZ3VueWFoX3ZtX21nci5o Cj4+IEBAIC0wLDAgKzEsODAgQEAKPj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwt Mi4wLW9ubHkgKi8KPj4gKy8qCj4+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMjItMjAyMyBRdWFsY29t bSBJbm5vdmF0aW9uIENlbnRlciwgSW5jLiBBbGwgCj4+IHJpZ2h0cyByZXNlcnZlZC4KPj4gKyAq Lwo+PiArCj4+ICsjaWZuZGVmIF9HVU5ZQUhfVk1fTUdSX0gKPj4gKyNkZWZpbmUgX0dVTllBSF9W TV9NR1JfSAo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgvY29tcGlsZXJfdHlwZXMuaD4KPj4gKyNp bmNsdWRlIDxsaW51eC9ndW55YWguaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9ndW55YWhfcnNjX21n ci5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9tb2Rf ZGV2aWNldGFibGUuaD4KPiA/Pwo+IAo+PiArI2luY2x1ZGUgPGxpbnV4L25vdGlmaWVyLmg+Cj4g Cj4gPz8KPiAKPj4gKwo+PiArI2luY2x1ZGUgPHVhcGkvbGludXgvZ3VueWFoLmg+Cj4+ICsKPj4g K3N0cnVjdCBnaF92bTsKPj4gKwo+PiAraW50IF9fbXVzdF9jaGVjayBnaF92bV9nZXQoc3RydWN0 IGdoX3ZtICpnaHZtKTsKPj4gK3ZvaWQgZ2hfdm1fcHV0KHN0cnVjdCBnaF92bSAqZ2h2bSk7Cj4+ ICsKPj4gK3N0cnVjdCBnaF92bV9mdW5jdGlvbl9pbnN0YW5jZTsKPj4gK3N0cnVjdCBnaF92bV9m dW5jdGlvbiB7Cj4+ICvCoMKgwqAgdTMyIHR5cGU7ID4gK8KgwqDCoCBjb25zdCBjaGFyICpuYW1l Owo+PiArwqDCoMKgIHN0cnVjdCBtb2R1bGUgKm1vZDsKPj4gK8KgwqDCoCBsb25nICgqYmluZCko c3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2luc3RhbmNlICpmKTsKPj4gK8KgwqDCoCB2b2lkICgqdW5i aW5kKShzdHJ1Y3QgZ2hfdm1fZnVuY3Rpb25faW5zdGFuY2UgKmYpOwo+PiArwqDCoMKgIHN0cnVj dCBtdXRleCBpbnN0YW5jZXNfbG9jazsKPj4gK8KgwqDCoCBzdHJ1Y3QgbGlzdF9oZWFkIGluc3Rh bmNlczsKPj4gK307Cj4+ICsKPj4gKy8qKgo+PiArICogc3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2lu c3RhbmNlIC0gUmVwcmVzZW50cyBvbmUgZnVuY3Rpb24gaW5zdGFuY2UKPj4gKyAqIEBhcmdfc2l6 ZTogc2l6ZSBvZiB1c2VyIGFyZ3VtZW50Cj4+ICsgKiBAYXJnOiB1c2VyIGFyZ3VtZW50IHRvIGRl c2NyaWJlIHRoZSBmdW5jdGlvbiBpbnN0YW5jZTsgYXJnX3NpemUgaXMgMAo+PiArICogQGFyZ3A6 IHBvaW50ZXIgdG8gdXNlciBhcmd1bWVudAo+PiArICogQGdodm06IFBvaW50ZXIgdG8gVk0gaW5z dGFuY2UKPj4gKyAqIEBybTogUG9pbnRlciB0byByZXNvdXJjZSBtYW5hZ2VyIGZvciB0aGUgVk0g aW5zdGFuY2UKPj4gKyAqIEBmbjogVGhlIG9wcyBmb3IgdGhlIGZ1bmN0aW9uCj4+ICsgKiBAZGF0 YTogUHJpdmF0ZSBkYXRhIGZvciBmdW5jdGlvbgo+PiArICogQHZtX2xpc3Q6IGZvciBnaF92bSdz IGZ1bmN0aW9ucyBsaXN0Cj4+ICsgKiBAZm5fbGlzdDogZm9yIGdoX3ZtX2Z1bmN0aW9uJ3MgaW5z dGFuY2VzIGxpc3QKPj4gKyAqLwo+PiArc3RydWN0IGdoX3ZtX2Z1bmN0aW9uX2luc3RhbmNlIHsK Pj4gK8KgwqDCoCBzaXplX3QgYXJnX3NpemU7Cj4+ICvCoMKgwqAgdW5pb24gewo+PiArwqDCoMKg wqDCoMKgwqAgdTY0IGFyZzsKPj4gK8KgwqDCoMKgwqDCoMKgIHZvaWQgKmFyZ3A7Cj4+ICvCoMKg wqAgfTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfdm0gKmdodm07Cj4+ICvCoMKgwqAgc3RydWN0IGdo X3JtICpybTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZ2hfdm1fZnVuY3Rpb24gKmZuOwo+PiArwqDCoMKg IHZvaWQgKmRhdGE7Cj4+ICvCoMKgwqAgc3RydWN0IGxpc3RfaGVhZCB2bV9saXN0Owo+PiArwqDC oMKgIHN0cnVjdCBsaXN0X2hlYWQgZm5fbGlzdDsKPiBBbSBub3Qgc2VlaW5nIGFueSBhZHZhbnRh Z2Ugb2Ygc3RvcmluZyB0aGUgaW5zdGFuY2UgaW4gdHdvIGRpZmZlcmVudCAKPiBsaXN0LCB0aGV5 IGxvb2sgcmVkdW5kYW50IHRvIG1lLiBzdG9yaW5nIHRoZSBmdW5jdGlvbiBpbnN0YW5jZXMgaW4g dm0gCj4gc2hvdWxkIGJlIGdvb2QgSU1PLgo+IAoKSSB3YXMgY29uY2VybmVkIGFib3V0IHJlbW92 YWwgb2YgZnVuY3Rpb24gb3V0c2lkZSBvZiBtb2R1bGVfcmVtb3ZhbCwgYnV0IAp3ZSBkb24ndCBo YXZlIHJlYXNvbi9hYmlsaXR5IHRvIGRvIGl0LgoKPiAKPj4gK307Cj4+ICsKPj4gK2ludCBnaF92 bV9mdW5jdGlvbl9yZWdpc3RlcihzdHJ1Y3QgZ2hfdm1fZnVuY3Rpb24gKmYpOwo+PiArdm9pZCBn aF92bV9mdW5jdGlvbl91bnJlZ2lzdGVyKHN0cnVjdCBnaF92bV9mdW5jdGlvbiAqZik7Cj4+ICsK Pj4gKyNkZWZpbmUgREVDTEFSRV9HVU5ZQUhfVk1fRlVOQ1RJT04oX25hbWUsIF90eXBlLCBfYmlu ZCwgX3VuYmluZCnCoMKgwqAgXAo+PiArwqDCoMKgIHN0YXRpYyBzdHJ1Y3QgZ2hfdm1fZnVuY3Rp b24gX25hbWUgPSB7wqDCoMKgwqDCoMKgwqAgXAo+PiArwqDCoMKgwqDCoMKgwqAgLnR5cGUgPSBf dHlwZSzCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIFwKPj4g K8KgwqDCoMKgwqDCoMKgIC5uYW1lID0gX19zdHJpbmdpZnkoX25hbWUpLMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoCBcCj4+ICvCoMKgwqDCoMKgwqDCoCAubW9kID0gVEhJU19NT0RVTEUs wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgXAo+PiArwqDCoMKgwqDCoMKg wqAgLmJpbmQgPSBfYmluZCzCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIFwKPj4gK8KgwqDCoMKgwqDCoMKgIC51bmJpbmQgPSBfdW5iaW5kLMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIFwKPj4gK8KgwqDCoCB9O8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIFwKPj4gK8Kg wqDCoCBNT0RVTEVfQUxJQVMoImdoZnVuYzoiX19zdHJpbmdpZnkoX3R5cGUpKQo+PiArCj4+ICsj ZGVmaW5lIG1vZHVsZV9ndW55YWhfdm1fZnVuY3Rpb24oX19nZinCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCBcCj4+ICvCoMKgwqAgbW9kdWxlX2RyaXZlcihfX2dmLCBnaF92 bV9mdW5jdGlvbl9yZWdpc3RlciwgCj4+IGdoX3ZtX2Z1bmN0aW9uX3VucmVnaXN0ZXIpCj4+ICsK Pj4gKyNkZWZpbmUgREVDTEFSRV9HVU5ZQUhfVk1fRlVOQ1RJT05fSU5JVChfbmFtZSwgX3R5cGUs IF9iaW5kLCAKPj4gX3VuYmluZCnCoMKgwqAgXAo+PiArwqDCoMKgIERFQ0xBUkVfR1VOWUFIX1ZN X0ZVTkNUSU9OKF9uYW1lLCBfdHlwZSwgX2JpbmQsIF91bmJpbmQpO8KgwqDCoCBcCj4+ICvCoMKg wqAgbW9kdWxlX2d1bnlhaF92bV9mdW5jdGlvbihfbmFtZSkKPj4gKwo+PiArI2VuZGlmCj4+IGRp ZmYgLS1naXQgYS9pbmNsdWRlL3VhcGkvbGludXgvZ3VueWFoLmggYi9pbmNsdWRlL3VhcGkvbGlu dXgvZ3VueWFoLmgKPj4gaW5kZXggZDg5OWJiYTZhNGM2Li44ZGY0NTVhMmEyOTMgMTAwNjQ0Cj4+ IC0tLSBhL2luY2x1ZGUvdWFwaS9saW51eC9ndW55YWguaAo+PiArKysgYi9pbmNsdWRlL3VhcGkv bGludXgvZ3VueWFoLmgKPj4gQEAgLTY2LDQgKzY2LDIxIEBAIHN0cnVjdCBnaF92bV9kdGJfY29u ZmlnIHsKPj4gwqAgI2RlZmluZSBHSF9WTV9TVEFSVMKgwqDCoMKgwqDCoMKgIF9JTyhHSF9JT0NU TF9UWVBFLCAweDMpCj4+ICsjZGVmaW5lIEdIX0ZOX01BWF9BUkdfU0laRcKgwqDCoMKgwqDCoMKg IDI1Ngo+PiArCj4+ICsvKioKPj4gKyAqIHN0cnVjdCBnaF9mbl9kZXNjIC0gQXJndW1lbnRzIHRv IGNyZWF0ZSBhIFZNIGZ1bmN0aW9uCj4+ICsgKiBAdHlwZTogVHlwZSBvZiB0aGUgZnVuY3Rpb24u IFNlZSBHSF9GTl8qIG1hY3JvIGZvciBzdXBwb3J0ZWQgdHlwZXMKPj4gKyAqIEBhcmdfc2l6ZTog U2l6ZSBvZiBhcmd1bWVudCB0byBwYXNzIHRvIHRoZSBmdW5jdGlvbgo+IAo+IGEgbm90ZSBvbiBt YXggYXJnIHNpemXCoCBvZiAyNTYgYnl0ZXMgd291bGQgYmUgdXNlZnVsLgo+IAo+PiArICogQGFy ZzogVmFsdWUgb3IgcG9pbnRlciB0byBhcmd1bWVudCBnaXZlbiB0byB0aGUgZnVuY3Rpb24KPiAK PiBUcmVhdGluZyB0aGlzIGFzIHZhbHVlIHdoZW4gYXJnX3NpemUgPT0gMCBpcyByZWFsbHkgY29u ZnVzaW5nIGFiaS4KPiBob3cgYWJvdXQganVzdCB1c2UgYXMgYXJnIGFzIHB0ciB0byBkYXRhIGFs b25nIHdpdGggYXJnX3NpemU7Cj4gCj4gLS1zcmluaQo+PiArICovCj4+ICtzdHJ1Y3QgZ2hfZm5f ZGVzYyB7Cj4+ICvCoMKgwqAgX191MzIgdHlwZTsKPj4gK8KgwqDCoCBfX3UzMiBhcmdfc2l6ZTsK Pj4gK8KgwqDCoCBfX3U2NCBhcmc7Cj4+ICt9Owo+PiArCj4+ICsjZGVmaW5lIEdIX1ZNX0FERF9G VU5DVElPTsKgwqDCoCBfSU9XKEdIX0lPQ1RMX1RZUEUsIDB4NCwgc3RydWN0IAo+PiBnaF9mbl9k ZXNjKQo+PiArI2RlZmluZSBHSF9WTV9SRU1PVkVfRlVOQ1RJT07CoMKgwqAgX0lPVyhHSF9JT0NU TF9UWVBFLCAweDcsIHN0cnVjdCAKPj4gZ2hfZm5fZGVzYykKPiAKPiBEbyB5b3UgaGF2ZSBhbiBl eGFtcGxlIG9mIGhvdyBhZGQgYW5kIHJtIGlvY3RscyBhcmUgdXNlZCB3LnIudCB0byBhcmcsIGkg Cj4gc2VlIHRoYXQgd2UgY2hlY2sgY29ycmVjdGVuZXNzIG9mIGFyZyBpbiBiZXR3ZWVuIGFkZCBh bmQgcmVtb3ZlLgo+IAo+IC0tc3JpbmkKPj4gKwo+PiDCoCAjZW5kaWYKCl9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGlu ZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK