From e8c909db03f42739388fe25d494c5d740ccd7964 Mon Sep 17 00:00:00 2001 From: Prakruthi Deepak Heragu Date: Mon, 24 Feb 2025 14:32:10 -0800 Subject: [PATCH] ANDROID: gunyah: auth_mgr: Introduce auth_mgr within vm_mgr Add an IOCTL to choose the authentication mechanism for a Virtual Machine. vm_mgr can setup differently authenticated VMs based on the ops setup by the auth_mgr chosen by the VMM. Bug: 399219478 Change-Id: Ibb6bb30e3f422e606500c04714cda27b2276baf6 Signed-off-by: Prakruthi Deepak Heragu --- drivers/virt/gunyah/vm_mgr.c | 63 ++++++++++++++++++++++++++++++++++++ include/linux/gunyah.h | 18 +++++++++++ include/uapi/linux/gunyah.h | 36 +++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c index 0395316a4bbd..40198d74fb9a 100644 --- a/drivers/virt/gunyah/vm_mgr.c +++ b/drivers/virt/gunyah/vm_mgr.c @@ -33,6 +33,7 @@ #define GUNYAH_EVENT_DESTROY_VM 1 static DEFINE_XARRAY(gunyah_vm_functions); +static DEFINE_XARRAY(gunyah_auth_vm_mgr); static inline int gunyah_vm_fill_boot_context(struct gunyah_vm *ghvm) { @@ -53,6 +54,59 @@ static inline int gunyah_vm_fill_boot_context(struct gunyah_vm *ghvm) return 0; } +int gunyah_auth_vm_mgr_register(struct gunyah_auth_vm_mgr *auth_vm) +{ + if (!auth_vm->vm_attach || !auth_vm->vm_detach) + return -EINVAL; + + return xa_err(xa_store(&gunyah_auth_vm_mgr, auth_vm->type, auth_vm, GFP_KERNEL)); +} +EXPORT_SYMBOL_GPL(gunyah_auth_vm_mgr_register); + +void gunyah_auth_vm_mgr_unregister(struct gunyah_auth_vm_mgr *auth_vm) +{ + /* Expecting unregister to only come when unloading a module */ + WARN_ON(auth_vm->mod && module_refcount(auth_vm->mod)); + xa_erase(&gunyah_auth_vm_mgr, auth_vm->type); +} +EXPORT_SYMBOL_GPL(gunyah_auth_vm_mgr_unregister); + +static struct gunyah_auth_vm_mgr *gunyah_get_auth_vm_mgr(u32 auth_type) +{ + struct gunyah_auth_vm_mgr *auth_vm; + + auth_vm = xa_load(&gunyah_auth_vm_mgr, auth_type); + if (!auth_vm || !try_module_get(auth_vm->mod)) + auth_vm = ERR_PTR(-ENOENT); + + return auth_vm; +} + +static void gunyah_put_auth_vm_mgr(struct gunyah_vm *ghvm) +{ + struct gunyah_auth_vm_mgr *auth_vm; + + auth_vm = xa_load(&gunyah_auth_vm_mgr, ghvm->auth); + if (!auth_vm) + return; + + auth_vm->vm_detach(ghvm); + module_put(auth_vm->mod); +} + +static long gunyah_vm_set_auth_type(struct gunyah_vm *ghvm, + struct gunyah_auth_desc *auth_desc) +{ + struct gunyah_auth_vm_mgr *auth_vm; + + auth_vm = gunyah_get_auth_vm_mgr(auth_desc->type); + if (IS_ERR(auth_vm)) + return PTR_ERR(auth_vm); + + /* The auth mgr should be populating the auth_vm_mgr_ops*/ + return auth_vm->vm_attach(ghvm, auth_desc); +} + static int gunyah_generic_pre_vm_configure(struct gunyah_vm *ghvm) { /* @@ -1016,6 +1070,14 @@ static long gunyah_vm_ioctl(struct file *filp, unsigned int cmd, return gunyah_vm_set_boot_context(ghvm, &boot_ctx); } + case GH_VM_ANDROID_SET_AUTH_TYPE: { + struct gunyah_auth_desc auth_desc; + + if (copy_from_user(&auth_desc, argp, sizeof(auth_desc))) + return -EFAULT; + + return gunyah_vm_set_auth_type(ghvm, &auth_desc); + } default: r = -ENOTTY; break; @@ -1103,6 +1165,7 @@ static void _gunyah_vm_put(struct kref *kref) xa_for_each(&ghvm->boot_context, index, entry) kfree(entry); + gunyah_put_auth_vm_mgr(ghvm); xa_destroy(&ghvm->boot_context); gunyah_rm_put(ghvm->rm); mmdrop(ghvm->mm_s); diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h index 7219647d89f0..5717b0710c45 100644 --- a/include/linux/gunyah.h +++ b/include/linux/gunyah.h @@ -49,6 +49,24 @@ struct gunyah_auth_vm_mgr_ops { void (*vm_start_fail)(struct gunyah_vm *ghvm); }; +/** + * struct gunyah_auth_vm - Represents an authentication type handler + * @type: value from &enum gunyah_auth_type + * @name: friendly name for debug purposes + * @mod: owner of the auth type + * @vm_attach: attach ops/private_data with the VM. + * @vm_detach: detach ops/private_data with the VM. + */ +struct gunyah_auth_vm_mgr { + u32 type; + const char *name; + struct module *mod; + long (*vm_attach)(struct gunyah_vm *ghvm, struct gunyah_auth_desc *d); + void (*vm_detach)(struct gunyah_vm *ghvm); +}; +int gunyah_auth_vm_mgr_register(struct gunyah_auth_vm_mgr *auth_vm); +void gunyah_auth_vm_mgr_unregister(struct gunyah_auth_vm_mgr *auth_vm); + struct gunyah_vm_function_instance; /** * struct gunyah_vm_function - Represents a function type diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h index a41bedef6fe2..27e746d131df 100644 --- a/include/uapi/linux/gunyah.h +++ b/include/uapi/linux/gunyah.h @@ -420,4 +420,40 @@ struct gunyah_map_cma_mem_args { }; #define GH_VM_ANDROID_MAP_CMA_MEM _IOW(GH_ANDROID_IOCTL_TYPE, 0x15, struct gunyah_map_cma_mem_args) + +/** + * enum gunyah_auth_type - Valid types of authentication supported by Gunyah + */ +enum gunyah_auth_type { + GUNYAH_QCOM_TRUSTED_VM_TYPE = 1, +}; + +/** + * struct gunyah_qtvm_auth_arg - Argument to QTVM auth vm manager + * @vm_id: The VM ID that Gunyah associates with the QTVM. + * @peripheral_id: Also called pas_id which firmware needs for authenticating the QTVM. + * @guest_phys_addr: Address where the VM image should be mapped to. + * @size: Size of the VM image + */ +struct gunyah_qtvm_auth_arg { + __u16 vm_id; + __u32 peripheral_id; + __u64 guest_phys_addr; + __u64 size; +}; + +/** + * struct gunyah_auth_desc - Arguments to match with an auth vm manager + * @type: Type of the authentication mechanism. See &enum gunyah_auth_type. + * @arg_size: Size of argument to pass to the auth vm mgr. arg_size <= GUNYAH_FN_MAX_ARG_SIZE + * @arg: Pointer to argument given to the auth vm mgr. See &enum gunyah_auth_type for expected + * arguments for a function type. + */ +struct gunyah_auth_desc { + __u32 type; + __u32 arg_size; + __u64 arg; +}; +#define GH_VM_ANDROID_SET_AUTH_TYPE _IOW(GH_ANDROID_IOCTL_TYPE, 0x16, \ + struct gunyah_auth_desc) #endif