This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit dbc9a233f14769b9b0e4ca07f2027fa57c52dfa5 Author: Royyan Zahir <[email protected]> AuthorDate: Thu Oct 1 03:52:06 2026 +0400 arch: translate an address with the MMU in a kernel build risc-v and x86_64 walk the active page tables for up_addrenv_va_to_pa() the way arm64 does. drivers/misc/addrenv.c defined the same symbol from a static table, which cannot see user mappings: in a kernel build it now steps aside and arm64 builds its walker there too. Outside a kernel build nothing changes. Signed-off-by: Royyan Zahir <[email protected]> --- arch/arm64/src/common/CMakeLists.txt | 5 ++-- arch/arm64/src/common/Make.defs | 5 +++- arch/risc-v/src/common/riscv_addrenv_pgmap.c | 28 ++++++++++++++++++++ arch/x86_64/src/common/x86_64_addrenv.c | 38 ++++++++++++++++++++++++++++ drivers/misc/addrenv.c | 2 ++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/arch/arm64/src/common/CMakeLists.txt b/arch/arm64/src/common/CMakeLists.txt index bd53b5aba86..3da5d5e4868 100644 --- a/arch/arm64/src/common/CMakeLists.txt +++ b/arch/arm64/src/common/CMakeLists.txt @@ -74,9 +74,10 @@ endif() if(CONFIG_ARCH_HAVE_MMU) list(APPEND SRCS arm64_mmu.c) - # drivers/misc/addrenv.c defines the same entry points from a table. + # Outside a kernel build, drivers/misc/addrenv.c defines the same entry point + # from a table. - if(NOT CONFIG_DEV_SIMPLE_ADDRENV) + if(NOT CONFIG_DEV_SIMPLE_ADDRENV OR CONFIG_BUILD_KERNEL) list(APPEND SRCS arm64_physpgaddr.c) endif() endif() diff --git a/arch/arm64/src/common/Make.defs b/arch/arm64/src/common/Make.defs index 05b7f5a90ab..1d4053d7812 100644 --- a/arch/arm64/src/common/Make.defs +++ b/arch/arm64/src/common/Make.defs @@ -81,10 +81,13 @@ endif ifeq ($(CONFIG_ARCH_HAVE_MMU),y) CMN_CSRCS += arm64_mmu.c -# drivers/misc/addrenv.c defines the same entry points from a table. +# Outside a kernel build, drivers/misc/addrenv.c defines the same entry +# point from a table. ifneq ($(CONFIG_DEV_SIMPLE_ADDRENV),y) CMN_CSRCS += arm64_physpgaddr.c +else ifeq ($(CONFIG_BUILD_KERNEL),y) +CMN_CSRCS += arm64_physpgaddr.c endif endif diff --git a/arch/risc-v/src/common/riscv_addrenv_pgmap.c b/arch/risc-v/src/common/riscv_addrenv_pgmap.c index d25bacafd9c..bf37d39fac8 100644 --- a/arch/risc-v/src/common/riscv_addrenv_pgmap.c +++ b/arch/risc-v/src/common/riscv_addrenv_pgmap.c @@ -149,6 +149,34 @@ bool up_addrenv_user_vaddr(uintptr_t vaddr) return riscv_uservaddr(vaddr); } +uintptr_t up_addrenv_va_to_pa(FAR void *va) +{ + uintptr_t vaddr = (uintptr_t)va; + uintptr_t lnvaddr = riscv_pgvaddr(mmu_get_satp_pgbase()); + uintptr_t size = RV_MMU_L1_PAGE_SIZE; + uintptr_t pte; + uint32_t ptlevel; + + for (ptlevel = 1; ptlevel <= RV_MMU_PT_LEVELS && lnvaddr; ptlevel++) + { + pte = mmu_ln_getentry(ptlevel, lnvaddr, vaddr); + if ((pte & PTE_VALID) == 0) + { + break; + } + + if ((pte & (PTE_R | PTE_X)) != 0) + { + return mmu_pte_to_paddr(pte) | (vaddr & (size - 1)); + } + + lnvaddr = riscv_pgvaddr(mmu_pte_to_paddr(pte)); + size >>= RV_MMU_VPN_WIDTH; + } + + return 0; +} + /**************************************************************************** * Name: up_addrenv_page_wipe * diff --git a/arch/x86_64/src/common/x86_64_addrenv.c b/arch/x86_64/src/common/x86_64_addrenv.c index d9c3d934dfd..de6296af984 100644 --- a/arch/x86_64/src/common/x86_64_addrenv.c +++ b/arch/x86_64/src/common/x86_64_addrenv.c @@ -1011,3 +1011,41 @@ bool up_addrenv_user_vaddr(uintptr_t vaddr) #endif ; } + +/**************************************************************************** + * Name: up_addrenv_va_to_pa + * + * Description: + * Translate a virtual address through the active page tables; 0 when it + * is not mapped. + * + ****************************************************************************/ + +uintptr_t up_addrenv_va_to_pa(FAR void *va) +{ + uintptr_t vaddr = (uintptr_t)va; + uintptr_t lnvaddr = x86_64_pgvaddr(get_pml4()); + uintptr_t mask; + uintptr_t pte; + uint32_t ptlevel; + + for (ptlevel = 0; ptlevel < X86_MMU_PT_LEVELS && lnvaddr; ptlevel++) + { + pte = mmu_ln_getentry(ptlevel, lnvaddr, vaddr); + if ((pte & X86_PAGE_PRESENT) == 0) + { + break; + } + + if (ptlevel == X86_MMU_PT_LEVELS - 1 || + (ptlevel > 0 && (pte & X86_PAGE_HUGE) != 0)) + { + mask = ((uintptr_t)1 << X86_MMU_VADDR_SHIFT(ptlevel)) - 1; + return (mmu_pte_to_paddr(pte) & ~mask) | (vaddr & mask); + } + + lnvaddr = x86_64_pgvaddr(mmu_pte_to_paddr(pte)); + } + + return 0; +} diff --git a/drivers/misc/addrenv.c b/drivers/misc/addrenv.c index ec1d7f76dfd..bf32e154f2c 100644 --- a/drivers/misc/addrenv.c +++ b/drivers/misc/addrenv.c @@ -89,6 +89,7 @@ FAR void *up_addrenv_pa_to_va(uintptr_t pa) return (FAR void *)pa; } +#ifndef CONFIG_BUILD_KERNEL uintptr_t up_addrenv_va_to_pa(FAR void *va_) { FAR struct simple_addrenv_node_s *node; @@ -112,3 +113,4 @@ uintptr_t up_addrenv_va_to_pa(FAR void *va_) return va; } +#endif
