[RFC PATCH 4/6] char: fastrpc: Add support for create remote init process

From: Srinivas Kandagatla
Date: Fri Nov 30 2018 - 05:48:28 EST


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@xxxxxxxxxxxxxx>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx>
---
drivers/char/fastrpc.c | 172 +++++++++++++++++++++++++++++++++++
include/uapi/linux/fastrpc.h | 18 ++++
2 files changed, 190 insertions(+)

diff --git a/drivers/char/fastrpc.c b/drivers/char/fastrpc.c
index 5bb224adc24f..3630e883d3f4 100644
--- a/drivers/char/fastrpc.c
+++ b/drivers/char/fastrpc.c
@@ -30,6 +30,8 @@
#define FASTRPC_PHYS(p) (p & 0xffffffff)
#define FASTRPC_CTX_MAX (256)
#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 */
@@ -59,6 +61,14 @@

#define FASTRPC_SCALARS(method, in, out) \
FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0)
+
+/* 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 cdev_to_cctx(d) container_of(d, struct fastrpc_channel_ctx, cdev)

static const char *domains[FASTRPC_DEV_MAX] = { "adsp", "mdsp",
@@ -735,6 +745,130 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl,

return err;
}
+
+static int fastrpc_init_process(struct fastrpc_user *fl,
+ struct fastrpc_ioctl_init *init)
+{
+ struct fastrpc_ioctl_invoke *ioctl;
+ struct fastrpc_phy_page pages[1];
+ struct fastrpc_map *file = NULL, *mem = NULL;
+ struct fastrpc_buf *imem = NULL;
+ int err = 0;
+
+ ioctl = kzalloc(sizeof(*ioctl), GFP_KERNEL);
+ if (!ioctl)
+ return -ENOMEM;
+
+ if (init->flags == FASTRPC_INIT_ATTACH) {
+ remote_arg_t ra[1];
+ int tgid = fl->tgid;
+
+ ra[0].buf.pv = (void *)&tgid;
+ ra[0].buf.len = sizeof(tgid);
+ ioctl->handle = 1;
+ ioctl->sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_ATTACH, 1, 0);
+ ioctl->pra = ra;
+ fl->pd = 0;
+
+ err = fastrpc_internal_invoke(fl, 1, ioctl);
+ if (err)
+ goto bail;
+ } else if (init->flags == FASTRPC_INIT_CREATE) {
+ int memlen;
+ remote_arg_t ra[6];
+ int fds[6];
+ struct {
+ int pgid;
+ unsigned int namelen;
+ unsigned int filelen;
+ unsigned int pageslen;
+ int attrs;
+ int siglen;
+ } inbuf;
+
+ inbuf.pgid = fl->tgid;
+ inbuf.namelen = strlen(current->comm) + 1;
+ inbuf.filelen = init->filelen;
+ fl->pd = 1;
+
+ if (init->filelen) {
+ err = fastrpc_map_create(fl, init->filefd,
+ init->file, init->filelen,
+ &file);
+ if (err)
+ goto bail;
+ }
+ inbuf.pageslen = 1;
+
+ if (init->mem) {
+ err = -EINVAL;
+ pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n",
+ current->comm, __func__);
+ 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)
+ goto bail;
+
+ fl->init_mem = imem;
+ inbuf.pageslen = 1;
+ ra[0].buf.pv = (void *)&inbuf;
+ ra[0].buf.len = sizeof(inbuf);
+ fds[0] = 0;
+
+ ra[1].buf.pv = (void *)current->comm;
+ ra[1].buf.len = inbuf.namelen;
+ fds[1] = 0;
+
+ ra[2].buf.pv = (void *)init->file;
+ ra[2].buf.len = inbuf.filelen;
+ fds[2] = init->filefd;
+
+ pages[0].addr = imem->phys;
+ pages[0].size = imem->size;
+
+ ra[3].buf.pv = (void *)pages;
+ ra[3].buf.len = 1 * sizeof(*pages);
+ fds[3] = 0;
+
+ inbuf.attrs = init->attrs;
+ ra[4].buf.pv = (void *)&(inbuf.attrs);
+ ra[4].buf.len = sizeof(inbuf.attrs);
+ fds[4] = 0;
+
+ inbuf.siglen = init->siglen;
+ ra[5].buf.pv = (void *)&(inbuf.siglen);
+ ra[5].buf.len = sizeof(inbuf.siglen);
+ fds[5] = 0;
+
+ ioctl->handle = 1;
+ ioctl->sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
+ if (init->attrs)
+ ioctl->sc = FASTRPC_SCALARS(
+ FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+ ioctl->pra = ra;
+ ioctl->fds = fds;
+ err = fastrpc_internal_invoke(fl, 1, ioctl);
+ if (err)
+ goto bail;
+ } else {
+ err = -ENOTTY;
+ }
+bail:
+ kfree(ioctl);
+
+ if (mem && err)
+ fastrpc_map_put(mem);
+
+ if (file)
+ fastrpc_map_put(file);
+
+ return err;
+}
+
static struct fastrpc_session_ctx *fastrpc_session_alloc(
struct fastrpc_channel_ctx *cctx,
int secure)
@@ -769,6 +903,25 @@ static const struct of_device_id fastrpc_match_table[] = {
{}
};

+static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
+{
+ struct fastrpc_ioctl_invoke ioctl;
+ remote_arg_t ra[1];
+ int tgid = 0;
+
+ tgid = fl->tgid;
+ ra[0].buf.pv = (void *)&tgid;
+ ra[0].buf.len = sizeof(tgid);
+ ioctl.handle = 1;
+ ioctl.sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_RELEASE, 1, 0);
+ ioctl.pra = ra;
+ ioctl.fds = NULL;
+ ioctl.attrs = NULL;
+ ioctl.crc = NULL;
+
+ return fastrpc_internal_invoke(fl, 1, &ioctl);
+}
+
static int fastrpc_device_release(struct inode *inode, struct file *file)
{
struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
@@ -776,6 +929,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);
@@ -855,6 +1010,23 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
goto bail;
break;
}
+ case FASTRPC_IOCTL_INIT: {
+ struct fastrpc_ioctl_init init;
+
+ init.attrs = 0;
+ init.siglen = 0;
+ err = copy_from_user(&init, argp, sizeof(init));
+ if (err)
+ goto bail;
+ if (init.filelen > INIT_FILELEN_MAX)
+ goto bail;
+ if (init.memlen > INIT_MEMLEN_MAX)
+ goto bail;
+ err = fastrpc_init_process(fl, &init);
+ if (err)
+ goto bail;
+ }
+ break;
default:
err = -ENOTTY;
pr_info("bad ioctl: %d\n", cmd);
diff --git a/include/uapi/linux/fastrpc.h b/include/uapi/linux/fastrpc.h
index 8fec66601337..6b596fc7ddf3 100644
--- a/include/uapi/linux/fastrpc.h
+++ b/include/uapi/linux/fastrpc.h
@@ -6,6 +6,12 @@
#include <linux/types.h>

#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_ioctl_invoke)
+#define FASTRPC_IOCTL_INIT _IOWR('R', 4, struct fastrpc_ioctl_init)
+
+/* INIT a new process or attach to guestos */
+#define FASTRPC_INIT_ATTACH 0
+#define FASTRPC_INIT_CREATE 1
+#define FASTRPC_INIT_CREATE_STATIC 2

#define remote_arg64_t union remote_arg64

@@ -53,4 +59,16 @@ struct fastrpc_ioctl_invoke {
unsigned int *crc;
};

+struct fastrpc_ioctl_init {
+ uint32_t flags; /* one of FASTRPC_INIT_* macros */
+ uintptr_t file; /* pointer to elf file */
+ uint32_t filelen; /* elf file length */
+ int32_t filefd; /* ION fd for the file */
+ uintptr_t mem; /* mem for the PD */
+ uint32_t memlen; /* mem length */
+ int32_t memfd; /* fd for the mem */
+ int attrs;
+ unsigned int siglen;
+};
+
#endif /* __QCOM_FASTRPC_H__ */
--
2.19.2