This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 596ce5e7b122cafeedbc990646667a4f62d78364 Author: Ville Juven <ville.ju...@unikie.com> AuthorDate: Wed Nov 16 14:38:53 2022 +0200 riscv/addrenv: Implement up_shmat/shmdt for RISC-V These are great utility functions to create/destroy anonymous mappings --- arch/risc-v/src/common/Make.defs | 2 +- arch/risc-v/src/common/riscv_addrenv_shm.c | 176 +++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index 54fae2ae52..7b8bcfc417 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -103,5 +103,5 @@ endif ifeq ($(CONFIG_ARCH_ADDRENV),y) CMN_CSRCS += riscv_addrenv.c riscv_pgalloc.c riscv_addrenv_perms.c -CMN_CSRCS += riscv_addrenv_utils.c +CMN_CSRCS += riscv_addrenv_utils.c riscv_addrenv_shm.c endif diff --git a/arch/risc-v/src/common/riscv_addrenv_shm.c b/arch/risc-v/src/common/riscv_addrenv_shm.c new file mode 100644 index 0000000000..f850c3051a --- /dev/null +++ b/arch/risc-v/src/common/riscv_addrenv_shm.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_addrenv_shm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/addrenv.h> +#include <nuttx/arch.h> +#include <nuttx/irq.h> +#include <nuttx/pgalloc.h> + +#include <arch/barriers.h> + +#include "addrenv.h" +#include "pgalloc.h" +#include "riscv_mmu.h" + +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_shmat + * + * Description: + * Attach, i.e, map, on shared memory region to a user virtual address + * + * Input Parameters: + * 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 + * (contiguous) virtual address region. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) +{ + struct tcb_s *tcb = nxsched_self(); + struct task_group_s *group; + uintptr_t ptlast; + uintptr_t ptlevel; + uintptr_t paddr; + + /* Sanity checks */ + + DEBUGASSERT(tcb && tcb->group); + DEBUGASSERT(pages != NULL && npages > 0); + DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); + DEBUGASSERT(MM_ISALIGNED(vaddr)); + + group = tcb->group; + 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(&group->tg_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; +} + +/**************************************************************************** + * Name: up_shmdt + * + * Description: + * Detach, i.e, unmap, on shared memory region from a user virtual address + * + * Input Parameters: + * vaddr - The virtual address corresponding to the beginning of the + * (contiguous) 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 up_shmdt(uintptr_t vaddr, unsigned int npages) +{ + struct tcb_s *tcb = nxsched_self(); + struct task_group_s *group; + uintptr_t ptlast; + uintptr_t ptprev; + uintptr_t ptlevel; + uintptr_t paddr; + + /* Sanity checks */ + + DEBUGASSERT(tcb && tcb->group); + DEBUGASSERT(npages > 0); + DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); + DEBUGASSERT(MM_ISALIGNED(vaddr)); + + group = tcb->group; + ptlevel = ARCH_SPGTS; + ptprev = riscv_pgvaddr(group->tg_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); + + /* 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 */