Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3469531d authored by Sathish Ambley's avatar Sathish Ambley Committed by Jeevan Shriram
Browse files

msm: ADSPRPC: Support for secure context banks



Add support for secure session that checks whether the
buffer being passed was allocated from a secure heap and
appropriately maps the buffers in the secure context bank.

Change-Id: If590f65d033e264c04f0ad782895b02765ff4f3d
Signed-off-by: default avatarSathish Ambley <sathishambley@codeaurora.org>
parent 06761098
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -957,6 +957,12 @@
		compatible = "qcom,msm-fastrpc-adsp";
		qcom,fastrpc-glink;

		qcom,msm_fastrpc_cpz_cb1 {
			compatible = "qcom,msm-fastrpc-compute-cb";
			label = "adsprpc-smd";
			iommus = <&lpass_q6_smmu 2>;
			qcom,secure-context-bank;
		};
		qcom,msm_fastrpc_compute_cb1 {
			compatible = "qcom,msm-fastrpc-compute-cb";
			label = "adsprpc-smd";
+236 −141
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@

#define RPC_TIMEOUT	(5 * HZ)
#define BALIGN		128
#define NUM_CHANNELS	3		/*1 compute 1 cpz 1 mdsp*/
#define NUM_SESSIONS	8		/*8 compute*/
#define NUM_CHANNELS	3		/*1 adsp, 1 mdsp*/
#define NUM_SESSIONS	9		/*8 compute, 1 cpz*/

#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)

@@ -131,6 +131,7 @@ struct smq_invoke_ctx {
	remote_arg_t *lpra;
	remote_arg64_t *rpra;
	int *fds;
	unsigned *attrs;
	struct fastrpc_mmap **maps;
	struct fastrpc_buf *buf;
	ssize_t used;
@@ -151,11 +152,13 @@ struct fastrpc_smmu {
	int cb;
	int enabled;
	int faults;
	int secure;
};

struct fastrpc_session_ctx {
	struct device *dev;
	struct fastrpc_smmu smmu;
	int used;
};

struct fastrpc_channel_ctx {
@@ -167,7 +170,6 @@ struct fastrpc_channel_ctx {
	struct completion work;
	struct notifier_block nb;
	struct kref kref;
	unsigned long bitmap;
	int channel;
	int sesscount;
	int ssrcount;
@@ -215,6 +217,8 @@ struct fastrpc_mmap {
	int refs;
	uintptr_t raddr;
	int uncached;
	int secure;
	uintptr_t attr;
};

struct fastrpc_file {
@@ -224,6 +228,7 @@ struct fastrpc_file {
	struct hlist_head bufs;
	struct fastrpc_ctx_lst clst;
	struct fastrpc_session_ctx *sctx;
	struct fastrpc_session_ctx *secsctx;
	uint32_t mode;
	int tgid;
	int cid;
@@ -421,9 +426,11 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_file *fl;
	int vmid;
	struct fastrpc_session_ctx *sess;

	if (!map)
		return;
	fl = map->fl;
	if (map->flags == ADSP_MMAP_HEAP_ADDR) {
		spin_lock(&me->hlock);
		map->refs--;
@@ -431,18 +438,6 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
			hlist_del_init(&map->hn);
		spin_unlock(&me->hlock);
	} else {
		int destVM[1] = {VMID_HLOS};
		int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};

		fl = map->fl;
		vmid = fl->apps->channel[fl->cid].vmid;
		if (vmid) {
			int srcVM[2] = {VMID_HLOS, vmid};

			hyp_assign_phys(map->phys, buf_page_size(map->size),
				srcVM, 2, destVM, destVMperm, 1);
		}

		spin_lock(&fl->hlock);
		map->refs--;
		if (!map->refs)
@@ -451,6 +446,10 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
	}
	if (map->refs > 0)
		return;
	if (map->secure)
		sess = fl->secsctx;
	else
		sess = fl->sctx;
	if (map->flags == ADSP_MMAP_HEAP_ADDR) {
		DEFINE_DMA_ATTRS(attrs);

@@ -465,15 +464,26 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
					&(map->va), map->phys,	&attrs);
		}
	} else {
		int destVM[1] = {VMID_HLOS};
		int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};

		if (!IS_ERR_OR_NULL(map->handle))
			ion_free(fl->apps->client, map->handle);
		if (fl->sctx->smmu.enabled) {
		if (sess->smmu.enabled) {
			if (map->size || map->phys)
				msm_dma_unmap_sg(fl->sctx->dev,
					map->table->sgl,
					map->table->nents, DMA_BIDIRECTIONAL,
					map->buf);
		}
		vmid = fl->apps->channel[fl->cid].vmid;
		if (vmid && map->phys) {
			int srcVM[2] = {VMID_HLOS, vmid};

			hyp_assign_phys(map->phys, buf_page_size(map->size),
				srcVM, 2, destVM, destVMperm, 1);
		}

		if (!IS_ERR_OR_NULL(map->table))
			dma_buf_unmap_attachment(map->attach, map->table,
					DMA_BIDIRECTIONAL);
@@ -485,11 +495,17 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
	kfree(map);
}

static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va,
			ssize_t len, int mflags, struct fastrpc_mmap **ppmap)
static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure,
					struct fastrpc_session_ctx **session);

static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
	uintptr_t va, ssize_t len, int mflags, struct fastrpc_mmap **ppmap)
{
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_session_ctx *sess = fl->sctx;
	struct fastrpc_session_ctx *sess;
	struct fastrpc_apps *apps = fl->apps;
	int cid = fl->cid;
	struct fastrpc_channel_ctx *chan = &apps->channel[cid];
	struct fastrpc_mmap *map = 0;
	struct dma_attrs attrs;
	phys_addr_t region_start = 0;
@@ -502,11 +518,12 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va,
	VERIFY(err, !IS_ERR_OR_NULL(map));
	if (err)
		goto bail;
	INIT_HLIST_NODE(&map->hn);
	map->flags = mflags;
	map->refs = 1;
	INIT_HLIST_NODE(&map->hn);
	map->fl = fl;
	map->fd = fd;
	map->attr = attr;
	if (mflags == ADSP_MMAP_HEAP_ADDR) {
		map->apps = me;
		map->fl = 0;
@@ -516,6 +533,32 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va,
		map->phys = (uintptr_t)region_start;
		map->size = len;
	} else {
		VERIFY(err, !IS_ERR_OR_NULL(map->handle =
				ion_import_dma_buf(fl->apps->client, fd)));
		if (err)
			goto bail;
		VERIFY(err, !ion_handle_get_flags(fl->apps->client, map->handle,
						&flags));
		if (err)
			goto bail;

		map->uncached = !ION_IS_CACHED(flags);
		if (map->attr & FASTRPC_ATTR_NOVA)
			map->uncached = 1;

		map->secure = flags & ION_FLAG_SECURE;
		if (map->secure) {
			if (!fl->secsctx)
				err = fastrpc_session_alloc(chan, 1,
							&fl->secsctx);
			if (err)
				goto bail;
		}
		if (map->secure)
			sess = fl->secsctx;
		else
			sess = fl->sctx;

		VERIFY(err, !IS_ERR_OR_NULL(map->buf = dma_buf_get(fd)));
		if (err)
			goto bail;
@@ -542,19 +585,13 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va,
			if (err)
				goto bail;
		}
		VERIFY(err, !IS_ERR_OR_NULL(map->handle =
				ion_import_dma_buf(fl->apps->client, fd)));
		if (err)
			goto bail;
		VERIFY(err, !ion_handle_get_flags(fl->apps->client,
							map->handle, &flags));
		if (err)
			goto bail;
		map->uncached = !ION_IS_CACHED(flags);
		map->phys = sg_dma_address(map->table->sgl);
		map->size = sg_dma_len(map->table->sgl);
		if (sess->smmu.cb)
		if (sess->smmu.cb) {
			map->phys += ((uint64_t)sess->smmu.cb << 32);
			map->size = sg_dma_len(map->table->sgl);
		} else {
			map->size = buf_page_size(len);
		}
		vmid = fl->apps->channel[fl->cid].vmid;
		if (vmid) {
			int srcVM[1] = {VMID_HLOS};
@@ -647,14 +684,15 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size,
	return err;
}


static int context_restore_interrupted(struct fastrpc_file *fl,
				       struct fastrpc_ioctl_invoke_fd *invokefd,
				       struct fastrpc_ioctl_invoke_attrs *inv,
				       struct smq_invoke_ctx **po)
{
	int err = 0;
	struct smq_invoke_ctx *ctx = 0, *ictx = 0;
	struct hlist_node *n;
	struct fastrpc_ioctl_invoke *invoke = &invokefd->inv;
	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
	spin_lock(&fl->hlock);
	hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
		if (ictx->pid == current->pid) {
@@ -746,7 +784,7 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx)
static void context_free(struct smq_invoke_ctx *ctx);

static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
			 struct fastrpc_ioctl_invoke_fd *invokefd,
			 struct fastrpc_ioctl_invoke_attrs *invokefd,
			 struct smq_invoke_ctx **po)
{
	int err = 0, bufs, size = 0;
@@ -757,6 +795,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
	bufs = REMOTE_SCALARS_LENGTH(invoke->sc);
	size = bufs * sizeof(*ctx->lpra) + bufs * sizeof(*ctx->maps) +
		sizeof(*ctx->fds) * (bufs) +
		sizeof(*ctx->attrs) * (bufs) +
		sizeof(*ctx->overs) * (bufs) +
		sizeof(*ctx->overps) * (bufs);

@@ -770,7 +809,8 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
	ctx->maps = (struct fastrpc_mmap **)(&ctx[1]);
	ctx->lpra = (remote_arg_t *)(&ctx->maps[bufs]);
	ctx->fds = (int *)(&ctx->lpra[bufs]);
	ctx->overs = (struct overlap *)(&ctx->fds[bufs]);
	ctx->attrs = (unsigned *)(&ctx->fds[bufs]);
	ctx->overs = (struct overlap *)(&ctx->attrs[bufs]);
	ctx->overps = (struct overlap **)(&ctx->overs[bufs]);

	K_COPY_FROM_USER(err, kernel, ctx->lpra, invoke->pra,
@@ -784,6 +824,13 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
		if (err)
			goto bail;
	}
	if (invokefd->attrs) {
		K_COPY_FROM_USER(err, kernel, ctx->attrs, invokefd->attrs,
						bufs * sizeof(*ctx->attrs));
		if (err)
			goto bail;
	}

	ctx->sc = invoke->sc;
	if (bufs)
		context_build_overlap(ctx);
@@ -943,8 +990,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
	for (i = 0; i < bufs; ++i) {
		uintptr_t buf = (uintptr_t)lpra[i].buf.pv;
		ssize_t len = lpra[i].buf.len;
		if (ctx->fds[i])
			fastrpc_mmap_create(ctx->fl, ctx->fds[i], buf, len,

		if (ctx->fds[i] && (ctx->fds[i] != -1))
			fastrpc_mmap_create(ctx->fl, ctx->fds[i],
					ctx->attrs[i], buf, len,
					mflags, &ctx->maps[i]);
		ipage += 1;
	}
@@ -1001,6 +1050,9 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
			int num = buf_num_pages(buf, len);
			int idx = list[i].pgidx;

			if (map->attr & FASTRPC_ATTR_NOVA) {
				offset = (uintptr_t)lpra[i].buf.pv;
			} else {
				down_read(&current->mm->mmap_sem);
				VERIFY(err, NULL != (vma = find_vma(current->mm,
								map->va)));
@@ -1010,10 +1062,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
				}
				offset = buf_page_start(buf) - vma->vm_start;
				up_read(&current->mm->mmap_sem);

				VERIFY(err, offset < (uintptr_t)map->size);
				if (err)
					goto bail;
			}
			pages[idx].addr = map->phys + offset;
			pages[idx].size = num << PAGE_SHIFT;
		}
@@ -1110,14 +1162,20 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
	return err;
}

static void inv_args_pre(uint32_t sc, remote_arg64_t *rpra)
static void inv_args_pre(struct smq_invoke_ctx *ctx)
{
	int i, inbufs, outbufs;
	uint32_t sc = ctx->sc;
	remote_arg64_t *rpra = ctx->rpra;
	uintptr_t end;

	inbufs = REMOTE_SCALARS_INBUFS(sc);
	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
	for (i = inbufs; i < inbufs + outbufs; ++i) {
		struct fastrpc_mmap *map = ctx->maps[i];

		if (map && map->uncached)
			continue;
		if (!rpra[i].buf.len)
			continue;
		if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
@@ -1247,7 +1305,6 @@ static void fastrpc_init(struct fastrpc_apps *me)
	me->channel = &gcinfo[0];
	for (i = 0; i < NUM_CHANNELS; i++) {
		init_completion(&me->channel[i].work);
		me->channel[i].bitmap = 0;
		me->channel[i].sesscount = 0;
	}
}
@@ -1256,16 +1313,16 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl);

static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
				   uint32_t kernel,
				   struct fastrpc_ioctl_invoke_fd *invokefd)
				   struct fastrpc_ioctl_invoke_attrs *inv)
{
	struct smq_invoke_ctx *ctx = 0;
	struct fastrpc_ioctl_invoke *invoke = &invokefd->inv;
	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
	int cid = fl->cid;
	int interrupted = 0;
	int err = 0;

	if (!kernel) {
		VERIFY(err, 0 == context_restore_interrupted(fl, invokefd,
		VERIFY(err, 0 == context_restore_interrupted(fl, inv,
								&ctx));
		if (err)
			goto bail;
@@ -1277,7 +1334,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
			goto wait;
	}

	VERIFY(err, 0 == context_alloc(fl, kernel, invokefd, &ctx));
	VERIFY(err, 0 == context_alloc(fl, kernel, inv, &ctx));
	if (err)
		goto bail;

@@ -1287,7 +1344,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
			goto bail;
	}

	inv_args_pre(ctx->sc, ctx->rpra);
	inv_args_pre(ctx);
	if (FASTRPC_MODE_SERIAL == mode)
		inv_args(ctx);
	VERIFY(err, 0 == fastrpc_invoke_send(ctx, kernel, invoke->handle));
@@ -1324,7 +1381,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
				struct fastrpc_ioctl_init *init)
{
	int err = 0;
	struct fastrpc_ioctl_invoke_fd ioctl;
	struct fastrpc_ioctl_invoke_attrs ioctl;
	struct smq_phy_page pages[1];
	struct fastrpc_mmap *file = 0, *mem = 0;
	if (init->flags == FASTRPC_INIT_ATTACH) {
@@ -1336,6 +1393,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
		ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
		ioctl.inv.pra = ra;
		ioctl.fds = 0;
		ioctl.attrs = 0;
		VERIFY(err, !(err = fastrpc_internal_invoke(fl,
			FASTRPC_MODE_PARALLEL, 1, &ioctl)));
		if (err)
@@ -1353,13 +1411,13 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
		inbuf.pgid = current->tgid;
		inbuf.namelen = strlen(current->comm) + 1;
		inbuf.filelen = init->filelen;
		VERIFY(err, !fastrpc_mmap_create(fl, init->filefd, init->file,
					init->filelen, mflags, &file));
		VERIFY(err, !fastrpc_mmap_create(fl, init->filefd, 0,
				init->file, init->filelen, mflags, &file));
		if (err)
			goto bail;
		inbuf.pageslen = 1;
		VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, init->mem,
					init->memlen, mflags, &mem));
		VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0,
				init->mem, init->memlen, mflags, &mem));
		if (err)
			goto bail;
		inbuf.pageslen = 1;
@@ -1385,6 +1443,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
		ioctl.inv.sc = REMOTE_SCALARS_MAKE(6, 4, 0);
		ioctl.inv.pra = ra;
		ioctl.fds = fds;
		ioctl.attrs = 0;
		VERIFY(err, !(err = fastrpc_internal_invoke(fl,
			FASTRPC_MODE_PARALLEL, 1, &ioctl)));
		if (err)
@@ -1403,7 +1462,7 @@ bail:
static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
{
	int err = 0;
	struct fastrpc_ioctl_invoke_fd ioctl;
	struct fastrpc_ioctl_invoke_attrs ioctl;
	remote_arg_t ra[1];
	int tgid = 0;

@@ -1417,6 +1476,7 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
	ioctl.inv.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
	ioctl.inv.pra = ra;
	ioctl.fds = 0;
	ioctl.attrs = 0;
	VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
		FASTRPC_MODE_PARALLEL, 1, &ioctl)));
bail:
@@ -1426,7 +1486,7 @@ bail:
static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
			       struct fastrpc_mmap *map)
{
	struct fastrpc_ioctl_invoke_fd ioctl;
	struct fastrpc_ioctl_invoke_attrs ioctl;
	struct smq_phy_page page;
	int num = 1;
	remote_arg_t ra[3];
@@ -1462,6 +1522,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
		ioctl.inv.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
	ioctl.inv.pra = ra;
	ioctl.fds = 0;
	ioctl.attrs = 0;
	VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
		FASTRPC_MODE_PARALLEL, 1, &ioctl)));
	map->raddr = (uintptr_t)routargs.vaddrout;
@@ -1485,7 +1546,7 @@ bail:
static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
				 struct fastrpc_mmap *map)
{
	struct fastrpc_ioctl_invoke_fd ioctl;
	struct fastrpc_ioctl_invoke_attrs ioctl;
	struct scm_desc desc = {0};
	remote_arg_t ra[1];
	int err = 0;
@@ -1500,6 +1561,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
	ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1);
	ioctl.inv.pra = ra;
	ioctl.fds = 0;
	ioctl.attrs = 0;

	VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
			FASTRPC_MODE_PARALLEL, 1, &ioctl)));
@@ -1520,7 +1582,7 @@ bail:
static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
				 struct fastrpc_mmap *map)
{
	struct fastrpc_ioctl_invoke_fd ioctl;
	struct fastrpc_ioctl_invoke_attrs ioctl;
	remote_arg_t ra[1];
	int err = 0;
	struct {
@@ -1547,6 +1609,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl,
		ioctl.inv.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
	ioctl.inv.pra = ra;
	ioctl.fds = 0;
	ioctl.attrs = 0;
	VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
		FASTRPC_MODE_PARALLEL, 1, &ioctl)));
bail:
@@ -1605,13 +1668,14 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl,
{
	int err = 0;
	struct fastrpc_mmap *map = 0;
	if (!fastrpc_mmap_remove(fl, ud->vaddrout, ud->size,
				 &map)) {

	VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map));
	if (err)
		goto bail;
	VERIFY(err, !fastrpc_munmap_on_dsp(fl, map));
	if (err)
		goto bail;
	fastrpc_mmap_free(map);
	}
bail:
	if (err && map)
		fastrpc_mmap_add(map);
@@ -1628,8 +1692,8 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl,
			       ud->flags, &map))
		return 0;

	VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, (uintptr_t)ud->vaddrin,
					 ud->size, ud->flags, &map));
	VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0,
			(uintptr_t)ud->vaddrin, ud->size, ud->flags, &map));
	if (err)
		goto bail;
	VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map));
@@ -1664,44 +1728,24 @@ static void fastrpc_channel_close(struct kref *kref)

static void fastrpc_context_list_dtor(struct fastrpc_file *fl);

static int fastrpc_file_free(struct fastrpc_file *fl)
{
	struct hlist_node *n;
	struct fastrpc_mmap *map = 0;
	int cid;

	if (!fl)
		return 0;
	cid = fl->cid;

	spin_lock(&fl->apps->hlock);
	hlist_del_init(&fl->hn);
	spin_unlock(&fl->apps->hlock);

	(void)fastrpc_release_current_dsp_process(fl);
	fastrpc_context_list_dtor(fl);
	fastrpc_buf_list_free(fl);
	hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
		fastrpc_mmap_free(map);
	}
	if (fl->ssrcount == fl->apps->channel[cid].ssrcount)
		kref_put_mutex(&fl->apps->channel[cid].kref,
				fastrpc_channel_close, &fl->apps->smd_mutex);
	kfree(fl);
	return 0;
}

static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int *session)
static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
			int secure, struct fastrpc_session_ctx **session)
{
	struct fastrpc_apps *me = &gfa;
	int idx = 0, err = 0;

	if (chan->sesscount) {
		idx = ffz(chan->bitmap);
		for (idx = 0; idx < chan->sesscount; ++idx) {
			if (!chan->session[idx].used &&
				chan->session[idx].smmu.secure == secure) {
				chan->session[idx].used = 1;
				break;
			}
		}
		VERIFY(err, idx < chan->sesscount);
		if (err)
			goto bail;
		set_bit(idx, &chan->bitmap);
		chan->session[idx].smmu.faults = 0;
	} else {
		VERIFY(err, me->dev != NULL);
		if (err)
@@ -1709,22 +1753,7 @@ static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int *session)
		chan->session[0].dev = me->dev;
	}

	chan->session[idx].smmu.faults = 0;
	*session = idx;
 bail:
	return err;
}

static int fastrpc_session_free(struct fastrpc_channel_ctx *chan, int session)
{
	int err = 0;

	if (chan->sesscount) {
		VERIFY(err, session < chan->sesscount);
		if (err)
			goto bail;
		clear_bit(session, &chan->bitmap);
	}
	*session = &chan->session[idx];
 bail:
	return err;
}
@@ -1772,18 +1801,65 @@ void fastrpc_glink_notify_state(void *handle, const void *priv, unsigned event)
	}
}

static int fastrpc_device_release(struct inode *inode, struct file *file)
static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure,
					struct fastrpc_session_ctx **session)
{
	int err = 0;
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
	int session, cid;

	if (fl) {
	mutex_lock(&me->smd_mutex);
	if (!*session)
		err = fastrpc_session_alloc_locked(chan, secure, session);
	mutex_unlock(&me->smd_mutex);
	return err;
}

static void fastrpc_session_free(struct fastrpc_channel_ctx *chan,
				struct fastrpc_session_ctx *session)
{
	struct fastrpc_apps *me = &gfa;

	mutex_lock(&me->smd_mutex);
	session->used = 0;
	mutex_unlock(&me->smd_mutex);
}

static int fastrpc_file_free(struct fastrpc_file *fl)
{
	struct hlist_node *n;
	struct fastrpc_mmap *map = 0;
	int cid;

	if (!fl)
		return 0;
	cid = fl->cid;
		if (fl->sctx) {
			session = fl->sctx - &me->channel[cid].session[0];
			fastrpc_session_free(&me->channel[cid], session);

	spin_lock(&fl->apps->hlock);
	hlist_del_init(&fl->hn);
	spin_unlock(&fl->apps->hlock);

	(void)fastrpc_release_current_dsp_process(fl);
	fastrpc_context_list_dtor(fl);
	fastrpc_buf_list_free(fl);
	hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
		fastrpc_mmap_free(map);
	}
	if (fl->ssrcount == fl->apps->channel[cid].ssrcount)
		kref_put_mutex(&fl->apps->channel[cid].kref,
				fastrpc_channel_close, &fl->apps->smd_mutex);
	if (fl->sctx)
		fastrpc_session_free(&fl->apps->channel[cid], fl->sctx);
	if (fl->secsctx)
		fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx);
	kfree(fl);
	return 0;
}

static int fastrpc_device_release(struct inode *inode, struct file *file)
{
	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;

	if (fl) {
		fastrpc_file_free(fl);
		file->private_data = 0;
	}
@@ -1842,7 +1918,7 @@ bail:
static int fastrpc_device_open(struct inode *inode, struct file *filp)
{
	int cid = MINOR(inode->i_rdev);
	int err = 0, session;
	int err = 0;
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_file *fl = 0;

@@ -1862,11 +1938,11 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
	fl->tgid = current->tgid;
	fl->apps = me;
	fl->cid = cid;
	VERIFY(err, !fastrpc_session_alloc(&me->channel[cid], &session));
	VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0,
							&fl->sctx));
	if (err)
		goto bail;
	fl->sctx = &me->channel[cid].session[session];

	fl->cid = cid;
	fl->ssrcount = me->channel[cid].ssrcount;
	if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
	    (me->channel[cid].chan == 0)) {
@@ -1916,7 +1992,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
				 unsigned long ioctl_param)
{
	union {
		struct fastrpc_ioctl_invoke_fd invokefd;
		struct fastrpc_ioctl_invoke_attrs inv;
		struct fastrpc_ioctl_mmap mmap;
		struct fastrpc_ioctl_munmap munmap;
		struct fastrpc_ioctl_init init;
@@ -1924,18 +2000,24 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
	void *param = (char *)ioctl_param;
	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
	int size = 0, err = 0;
	p.inv.fds = 0;
	p.inv.attrs = 0;

	switch (ioctl_num) {
	case FASTRPC_IOCTL_INVOKE_FD:
	case FASTRPC_IOCTL_INVOKE:
		p.invokefd.fds = 0;
		size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ?
				sizeof(p.invokefd.inv) : sizeof(p.invokefd);
		VERIFY(err, 0 == copy_from_user(&p.invokefd, param, size));
		size = sizeof(struct fastrpc_ioctl_invoke);
	case FASTRPC_IOCTL_INVOKE_FD:
		if (!size)
			size = sizeof(struct fastrpc_ioctl_invoke_fd);
		/* fall through */
	case FASTRPC_IOCTL_INVOKE_ATTRS:
		if (!size)
			size = sizeof(struct fastrpc_ioctl_invoke_attrs);
		VERIFY(err, 0 == copy_from_user(&p.inv, param, size));
		if (err)
			goto bail;
		VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, fl->mode,
						0, &p.invokefd)));
						0, &p.inv)));
		if (err)
			goto bail;
		break;
@@ -1984,6 +2066,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,

	default:
		err = -ENOTTY;
		pr_info("bad ioctl: %d\n", ioctl_num);
		break;
	}
 bail:
@@ -2064,8 +2147,10 @@ static int fastrpc_cb_probe(struct device *dev)
	struct fastrpc_session_ctx *sess;
	struct of_phandle_args iommuspec;
	const char *name;
	unsigned int start = 0x80000000;
	int err = 0, i;
	int disable_htw = 1;
	int secure_vmid = VMID_CP_PIXEL;

	VERIFY(err, 0 != (name = of_get_property(dev->of_node, "label", NULL)));
	if (err)
@@ -2090,9 +2175,14 @@ static int fastrpc_cb_probe(struct device *dev)
		goto bail;
	sess = &chan->session[chan->sesscount];
	sess->smmu.cb = iommuspec.args[0];
	sess->used = 0;
	sess->smmu.secure = of_property_read_bool(dev->of_node,
						"qcom,secure-context-bank");
	if (sess->smmu.secure)
		start = 0x60000000;
	VERIFY(err, !IS_ERR_OR_NULL(sess->smmu.mapping =
				arm_iommu_create_mapping(&platform_bus_type,
						0x80000000, 0x7fffffff)));
						start, 0x7fffffff)));
	if (err)
		goto bail;
	iommu_domain_set_attr(sess->smmu.mapping->domain,
@@ -2100,6 +2190,11 @@ static int fastrpc_cb_probe(struct device *dev)
				&disable_htw);
	iommu_set_fault_handler(sess->smmu.mapping->domain,
				fastrpc_smmu_fault_handler, sess);
	if (sess->smmu.secure)
		iommu_domain_set_attr(sess->smmu.mapping->domain,
				DOMAIN_ATTR_SECURE_VMID,
				&secure_vmid);

	VERIFY(err, !arm_iommu_attach_device(dev, sess->smmu.mapping));
	if (err)
		goto bail;
+24 −10
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
		_IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
#define COMPAT_FASTRPC_IOCTL_INIT \
		_IOWR('R', 6, struct compat_fastrpc_ioctl_init)
#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
		_IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)

struct compat_remote_buf {
	compat_uptr_t pv;	/* buffer pointer */
@@ -52,6 +54,12 @@ struct compat_fastrpc_ioctl_invoke_fd {
	compat_uptr_t fds;	/* fd list */
};

struct compat_fastrpc_ioctl_invoke_attrs {
	struct compat_fastrpc_ioctl_invoke inv;
	compat_uptr_t fds;	/* fd list */
	compat_uptr_t attrs;	/* attribute list */
};

struct compat_fastrpc_ioctl_mmap {
	compat_int_t fd;	/* ion fd */
	compat_uint_t flags;	/* flags for dsp to map with */
@@ -76,14 +84,14 @@ struct compat_fastrpc_ioctl_init {
};

static int compat_get_fastrpc_ioctl_invoke(
			struct compat_fastrpc_ioctl_invoke_fd __user *inv32,
			struct fastrpc_ioctl_invoke_fd __user **inva,
			struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
			struct fastrpc_ioctl_invoke_attrs __user **inva,
			unsigned int cmd)
{
	compat_uint_t u, sc;
	compat_ssize_t s;
	compat_uptr_t p;
	struct fastrpc_ioctl_invoke_fd *inv;
	struct fastrpc_ioctl_invoke_attrs *inv;
	union compat_remote_arg *pra32;
	union remote_arg *pra;
	int err, len, num, j;
@@ -122,18 +130,23 @@ static int compat_get_fastrpc_ioctl_invoke(
	}

	err |= put_user(NULL, &inv->fds);
	if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_FD) {
	if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
		err |= get_user(p, &inv32->fds);
		err |= put_user(p, (compat_uptr_t *)&inv->fds);
	}
	err |= put_user(NULL, &inv->attrs);
	if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) {
		err |= get_user(p, &inv32->attrs);
		err |= put_user(p, (compat_uptr_t *)&inv->attrs);
	}

	*inva = inv;
	return err;
}

static int compat_put_fastrpc_ioctl_invoke(
			struct compat_fastrpc_ioctl_invoke_fd __user *inv32,
			struct fastrpc_ioctl_invoke_fd __user *inv)
			struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
			struct fastrpc_ioctl_invoke_attrs __user *inv)
{
	compat_uptr_t p;
	compat_uint_t u, h;
@@ -247,9 +260,10 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
	switch (cmd) {
	case COMPAT_FASTRPC_IOCTL_INVOKE:
	case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
	case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
	{
		struct compat_fastrpc_ioctl_invoke_fd __user *inv32;
		struct fastrpc_ioctl_invoke_fd __user *inv;
		struct compat_fastrpc_ioctl_invoke_attrs __user *inv32;
		struct fastrpc_ioctl_invoke_attrs __user *inv;
		long ret;

		inv32 = compat_ptr(arg);
@@ -257,8 +271,8 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
							&inv, cmd));
		if (err)
			return err;
		ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_INVOKE_FD,
							(unsigned long)inv);
		ret = filp->f_op->unlocked_ioctl(filp,
				FASTRPC_IOCTL_INVOKE_ATTRS, (unsigned long)inv);
		if (ret)
			return ret;
		VERIFY(err, 0 == compat_put_fastrpc_ioctl_invoke(inv32, inv));
+17 −6
Original line number Diff line number Diff line
@@ -22,10 +22,15 @@
#define FASTRPC_IOCTL_INVOKE_FD	_IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
#define FASTRPC_IOCTL_SETMODE	_IOWR('R', 5, uint32_t)
#define FASTRPC_IOCTL_INIT	_IOWR('R', 6, struct fastrpc_ioctl_init)
#define FASTRPC_IOCTL_INVOKE_ATTRS \
				_IOWR('R', 7, struct fastrpc_ioctl_invoke_attrs)
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
#define DEVICE_NAME      "adsprpc-smd"

/* Set for buffers that have no virtual mapping in userspace */
#define FASTRPC_ATTR_NOVA 0x1

/* Driver should operate in parallel with the co-processor */
#define FASTRPC_MODE_PARALLEL    0

@@ -125,6 +130,12 @@ struct fastrpc_ioctl_invoke_fd {
	int *fds;		/* fd list */
};

struct fastrpc_ioctl_invoke_attrs {
	struct fastrpc_ioctl_invoke inv;
	int *fds;		/* fd list */
	unsigned *attrs;	/* attribute list */
};

struct fastrpc_ioctl_init {
	uint32_t flags;		/* one of FASTRPC_INIT_* macros */
	uintptr_t __user file;	/* pointer to elf file */