summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSathish Ambley <sathishambley@codeaurora.org>2015-09-11 14:55:37 -0700
committerJeevan Shriram <jshriram@codeaurora.org>2016-05-19 16:08:07 -0700
commit3469531db393096ed4a93b6849c1d27660480896 (patch)
tree279c48be81867edce072fbe192377bd58f97e892
parent06761098a186c4b64d33d2ed3949408965db3687 (diff)
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: Sathish Ambley <sathishambley@codeaurora.org>
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi6
-rw-r--r--drivers/char/adsprpc.c377
-rw-r--r--drivers/char/adsprpc_compat.c34
-rw-r--r--drivers/char/adsprpc_shared.h23
4 files changed, 283 insertions, 157 deletions
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 1ca911192eb7..057f388b3a15 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -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";
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 73e615dabe41..83e0e25f95e0 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -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;
@@ -524,8 +567,8 @@ 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->table =
- dma_buf_map_attachment(map->attach,
- DMA_BIDIRECTIONAL)));
+ dma_buf_map_attachment(map->attach,
+ DMA_BIDIRECTIONAL)));
if (err)
goto bail;
if (sess->smmu.enabled) {
@@ -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,9 +990,11 @@ 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,
- mflags, &ctx->maps[i]);
+
+ 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;
}
metalen = copylen = (ssize_t)&ipage[0];
@@ -1001,19 +1050,22 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
int num = buf_num_pages(buf, len);
int idx = list[i].pgidx;
- down_read(&current->mm->mmap_sem);
- VERIFY(err, NULL != (vma = find_vma(current->mm,
+ 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)));
- if (err) {
+ if (err) {
+ up_read(&current->mm->mmap_sem);
+ goto bail;
+ }
+ offset = buf_page_start(buf) - vma->vm_start;
up_read(&current->mm->mmap_sem);
- goto bail;
+ VERIFY(err, offset < (uintptr_t)map->size);
+ if (err)
+ goto bail;
}
- 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_munmap_on_dsp(fl, map));
- if (err)
- goto bail;
- fastrpc_mmap_free(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;
+
+ 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;
+
+ 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;
- int session, cid;
if (fl) {
- cid = fl->cid;
- if (fl->sctx) {
- session = fl->sctx - &me->channel[cid].session[0];
- fastrpc_session_free(&me->channel[cid], session);
- }
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)) {
@@ -1883,7 +1959,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
goto bail;
VERIFY(err, wait_for_completion_timeout(&me->channel[cid].work,
- RPC_TIMEOUT));
+ RPC_TIMEOUT));
if (err) {
me->channel[cid].chan = 0;
goto bail;
@@ -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;
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 80b30a2a2b73..c5b3405ed644 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -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));
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index d0a1e11871f3..b1b7bfba4cf3 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -16,16 +16,21 @@
#include <linux/types.h>
-#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
-#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
-#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
-#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 _IOWR('R', 1, struct fastrpc_ioctl_invoke)
+#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
+#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
+#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 */