Merge 7fd02f3859
on remote branch
Change-Id: I9b926588408013e5dfd871aee12e5d3356da20ba
This commit is contained in:
163
dsp/adsprpc.c
163
dsp/adsprpc.c
@@ -43,6 +43,7 @@
|
||||
#include "adsprpc_shared.h"
|
||||
#include <soc/qcom/qcom_ramdump.h>
|
||||
#include <soc/qcom/minidump.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pm_qos.h>
|
||||
@@ -1159,6 +1160,77 @@ bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int get_buffer_attr(struct dma_buf *buf, bool *exclusive_access, bool *hlos_access)
|
||||
{
|
||||
const int *vmids_list = NULL, *perms = NULL;
|
||||
int err = 0, vmids_list_len = 0;
|
||||
|
||||
*exclusive_access = false;
|
||||
*hlos_access = false;
|
||||
err = mem_buf_dma_buf_get_vmperm(buf, &vmids_list, &perms, &vmids_list_len);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* If one VM has access to buffer and is the current VM,
|
||||
* then VM has exclusive access to buffer
|
||||
*/
|
||||
if (vmids_list_len == 1 && vmids_list[0] == mem_buf_current_vmid())
|
||||
*exclusive_access = true;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
/*
|
||||
* PVM (HLOS) can share buffers with TVM. In that case,
|
||||
* it is expected to relinquish its ownership to those buffers
|
||||
* before sharing. But if the PVM still retains access, then
|
||||
* these buffers cannot be used by TVM.
|
||||
*/
|
||||
|
||||
for (int ii = 0; ii < vmids_list_len; ii++) {
|
||||
if (vmids_list[ii] == VMID_HLOS) {
|
||||
*hlos_access = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int set_buffer_secure_type(struct fastrpc_mmap *map)
|
||||
{
|
||||
int err = 0;
|
||||
bool hlos_access = false, exclusive_access = false;
|
||||
|
||||
VERIFY(err, 0 == (err = get_buffer_attr(map->buf, &exclusive_access, &hlos_access)));
|
||||
if (err) {
|
||||
ADSPRPC_ERR("failed to obtain buffer attributes for fd %d ret %d\n", map->fd, err);
|
||||
err = -EBADFD;
|
||||
goto bail;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
if (hlos_access) {
|
||||
ADSPRPC_ERR("Sharing HLOS buffer (fd %d) not allowed on TVM\n", map->fd);
|
||||
err = -EACCES;
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Secure buffers would always be owned by multiple VMs.
|
||||
* If current VM is the exclusive owner of a buffer, it is considered non-secure.
|
||||
* In PVM:
|
||||
* - CPZ buffers are secure
|
||||
* - All other buffers are non-secure
|
||||
* In TVM:
|
||||
* - Since it is a secure environment by default, there are no explicit "secure" buffers
|
||||
* - All buffers are marked "non-secure"
|
||||
*/
|
||||
map->secure = (exclusive_access) ? 0 : 1;
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, struct dma_buf *buf,
|
||||
unsigned int attr, uintptr_t va, size_t len, int mflags,
|
||||
struct fastrpc_mmap **ppmap)
|
||||
@@ -1224,10 +1296,10 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, struct dma_buf *
|
||||
err = -EBADFD;
|
||||
goto bail;
|
||||
}
|
||||
err = set_buffer_secure_type(map);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
#if !IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
map->secure = (mem_buf_dma_buf_exclusive_owner(map->buf)) ? 0 : 1;
|
||||
#endif
|
||||
map->va = 0;
|
||||
map->phys = 0;
|
||||
|
||||
@@ -1293,10 +1365,10 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, struct dma_buf *
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
err = set_buffer_secure_type(map);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
#if !IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
map->secure = (mem_buf_dma_buf_exclusive_owner(map->buf)) ? 0 : 1;
|
||||
#endif
|
||||
if (map->secure) {
|
||||
if (!fl->secsctx)
|
||||
err = fastrpc_session_alloc_secure_memory(chan, 1,
|
||||
@@ -2488,6 +2560,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
|
||||
err = -EFAULT;
|
||||
goto bail;
|
||||
}
|
||||
if (templen > DEBUG_PRINT_SIZE_LIMIT)
|
||||
ADSPRPC_WARN(
|
||||
"user passed non ion buffer size %zu, mend 0x%llx mstart 0x%llx, sc 0x%x handle 0x%x\n",
|
||||
templen, mend, mstart, sc, ctx->handle);
|
||||
copylen += templen;
|
||||
}
|
||||
totallen = ALIGN(totallen, BALIGN) + copylen;
|
||||
@@ -3943,9 +4019,12 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
|
||||
struct smq_phy_page pages[PAGESLEN_WITH_SHAREDBUF];
|
||||
struct fastrpc_mmap *file = NULL;
|
||||
struct fastrpc_buf *imem = NULL;
|
||||
unsigned long imem_dma_attr = 0;
|
||||
unsigned long imem_dma_attr = 0, irq_flags = 0;
|
||||
remote_arg_t ra[6];
|
||||
int fds[6];
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
struct hlist_node *n = NULL;
|
||||
struct fastrpc_file *fl_curr = NULL;
|
||||
unsigned int gid = 0, one_mb = 1024*1024;
|
||||
unsigned int dsp_userpd_memlen = 0;
|
||||
struct fastrpc_buf *init_mem;
|
||||
@@ -3993,6 +4072,20 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
|
||||
if (uproc->attrs & FASTRPC_MODE_UNSIGNED_MODULE)
|
||||
fl->is_unsigned_pd = true;
|
||||
|
||||
/* Validate that any existing sessions of process are of same pd type */
|
||||
spin_lock_irqsave(&me->hlock, irq_flags);
|
||||
hlist_for_each_entry_safe(fl_curr, n, &me->drivers, hn) {
|
||||
if ((fl != fl_curr) && (fl->tgid == fl_curr->tgid) && (fl->cid == fl_curr->cid)) {
|
||||
err = (fl->is_unsigned_pd != fl_curr->is_unsigned_pd) ? -ECONNREFUSED : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&me->hlock, irq_flags);
|
||||
if (err) {
|
||||
ADSPRPC_ERR("existing session pd type %u not same as requested pd type %u \n",
|
||||
fl_curr->is_unsigned_pd, fl->is_unsigned_pd);
|
||||
goto bail;
|
||||
}
|
||||
/* Check if file memory passed by userspace is valid */
|
||||
VERIFY(err, access_ok((void __user *)init->file, init->filelen));
|
||||
if (err)
|
||||
@@ -5652,6 +5745,7 @@ static void handle_remote_signal(uint64_t msg, int cid)
|
||||
(sig->state == DSPSIGNAL_STATE_SIGNALED)) {
|
||||
DSPSIGNAL_VERBOSE("Signaling signal %u for PID %u\n",
|
||||
signal_id, pid);
|
||||
trace_fastrpc_dspsignal("complete", signal_id, sig->state, 0);
|
||||
complete(&sig->comp);
|
||||
sig->state = DSPSIGNAL_STATE_SIGNALED;
|
||||
} else if (sig->state == DSPSIGNAL_STATE_UNUSED) {
|
||||
@@ -5682,7 +5776,7 @@ int fastrpc_handle_rpc_response(void *data, int len, int cid)
|
||||
struct fastrpc_channel_ctx *chan = NULL;
|
||||
unsigned long irq_flags = 0;
|
||||
int64_t ns = 0;
|
||||
uint64_t xo_time_in_us = 0;
|
||||
uint64_t xo_time_in_us = 0, dspsig_msg = 0;
|
||||
|
||||
xo_time_in_us = CONVERT_CNT_TO_US(__arch_counter_get_cntvct());
|
||||
|
||||
@@ -5690,7 +5784,9 @@ int fastrpc_handle_rpc_response(void *data, int len, int cid)
|
||||
/*
|
||||
* dspsignal message from the DSP
|
||||
*/
|
||||
handle_remote_signal(*((uint64_t *)data), cid);
|
||||
dspsig_msg = *((uint64_t *)data);
|
||||
trace_fastrpc_transport_response(cid, dspsig_msg, 0, 0, 0);
|
||||
handle_remote_signal(dspsig_msg, cid);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
@@ -6762,12 +6858,6 @@ int fastrpc_setmode(unsigned long ioctl_param,
|
||||
fl->profile = (uint32_t)ioctl_param;
|
||||
break;
|
||||
case FASTRPC_MODE_SESSION:
|
||||
if (fl->untrusted_process) {
|
||||
err = -EPERM;
|
||||
ADSPRPC_ERR(
|
||||
"multiple sessions not allowed for untrusted apps\n");
|
||||
goto bail;
|
||||
}
|
||||
if (!fl->multi_session_support)
|
||||
fl->sessionid = 1;
|
||||
break;
|
||||
@@ -6775,7 +6865,6 @@ int fastrpc_setmode(unsigned long ioctl_param,
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -6870,7 +6959,7 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
|
||||
msg = (((uint64_t)fl->tgid_frpc) << 32) | ((uint64_t)sig->signal_id);
|
||||
err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->tvm_remote_domain);
|
||||
mutex_unlock(&channel_ctx->smd_mutex);
|
||||
|
||||
trace_fastrpc_dspsignal("signal", sig->signal_id, 0, 0);
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
@@ -6923,10 +7012,12 @@ int fastrpc_dspsignal_wait(struct fastrpc_file *fl,
|
||||
}
|
||||
spin_unlock_irqrestore(&fl->dspsignals_lock, irq_flags);
|
||||
|
||||
trace_fastrpc_dspsignal("wait", signal_id, s->state, wait->timeout_usec);
|
||||
if (timeout != 0xffffffff)
|
||||
ret = wait_for_completion_interruptible_timeout(&s->comp, timeout);
|
||||
else
|
||||
ret = wait_for_completion_interruptible(&s->comp);
|
||||
trace_fastrpc_dspsignal("wakeup", signal_id, s->state, wait->timeout_usec);
|
||||
|
||||
if (ret == 0) {
|
||||
DSPSIGNAL_VERBOSE("Wait for signal %u timed out\n", signal_id);
|
||||
@@ -7114,6 +7205,7 @@ int fastrpc_dspsignal_cancel_wait(struct fastrpc_file *fl,
|
||||
|
||||
if (s->state != DSPSIGNAL_STATE_CANCELED) {
|
||||
s->state = DSPSIGNAL_STATE_CANCELED;
|
||||
trace_fastrpc_dspsignal("cancel", signal_id, s->state, 0);
|
||||
complete_all(&s->comp);
|
||||
}
|
||||
|
||||
@@ -8828,7 +8920,12 @@ static int __init fastrpc_device_init(void)
|
||||
VERIFY(err, !IS_ERR(me->class));
|
||||
if (err)
|
||||
goto class_create_bail;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
me->compat = 1;
|
||||
#else
|
||||
me->compat = (fops.compat_ioctl == NULL) ? 0 : 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create devices and register with sysfs
|
||||
@@ -8866,29 +8963,33 @@ static int __init fastrpc_device_init(void)
|
||||
if (i == CDSP_DOMAIN_ID) {
|
||||
me->channel[i].dev = me->non_secure_dev;
|
||||
#if !IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
/*
|
||||
* Allocate CMA memory for mini dump.
|
||||
* Ignore error as CMA node may not be available on all targets.
|
||||
*/
|
||||
err = fastrpc_alloc_cma_memory(®ion_phys,
|
||||
®ion_vaddr,
|
||||
MINI_DUMP_DBG_SIZE,
|
||||
(unsigned long)attr);
|
||||
#endif
|
||||
if (err)
|
||||
ADSPRPC_WARN("%s: CMA alloc failed err 0x%x\n",
|
||||
__func__, err);
|
||||
if (err) {
|
||||
ADSPRPC_WARN("CMA alloc failed err 0x%x\n", err);
|
||||
err = 0;
|
||||
}
|
||||
VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL)));
|
||||
if (err) {
|
||||
err = -ENOMEM;
|
||||
ADSPRPC_ERR("%s: CMA alloc failed err 0x%x\n",
|
||||
__func__, err);
|
||||
goto device_create_bail;
|
||||
ADSPRPC_WARN("kzalloc failed err 0x%x\n", err);
|
||||
err = 0;
|
||||
} else {
|
||||
INIT_HLIST_NODE(&buf->hn);
|
||||
buf->virt = region_vaddr;
|
||||
buf->phys = (uintptr_t)region_phys;
|
||||
buf->size = MINI_DUMP_DBG_SIZE;
|
||||
buf->dma_attr = attr;
|
||||
buf->raddr = 0;
|
||||
me->channel[i].buf = buf;
|
||||
}
|
||||
INIT_HLIST_NODE(&buf->hn);
|
||||
buf->virt = region_vaddr;
|
||||
buf->phys = (uintptr_t)region_phys;
|
||||
buf->size = MINI_DUMP_DBG_SIZE;
|
||||
buf->dma_attr = attr;
|
||||
buf->raddr = 0;
|
||||
ktime_get_real_ts64(&buf->buf_start_time);
|
||||
me->channel[i].buf = buf;
|
||||
}
|
||||
if (IS_ERR_OR_NULL(me->channel[i].handle))
|
||||
pr_warn("adsprpc: %s: SSR notifier register failed for %s with err %d\n",
|
||||
|
@@ -391,6 +391,36 @@ TRACE_EVENT(fastrpc_msg,
|
||||
TP_printk(" %s", __get_str(buf))
|
||||
);
|
||||
|
||||
TRACE_EVENT(fastrpc_dspsignal,
|
||||
|
||||
TP_PROTO(const char *event, uint32_t signal_id,
|
||||
int state, uint32_t timeout),
|
||||
|
||||
TP_ARGS(event, signal_id, state, timeout),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(buf, event)
|
||||
__field(u32, signal_id)
|
||||
__field(int, state)
|
||||
__field(u32, timeout)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
#if IS_ENABLED(CONFIG_MSM_ADSPRPC_TRUSTED)
|
||||
memcpy(__get_str(buf), (event), (sizeof(event) - 1));
|
||||
__get_str(buf)[sizeof(event) - 1] = '\0';
|
||||
#else
|
||||
__assign_str(buf, event);
|
||||
#endif
|
||||
__entry->signal_id = signal_id;
|
||||
__entry->state = state;
|
||||
__entry->timeout = timeout;
|
||||
),
|
||||
|
||||
TP_printk("%s for sig id %u, state %d, timeout %u",
|
||||
__get_str(buf), __entry->signal_id, __entry->state, __entry->timeout)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
Reference in New Issue
Block a user