Skip to content

Commit 3b0c335

Browse files
committed
FROMLIST: misc: fastrpc: Allocate entire reserved memory for Audio PD in probe
Allocating and freeing Audio PD memory from userspace is unsafe because the kernel cannot reliably determine when the DSP has finished using the memory. Userspace may free buffers while they are still in use by the DSP, and remote free requests cannot be safely trusted. Allocate the entire Audio PD reserved-memory region upfront during rpmsg probe and tie its lifetime to the rpmsg channel. This avoids userspace- controlled alloc/free and ensures memory is reclaimed only when the DSP shuts down. Link: https://lore.kernel.org/all/20260409062617.1182-4-jianping.li@oss.qualcomm.com/ Signed-off-by: Jianping Li <jianping.li@oss.qualcomm.com>
1 parent 5d08c5a commit 3b0c335

1 file changed

Lines changed: 51 additions & 50 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ struct fastrpc_channel_ctx {
294294
struct kref refcount;
295295
/* Flag if dsp attributes are cached */
296296
bool valid_attributes;
297+
/* Flag if audio PD init mem was allocated */
298+
bool audio_init_mem;
297299
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
298300
struct fastrpc_device *secure_fdevice;
299301
struct fastrpc_device *fdevice;
@@ -1394,15 +1396,16 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
13941396
struct fastrpc_init_create_static init;
13951397
struct fastrpc_invoke_args *args;
13961398
struct fastrpc_phy_page pages[1];
1399+
struct fastrpc_channel_ctx *cctx = fl->cctx;
13971400
char *name;
13981401
int err;
1399-
bool scm_done = false;
14001402
struct {
14011403
int client_id;
14021404
u32 namelen;
14031405
u32 pageslen;
14041406
} inbuf;
14051407
u32 sc;
1408+
unsigned long flags;
14061409

14071410
args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
14081411
if (!args)
@@ -1426,29 +1429,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14261429
inbuf.client_id = fl->client_id;
14271430
inbuf.namelen = init.namelen;
14281431
inbuf.pageslen = 0;
1429-
if (!fl->cctx->remote_heap) {
1430-
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
1431-
&fl->cctx->remote_heap);
1432-
if (err)
1433-
goto err_name;
1434-
1435-
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
1436-
if (fl->cctx->vmcount) {
1437-
u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
1438-
1439-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1440-
(u64)fl->cctx->remote_heap->size,
1441-
&src_perms,
1442-
fl->cctx->vmperms, fl->cctx->vmcount);
1443-
if (err) {
1444-
dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
1445-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1446-
goto err_map;
1447-
}
1448-
scm_done = true;
1449-
inbuf.pageslen = 1;
1450-
}
1451-
}
14521432

14531433
fl->pd = USER_PD;
14541434

@@ -1460,8 +1440,25 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14601440
args[1].length = inbuf.namelen;
14611441
args[1].fd = -1;
14621442

1463-
pages[0].addr = fl->cctx->remote_heap->phys;
1464-
pages[0].size = fl->cctx->remote_heap->size;
1443+
spin_lock_irqsave(&cctx->lock, flags);
1444+
if (!fl->cctx->audio_init_mem) {
1445+
if (!fl->cctx->remote_heap ||
1446+
!fl->cctx->remote_heap->dma_addr ||
1447+
!fl->cctx->remote_heap->size) {
1448+
spin_unlock_irqrestore(&cctx->lock, flags);
1449+
err = -ENOMEM;
1450+
goto err;
1451+
}
1452+
1453+
pages[0].addr = fl->cctx->remote_heap->dma_addr;
1454+
pages[0].size = fl->cctx->remote_heap->size;
1455+
fl->cctx->audio_init_mem = true;
1456+
inbuf.pageslen = 1;
1457+
} else {
1458+
pages[0].addr = 0;
1459+
pages[0].size = 0;
1460+
}
1461+
spin_unlock_irqrestore(&cctx->lock, flags);
14651462

14661463
args[2].ptr = (u64)(uintptr_t) pages;
14671464
args[2].length = sizeof(*pages);
@@ -1479,26 +1476,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14791476

14801477
return 0;
14811478
err_invoke:
1482-
if (fl->cctx->vmcount && scm_done) {
1483-
u64 src_perms = 0;
1484-
struct qcom_scm_vmperm dst_perms;
1485-
u32 i;
1486-
1487-
for (i = 0; i < fl->cctx->vmcount; i++)
1488-
src_perms |= BIT(fl->cctx->vmperms[i].vmid);
1489-
1490-
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
1491-
dst_perms.perm = QCOM_SCM_PERM_RWX;
1492-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1493-
(u64)fl->cctx->remote_heap->size,
1494-
&src_perms, &dst_perms, 1);
1495-
if (err)
1496-
dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
1497-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1498-
}
1499-
err_map:
1500-
fastrpc_buf_free(fl->cctx->remote_heap);
1501-
err_name:
1479+
fl->cctx->audio_init_mem = false;
15021480
kfree(name);
15031481
err:
15041482
kfree(args);
@@ -2465,7 +2443,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24652443
}
24662444
}
24672445

2468-
if (domain_id == SDSP_DOMAIN_ID) {
2446+
if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) {
24692447
struct resource res;
24702448
u64 src_perms;
24712449

@@ -2476,7 +2454,15 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24762454
qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms,
24772455
data->vmperms, data->vmcount);
24782456
}
2479-
2457+
if (domain_id == ADSP_DOMAIN_ID) {
2458+
data->remote_heap =
2459+
kzalloc_obj(*data->remote_heap, GFP_KERNEL);
2460+
if (!data->remote_heap)
2461+
return -ENOMEM;
2462+
2463+
data->remote_heap->dma_addr = res.start;
2464+
data->remote_heap->size = resource_size(&res);
2465+
}
24802466
}
24812467

24822468
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
@@ -2556,6 +2542,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25562542
struct fastrpc_buf *buf, *b;
25572543
struct fastrpc_user *user;
25582544
unsigned long flags;
2545+
int err;
25592546

25602547
/* No invocations past this point */
25612548
spin_lock_irqsave(&cctx->lock, flags);
@@ -2573,8 +2560,22 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25732560
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
25742561
list_del(&buf->node);
25752562

2576-
if (cctx->remote_heap)
2577-
fastrpc_buf_free(cctx->remote_heap);
2563+
if (cctx->remote_heap && cctx->vmcount) {
2564+
u64 src_perms = 0;
2565+
struct qcom_scm_vmperm dst_perms;
2566+
2567+
for (u32 i = 0; i < cctx->vmcount; i++)
2568+
src_perms |= BIT(cctx->vmperms[i].vmid);
2569+
2570+
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
2571+
dst_perms.perm = QCOM_SCM_PERM_RWX;
2572+
2573+
err = qcom_scm_assign_mem(cctx->remote_heap->dma_addr,
2574+
cctx->remote_heap->size, &src_perms,
2575+
&dst_perms, 1);
2576+
if (!err)
2577+
fastrpc_buf_free(cctx->remote_heap);
2578+
}
25782579

25792580
of_platform_depopulate(&rpdev->dev);
25802581

0 commit comments

Comments
 (0)