diff --git a/arch/risc-v/src/common/addrenv.h b/arch/risc-v/src/common/addrenv.h index e21bb72460..051d04758f 100644 --- a/arch/risc-v/src/common/addrenv.h +++ b/arch/risc-v/src/common/addrenv.h @@ -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 */ diff --git a/arch/risc-v/src/common/riscv_addrenv_shm.c b/arch/risc-v/src/common/riscv_addrenv_shm.c index 0183537db2..bd53a5eb05 100644 --- a/arch/risc-v/src/common/riscv_addrenv_shm.c +++ b/arch/risc-v/src/common/riscv_addrenv_shm.c @@ -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 */ diff --git a/arch/risc-v/src/common/riscv_addrenv_utils.c b/arch/risc-v/src/common/riscv_addrenv_utils.c index 0010368047..810563aedd 100644 --- a/arch/risc-v/src/common/riscv_addrenv_utils.c +++ b/arch/risc-v/src/common/riscv_addrenv_utils.c @@ -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 */