On Fri, Jul 04, 2025 at 02:07:26PM +0530, Ekansh Gupta wrote:
> Support mapping userspace allocated buffers. If userspace allocates a
> buffer using rpcmem or DMABUF and sends it via a map request, fastrpc
> will map it to SMMU and DSP. Add support for both map and unmap
> requests.
> 
> Signed-off-by: Ekansh Gupta <[email protected]>
> ---
>  drivers/misc/fastrpc.c | 188 ++++++++++++++++++++++++++++++++---------
>  1 file changed, 150 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index 378923594f02..3c88c8e9ba51 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -1797,17 +1797,16 @@ static int fastrpc_get_dsp_info(struct fastrpc_user 
> *fl, char __user *argp)
>       return 0;
>  }
>  
> -static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct 
> fastrpc_buf *buf)
> +static int fastrpc_req_munmap_dsp(struct fastrpc_user *fl, uintptr_t raddr, 
> u64 size)

uintptr_t is not a valid kernel type, please use our real ones :)

"*u64"?

>  {
>       struct fastrpc_invoke_args args[1] = { [0] = { 0 } };
>       struct fastrpc_munmap_req_msg req_msg;
> -     struct device *dev = fl->sctx->dev;
>       int err;
>       u32 sc;
>  
>       req_msg.client_id = fl->client_id;
> -     req_msg.size = buf->size;
> -     req_msg.vaddr = buf->raddr;
> +     req_msg.size = size;
> +     req_msg.vaddr = raddr;
>  
>       args[0].ptr = (u64) (uintptr_t) &req_msg;
>       args[0].length = sizeof(req_msg);
> @@ -1815,6 +1814,16 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user 
> *fl, struct fastrpc_buf *
>       sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_MUNMAP, 1, 0);
>       err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc,
>                                     &args[0]);
> +
> +     return err;
> +}
> +
> +static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct 
> fastrpc_buf *buf)
> +{
> +     struct device *dev = fl->sctx->dev;
> +     int err;
> +
> +     err = fastrpc_req_munmap_dsp(fl, buf->raddr, buf->size);
>       if (!err) {
>               dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr);
>               spin_lock(&fl->lock);
> @@ -1831,8 +1840,10 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user 
> *fl, struct fastrpc_buf *
>  static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
>  {
>       struct fastrpc_buf *buf = NULL, *iter, *b;
> +     struct fastrpc_map *map = NULL, *iterm, *m;
>       struct fastrpc_req_munmap req;
>       struct device *dev = fl->sctx->dev;
> +     int err;
>  
>       if (copy_from_user(&req, argp, sizeof(req)))
>               return -EFAULT;
> @@ -1846,35 +1857,91 @@ static int fastrpc_req_munmap(struct fastrpc_user 
> *fl, char __user *argp)
>       }
>       spin_unlock(&fl->lock);
>  
> -     if (!buf) {
> -             dev_err(dev, "mmap\t\tpt 0x%09llx [len 0x%08llx] not in list\n",
> +     if (buf) {
> +             err = fastrpc_req_munmap_impl(fl, buf);
> +             if (err) {
> +                     spin_lock(&fl->lock);
> +                     list_add_tail(&buf->node, &fl->mmaps);
> +                     spin_unlock(&fl->lock);
> +             }
> +             return err;
> +     }
> +
> +     spin_lock(&fl->lock);
> +     list_for_each_entry_safe(iterm, m, &fl->maps, node) {
> +             if (iterm->raddr == req.vaddrout) {
> +                     map = iterm;
> +                     list_del(&iterm->node);
> +                     break;
> +             }
> +     }
> +     spin_unlock(&fl->lock);
> +     if (!map) {
> +             dev_dbg(dev, "buffer/map not found addr 0x%09llx, len 
> 0x%08llx\n",
>                       req.vaddrout, req.size);
>               return -EINVAL;
>       }
>  
> -     return fastrpc_req_munmap_impl(fl, buf);
> +     err = fastrpc_req_munmap_dsp(fl, map->raddr, map->size);
> +     if (err) {
> +             dev_dbg(dev, "unmmap\tpt fd = %d, 0x%09llx error\n",  map->fd, 
> map->raddr);
> +             spin_lock(&fl->lock);
> +             list_add_tail(&map->node, &fl->maps);
> +             spin_unlock(&fl->lock);
> +     } else {
> +             fastrpc_map_put(map);
> +     }
> +     return err;
>  }
>  
> -static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
> +static int fastrpc_req_map_dsp(struct fastrpc_user *fl, u64 phys,
> +                            u64 size, u32 flag, uintptr_t vaddrin,
> +                            u64 *raddr)
>  {
>       struct fastrpc_invoke_args args[3] = { [0 ... 2] = { 0 } };
> -     struct fastrpc_buf *buf = NULL;
>       struct fastrpc_mmap_req_msg req_msg;
>       struct fastrpc_mmap_rsp_msg rsp_msg;
>       struct fastrpc_phy_page pages;
> -     struct fastrpc_req_mmap req;
> -     struct device *dev = fl->sctx->dev;
>       int err;
>       u32 sc;
>  
> -     if (copy_from_user(&req, argp, sizeof(req)))
> -             return -EFAULT;
> +     req_msg.client_id = fl->client_id;
> +     req_msg.flags = flag;
> +     req_msg.vaddr = vaddrin;
> +     req_msg.num = sizeof(pages);

No validation of these user-provided values?  Or did I miss where that
happens?

>  
> -     if (req.flags != ADSP_MMAP_ADD_PAGES && req.flags != 
> ADSP_MMAP_REMOTE_HEAP_ADDR) {
> -             dev_err(dev, "flag not supported 0x%x\n", req.flags);
> +     args[0].ptr = (u64)(uintptr_t)&req_msg;

Again, "uintptr_t" isn't for the kernel please.

thanks,

greg k-h

Reply via email to