riscv/addrenv: Create utility function for dynamic mappings

Move the mapping functionality from up_shmat/shmdt into two generic
mapping functions. This makes it possible to do other mappings besides
user shared memory area mappings.
This commit is contained in:
Ville Juven 2023-05-11 11:08:36 +03:00 committed by Xiang Xiao
parent 2e6d0815b2
commit aee45c9c43
3 changed files with 170 additions and 70 deletions

View File

@ -67,5 +67,50 @@
uintptr_t riscv_get_pgtable(arch_addrenv_t *addrenv, uintptr_t vaddr);
/****************************************************************************
* Name: riscv_map_pages
*
* Description:
* Map physical pages into a continuous virtual memory block.
*
* Input Parameters:
* addrenv - Pointer to a structure describing the address environment.
* pages - A pointer to the first element in a array of physical address,
* each corresponding to one page of memory.
* npages - The number of pages in the list of physical pages to be mapped.
* vaddr - The virtual address corresponding to the beginning of the
* (continuous) virtual address region.
* prot - MMU flags to use.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int riscv_map_pages(arch_addrenv_t *addrenv, uintptr_t *pages,
unsigned int npages, uintptr_t vaddr, int prot);
/****************************************************************************
* Name: riscv_unmap_pages
*
* Description:
* Unmap a previously mapped virtual memory region.
*
* Input Parameters:
* addrenv - Pointer to a structure describing the address environment.
* vaddr - The virtual address corresponding to the beginning of the
* (continuous) virtual address region.
* npages - The number of pages to be unmapped
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int riscv_unmap_pages(arch_addrenv_t *addrenv, uintptr_t vaddr,
unsigned int npages);
#endif /* CONFIG_ARCH_ADDRENV */
#endif /* __ARCH_RISC_V_SRC_COMMON_ADDRENV_H */

View File

@ -66,11 +66,8 @@
int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr)
{
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv;
uintptr_t ptlast;
uintptr_t ptlevel;
uintptr_t paddr;
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv = &tcb->addrenv_own->addrenv;
/* Sanity checks */
@ -79,33 +76,9 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr)
DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND);
DEBUGASSERT(MM_ISALIGNED(vaddr));
addrenv = &tcb->addrenv_own->addrenv;
ptlevel = RV_MMU_PT_LEVELS;
/* Let riscv_map_pages do the work */
/* Add the references to pages[] into the caller's address environment */
for (; npages > 0; npages--)
{
/* Get the address of the last level page table */
ptlast = riscv_pgvaddr(riscv_get_pgtable(addrenv, vaddr));
if (!ptlast)
{
return -ENOMEM;
}
/* Then add the reference */
paddr = *pages++;
mmu_ln_setentry(ptlevel, ptlast, paddr, vaddr, MMU_UDATA_FLAGS);
vaddr += MM_PGSIZE;
}
/* Flush the data cache, so the changes are committed to memory */
__DMB();
return OK;
return riscv_map_pages(addrenv, pages, npages, vaddr, MMU_UDATA_FLAGS);
}
/****************************************************************************
@ -127,12 +100,8 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr)
int up_shmdt(uintptr_t vaddr, unsigned int npages)
{
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv;
uintptr_t ptlast;
uintptr_t ptprev;
uintptr_t ptlevel;
uintptr_t paddr;
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv = &tcb->addrenv_own->addrenv;
/* Sanity checks */
@ -141,40 +110,9 @@ int up_shmdt(uintptr_t vaddr, unsigned int npages)
DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND);
DEBUGASSERT(MM_ISALIGNED(vaddr));
addrenv = &tcb->addrenv_own->addrenv;
ptlevel = ARCH_SPGTS;
ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]);
if (!ptprev)
{
/* Something is very wrong */
/* Let riscv_unmap_pages do the work */
return -EFAULT;
}
/* Remove the references from the caller's address environment */
for (; npages > 0; npages--)
{
/* Get the current final level entry corresponding to this vaddr */
paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr));
ptlast = riscv_pgvaddr(paddr);
if (!ptlast)
{
return -EFAULT;
}
/* Then wipe the reference */
mmu_ln_clear(ptlevel + 1, ptlast, vaddr);
vaddr += MM_PGSIZE;
}
/* Flush the data cache, so the changes are committed to memory */
__DMB();
return OK;
return riscv_unmap_pages(addrenv, vaddr, npages);
}
#endif /* CONFIG_BUILD_KERNEL */

View File

@ -91,4 +91,121 @@ uintptr_t riscv_get_pgtable(arch_addrenv_t *addrenv, uintptr_t vaddr)
return paddr;
}
/****************************************************************************
* Name: riscv_map_pages
*
* Description:
* Map physical pages into a continuous virtual memory block.
*
* Input Parameters:
* addrenv - Pointer to a structure describing the address environment.
* pages - A pointer to the first element in a array of physical address,
* each corresponding to one page of memory.
* npages - The number of pages in the list of physical pages to be mapped.
* vaddr - The virtual address corresponding to the beginning of the
* (continuous) virtual address region.
* prot - MMU flags to use.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int riscv_map_pages(arch_addrenv_t *addrenv, uintptr_t *pages,
unsigned int npages, uintptr_t vaddr, int prot)
{
uintptr_t ptlast;
uintptr_t ptlevel;
uintptr_t paddr;
ptlevel = RV_MMU_PT_LEVELS;
/* Add the references to pages[] into the caller's address environment */
for (; npages > 0; npages--)
{
/* Get the address of the last level page table */
ptlast = riscv_pgvaddr(riscv_get_pgtable(addrenv, vaddr));
if (!ptlast)
{
return -ENOMEM;
}
/* Then add the reference */
paddr = *pages++;
mmu_ln_setentry(ptlevel, ptlast, paddr, vaddr, prot);
vaddr += MM_PGSIZE;
}
/* Flush the data cache, so the changes are committed to memory */
__DMB();
return OK;
}
/****************************************************************************
* Name: riscv_unmap_pages
*
* Description:
* Unmap a previously mapped virtual memory region.
*
* Input Parameters:
* addrenv - Pointer to a structure describing the address environment.
* vaddr - The virtual address corresponding to the beginning of the
* (continuous) virtual address region.
* npages - The number of pages to be unmapped
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int riscv_unmap_pages(arch_addrenv_t *addrenv, uintptr_t vaddr,
unsigned int npages)
{
uintptr_t ptlast;
uintptr_t ptprev;
uintptr_t ptlevel;
uintptr_t paddr;
ptlevel = ARCH_SPGTS;
ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]);
if (!ptprev)
{
/* Something is very wrong */
return -EFAULT;
}
/* Remove the references from the caller's address environment */
for (; npages > 0; npages--)
{
/* Get the current final level entry corresponding to this vaddr */
paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr));
ptlast = riscv_pgvaddr(paddr);
if (!ptlast)
{
return -EFAULT;
}
/* Then wipe the reference */
mmu_ln_clear(ptlevel + 1, ptlast, vaddr);
vaddr += MM_PGSIZE;
}
/* Flush the data cache, so the changes are committed to memory */
__DMB();
return OK;
}
#endif /* CONFIG_BUILD_KERNEL */