Skip to content

Commit c9010fc

Browse files
Jianping-Lisgaud-quic
authored andcommitted
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 cd522d4 commit c9010fc

1 file changed

Lines changed: 51 additions & 52 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ struct fastrpc_channel_ctx {
292292
struct kref refcount;
293293
/* Flag if dsp attributes are cached */
294294
bool valid_attributes;
295+
/* Flag if audio PD init mem was allocated */
296+
bool audio_init_mem;
295297
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
296298
struct fastrpc_device *secure_fdevice;
297299
struct fastrpc_device *fdevice;
@@ -1417,15 +1419,16 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14171419
struct fastrpc_init_create_static init;
14181420
struct fastrpc_invoke_args *args;
14191421
struct fastrpc_phy_page pages[1];
1422+
struct fastrpc_channel_ctx *cctx = fl->cctx;
14201423
char *name;
14211424
int err;
1422-
bool scm_done = false;
14231425
struct {
14241426
int client_id;
14251427
u32 namelen;
14261428
u32 pageslen;
14271429
} inbuf;
14281430
u32 sc;
1431+
unsigned long flags;
14291432

14301433
args = kzalloc_objs(*args, FASTRPC_CREATE_STATIC_PROCESS_NARGS);
14311434
if (!args)
@@ -1449,31 +1452,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14491452
inbuf.client_id = fl->client_id;
14501453
inbuf.namelen = init.namelen;
14511454
inbuf.pageslen = 0;
1452-
if (!fl->cctx->remote_heap) {
1453-
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
1454-
&fl->cctx->remote_heap);
1455-
if (err)
1456-
goto err_name;
1457-
1458-
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
1459-
if (fl->cctx->vmcount) {
1460-
u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
1461-
1462-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr,
1463-
(u64)fl->cctx->remote_heap->size,
1464-
&src_perms,
1465-
fl->cctx->vmperms, fl->cctx->vmcount);
1466-
if (err) {
1467-
dev_err(fl->sctx->dev,
1468-
"Failed to assign memory with dma_addr %pad size 0x%llx err %d\n",
1469-
&fl->cctx->remote_heap->dma_addr,
1470-
fl->cctx->remote_heap->size, err);
1471-
goto err_map;
1472-
}
1473-
scm_done = true;
1474-
inbuf.pageslen = 1;
1475-
}
1476-
}
14771455

14781456
fl->pd = USER_PD;
14791457

@@ -1485,8 +1463,25 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14851463
args[1].length = inbuf.namelen;
14861464
args[1].fd = -1;
14871465

1488-
pages[0].addr = fl->cctx->remote_heap->dma_addr;
1489-
pages[0].size = fl->cctx->remote_heap->size;
1466+
spin_lock_irqsave(&cctx->lock, flags);
1467+
if (!fl->cctx->audio_init_mem) {
1468+
if (!fl->cctx->remote_heap ||
1469+
!fl->cctx->remote_heap->dma_addr ||
1470+
!fl->cctx->remote_heap->size) {
1471+
spin_unlock_irqrestore(&cctx->lock, flags);
1472+
err = -ENOMEM;
1473+
goto err;
1474+
}
1475+
1476+
pages[0].addr = fl->cctx->remote_heap->dma_addr;
1477+
pages[0].size = fl->cctx->remote_heap->size;
1478+
fl->cctx->audio_init_mem = true;
1479+
inbuf.pageslen = 1;
1480+
} else {
1481+
pages[0].addr = 0;
1482+
pages[0].size = 0;
1483+
}
1484+
spin_unlock_irqrestore(&cctx->lock, flags);
14901485

14911486
args[2].ptr = (u64)(uintptr_t) pages;
14921487
args[2].length = sizeof(*pages);
@@ -1504,27 +1499,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
15041499

15051500
return 0;
15061501
err_invoke:
1507-
if (fl->cctx->vmcount && scm_done) {
1508-
u64 src_perms = 0;
1509-
struct qcom_scm_vmperm dst_perms;
1510-
u32 i;
1511-
1512-
for (i = 0; i < fl->cctx->vmcount; i++)
1513-
src_perms |= BIT(fl->cctx->vmperms[i].vmid);
1514-
1515-
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
1516-
dst_perms.perm = QCOM_SCM_PERM_RWX;
1517-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr,
1518-
(u64)fl->cctx->remote_heap->size,
1519-
&src_perms, &dst_perms, 1);
1520-
if (err)
1521-
dev_err(fl->sctx->dev, "Failed to assign memory dma_addr %pad size 0x%llx err %d\n",
1522-
&fl->cctx->remote_heap->dma_addr, fl->cctx->remote_heap->size, err);
1523-
}
1524-
err_map:
1525-
fastrpc_buf_free(fl->cctx->remote_heap);
1526-
fl->cctx->remote_heap = NULL;
1527-
err_name:
1502+
fl->cctx->audio_init_mem = false;
15281503
kfree(name);
15291504
err:
15301505
kfree(args);
@@ -2539,7 +2514,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
25392514
}
25402515
}
25412516

2542-
if (domain_id == SDSP_DOMAIN_ID) {
2517+
if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) {
25432518
struct resource res;
25442519
u64 src_perms;
25452520

@@ -2553,6 +2528,15 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
25532528
goto err_free_data;
25542529
}
25552530

2531+
if (domain_id == ADSP_DOMAIN_ID) {
2532+
data->remote_heap =
2533+
kzalloc_obj(*data->remote_heap, GFP_KERNEL);
2534+
if (!data->remote_heap)
2535+
return -ENOMEM;
2536+
2537+
data->remote_heap->dma_addr = res.start;
2538+
data->remote_heap->size = resource_size(&res);
2539+
}
25562540
}
25572541

25582542
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
@@ -2633,6 +2617,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
26332617
struct fastrpc_buf *buf, *b;
26342618
struct fastrpc_user *user;
26352619
unsigned long flags;
2620+
int err;
26362621

26372622
/* No invocations past this point */
26382623
spin_lock_irqsave(&cctx->lock, flags);
@@ -2650,8 +2635,22 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
26502635
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
26512636
list_del(&buf->node);
26522637

2653-
if (cctx->remote_heap)
2654-
fastrpc_buf_free(cctx->remote_heap);
2638+
if (cctx->remote_heap && cctx->vmcount) {
2639+
u64 src_perms = 0;
2640+
struct qcom_scm_vmperm dst_perms;
2641+
2642+
for (u32 i = 0; i < cctx->vmcount; i++)
2643+
src_perms |= BIT(cctx->vmperms[i].vmid);
2644+
2645+
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
2646+
dst_perms.perm = QCOM_SCM_PERM_RWX;
2647+
2648+
err = qcom_scm_assign_mem(cctx->remote_heap->dma_addr,
2649+
cctx->remote_heap->size, &src_perms,
2650+
&dst_perms, 1);
2651+
if (!err)
2652+
fastrpc_buf_free(cctx->remote_heap);
2653+
}
26552654

26562655
of_platform_depopulate(&rpdev->dev);
26572656

0 commit comments

Comments
 (0)