Merge "msm: adsprpc: Support multiple sessions per process"

This commit is contained in:
qctecmdr
2023-12-21 19:35:09 -08:00
committed by Gerrit - the friendly Code Review server
2 changed files with 139 additions and 39 deletions

View File

@@ -103,9 +103,6 @@
#define M_KERNEL_PERF_LIST (PERF_KEY_MAX)
#define M_DSP_PERF_LIST (12)
#define SESSION_ID_INDEX (30)
#define SESSION_ID_MASK (1 << SESSION_ID_INDEX)
#define PROCESS_ID_MASK ((2^SESSION_ID_INDEX) - 1)
#define FASTRPC_CTX_MAGIC (0xbeeddeed)
/* Process status notifications from DSP will be sent with this unique context */
@@ -198,6 +195,9 @@
/* Max no. of persistent headers pre-allocated per process */
#define MAX_PERSISTENT_HEADERS (25)
/* Max value of the unique fastrpc tgid */
#define MAX_FRPC_TGID 256
#define PERF_CAPABILITY_SUPPORT (1 << 1)
#define KERNEL_ERROR_CODE_V1_SUPPORT 1
#define USERSPACE_ALLOCATION_SUPPORT 1
@@ -224,6 +224,9 @@
/* Unique index flag used for mini dump */
static int md_unique_index_flag[MAX_UNIQUE_ID] = { 0, 0, 0, 0, 0 };
/* Array to keep track unique tgid_frpc usage */
static bool frpc_tgid_usage_array[MAX_FRPC_TGID] = {0};
/* Fastrpc remote process attributes */
enum fastrpc_proc_attr {
/* Macro for Debug attr */
@@ -1872,6 +1875,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
}
ctx->retval = -1;
ctx->pid = current->pid;
/* Store HLOS PID in context, it is not being sent to DSP */
ctx->tgid = fl->tgid;
init_completion(&ctx->work);
ctx->magic = FASTRPC_CTX_MAGIC;
@@ -1889,6 +1893,10 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
goto bail;
}
memset(ctx->perf, 0, sizeof(*(ctx->perf)));
/*
* Use HLOS PID, as perf tid is not being sent
* to DSP and is used to log in traces.
*/
ctx->perf->tid = fl->tgid;
}
if (invokefd->job) {
@@ -2066,13 +2074,11 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
struct fastrpc_file *fl = NULL;
struct hlist_node *n;
bool is_process_found = false;
int sessionid = 0;
unsigned long irq_flags = 0;
spin_lock_irqsave(&me->hlock, irq_flags);
hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
if (fl->tgid == notif->pid ||
(fl->tgid == (notif->pid & PROCESS_ID_MASK))) {
if (fl->tgid_frpc == notif->pid) {
is_process_found = true;
break;
}
@@ -2081,9 +2087,7 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
if (!is_process_found)
return;
if (notif->pid & SESSION_ID_MASK)
sessionid = 1;
fastrpc_queue_pd_status(fl, domain, notif->status, sessionid);
fastrpc_queue_pd_status(fl, domain, notif->status, fl->sessionid);
}
static void context_notify_user(struct smq_invoke_ctx *ctx,
@@ -2915,10 +2919,9 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
channel_ctx = &fl->apps->channel[cid];
mutex_lock(&channel_ctx->smd_mutex);
msg->pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
msg->pid = fl->tgid_frpc;
msg->tid = current->pid;
if (fl->sessionid)
msg->tid |= SESSION_ID_MASK;
if (kernel == KERNEL_MSG_WITH_ZERO_PID)
msg->pid = 0;
msg->invoke.header.ctx = ctx->ctxid | fl->pd;
@@ -3002,6 +3005,7 @@ static void fastrpc_init(struct fastrpc_apps *me)
spin_lock_init(&me->hlock);
me->channel = &gcinfo[0];
mutex_init(&me->mut_uid);
me->max_sess_per_proc = DEFAULT_MAX_SESS_PER_PROC;
for (i = 0; i < NUM_CHANNELS; i++) {
init_completion(&me->channel[i].work);
init_completion(&me->channel[i].workport);
@@ -3568,6 +3572,12 @@ static int fastrpc_set_session_info(
int err = 0;
struct fastrpc_apps *me = &gfa;
if (fl->set_session_info) {
ADSPRPC_ERR("Set session info invoked multiple times\n");
err = -EBADR;
goto bail;
}
/*
* Third-party apps don't have permission to open the fastrpc device, so
* it is opened on their behalf by DSP HAL. This is detected by
@@ -3600,6 +3610,16 @@ static int fastrpc_set_session_info(
// Processes attaching to Sensor Static PD, share context bank.
if (sess_info->pd_type == SENSORS_STATICPD)
fl->sharedcb = 1;
if (sess_info->session_id >= me->max_sess_per_proc) {
ADSPRPC_ERR(
"Session ID %u cannot be beyond %u\n",
sess_info->session_id, me->max_sess_per_proc);
err = -EBADR;
goto bail;
}
fl->sessionid = sess_info->session_id;
// Set multi_session_support, to disable old way of setting session_id
fl->multi_session_support = true;
VERIFY(err, 0 == (err = fastrpc_get_info(fl, &(sess_info->domain_id))));
if (err)
goto bail;
@@ -3849,7 +3869,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl, int locked);
static int fastrpc_init_attach_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init *init)
{
int err = 0, tgid = fl->tgid;
int err = 0, tgid = fl->tgid_frpc;
remote_arg_t ra[1];
struct fastrpc_ioctl_invoke_async ioctl;
@@ -3862,6 +3882,7 @@ static int fastrpc_init_attach_process(struct fastrpc_file *fl,
/*
* Prepare remote arguments for creating thread group
* in guestOS/staticPD on the remote subsystem.
* Send unique fastrpc id to dsp
*/
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
@@ -3930,7 +3951,7 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
fl->dsp_process_state = PROCESS_CREATE_IS_INPROGRESS;
spin_unlock(&fl->hlock);
inbuf.pgid = fl->tgid;
inbuf.pgid = fl->tgid_frpc;
inbuf.namelen = strlen(current->comm) + 1;
inbuf.filelen = init->filelen;
fl->pd = 1;
@@ -4174,7 +4195,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
}
fl->pd = 1;
inbuf.pgid = fl->tgid;
inbuf.pgid = fl->tgid_frpc;
inbuf.namelen = init->filelen;
inbuf.pageslen = 0;
@@ -4628,7 +4649,8 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
err = -ECONNRESET;
goto bail;
}
tgid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
tgid = fl->tgid_frpc;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
@@ -4687,7 +4709,8 @@ static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset,
uint64_t vaddrout;
} routargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.fd = fd;
inargs.offset = offset;
inargs.vaddrin = (uintptr_t)va;
@@ -4738,7 +4761,8 @@ static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd,
uint64_t len;
} inargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.fd = fd;
inargs.vaddrin = (uint64_t)va;
inargs.len = (uint64_t)size;
@@ -4774,7 +4798,8 @@ static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl,
size_t size;
} inargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.size = size;
inargs.vaddrout = raddr;
ra[0].buf.pv = (void *)&inargs;
@@ -4826,7 +4851,8 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
goto bail;
}
cid = fl->cid;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.vaddrin = (uintptr_t)va;
inargs.flags = flags;
inargs.num = fl->apps->compat ? num * sizeof(page) : num;
@@ -5604,7 +5630,11 @@ static void handle_remote_signal(uint64_t msg, int cid)
spin_lock_irqsave(&me->hlock, irq_flags);
hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
if ((fl->tgid == pid) && (fl->cid == cid)) {
/*
* Response from DSP contains unique fastrpc process id,
* use unique fastrpc process ID to compare.
*/
if ((fl->tgid_frpc == pid) && (fl->cid == cid)) {
unsigned long fflags = 0;
spin_lock_irqsave(&fl->dspsignals_lock, fflags);
@@ -5825,6 +5855,9 @@ skip_dump_wait:
fl->is_ramdump_pend = false;
fl->is_dma_invoke_pend = false;
fl->dsp_process_state = PROCESS_CREATE_DEFAULT;
/* Reset the tgid usage to false */
if (fl->tgid_frpc != -1)
frpc_tgid_usage_array[fl->tgid_frpc] = false;
is_locked = false;
spin_unlock_irqrestore(&fl->apps->hlock, irq_flags);
@@ -6274,6 +6307,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->apps = me;
fl->mode = FASTRPC_MODE_SERIAL;
fl->cid = -1;
fl->tgid_frpc = -1;
fl->dev_minor = dev_minor;
fl->init_mem = NULL;
fl->qos_request = 0;
@@ -6284,6 +6318,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->is_compat = false;
fl->exit_notif = false;
fl->exit_async = false;
fl->multi_session_support = false;
fl->set_session_info = false;
init_completion(&fl->work);
init_completion(&fl->dma_invoke);
fl->file_close = FASTRPC_PROCESS_DEFAULT_STATE;
@@ -6332,6 +6368,25 @@ bail:
return err;
}
// Generate a unique process ID to DSP process
static int get_unique_hlos_process_id(void)
{
int tgid_frpc = -1, tgid_index = 1;
struct fastrpc_apps *me = &gfa;
spin_lock(&me->hlock);
for (tgid_index = 1; tgid_index < MAX_FRPC_TGID; tgid_index++) {
if (!frpc_tgid_usage_array[tgid_index]) {
tgid_frpc = tgid_index;
/* Set the tgid usage to false */
frpc_tgid_usage_array[tgid_index] = true;
break;
}
}
spin_unlock(&me->hlock);
return tgid_frpc;
}
static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
{
int err = 0, buf_size = 0;
@@ -6341,6 +6396,13 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
memcpy(cur_comm, current->comm, TASK_COMM_LEN);
cur_comm[TASK_COMM_LEN-1] = '\0';
fl->tgid = current->tgid;
fl->tgid_frpc = get_unique_hlos_process_id();
VERIFY(err, fl->tgid_frpc != -1);
if (err) {
ADSPRPC_ERR("too many fastrpc clients, max %u allowed\n", MAX_FRPC_TGID);
err = -EUSERS;
goto bail;
}
/*
* Third-party apps don't have permission to open the fastrpc device, so
@@ -6373,8 +6435,12 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
err = -ENOMEM;
return err;
}
snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d",
cur_comm, "_", current->pid, "_", cid);
/*
* Use HLOS PID, unique fastrpc PID, CID in debugfs filename,
* for better ability to debug.
*/
snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d%s%d",
cur_comm, "_", current->pid, "_", fl->tgid_frpc, "_", cid);
fl->debugfs_file = debugfs_create_file(fl->debug_buf, 0644,
debugfs_root, fl, &debugfs_fops);
if (IS_ERR_OR_NULL(fl->debugfs_file)) {
@@ -6400,6 +6466,21 @@ int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
err = -EBADF;
goto bail;
}
spin_lock(&fl->hlock);
if (fl->set_session_info) {
spin_unlock(&fl->hlock);
ADSPRPC_ERR("Set session info invoked multiple times\n");
err = -EBADR;
goto bail;
}
// Set set_session_info to true
fl->set_session_info = true;
spin_unlock(&fl->hlock);
VERIFY(err, VALID_FASTRPC_CID(cid));
if (err) {
err = -ECHRNG;
goto bail;
}
fastrpc_get_process_gids(&fl->gidlist);
err = fastrpc_set_process_info(fl, cid);
@@ -6494,7 +6575,6 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
int err = 0;
unsigned int latency;
struct fastrpc_apps *me = &gfa;
int sessionid = 0;
unsigned int cpu;
unsigned long flags = 0;
@@ -6590,9 +6670,7 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
break;
case FASTRPC_CONTROL_DSPPROCESS_CLEAN:
(void)fastrpc_release_current_dsp_process(fl);
if (fl->tgid & SESSION_ID_MASK)
sessionid = 1;
fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, sessionid);
fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, fl->sessionid);
break;
case FASTRPC_CONTROL_RPC_POLL:
err = fastrpc_manage_poll_mode(fl, cp->lp.enable, cp->lp.latency);
@@ -6669,8 +6747,8 @@ int fastrpc_setmode(unsigned long ioctl_param,
"multiple sessions not allowed for untrusted apps\n");
goto bail;
}
fl->sessionid = 1;
fl->tgid |= SESSION_ID_MASK;
if (!fl->multi_session_support)
fl->sessionid = 1;
break;
default:
err = -ENOTTY;
@@ -6741,8 +6819,9 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
// track outgoing signals in the driver. The userspace library does a
// basic sanity check and any security validation needs to be done by
// the recipient.
DSPSIGNAL_VERBOSE("Send signal PID %u, signal %u\n",
(unsigned int)fl->tgid, (unsigned int)sig->signal_id);
DSPSIGNAL_VERBOSE("Send signal PID %u, unique fastrpc pid %u signal %u\n",
(unsigned int)fl->tgid, (unsigned int)fl->tgid_frpc,
(unsigned int)sig->signal_id);
VERIFY(err, sig->signal_id < DSPSIGNAL_NUM_SIGNALS);
if (err) {
ADSPRPC_ERR("Sending bad signal %u for PID %u",
@@ -6766,7 +6845,8 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
goto bail;
}
msg = (((uint64_t)fl->tgid) << 32) | ((uint64_t)sig->signal_id);
/* Use unique fastrpc pid, to signal DSP process */
msg = (((uint64_t)fl->tgid_frpc) << 32) | ((uint64_t)sig->signal_id);
err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->trusted_vm);
mutex_unlock(&channel_ctx->smd_mutex);
@@ -7849,10 +7929,10 @@ static int fastrpc_cb_probe(struct device *dev)
if (of_get_property(dev->of_node, "pd-type", NULL) != NULL) {
err = of_property_read_u32(dev->of_node, "pd-type",
&(sess->smmu.pd_type));
/* Set cb_pd_type, if the process type is set for context banks */
me->cb_pd_type = true;
if (err)
goto bail;
// Set cb_pd_type, if the process type is configured for context banks
me->cb_pd_type = true;
}
if (of_get_property(dev->of_node, "shared-cb", NULL) != NULL) {
sess->smmu.sharedcb = 1;
@@ -8186,6 +8266,8 @@ static int fastrpc_probe(struct platform_device *pdev)
me->lowest_capacity_core_count = 1;
of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
&me->latency);
of_property_read_u32(dev->of_node, "qcom,max-sessions",
&me->max_sess_per_proc);
if (of_get_property(dev->of_node,
"qcom,secure-domains", NULL) != NULL) {
VERIFY(err, !of_property_read_u32(dev->of_node,
@@ -8602,17 +8684,24 @@ static int fastrpc_device_create(struct fastrpc_file *fl)
frpc_dev->dev.parent = &fastrpc_bus;
frpc_dev->dev.bus = &fastrpc_bus_type;
dev_set_name(&frpc_dev->dev, "%s-%d-%d",
dev_name(frpc_dev->dev.parent), fl->tgid, fl->cid);
/*
* Use HLOS PID, unique fastrpc process ID and CID to create device file,
* Else names would conflict for multiple sessions
* And also for better ability to debug
*/
dev_set_name(&frpc_dev->dev, "%s-%d-%d-%d",
dev_name(frpc_dev->dev.parent), fl->tgid, fl->tgid_frpc, fl->cid);
frpc_dev->dev.release = fastrpc_dev_release;
frpc_dev->fl = fl;
frpc_dev->handle = fl->tgid;
/* Use unique fastrpc tgid as handle */
frpc_dev->handle = fl->tgid_frpc;
err = device_register(&frpc_dev->dev);
if (err) {
put_device(&frpc_dev->dev);
ADSPRPC_ERR("fastrpc device register failed for process %d with error %d\n",
fl->tgid, err);
ADSPRPC_ERR(
"fastrpc device register failed for process %d unique fastrpc tgid %d session %d with error %d\n",
fl->tgid, fl->tgid_frpc, fl->sessionid, err);
goto bail;
}
fl->device = frpc_dev;

View File

@@ -120,6 +120,9 @@
#define NUM_CHANNELS (MAX_DOMAIN_ID + 1) /* adsp, mdsp, slpi, cdsp, cdsp1, gpdsp, gpdsp1*/
#define NUM_SESSIONS 13 /* max 12 compute, 1 cpz */
/* Default maximum sessions allowed per process */
#define DEFAULT_MAX_SESS_PER_PROC 4
#define RH_CID ADSP_DOMAIN_ID
#define VALID_FASTRPC_CID(cid) \
@@ -995,6 +998,8 @@ struct fastrpc_apps {
bool single_core_latency_vote;
/* Indicates process type is configured for SMMU context bank */
bool cb_pd_type;
/* Maximum sessions allowed to be created per process */
uint32_t max_sess_per_proc;
};
struct fastrpc_mmap {
@@ -1095,6 +1100,8 @@ struct fastrpc_file {
int sessionid;
int tgid_open; /* Process ID during device open */
int tgid; /* Process ID that uses device for RPC calls */
/* Unique HLOS process ID created by fastrpc for each client */
int tgid_frpc;
int cid;
bool trusted_vm;
uint64_t ssrcount;
@@ -1166,6 +1173,10 @@ struct fastrpc_file {
* config parameters.
*/
struct fastrpc_proc_sharedbuf_info sharedbuf_info;
/* Flag to indicate 4 session support available */
bool multi_session_support;
/* Flag to indicate session info is set */
bool set_session_info;
};
union fastrpc_ioctl_param {