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

Reply via email to