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/nuttx.git

commit e0183927b451e6365f4eaa90f85fb9205d396353
Author: p-szafonimateusz <[email protected]>
AuthorDate: Mon Jun 17 14:04:48 2024 +0200

    arch/x86_64: add MMU interface
    
    add MMU api for x86_64
    
    Signed-off-by: p-szafonimateusz <[email protected]>
---
 arch/x86_64/Kconfig                   |   4 +-
 arch/x86_64/include/intel64/irq.h     |  19 ++++
 arch/x86_64/src/common/CMakeLists.txt |   4 +
 arch/x86_64/src/common/Make.defs      |   4 +
 arch/x86_64/src/common/addrenv.h      |  89 +++++++++++++++++
 arch/x86_64/src/common/x86_64_mmu.c   | 146 ++++++++++++++++++++++++++++
 arch/x86_64/src/common/x86_64_mmu.h   | 178 ++++++++++++++++++++++++++++++++++
 7 files changed, 442 insertions(+), 2 deletions(-)

diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index a22b9310b3..4a8458bd77 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -16,8 +16,8 @@ choice
 
 config ARCH_INTEL64
        bool "Intel x86_64"
-       select ARCH_HAVE_MPU
-       select ARCH_USE_MPU
+       select ARCH_HAVE_MMU
+       select ARCH_USE_MMU
        select ARCH_HAVE_TICKLESS
        select ARCH_HAVE_STACKCHECK
        select ARCH_HAVE_RNG
diff --git a/arch/x86_64/include/intel64/irq.h 
b/arch/x86_64/include/intel64/irq.h
index 3f3d27c2d9..d27019d457 100644
--- a/arch/x86_64/include/intel64/irq.h
+++ b/arch/x86_64/include/intel64/irq.h
@@ -558,6 +558,25 @@ static inline void set_pcid(uint64_t pcid)
       }
 }
 
+static inline void set_cr3(uint64_t cr3)
+{
+  asm volatile("mov %0, %%cr3" : "=rm"(cr3) : : "memory");
+}
+
+static inline uint64_t get_cr3(void)
+{
+  uint64_t cr3;
+  asm volatile("mov %%cr3, %0" : "=rm"(cr3) : : "memory");
+  return cr3;
+}
+
+static inline uint64_t get_pml4(void)
+{
+  /* Aligned to a 4-KByte boundary */
+
+  return get_cr3() & 0xfffffffffffff000;
+}
+
 static inline unsigned long read_msr(unsigned int msr)
 {
   uint32_t low;
diff --git a/arch/x86_64/src/common/CMakeLists.txt 
b/arch/x86_64/src/common/CMakeLists.txt
index f50ff808e3..600a643f05 100644
--- a/arch/x86_64/src/common/CMakeLists.txt
+++ b/arch/x86_64/src/common/CMakeLists.txt
@@ -41,4 +41,8 @@ if(CONFIG_ARCH_X86_64_ACPI)
   list(APPEND SRCS x86_64_acpi.c)
 endif()
 
+if(CONFIG_ARCH_USE_MMU)
+  list(APPEND SRCS x86_64_mmu.c)
+endif()
+
 target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/x86_64/src/common/Make.defs b/arch/x86_64/src/common/Make.defs
index 12db901b99..97756c9e91 100644
--- a/arch/x86_64/src/common/Make.defs
+++ b/arch/x86_64/src/common/Make.defs
@@ -32,3 +32,7 @@ endif
 ifeq ($(CONFIG_ARCH_X86_64_ACPI),y)
 CMN_CSRCS += x86_64_acpi.c
 endif
+
+ifeq ($(CONFIG_ARCH_USE_MMU),y)
+CMN_CSRCS += x86_64_mmu.c
+endif
diff --git a/arch/x86_64/src/common/addrenv.h b/arch/x86_64/src/common/addrenv.h
new file mode 100644
index 0000000000..9c6dc9a1ca
--- /dev/null
+++ b/arch/x86_64/src/common/addrenv.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+ * arch/x86_64/src/common/addrenv.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_X86_64_SRC_COMMON_ADDRENV_H
+#define __ARCH_X86_64_SRC_COMMON_ADDRENV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include "x86_64_internal.h"
+
+#ifdef CONFIG_ARCH_ADDRENV
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Aligned size of the kernel stack */
+
+#ifdef CONFIG_ARCH_KERNEL_STACK
+#  define ARCH_KERNEL_STACKSIZE STACK_ALIGN_UP(CONFIG_ARCH_KERNEL_STACKSIZE)
+#endif
+
+/* Base address for address environment */
+
+#if CONFIG_ARCH_TEXT_VBASE != 0
+#  define ARCH_ADDRENV_VBASE    (CONFIG_ARCH_TEXT_VBASE)
+#else
+#  define ARCH_ADDRENV_VBASE    (CONFIG_ARCH_DATA_VBASE)
+#endif
+
+/* Maximum user address environment size */
+
+#define ARCH_ADDRENV_MAX_SIZE   (0x40000000)
+
+/* User address environment end */
+
+#define ARCH_ADDRENV_VEND       (ARCH_ADDRENV_VBASE + ARCH_ADDRENV_MAX_SIZE - 
1)
+
+/* Flags for kernel page tables */
+
+#define MMU_KPGT_FLAGS          (X86_PAGE_WR)
+
+/* Mark user memory if in kernel build */
+
+#ifndef CONFIG_BUILD_KERNEL
+#  define MMU_USER_DEFAULT      (X86_PAGE_USER)
+#else
+#  define MMU_USER_DEFAULT      (0)
+#endif
+
+/* Flags for user page tables */
+
+#define MMU_UPGT_FLAGS          (X86_PAGE_WR | MMU_USER_DEFAULT)
+
+/* Flags for user FLASH (RX) and user RAM (RW) */
+
+#define MMU_UDATA_FLAGS         (X86_PAGE_WR | MMU_USER_DEFAULT)
+#define MMU_UTEXT_FLAGS         (X86_PAGE_WR | MMU_USER_DEFAULT)
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* CONFIG_ARCH_ADDRENV */
+#endif /* __ARCH_X86_64_SRC_COMMON_ADDRENV_H */
diff --git a/arch/x86_64/src/common/x86_64_mmu.c 
b/arch/x86_64/src/common/x86_64_mmu.c
new file mode 100644
index 0000000000..99482a9578
--- /dev/null
+++ b/arch/x86_64/src/common/x86_64_mmu.c
@@ -0,0 +1,146 @@
+/****************************************************************************
+ * arch/x86_64/src/common/x86_64_mmu.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 <nuttx/arch.h>
+
+#include "x86_64_internal.h"
+#include "x86_64_mmu.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mmu_ln_setentry
+ *
+ * Description:
+ *   Set a level n translation table entry.
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   paddr - The physical address to be mapped
+ *   vaddr - The virtual address to be mapped
+ *   mmuflags - The MMU flags to use in the mapping.
+ *
+ ****************************************************************************/
+
+void mmu_ln_setentry(uint32_t ptlevel, uintptr_t lnvaddr, uintptr_t paddr,
+                     uintptr_t vaddr, uint32_t mmuflags)
+{
+  uintptr_t *lntable = (uintptr_t *)lnvaddr;
+  uint32_t   index;
+
+  DEBUGASSERT(ptlevel >= 0 && ptlevel < X86_MMU_PT_LEVELS);
+
+  /* Make sure the entry is valid */
+
+  mmuflags |= X86_PAGE_PRESENT;
+
+  /* Calculate index for lntable */
+
+  index = X86_MMU_VADDR_INDEX(vaddr, ptlevel);
+
+  /* Save it */
+
+  lntable[index] = (paddr | mmuflags);
+
+  /* Update with memory by flushing the cache(s) */
+
+  up_invalid_tlb(vaddr, vaddr + 1);
+}
+
+/****************************************************************************
+ * Name: mmu_ln_getentry
+ *
+ * Description:
+ *   Get a level n translation table entry.
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   vaddr - The virtual address to get pte for
+ *
+ ****************************************************************************/
+
+uintptr_t mmu_ln_getentry(uint32_t ptlevel, uintptr_t lnvaddr,
+                          uintptr_t vaddr)
+{
+  uintptr_t *lntable = (uintptr_t *)lnvaddr;
+  uint32_t  index;
+
+  DEBUGASSERT(ptlevel >= 0 && ptlevel < X86_MMU_PT_LEVELS);
+
+  index = X86_MMU_VADDR_INDEX(vaddr, ptlevel);
+
+  return lntable[index];
+}
+
+/****************************************************************************
+ * Name: mmu_ln_map_region
+ *
+ * Description:
+ *   Set a translation table region for level n
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   paddr - The physical address to be mapped
+ *   vaddr - The virtual address to be mapped
+ *   size - The size of the region in bytes
+ *   mmuflags - The MMU flags to use in the mapping.
+ *
+ ****************************************************************************/
+
+void mmu_ln_map_region(uint32_t ptlevel, uintptr_t lnvaddr, uintptr_t paddr,
+                       uintptr_t vaddr, size_t size, uint32_t mmuflags)
+{
+  uintptr_t end_paddr = paddr + size;
+  size_t    page_size = X86_MMU_PAGE_SIZE;
+
+  DEBUGASSERT(ptlevel >= 0 && ptlevel < X86_MMU_PT_LEVELS);
+
+  while (paddr < end_paddr)
+    {
+      mmu_ln_setentry(ptlevel, lnvaddr, paddr, vaddr, mmuflags);
+      paddr += page_size;
+      vaddr += page_size;
+    }
+}
diff --git a/arch/x86_64/src/common/x86_64_mmu.h 
b/arch/x86_64/src/common/x86_64_mmu.h
new file mode 100644
index 0000000000..ac95dbc746
--- /dev/null
+++ b/arch/x86_64/src/common/x86_64_mmu.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+ * arch/x86_64/src/common/x86_64_mmu.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_X86_64_SRC_COMMON_X86_64_MMU_H
+#define __ARCH_X86_64_SRC_COMMON_X86_64_MMU_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/arch.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* 4 level paging, 4K pages */
+
+#define X86_MMU_PT_LEVELS       4
+#define X86_MMU_PAGE_SHIFT      12
+#define X86_MMU_PAGE_SIZE       (1 << X86_MMU_PAGE_SHIFT)
+#define X86_MMU_ENTRIES_PER_PGT (X86_MMU_PAGE_SIZE / 8)
+
+/* Get virtual address shift for a given paging level.
+ * NOTE: in this implementation PTL4 has index 0, PT has index 3 !
+ */
+
+#define X86_MMU_PADDR_SHIFT     12
+#define X86_MMU_VPN_WIDTH       9
+#define X86_MMU_VPN_MASK        ((1 << X86_MMU_VPN_WIDTH) - 1)
+#define X86_MMU_VADDR_SHIFT(n)  (X86_MMU_PADDR_SHIFT + X86_MMU_VPN_WIDTH * \
+                                 (X86_MMU_PT_LEVELS - ((n) + 1)))
+
+/* Get index in a given page table level for a given virtual address */
+
+#define X86_MMU_VADDR_INDEX(vaddr, ptlevel) \
+  ((vaddr >> X86_MMU_VADDR_SHIFT(ptlevel)) & X86_MMU_VPN_MASK)
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mmu_cr3_reg
+ *
+ * Description:
+ *   Utility function to build cr3 register value for input parameters
+ *
+ * Input Parameters:
+ *   pgbase - The physical base address of the translation table base
+ *   asid - Address space identifier. Not used now.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t mmu_cr3_reg(uintptr_t pgbase, uint16_t asid)
+{
+  uintptr_t reg;
+
+  UNUSED(asid);
+
+  reg = pgbase;
+  return reg;
+}
+
+/****************************************************************************
+ * Name: mmu_pte_to_paddr
+ *
+ * Description:
+ *   Extract physical address from PTE
+ *
+ * Input Parameters:
+ *   pte - Page table entry
+ *
+ * Returned Value:
+ *   Physical address from PTE
+ *
+ ****************************************************************************/
+
+static inline uintptr_t mmu_pte_to_paddr(uintptr_t pte)
+{
+  uintptr_t paddr = 0;
+
+  if (pte & X86_PAGE_PRESENT)
+    {
+      paddr = pte;
+
+      /* Get page addres - remove flags */
+
+      paddr &= 0x0dfffffffffff000;
+    }
+
+  return paddr;
+}
+
+/****************************************************************************
+ * Name: mmu_ln_setentry
+ *
+ * Description:
+ *   Set a level n translation table entry.
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   paddr - The physical address to be mapped. Must be aligned to a PPN
+ *     address boundary which is dependent on the level of the entry
+ *   vaddr - The virtual address to be mapped. Must be aligned to a PPN
+ *     address boundary which is dependent on the level of the entry
+ *   mmuflags - The MMU flags to use in the mapping.
+ *
+ ****************************************************************************/
+
+void mmu_ln_setentry(uint32_t ptlevel, uintptr_t lnvaddr, uintptr_t paddr,
+                     uintptr_t vaddr, uint32_t mmuflags);
+
+/****************************************************************************
+ * Name: mmu_ln_getentry
+ *
+ * Description:
+ *   Get a level n translation table entry.
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   vaddr - The virtual address to get pte for. Must be aligned to a PPN
+ *     address boundary which is dependent on the level of the entry
+ *
+ ****************************************************************************/
+
+uintptr_t mmu_ln_getentry(uint32_t ptlevel, uintptr_t lnvaddr,
+                          uintptr_t vaddr);
+
+/****************************************************************************
+ * Name: mmu_ln_map_region
+ *
+ * Description:
+ *   Set a translation table region for level n
+ *
+ * Input Parameters:
+ *   ptlevel - The translation table level, amount of levels is
+ *     MMU implementation specific
+ *   lnvaddr - The virtual address of the beginning of the page table at
+ *     level n
+ *   paddr - The physical address to be mapped. Must be aligned to a PPN
+ *     address boundary which is dependent on the level of the entry
+ *   vaddr - The virtual address to be mapped. Must be aligned to a PPN
+ *     address boundary which is dependent on the level of the entry
+ *   size - The size of the region in bytes
+ *   mmuflags - The MMU flags to use in the mapping.
+ *
+ ****************************************************************************/
+
+void mmu_ln_map_region(uint32_t ptlevel, uintptr_t lnvaddr, uintptr_t paddr,
+                       uintptr_t vaddr, size_t size, uint32_t mmuflags);
+
+#endif  /* __ARCH_X86_64_SRC_COMMON_X86_64_MMU_H */

Reply via email to