From patchwork Thu Feb 22 23:16:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elliot Berman X-Patchwork-Id: 13568235 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F652C47DD9 for ; Thu, 22 Feb 2024 23:17:18 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 516936B0096; Thu, 22 Feb 2024 18:16:47 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 499CA6B0098; Thu, 22 Feb 2024 18:16:47 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 252986B0099; Thu, 22 Feb 2024 18:16:47 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 0B2776B0096 for ; Thu, 22 Feb 2024 18:16:47 -0500 (EST) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id DBE7EA0AAD for ; Thu, 22 Feb 2024 23:16:46 +0000 (UTC) X-FDA: 81821001612.15.A82A164 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by imf20.hostedemail.com (Postfix) with ESMTP id D0F401C000D for ; Thu, 22 Feb 2024 23:16:44 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=quicinc.com header.s=qcppdkim1 header.b=ZYa5PvTE; dmarc=pass (policy=none) header.from=quicinc.com; spf=pass (imf20.hostedemail.com: domain of quic_eberman@quicinc.com designates 205.220.180.131 as permitted sender) smtp.mailfrom=quic_eberman@quicinc.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1708643804; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=hjkuOMml2lLPxrsAbD1E2lRJVtx0etVrUgoraJTr6dw=; b=Fi7EVPSKVVWD5msshgBhG5epbdQ/8bBWuz/j4wQUD5o1wAxa29lbmegJjwuikt3DorTZ/J 8TcJda+W+yY9xjAv1NmtqD2Pbk7PeJYTG9o1vX5Xt7XQ5WFue8FCaT/gctj1VwEho2IYVD DRCMI7k3Qr8chDvFtATPz9BwlfBWO+U= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=quicinc.com header.s=qcppdkim1 header.b=ZYa5PvTE; dmarc=pass (policy=none) header.from=quicinc.com; spf=pass (imf20.hostedemail.com: domain of quic_eberman@quicinc.com designates 205.220.180.131 as permitted sender) smtp.mailfrom=quic_eberman@quicinc.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1708643804; a=rsa-sha256; cv=none; b=qXIrB9OjSQpmYfK/v4OJ0TayEfU4/Hm7lkWsbRczhJ0xs8tVXESscURrQ/cEEPlrfB1/te FoMQ3pZ4+NgdVFy9GSm6FqjheDunx+GXvCmdRRqL0rioKZ2+yxcLZNUkxSd85jJ0lu2yqL qkZFPD44T4EB7P0+TeViCyxggEv2vPI= Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 41MLRZBE019938; Thu, 22 Feb 2024 23:16:36 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= from:date:subject:mime-version:content-type :content-transfer-encoding:message-id:references:in-reply-to:to :cc; s=qcppdkim1; bh=hjkuOMml2lLPxrsAbD1E2lRJVtx0etVrUgoraJTr6dw =; b=ZYa5PvTEjk/l4HzHk7E2mk3n7dwMldK1ZBClQiCLQha8iKxY/fy1X7EgERN rLrNbC0Fax8GD4vjgZzgb2Hg/z1DWrdDyodhHekM24xpG3O2U96N8tdtfAa015qf W+GyyWur7Z8/CyMnTYUD+9XMULOgkxvgWAZWOoM757//wat/3zZQvJiaYMwx7Kl8 NCQCAVlvfHBN+SqrRymFZrC+NTwQ89eTHqH7RRd6cDlRd6s1n560Dldfmfw4W0X5 WmUka47BVpaohG0XLu7+Z8Nn904IYwoRpsvucrqYlF9sg+plKEgk0oEKfDHgyJIN SkMi4cewIEmRIDUW5Fy26zvjjmg== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3we97tgf8b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 22 Feb 2024 23:16:35 +0000 (GMT) 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 41MNGYdX017469 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 22 Feb 2024 23:16:34 GMT Received: from hu-eberman-lv.qualcomm.com (10.49.16.6) 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.1118.40; Thu, 22 Feb 2024 15:16:34 -0800 From: Elliot Berman Date: Thu, 22 Feb 2024 15:16:36 -0800 Subject: [PATCH v17 13/35] gunyah: vm_mgr: Add framework for VM Functions MIME-Version: 1.0 Message-ID: <20240222-gunyah-v17-13-1e9da6763d38@quicinc.com> References: <20240222-gunyah-v17-0-1e9da6763d38@quicinc.com> In-Reply-To: <20240222-gunyah-v17-0-1e9da6763d38@quicinc.com> To: Alex Elder , Srinivas Kandagatla , Murali Nalajal , Trilok Soni , Srivatsa Vaddagiri , Carl van Schaik , Philip Derrin , Prakruthi Deepak Heragu , Jonathan Corbet , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon , Konrad Dybcio , Bjorn Andersson , Dmitry Baryshkov , "Fuad Tabba" , Sean Christopherson , "Andrew Morton" CC: , , , , , , Elliot Berman X-Mailer: b4 0.12.4 X-Originating-IP: [10.49.16.6] X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) 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: G4o5lshGena-Ci4TAmTqxq_ZScpiMa0Z X-Proofpoint-ORIG-GUID: G4o5lshGena-Ci4TAmTqxq_ZScpiMa0Z X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-02-22_15,2024-02-22_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 spamscore=0 bulkscore=0 priorityscore=1501 malwarescore=0 adultscore=0 phishscore=0 lowpriorityscore=0 mlxscore=0 suspectscore=0 mlxlogscore=999 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2402120000 definitions=main-2402220179 X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: D0F401C000D X-Stat-Signature: hrmqdosaioaa1ga5hktwc641g7srnqks X-Rspam-User: X-HE-Tag: 1708643804-783988 X-HE-Meta: U2FsdGVkX1+eV3Y29/Cdo1e0c0CHSzJafCcuKbEYz6V28HS1bOZag1djgK0X2qeGBhxHk8UgeMjltMP6n+ZvLYtXrRWr5hFCjFm2RlxC7HTG/aUI+Oj41F6FR9eIPknUFB2A9ZwEDSyCqRoYreAM0WQNR6DzMPxkgMNIHxJMu4JKYJxKvbetmUCRdMy2HhJllebnjO1WO45bKK9ftK60SvzY0FN3zwhE2Ij3+elaLiHkqCqgXwJBvrGCpJ2y9+mAEPnmJzr6nzgzowBF5h85TZ28kloeW5d6cuydBWcnqHB5L1oJcw/UWGjE3/s0Fn0Qw7P1+S8w3i40wy/52cL/OprpJ+ZznRS5gi71k6p1PFqqlfXmlAA1/VT/TcMiQY8jVyULyi66ZEv+XA5ODcqHGq4TD+741R3q0ji3Q+yvoSiRQSnO8ddhUL7nm2qFfKp2OHb4H2IiI/KV34S2BQAjuRaRsLtBlG9XcINUgjzKpSDSv/bSW7tzE/0lET3ZIuqLAQz/gac66btlqG2dJYdvyxV+sQ4uPoGqxS6R/H8IeLVCDfPfvNOF21Du0zSh4F5pEj341zY7G8I7ZUuehkZtiRmfxXcll2oHSl/tXntiI8QvC5yaY9wcpNqkjRfy1Uy7Q4eEyl+b55wqpfKuzsoiOXt9mMau3Ye0DWG6JKCiMLWO4IsVS+tIMYp83jy7JlvsZStIqBhkf7hJUX05ZgSf0e/ugr9mCZ/BtAa0oJykW/kxBE/DosRPX2lc4NMwFxm+yDdyMekqhFD+mgkT6XHhiDsfPX5IJMJSTO4c0u24c6HjUrvfDf35+UosB0rnnevp2TdHGL9rAlJiprLA2rGSQTInkPRzL2d0u3yGrCtwH2SB6YlX59qA4wv/xD7rPclrK+UPjekCCo+vDPS3sv9iXkvdqlblUcu0KVg6qo8ustFT56vh+4YGud4FdeBtk8uEwZmPej+pfyJ6cwlAPEq F0JcjSM/ MAmdCDy4TEqVoD89HNkrkmGUwH6uWADyCjXoO X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: 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 Reviewed-by: Srivatsa Vaddagiri --- drivers/virt/gunyah/vm_mgr.c | 207 ++++++++++++++++++++++++++++++++++++++++++- drivers/virt/gunyah/vm_mgr.h | 10 +++ include/linux/gunyah.h | 86 +++++++++++++++++- include/uapi/linux/gunyah.h | 18 ++++ 4 files changed, 317 insertions(+), 4 deletions(-) diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c index 2cde4d501204a..a619dd10972a5 100644 --- a/drivers/virt/gunyah/vm_mgr.c +++ b/drivers/virt/gunyah/vm_mgr.c @@ -6,15 +6,175 @@ #define pr_fmt(fmt) "gunyah_vm_mgr: " fmt #include +#include #include #include #include +#include #include #include "rsc_mgr.h" #include "vm_mgr.h" +static DEFINE_XARRAY(gunyah_vm_functions); + +static void gunyah_vm_put_function(struct gunyah_vm_function *fn) +{ + module_put(fn->mod); +} + +static struct gunyah_vm_function *gunyah_vm_get_function(u32 type) +{ + struct gunyah_vm_function *fn; + + fn = xa_load(&gunyah_vm_functions, type); + if (!fn) { + request_module("ghfunc:%d", type); + + fn = xa_load(&gunyah_vm_functions, type); + } + + if (!fn || !try_module_get(fn->mod)) + fn = ERR_PTR(-ENOENT); + + return fn; +} + +static void +gunyah_vm_remove_function_instance(struct gunyah_vm_function_instance *inst) + __must_hold(&inst->ghvm->fn_lock) +{ + inst->fn->unbind(inst); + list_del(&inst->vm_list); + gunyah_vm_put_function(inst->fn); + kfree(inst->argp); + kfree(inst); +} + +static void gunyah_vm_remove_functions(struct gunyah_vm *ghvm) +{ + struct gunyah_vm_function_instance *inst, *iiter; + + mutex_lock(&ghvm->fn_lock); + list_for_each_entry_safe(inst, iiter, &ghvm->functions, vm_list) { + gunyah_vm_remove_function_instance(inst); + } + mutex_unlock(&ghvm->fn_lock); +} + +static long gunyah_vm_add_function_instance(struct gunyah_vm *ghvm, + struct gunyah_fn_desc *f) +{ + struct gunyah_vm_function_instance *inst; + void __user *argp; + long r = 0; + + if (f->arg_size > GUNYAH_FN_MAX_ARG_SIZE) { + dev_err_ratelimited(ghvm->parent, "%s: arg_size > %d\n", + __func__, GUNYAH_FN_MAX_ARG_SIZE); + 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->argp) { + r = -ENOMEM; + goto free; + } + + argp = u64_to_user_ptr(f->arg); + if (copy_from_user(inst->argp, argp, f->arg_size)) { + r = -EFAULT; + goto free_arg; + } + } + + inst->fn = gunyah_vm_get_function(f->type); + if (IS_ERR(inst->fn)) { + r = PTR_ERR(inst->fn); + goto free_arg; + } + + inst->ghvm = ghvm; + inst->rm = ghvm->rm; + + mutex_lock(&ghvm->fn_lock); + r = inst->fn->bind(inst); + if (r < 0) { + mutex_unlock(&ghvm->fn_lock); + gunyah_vm_put_function(inst->fn); + goto free_arg; + } + + list_add(&inst->vm_list, &ghvm->functions); + mutex_unlock(&ghvm->fn_lock); + + return r; +free_arg: + kfree(inst->argp); +free: + kfree(inst); + return r; +} + +static long gunyah_vm_rm_function_instance(struct gunyah_vm *ghvm, + struct gunyah_fn_desc *f) +{ + struct gunyah_vm_function_instance *inst, *iter; + void __user *user_argp; + void *argp __free(kfree) = NULL; + long r = 0; + + if (f->arg_size) { + argp = kzalloc(f->arg_size, GFP_KERNEL); + if (!argp) + return -ENOMEM; + + user_argp = u64_to_user_ptr(f->arg); + if (copy_from_user(argp, user_argp, f->arg_size)) + return -EFAULT; + } + + r = mutex_lock_interruptible(&ghvm->fn_lock); + if (r) + return r; + + r = -ENOENT; + list_for_each_entry_safe(inst, iter, &ghvm->functions, vm_list) { + if (inst->fn->type == f->type && + inst->fn->compare(inst, argp, f->arg_size)) { + gunyah_vm_remove_function_instance(inst); + r = 0; + } + } + + mutex_unlock(&ghvm->fn_lock); + return r; +} + +int gunyah_vm_function_register(struct gunyah_vm_function *fn) +{ + if (!fn->bind || !fn->unbind) + return -EINVAL; + + return xa_err(xa_store(&gunyah_vm_functions, fn->type, fn, GFP_KERNEL)); +} +EXPORT_SYMBOL_GPL(gunyah_vm_function_register); + +void gunyah_vm_function_unregister(struct gunyah_vm_function *fn) +{ + /* Expecting unregister to only come when unloading a module */ + WARN_ON(fn->mod && module_refcount(fn->mod)); + xa_erase(&gunyah_vm_functions, fn->type); +} +EXPORT_SYMBOL_GPL(gunyah_vm_function_unregister); + int gunyah_vm_add_resource_ticket(struct gunyah_vm *ghvm, struct gunyah_vm_resource_ticket *ticket) { @@ -198,7 +358,11 @@ static __must_check struct gunyah_vm *gunyah_vm_alloc(struct gunyah_rm *rm) init_rwsem(&ghvm->status_lock); init_waitqueue_head(&ghvm->vm_status_wait); + kref_init(&ghvm->kref); ghvm->vm_status = GUNYAH_RM_VM_STATUS_NO_STATE; + + INIT_LIST_HEAD(&ghvm->functions); + mutex_init(&ghvm->fn_lock); mutex_init(&ghvm->resources_lock); INIT_LIST_HEAD(&ghvm->resources); INIT_LIST_HEAD(&ghvm->resource_tickets); @@ -311,6 +475,7 @@ static long gunyah_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct gunyah_vm *ghvm = filp->private_data; + void __user *argp = (void __user *)arg; long r; switch (cmd) { @@ -318,6 +483,24 @@ static long gunyah_vm_ioctl(struct file *filp, unsigned int cmd, r = gunyah_vm_ensure_started(ghvm); break; } + case GUNYAH_VM_ADD_FUNCTION: { + struct gunyah_fn_desc f; + + if (copy_from_user(&f, argp, sizeof(f))) + return -EFAULT; + + r = gunyah_vm_add_function_instance(ghvm, &f); + break; + } + case GUNYAH_VM_REMOVE_FUNCTION: { + struct gunyah_fn_desc f; + + if (copy_from_user(&f, argp, sizeof(f))) + return -EFAULT; + + r = gunyah_vm_rm_function_instance(ghvm, &f); + break; + } default: r = -ENOTTY; break; @@ -326,9 +509,15 @@ static long gunyah_vm_ioctl(struct file *filp, unsigned int cmd, return r; } -static int gunyah_vm_release(struct inode *inode, struct file *filp) +int __must_check gunyah_vm_get(struct gunyah_vm *ghvm) { - struct gunyah_vm *ghvm = filp->private_data; + return kref_get_unless_zero(&ghvm->kref); +} +EXPORT_SYMBOL_GPL(gunyah_vm_get); + +static void _gunyah_vm_put(struct kref *kref) +{ + struct gunyah_vm *ghvm = container_of(kref, struct gunyah_vm, kref); int ret; /** @@ -338,6 +527,7 @@ static int gunyah_vm_release(struct inode *inode, struct file *filp) if (ghvm->vm_status == GUNYAH_RM_VM_STATUS_RUNNING) gunyah_vm_stop(ghvm); + gunyah_vm_remove_functions(ghvm); gunyah_vm_clean_resources(ghvm); if (ghvm->vm_status == GUNYAH_RM_VM_STATUS_EXITED || @@ -364,6 +554,19 @@ static int gunyah_vm_release(struct inode *inode, struct file *filp) gunyah_rm_put(ghvm->rm); kfree(ghvm); +} + +void gunyah_vm_put(struct gunyah_vm *ghvm) +{ + kref_put(&ghvm->kref, _gunyah_vm_put); +} +EXPORT_SYMBOL_GPL(gunyah_vm_put); + +static int gunyah_vm_release(struct inode *inode, struct file *filp) +{ + struct gunyah_vm *ghvm = filp->private_data; + + gunyah_vm_put(ghvm); return 0; } diff --git a/drivers/virt/gunyah/vm_mgr.h b/drivers/virt/gunyah/vm_mgr.h index 0d291f7228859..190a95ee8da64 100644 --- a/drivers/virt/gunyah/vm_mgr.h +++ b/drivers/virt/gunyah/vm_mgr.h @@ -7,6 +7,8 @@ #define _GUNYAH_VM_MGR_PRIV_H #include +#include +#include #include #include @@ -26,6 +28,10 @@ long gunyah_dev_vm_mgr_ioctl(struct gunyah_rm *rm, unsigned int cmd, * @vm_status: Current state of the VM, as last reported by RM * @vm_status_wait: Wait queue for status @vm_status changes * @status_lock: Serializing state transitions + * @kref: Reference counter for VM functions + * @fn_lock: Serialization addition of functions + * @functions: List of &struct gunyah_vm_function_instance that have been + * created by user for this VM. * @resource_lock: Serializing addition of resources and resource tickets * @resources: List of &struct gunyah_resource that are associated with this VM * @resource_tickets: List of &struct gunyah_vm_resource_ticket @@ -42,6 +48,10 @@ struct gunyah_vm { enum gunyah_rm_vm_status vm_status; wait_queue_head_t vm_status_wait; struct rw_semaphore status_lock; + + struct kref kref; + struct mutex fn_lock; + struct list_head functions; struct mutex resources_lock; struct list_head resources; struct list_head resource_tickets; diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h index 0017691002607..18ecebf41a3ff 100644 --- a/include/linux/gunyah.h +++ b/include/linux/gunyah.h @@ -11,8 +11,92 @@ #include #include #include +#include #include +#include + +struct gunyah_vm; + +int __must_check gunyah_vm_get(struct gunyah_vm *ghvm); +void gunyah_vm_put(struct gunyah_vm *ghvm); + +struct gunyah_vm_function_instance; +/** + * struct gunyah_vm_function - Represents a function type + * @type: value from &enum gunyah_fn_type + * @name: friendly name for debug purposes + * @mod: owner of the function type + * @bind: Called when a new function of this type has been allocated. + * @unbind: Called when the function instance is being destroyed. + * @compare: Compare function instance @f's argument to the provided arg. + * Return true if they are equivalent. Used on GUNYAH_VM_REMOVE_FUNCTION. + */ +struct gunyah_vm_function { + u32 type; + const char *name; + struct module *mod; + long (*bind)(struct gunyah_vm_function_instance *f); + void (*unbind)(struct gunyah_vm_function_instance *f); + bool (*compare)(const struct gunyah_vm_function_instance *f, + const void *arg, size_t size); +}; + +/** + * struct gunyah_vm_function_instance - Represents one function instance + * @arg_size: size of user argument + * @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 gunyah_vm's functions list + */ +struct gunyah_vm_function_instance { + size_t arg_size; + void *argp; + struct gunyah_vm *ghvm; + struct gunyah_rm *rm; + struct gunyah_vm_function *fn; + void *data; + struct list_head vm_list; +}; + +int gunyah_vm_function_register(struct gunyah_vm_function *f); +void gunyah_vm_function_unregister(struct gunyah_vm_function *f); + +/* Since the function identifiers were setup in a uapi header as an + * enum and we do no want to change that, the user must supply the expanded + * constant as well and the compiler checks they are the same. + * See also MODULE_ALIAS_RDMA_NETLINK. + */ +#define MODULE_ALIAS_GUNYAH_VM_FUNCTION(_type, _idx) \ + static inline void __maybe_unused __chk##_idx(void) \ + { \ + BUILD_BUG_ON(_type != _idx); \ + } \ + MODULE_ALIAS("ghfunc:" __stringify(_idx)) + +#define DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind, _compare) \ + static struct gunyah_vm_function _name = { \ + .type = _type, \ + .name = __stringify(_name), \ + .mod = THIS_MODULE, \ + .bind = _bind, \ + .unbind = _unbind, \ + .compare = _compare, \ + } + +#define module_gunyah_vm_function(__gf) \ + module_driver(__gf, gunyah_vm_function_register, \ + gunyah_vm_function_unregister) + +#define DECLARE_GUNYAH_VM_FUNCTION_INIT(_name, _type, _idx, _bind, _unbind, \ + _compare) \ + DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind, _compare); \ + module_gunyah_vm_function(_name); \ + MODULE_ALIAS_GUNYAH_VM_FUNCTION(_type, _idx) + /* Matches resource manager's resource types for VM_GET_HYP_RESOURCES RPC */ enum gunyah_resource_type { /* clang-format off */ @@ -35,8 +119,6 @@ struct gunyah_resource { u32 rm_label; }; -struct gunyah_vm; - /** * struct gunyah_vm_resource_ticket - Represents a ticket to reserve access to VM resource(s) * @vm_list: for @gunyah_vm->resource_tickets diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h index 31e7f79a6c398..1b7cb5fde70a2 100644 --- a/include/uapi/linux/gunyah.h +++ b/include/uapi/linux/gunyah.h @@ -25,4 +25,22 @@ */ #define GUNYAH_VM_START _IO(GUNYAH_IOCTL_TYPE, 0x3) +#define GUNYAH_FN_MAX_ARG_SIZE 256 + +/** + * struct gunyah_fn_desc - Arguments to create a VM function + * @type: Type of the function. See &enum gunyah_fn_type. + * @arg_size: Size of argument to pass to the function. arg_size <= GUNYAH_FN_MAX_ARG_SIZE + * @arg: Pointer to argument given to the function. See &enum gunyah_fn_type for expected + * arguments for a function type. + */ +struct gunyah_fn_desc { + __u32 type; + __u32 arg_size; + __u64 arg; +}; + +#define GUNYAH_VM_ADD_FUNCTION _IOW(GUNYAH_IOCTL_TYPE, 0x4, struct gunyah_fn_desc) +#define GUNYAH_VM_REMOVE_FUNCTION _IOW(GUNYAH_IOCTL_TYPE, 0x7, struct gunyah_fn_desc) + #endif