misc: fastrpc: Add support for create remote init process
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Fri, 8 Feb 2019 17:11:26 +0000 (17:11 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Feb 2019 09:40:30 +0000 (10:40 +0100)
This patch adds support to create or attach remote shell process.
The shell process called fastrpc_shell_0 is usually loaded on the DSP
when a user process is spawned.

Most of the work is derived from various downstream Qualcomm kernels.
Credits to various Qualcomm authors who have contributed to this code.
Specially Tharun Kumar Merugu <mtharu@codeaurora.org>

Co-developed-by: Thierry Escande <thierry.escande@linaro.org>
Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/fastrpc.c
include/uapi/misc/fastrpc.h

index cd69f8b308f67931084f82fe63dae0aec381e69d..ceb498487569951a05887f50ae7d64b6268172fc 100644 (file)
 #define FASTRPC_MAX_CRCLIST    64
 #define FASTRPC_PHYS(p)        ((p) & 0xffffffff)
 #define FASTRPC_CTX_MAX (256)
+#define FASTRPC_INIT_HANDLE    1
 #define FASTRPC_CTXID_MASK (0xFF0)
+#define INIT_FILELEN_MAX (2 * 1024 * 1024)
+#define INIT_MEMLEN_MAX  (8 * 1024 * 1024)
 #define FASTRPC_DEVICE_NAME    "fastrpc"
 
 /* Retrives number of input buffers from the scalars parameter */
 #define FASTRPC_SCALARS(method, in, out) \
                FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0)
 
+#define FASTRPC_CREATE_PROCESS_NARGS   6
+/* Remote Method id table */
+#define FASTRPC_RMID_INIT_ATTACH       0
+#define FASTRPC_RMID_INIT_RELEASE      1
+#define FASTRPC_RMID_INIT_CREATE       6
+#define FASTRPC_RMID_INIT_CREATE_ATTR  7
+#define FASTRPC_RMID_INIT_CREATE_STATIC        8
+
 #define miscdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, miscdev)
 
 static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp",
@@ -688,6 +699,109 @@ bail:
        return err;
 }
 
+static int fastrpc_init_create_process(struct fastrpc_user *fl,
+                                       char __user *argp)
+{
+       struct fastrpc_init_create init;
+       struct fastrpc_invoke_args *args;
+       struct fastrpc_phy_page pages[1];
+       struct fastrpc_map *map = NULL;
+       struct fastrpc_buf *imem = NULL;
+       int memlen;
+       int err;
+       struct {
+               int pgid;
+               u32 namelen;
+               u32 filelen;
+               u32 pageslen;
+               u32 attrs;
+               u32 siglen;
+       } inbuf;
+       u32 sc;
+
+       args = kcalloc(FASTRPC_CREATE_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
+       if (!args)
+               return -ENOMEM;
+
+       if (copy_from_user(&init, argp, sizeof(init))) {
+               err = -EFAULT;
+               goto bail;
+       }
+
+       if (init.filelen > INIT_FILELEN_MAX) {
+               err = -EINVAL;
+               goto bail;
+       }
+
+       inbuf.pgid = fl->tgid;
+       inbuf.namelen = strlen(current->comm) + 1;
+       inbuf.filelen = init.filelen;
+       inbuf.pageslen = 1;
+       inbuf.attrs = init.attrs;
+       inbuf.siglen = init.siglen;
+       fl->pd = 1;
+
+       if (init.filelen && init.filefd) {
+               err = fastrpc_map_create(fl, init.filefd, init.filelen, &map);
+               if (err)
+                       goto bail;
+       }
+
+       memlen = ALIGN(max(INIT_FILELEN_MAX, (int)init.filelen * 4),
+                      1024 * 1024);
+       err = fastrpc_buf_alloc(fl, fl->sctx->dev, memlen,
+                               &imem);
+       if (err) {
+               fastrpc_map_put(map);
+               goto bail;
+       }
+
+       fl->init_mem = imem;
+       args[0].ptr = (u64)(uintptr_t)&inbuf;
+       args[0].length = sizeof(inbuf);
+       args[0].fd = -1;
+
+       args[1].ptr = (u64)(uintptr_t)current->comm;
+       args[1].length = inbuf.namelen;
+       args[1].fd = -1;
+
+       args[2].ptr = (u64) init.file;
+       args[2].length = inbuf.filelen;
+       args[2].fd = init.filefd;
+
+       pages[0].addr = imem->phys;
+       pages[0].size = imem->size;
+
+       args[3].ptr = (u64)(uintptr_t) pages;
+       args[3].length = 1 * sizeof(*pages);
+       args[3].fd = -1;
+
+       args[4].ptr = (u64)(uintptr_t)&inbuf.attrs;
+       args[4].length = sizeof(inbuf.attrs);
+       args[4].fd = -1;
+
+       args[5].ptr = (u64)(uintptr_t) &inbuf.siglen;
+       args[5].length = sizeof(inbuf.siglen);
+       args[5].fd = -1;
+
+       sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
+       if (init.attrs)
+               sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+
+       err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+                                     sc, args);
+
+       if (err) {
+               fastrpc_map_put(map);
+               fastrpc_buf_free(imem);
+       }
+
+bail:
+       kfree(args);
+
+       return err;
+}
+
 static struct fastrpc_session_ctx *fastrpc_session_alloc(
                                        struct fastrpc_channel_ctx *cctx)
 {
@@ -715,6 +829,23 @@ static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
        spin_unlock(&cctx->lock);
 }
 
+static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
+{
+       struct fastrpc_invoke_args args[1];
+       int tgid = 0;
+       u32 sc;
+
+       tgid = fl->tgid;
+       args[0].ptr = (u64)(uintptr_t) &tgid;
+       args[0].length = sizeof(tgid);
+       args[0].fd = -1;
+       args[0].reserved = 0;
+       sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0);
+
+       return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+                                      sc, &args[0]);
+}
+
 static int fastrpc_device_release(struct inode *inode, struct file *file)
 {
        struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
@@ -722,6 +853,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
        struct fastrpc_invoke_ctx *ctx, *n;
        struct fastrpc_map *map, *m;
 
+       fastrpc_release_current_dsp_process(fl);
+
        spin_lock(&cctx->lock);
        list_del(&fl->user);
        spin_unlock(&cctx->lock);
@@ -773,6 +906,23 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
        return 0;
 }
 
+static int fastrpc_init_attach(struct fastrpc_user *fl)
+{
+       struct fastrpc_invoke_args args[1];
+       int tgid = fl->tgid;
+       u32 sc;
+
+       args[0].ptr = (u64)(uintptr_t) &tgid;
+       args[0].length = sizeof(tgid);
+       args[0].fd = -1;
+       args[0].reserved = 0;
+       sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0);
+       fl->pd = 0;
+
+       return fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
+                                      sc, &args[0]);
+}
+
 static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp)
 {
        struct fastrpc_invoke_args *args = NULL;
@@ -814,6 +964,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
        case FASTRPC_IOCTL_INVOKE:
                err = fastrpc_invoke(fl, argp);
                break;
+       case FASTRPC_IOCTL_INIT_ATTACH:
+               err = fastrpc_init_attach(fl);
+               break;
+       case FASTRPC_IOCTL_INIT_CREATE:
+               err = fastrpc_init_create_process(fl, argp);
+               break;
        default:
                err = -ENOTTY;
                break;
index a69ef33dc37e94d6fa84a1770c63a9b96d43b643..32d191c3b7bc8fca4f0b7db201090327b4de09e5 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/types.h>
 
 #define FASTRPC_IOCTL_INVOKE           _IOWR('R', 3, struct fastrpc_invoke)
+#define FASTRPC_IOCTL_INIT_ATTACH      _IO('R', 4)
+#define FASTRPC_IOCTL_INIT_CREATE      _IOWR('R', 5, struct fastrpc_init_create)
 
 struct fastrpc_invoke_args {
        __u64 ptr;
@@ -20,4 +22,12 @@ struct fastrpc_invoke {
        __u64 args;
 };
 
+struct fastrpc_init_create {
+       __u32 filelen;  /* elf file length */
+       __s32 filefd;   /* fd for the file */
+       __u32 attrs;
+       __u32 siglen;
+       __u64 file;     /* pointer to elf file */
+};
+
 #endif /* __QCOM_FASTRPC_H__ */