arch/x86_64: add MMU interface
add MMU api for x86_64 Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
parent
53d112fa95
commit
e0183927b4
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 */
|
Loading…
Reference in New Issue