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:
parent
2e6d0815b2
commit
aee45c9c43
@ -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 */
|
||||
|
@ -67,10 +67,7 @@
|
||||
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 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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -128,11 +101,7 @@ 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 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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user