Skip to content

Commit 6e1f183

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/20260407100508.1027-4-jianping.li@oss.qualcomm.com/ Signed-off-by: Jianping Li <jianping.li@oss.qualcomm.com>
1 parent 044e5bf commit 6e1f183

1 file changed

Lines changed: 48 additions & 50 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 48 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,17 @@ 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+
pages[0].addr = fl->cctx->remote_heap->phys;
1446+
pages[0].size = fl->cctx->remote_heap->size;
1447+
fl->cctx->audio_init_mem = true;
1448+
inbuf.pageslen = 1;
1449+
} else {
1450+
pages[0].addr = 0;
1451+
pages[0].size = 0;
1452+
}
1453+
spin_unlock_irqrestore(&cctx->lock, flags);
14651454

14661455
args[2].ptr = (u64)(uintptr_t) pages;
14671456
args[2].length = sizeof(*pages);
@@ -1479,26 +1468,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14791468

14801469
return 0;
14811470
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:
1471+
fl->cctx->audio_init_mem = false;
15021472
kfree(name);
15031473
err:
15041474
kfree(args);
@@ -2465,7 +2435,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24652435
}
24662436
}
24672437

2468-
if (domain_id == SDSP_DOMAIN_ID) {
2438+
if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) {
24692439
struct resource res;
24702440
u64 src_perms;
24712441

@@ -2476,7 +2446,15 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24762446
qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms,
24772447
data->vmperms, data->vmcount);
24782448
}
2479-
2449+
if (domain_id == ADSP_DOMAIN_ID) {
2450+
data->remote_heap =
2451+
kzalloc(sizeof(*data->remote_heap), GFP_KERNEL);
2452+
if (!data->remote_heap)
2453+
return -ENOMEM;
2454+
2455+
data->remote_heap->phys = res.start;
2456+
data->remote_heap->size = resource_size(&res);
2457+
}
24802458
}
24812459

24822460
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
@@ -2556,6 +2534,8 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25562534
struct fastrpc_buf *buf, *b;
25572535
struct fastrpc_user *user;
25582536
unsigned long flags;
2537+
bool skip_free = false;
2538+
int err;
25592539

25602540
/* No invocations past this point */
25612541
spin_lock_irqsave(&cctx->lock, flags);
@@ -2573,8 +2553,26 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25732553
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
25742554
list_del(&buf->node);
25752555

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

25792577
of_platform_depopulate(&rpdev->dev);
25802578

0 commit comments

Comments
 (0)