1
0
Fork 0
forked from nuttx/nuttx-update

mm/kmap: Provide the user tcb as parameter to map_user()

This allows mapping pages from others than the running task. Obiously
this can only be done with proper preparations (the task in question
cannot exit before the mapping is released).
This commit is contained in:
Ville Juven 2024-12-17 11:55:39 +02:00 committed by Xiang Xiao
parent c3d03f02fb
commit 95d1e52535
2 changed files with 34 additions and 17 deletions

View file

@ -23,6 +23,16 @@
#ifndef __INCLUDE_NUTTX_MM_KMAP_H #ifndef __INCLUDE_NUTTX_MM_KMAP_H
#define __INCLUDE_NUTTX_MM_KMAP_H #define __INCLUDE_NUTTX_MM_KMAP_H
/****************************************************************************
* Public Type Definitions
****************************************************************************/
struct tcb_s; /* Forward reference to TCB */
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: kmm_map_initialize * Name: kmm_map_initialize
* *
@ -81,6 +91,8 @@ void kmm_unmap(FAR void *kaddr);
* a continuous virtual memory area. * a continuous virtual memory area.
* *
* Input Parameters: * Input Parameters:
* tcb - The tcb of the task whose address environment the mapping
* belongs to.
* uaddr - The user virtual address where mapping begins. * uaddr - The user virtual address where mapping begins.
* size - Size of the region. * size - Size of the region.
* *
@ -89,7 +101,7 @@ void kmm_unmap(FAR void *kaddr);
* *
****************************************************************************/ ****************************************************************************/
FAR void *kmm_map_user(FAR void *uaddr, size_t size); FAR void *kmm_map_user(FAR struct tcb_s *tcb, FAR void *uaddr, size_t size);
/**************************************************************************** /****************************************************************************
* Name: kmm_map_user_page * Name: kmm_map_user_page
@ -99,6 +111,8 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size);
* returns the kernel addressable page pool virtual address. * returns the kernel addressable page pool virtual address.
* *
* Input Parameters: * Input Parameters:
* tcb - The tcb of the task whose address environment the mapping
* belongs to.
* uaddr - The virtual address of the user page. * uaddr - The virtual address of the user page.
* *
* Returned Value: * Returned Value:
@ -106,6 +120,6 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size);
* *
****************************************************************************/ ****************************************************************************/
FAR void *kmm_map_user_page(FAR void *uaddr); FAR void *kmm_map_user_page(FAR struct tcb_s *tcb, FAR void *uaddr);
#endif /* __INCLUDE_NUTTX_MM_KMAP_H */ #endif /* __INCLUDE_NUTTX_MM_KMAP_H */

View file

@ -76,9 +76,9 @@ static struct mm_map_s g_kmm_map;
* *
****************************************************************************/ ****************************************************************************/
static int get_user_pages(FAR void **pages, size_t npages, uintptr_t vaddr) static int get_user_pages(FAR struct tcb_s *tcb, FAR void **pages,
size_t npages, uintptr_t vaddr)
{ {
FAR struct tcb_s *tcb = this_task();
uintptr_t page; uintptr_t page;
int i; int i;
@ -170,18 +170,17 @@ errout_with_vaddr:
* Map a single user page into kernel memory. * Map a single user page into kernel memory.
* *
* Input Parameters: * Input Parameters:
* pages - Pointer to buffer that contains the physical page addresses. * tcb - The tcb of the task whose address environment the mapping
* npages - Amount of pages. * belongs to.
* prot - Access right flags. * vaddr - The virtual address of the page to map.
* *
* Returned Value: * Returned Value:
* Pointer to the mapped virtual memory on success; NULL on failure * Pointer to the mapped virtual memory on success; NULL on failure
* *
****************************************************************************/ ****************************************************************************/
static FAR void *map_single_user_page(uintptr_t vaddr) static FAR void *map_single_user_page(FAR struct tcb_s *tcb, uintptr_t vaddr)
{ {
FAR struct tcb_s *tcb = this_task();
uintptr_t page; uintptr_t page;
/* Find the page associated with this virtual address */ /* Find the page associated with this virtual address */
@ -405,6 +404,8 @@ void kmm_unmap(FAR void *kaddr)
* a continuous virtual memory area. * a continuous virtual memory area.
* *
* Input Parameters: * Input Parameters:
* tcb - The tcb of the task whose address environment the mapping
* belongs to.
* uaddr - The user virtual address where mapping begins. * uaddr - The user virtual address where mapping begins.
* size - Size of the region. * size - Size of the region.
* *
@ -413,7 +414,7 @@ void kmm_unmap(FAR void *kaddr)
* *
****************************************************************************/ ****************************************************************************/
FAR void *kmm_map_user(FAR void *uaddr, size_t size) FAR void *kmm_map_user(FAR struct tcb_s *tcb, FAR void *uaddr, size_t size)
{ {
FAR void **pages; FAR void **pages;
uintptr_t vaddr; uintptr_t vaddr;
@ -446,7 +447,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size)
{ {
/* Yes, can simply return the kernel addressable virtual address */ /* Yes, can simply return the kernel addressable virtual address */
vaddr = (uintptr_t)map_single_user_page(vaddr); vaddr = (uintptr_t)map_single_user_page(tcb, vaddr);
return (FAR void *)(vaddr + offset); return (FAR void *)(vaddr + offset);
} }
@ -460,7 +461,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size)
/* Fetch the physical pages for the user virtual address range */ /* Fetch the physical pages for the user virtual address range */
ret = get_user_pages(pages, npages, vaddr); ret = get_user_pages(tcb, pages, npages, vaddr);
if (ret < 0) if (ret < 0)
{ {
goto errout_with_pages; goto errout_with_pages;
@ -492,6 +493,8 @@ errout_with_pages:
* returns the kernel addressable page pool virtual address. * returns the kernel addressable page pool virtual address.
* *
* Input Parameters: * Input Parameters:
* tcb - The tcb of the task whose address environment the mapping
* belongs to.
* uaddr - The virtual address of the user page. * uaddr - The virtual address of the user page.
* *
* Returned Value: * Returned Value:
@ -499,7 +502,7 @@ errout_with_pages:
* *
****************************************************************************/ ****************************************************************************/
FAR void *kmm_map_user_page(FAR void *uaddr) FAR void *kmm_map_user_page(FAR struct tcb_s *tcb, FAR void *uaddr)
{ {
uintptr_t vaddr; uintptr_t vaddr;
uintptr_t offset; uintptr_t offset;
@ -522,7 +525,7 @@ FAR void *kmm_map_user_page(FAR void *uaddr)
offset = vaddr & MM_PGMASK; offset = vaddr & MM_PGMASK;
vaddr = MM_PGALIGNDOWN(vaddr); vaddr = MM_PGALIGNDOWN(vaddr);
vaddr = (uintptr_t)map_single_user_page(vaddr); vaddr = (uintptr_t)map_single_user_page(tcb, vaddr);
if (!vaddr) if (!vaddr)
{ {
return NULL; return NULL;