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