Skip to content

Commit 3b6206f

Browse files
committed
Add internal mmap/munmap functions with DSP address tracking
Introduce fastrpc_mmap_internal() and fastrpc_munmap_internal() to handle buffer mapping with DSP virtual address management. These functions maintain mappings in the static map list and enable lookup by DSP virtual address. Extract common mmap logic into fastrpc_mmap_helper() to eliminate code duplication between fastrpc_mmap() and fastrpc_mmap_internal(). Simplify apps_mem_request_map64() by removing conditional allocation logic and always allocating in userspace, then using fastrpc_mmap_internal() for mapping. Update apps_mem_request_unmap64() to route to appropriate unmap function based on mapping type: - FASTRPC_ALLOC_HLOS_FD: use fastrpc_munmap() - ADSP_MMAP_HEAP_ADDR/ADSP_MMAP_REMOTE_HEAP_ADDR: use remote_munmap64() - Other allocations: use fastrpc_munmap_internal() Signed-off-by: Vinayak Katoch <vkatoch@qti.qualcomm.com>
1 parent 2c3dbc7 commit 3b6206f

3 files changed

Lines changed: 212 additions & 57 deletions

File tree

inc/fastrpc_mem.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,33 @@ int fastrpc_buffer_ref(int domain, int fd, int ref, void **va, size_t *size);
7373
*/
7474
void remote_register_buf(void *buf, int size, int fd);
7575

76+
/*
77+
* Internal function to map a buffer and return the DSP virtual address.
78+
* Creates a mapping on the DSP and stores the mapping information in the static map list.
79+
*
80+
* @param domain The DSP domain ID (-1 for current domain)
81+
* @param fd File descriptor of the buffer
82+
* @param vaddr Virtual address of the buffer on CPU side
83+
* @param offset Offset from the beginning of the buffer (must be 0)
84+
* @param length Size of buffer in bytes
85+
* @param flags Mapping flags (uint32_t)
86+
* @param raddr Output: DSP virtual address of the mapped buffer
87+
*
88+
* @return 0 on success, error code on failure
89+
*/
90+
int fastrpc_mmap_internal(int domain, int fd, void *vaddr, int offset, size_t length, uint32_t flags, uint64_t *raddr);
91+
92+
/*
93+
* Internal function to unmap a buffer using the DSP virtual address.
94+
* Looks up the mapping in the static map list using the DSP virtual address,
95+
* then performs the unmap operation and removes the mapping from the list.
96+
*
97+
* @param domain The DSP domain ID (-1 for current domain)
98+
* @param raddr DSP virtual address of the mapped buffer
99+
* @param length Size of buffer in bytes to unmap
100+
*
101+
* @return 0 on success, error code on failure
102+
*/
103+
int fastrpc_munmap_internal(int domain, uint64_t raddr, size_t length);
104+
76105
#endif //FASTRPC_MEM_H

src/apps_mem_imp.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,13 @@ __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32_t lflags, uint32_t rflags
163163
*/
164164
*vadsp = (uint64_t)fd;
165165
} else {
166-
/* Memory for unsignedPD's user-heap will be allocated in userspace for
167-
* security reasons. Memory for signedPD's user-heap will be allocated in
168-
* kernel.
169-
*/
170-
if (((rflags != ADSP_MMAP_ADD_PAGES) &&
171-
(rflags != ADSP_MMAP_ADD_PAGES_LLC)) ||
172-
(((rflags == ADSP_MMAP_ADD_PAGES) ||
173-
(rflags == ADSP_MMAP_ADD_PAGES_LLC)) &&
174-
(unsigned_module && ualloc_support))) {
175-
VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)),
176-
AEE_ENORPCMEMORY);
177-
fd = rpcmem_to_fd_internal(buf);
178-
VERIFYC(fd > 0, AEE_EBADPARM);
179-
}
166+
VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)),
167+
AEE_ENORPCMEMORY);
168+
fd = rpcmem_to_fd_internal(buf);
169+
VERIFYC(fd > 0, AEE_EBADPARM);
180170
VERIFY(AEE_SUCCESS ==
181-
(nErr = remote_mmap64_internal(fd, rflags, (uint64_t)buf, len,
182-
(uint64_t *)vadsp)));
171+
(nErr = fastrpc_mmap_internal(domain, fd, buf, 0, len,
172+
rflags, vadsp)));
183173
pbuf = (uint64_t)buf;
184174
*vapps = pbuf;
185175
minfo->vapps = *vapps;
@@ -250,17 +240,27 @@ __QAIC_IMPL(apps_mem_request_unmap64)(uint64_t vadsp,
250240
pthread_mutex_unlock(&me->mem_mut);
251241

252242
/* If apps_mem_request_map64 was called with flag FASTRPC_ALLOC_HLOS_FD,
253-
* use fastrpc_munmap else use remote_munmap64 to unmap.
243+
* use fastrpc_munmap. For ADSP_MMAP_HEAP_ADDR and ADSP_MMAP_REMOTE_HEAP_ADDR,
244+
* use remote_munmap64. For other cases, use fastrpc_munmap_with_raddr.
254245
*/
255246
if(mfree && mfree->rflags == FASTRPC_ALLOC_HLOS_FD) {
256247
fd = (int)vadsp;
257248
VERIFY(AEE_SUCCESS == (nErr = fastrpc_munmap(domain, fd, 0, len)));
249+
} else if (mfree && (mfree->rflags == ADSP_MMAP_HEAP_ADDR ||
250+
mfree->rflags == ADSP_MMAP_REMOTE_HEAP_ADDR)) {
251+
/* These cases use remote_mmap64_internal, so use remote_munmap64 */
252+
VERIFY(AEE_SUCCESS == (nErr = remote_munmap64((uint64_t)vadsp, len)));
258253
} else if (mfree || fastrpc_get_pd_type(domain) == AUDIO_STATICPD){
259254
/*
260255
* Map info not available for Audio static PD after daemon reconnect,
261256
* So continue to unmap to avoid driver global maps leak.
257+
* For other cases, use fastrpc_munmap_with_raddr as they were mapped with fastrpc_mmap_with_raddr.
262258
*/
263-
VERIFY(AEE_SUCCESS == (nErr = remote_munmap64((uint64_t)vadsp, len)));
259+
if (mfree) {
260+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_munmap_internal(domain, (uint64_t)vadsp, len)));
261+
} else {
262+
VERIFY(AEE_SUCCESS == (nErr = remote_munmap64((uint64_t)vadsp, len)));
263+
}
264264
if (!mfree)
265265
goto bail;
266266
}

src/fastrpc_mem.c

Lines changed: 165 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -440,51 +440,37 @@ int fdlist_fd_from_buf(void *buf, int bufLen, int *nova, void **base, int *attr,
440440
return 0;
441441
}
442442

443-
int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length,
444-
enum fastrpc_map_flags flags) {
443+
/**
444+
* Helper function to perform complete mmap operation including error handling
445+
* Returns 0 on success, error code on failure
446+
* On success, vaddrout contains the DSP virtual address
447+
*/
448+
static int fastrpc_mmap_helper(int *domain, int fd, void *vaddr, int offset,
449+
size_t length, uint32_t flags, int attrs,
450+
uint64_t *vaddrout) {
445451
struct fastrpc_map map = {0};
446-
int nErr = 0, dev = -1, iocErr = 0, attrs = 0, ref = 0;
447-
uint64_t vaddrout = 0;
452+
int nErr = 0, dev = -1, iocErr = 0, ref = 0;
448453
struct static_map *mNode = NULL, *tNode = NULL;
449454
QNode *pn, *pnn;
450455

451-
VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
452-
453-
FARF(RUNTIME_RPC_HIGH,
454-
"%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x",
455-
__func__, domain, fd, vaddr, length, flags, offset);
456-
457-
/**
458-
* Mask is applied on "flags" parameter to extract map control flags
459-
* and SMMU mapping control attributes. Currently no attributes are
460-
* suppported. It allows future extension of the fastrpc_mmap API
461-
* for SMMU mapping control attributes.
462-
*/
463-
attrs = flags & (~FASTRPC_MAP_FLAGS_MASK);
464-
flags = flags & FASTRPC_MAP_FLAGS_MASK;
465-
VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM);
466-
VERIFYC(flags >= 0 && flags < FASTRPC_MAP_MAX &&
467-
flags != FASTRPC_MAP_RESERVED,
468-
AEE_EBADPARM);
469-
470456
// Get domain and open session if not already open
471-
if (domain == -1) {
472-
domain = get_current_domain();
457+
if (*domain == -1) {
458+
*domain = get_current_domain();
473459
}
474-
VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM);
475-
FASTRPC_GET_REF(domain);
476-
VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev)));
460+
VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(*domain), AEE_EBADPARM);
461+
FASTRPC_GET_REF(*domain);
462+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(*domain, &dev)));
477463
VERIFYC(-1 != dev, AEE_ERPC);
478464

479465
/* Search for mapping in current session static map list */
480-
pthread_mutex_lock(&smaplst[domain].mut);
481-
QLIST_NEXTSAFE_FOR_ALL(&smaplst[domain].ql, pn, pnn) {
466+
pthread_mutex_lock(&smaplst[*domain].mut);
467+
QLIST_NEXTSAFE_FOR_ALL(&smaplst[*domain].ql, pn, pnn) {
482468
tNode = STD_RECOVER_REC(struct static_map, qn, pn);
483469
if (tNode->map.fd == fd) {
484470
break;
485471
}
486472
}
487-
pthread_mutex_unlock(&smaplst[domain].mut);
473+
pthread_mutex_unlock(&smaplst[*domain].mut);
488474

489475
// Raise error if map found already
490476
if (tNode) {
@@ -505,13 +491,13 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length,
505491
map.m.vaddrout = 0;
506492
mNode->map = map.m;
507493
iocErr = ioctl_mmap(dev, MEM_MAP, flags, attrs, fd, offset, length,
508-
(uint64_t)vaddr, &vaddrout);
494+
(uint64_t)vaddr, vaddrout);
509495
if (!iocErr) {
510-
mNode->map.vaddrout = vaddrout;
496+
mNode->map.vaddrout = *vaddrout;
511497
mNode->refs = 1;
512-
pthread_mutex_lock(&smaplst[domain].mut);
513-
QList_AppendNode(&smaplst[domain].ql, &mNode->qn);
514-
pthread_mutex_unlock(&smaplst[domain].mut);
498+
pthread_mutex_lock(&smaplst[*domain].mut);
499+
QList_AppendNode(&smaplst[*domain].ql, &mNode->qn);
500+
pthread_mutex_unlock(&smaplst[*domain].mut);
515501
mNode = NULL;
516502
} else if (errno == ENOTTY ||
517503
iocErr == (int)(DSP_AEE_EOFFSET | AEE_EUNSUPPORTED)) {
@@ -521,16 +507,17 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length,
521507
nErr = AEE_EFAILED;
522508
goto bail;
523509
}
510+
524511
bail:
525-
FASTRPC_PUT_REF(domain);
512+
FASTRPC_PUT_REF(*domain);
526513
if (nErr) {
527514
if (iocErr == 0) {
528515
errno = 0;
529516
}
530517
FARF(ERROR,
531-
"Error 0x%x: %s failed to map buffer fd %d, addr %p, length 0x%zx, "
518+
"Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, "
532519
"domain %d, flags 0x%x, ioctl ret 0x%x, errno %s",
533-
nErr, __func__, fd, vaddr, length, domain, flags, iocErr,
520+
nErr, __func__, fd, vaddr, length, *domain, flags, iocErr,
534521
strerror(errno));
535522
}
536523
if (mNode) {
@@ -540,6 +527,41 @@ int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length,
540527
return nErr;
541528
}
542529

530+
int fastrpc_mmap(int domain, int fd, void *vaddr, int offset, size_t length,
531+
enum fastrpc_map_flags flags) {
532+
int nErr = 0, attrs = 0;
533+
uint64_t vaddrout = 0;
534+
535+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
536+
537+
FARF(RUNTIME_RPC_HIGH,
538+
"%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x",
539+
__func__, domain, fd, vaddr, length, flags, offset);
540+
541+
/**
542+
* Mask is applied on "flags" parameter to extract map control flags
543+
* and SMMU mapping control attributes. Currently no attributes are
544+
* suppported. It allows future extension of the fastrpc_mmap API
545+
* for SMMU mapping control attributes.
546+
*/
547+
attrs = flags & (~FASTRPC_MAP_FLAGS_MASK);
548+
flags = flags & FASTRPC_MAP_FLAGS_MASK;
549+
VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM);
550+
VERIFYC(flags >= 0 && flags < FASTRPC_MAP_MAX &&
551+
flags != FASTRPC_MAP_RESERVED,
552+
AEE_EBADPARM);
553+
554+
nErr = fastrpc_mmap_helper(&domain, fd, vaddr, offset, length, flags, attrs,
555+
&vaddrout);
556+
557+
bail:
558+
if (nErr) {
559+
FARF(ERROR, "Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, domain %d, flags 0x%x",
560+
nErr, __func__, fd, vaddr, length, domain, flags);
561+
}
562+
return nErr;
563+
}
564+
543565
int fastrpc_munmap(int domain, int fd, void *vaddr, size_t length) {
544566
int nErr = 0, dev = -1, iocErr = 0, locked = 0, ref = 0;
545567
struct static_map *mNode = NULL;
@@ -614,6 +636,110 @@ int fastrpc_munmap(int domain, int fd, void *vaddr, size_t length) {
614636
return nErr;
615637
}
616638

639+
int fastrpc_mmap_internal(int domain, int fd, void *vaddr, int offset,
640+
size_t length, uint32_t flags, uint64_t *raddr) {
641+
int nErr = 0, attrs = 0;
642+
643+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
644+
645+
VERIFYC(raddr != NULL, AEE_EBADPARM);
646+
647+
FARF(RUNTIME_RPC_HIGH,
648+
"%s: domain %d fd %d addr %p length 0x%zx flags 0x%x offset 0x%x",
649+
__func__, domain, fd, vaddr, length, flags, offset);
650+
651+
/**
652+
* Mask is applied on "flags" parameter to extract map control flags
653+
* and SMMU mapping control attributes. Currently no attributes are
654+
* suppported. It allows future extension of the fastrpc_mmap API
655+
* for SMMU mapping control attributes.
656+
*/
657+
attrs = flags & (~FASTRPC_MAP_FLAGS_MASK);
658+
flags = flags & FASTRPC_MAP_FLAGS_MASK;
659+
VERIFYC(fd >= 0 && offset == 0 && attrs == 0, AEE_EBADPARM);
660+
661+
nErr = fastrpc_mmap_helper(&domain, fd, vaddr, offset, length, flags, attrs,
662+
raddr);
663+
664+
bail:
665+
if (nErr) {
666+
FARF(ERROR, "Error 0x%x: %s failed for fd %d, addr %p, length 0x%zx, domain %d, flags 0x%x",
667+
nErr, __func__, fd, vaddr, length, domain, flags);
668+
}
669+
return nErr;
670+
}
671+
672+
int fastrpc_munmap_internal(int domain, uint64_t raddr, size_t length) {
673+
int nErr = 0, dev = -1, iocErr = 0, locked = 0, ref = 0;
674+
struct static_map *mNode = NULL;
675+
QNode *pn, *pnn;
676+
677+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
678+
679+
FARF(RUNTIME_RPC_HIGH, "%s: domain %d raddr 0x%llx length 0x%zx", __func__,
680+
domain, raddr, length);
681+
if (domain == -1) {
682+
domain = get_current_domain();
683+
}
684+
VERIFYC(IS_VALID_EFFECTIVE_DOMAIN_ID(domain), AEE_EBADPARM);
685+
FASTRPC_GET_REF(domain);
686+
VERIFY(AEE_SUCCESS == (nErr = fastrpc_session_dev(domain, &dev)));
687+
/**
688+
* Search for mapping in current static map list using DSP virtual address (raddr).
689+
*/
690+
pthread_mutex_lock(&smaplst[domain].mut);
691+
locked = 1;
692+
QLIST_NEXTSAFE_FOR_ALL(&smaplst[domain].ql, pn, pnn) {
693+
mNode = STD_RECOVER_REC(struct static_map, qn, pn);
694+
if (mNode->map.vaddrout == raddr) {
695+
FARF(RUNTIME_RPC_HIGH, "%s: unmap found for raddr 0x%llx domain %d", __func__,
696+
raddr, domain);
697+
break;
698+
}
699+
}
700+
VERIFYC(mNode && mNode->map.vaddrout == raddr, AEE_ENOSUCHMAP);
701+
if (mNode->refs > 1) {
702+
FARF(ERROR, "%s: Attempt to unmap raddr 0x%llx with %d outstanding references",
703+
__func__, raddr, mNode->refs - 1);
704+
nErr = AEE_EBADPARM;
705+
goto bail;
706+
}
707+
mNode->refs = 0;
708+
locked = 0;
709+
pthread_mutex_unlock(&smaplst[domain].mut);
710+
711+
iocErr = ioctl_munmap(dev, MEM_UNMAP, 0, 0, mNode->map.fd, mNode->map.length,
712+
mNode->map.vaddrout);
713+
pthread_mutex_lock(&smaplst[domain].mut);
714+
locked = 1;
715+
if (iocErr == 0) {
716+
QNode_DequeueZ(&mNode->qn);
717+
free(mNode);
718+
mNode = NULL;
719+
} else if (errno == ENOTTY || errno == EINVAL) {
720+
nErr = AEE_EUNSUPPORTED;
721+
} else {
722+
mNode->refs = 1;
723+
nErr = AEE_EFAILED;
724+
}
725+
bail:
726+
if (locked == 1) {
727+
locked = 0;
728+
pthread_mutex_unlock(&smaplst[domain].mut);
729+
}
730+
FASTRPC_PUT_REF(domain);
731+
if (nErr) {
732+
if (iocErr == 0) {
733+
errno = 0;
734+
}
735+
FARF(ERROR,
736+
"Error 0x%x: %s failed raddr 0x%llx, length 0x%zx, domain %d, "
737+
"ioctl ret 0x%x, errno %s",
738+
nErr, __func__, raddr, length, domain, iocErr, strerror(errno));
739+
}
740+
return nErr;
741+
}
742+
617743
int remote_mem_map(int domain, int fd, int flags, uint64_t vaddr, size_t size,
618744
uint64_t *raddr) {
619745
int nErr = 0;

0 commit comments

Comments
 (0)