mirror of
https://github.com/apache/nuttx.git
synced 2026-09-01 14:43:02 +00:00
arm64: add MPU-based address environment support and refactor MMU variant
Rename arm64_addrenv.c to arm64_addrenv_mmu.c to separate MMU-specific logic. Add new arm64_addrenv_mpu.c with stub implementations of address environment functions for MPU-based systems. Enable address environment support in FVP ARMv8-R Kconfig to support kernel stacks in protected mode. Conditionally build MPU or MMU address environment code based on CONFIG_ARCH_USE_MMU/CONFIG_ARCH_USE_MPU. Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
14e5d8a995
commit
b0cb4e5968
9 changed files with 454 additions and 11 deletions
|
|
@ -85,6 +85,8 @@ config ARCH_CHIP_FVP_ARMV8R
|
|||
select ARCH_CORTEX_R82
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
select ARCH_HAVE_IRQPRIO
|
||||
select ARCH_HAVE_ADDRENV
|
||||
select ARCH_NEED_ADDRENV_MAPPING
|
||||
---help---
|
||||
ARM FVP virt platform (ARMv8r)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,6 @@
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
#if CONFIG_MM_PGSIZE != 4096
|
||||
# error Only pages sizes of 4096 are currently supported (CONFIG_ARCH_ADDRENV)
|
||||
#endif
|
||||
|
||||
/* All implementations have 4 levels of page tables */
|
||||
|
||||
|
|
|
|||
|
|
@ -103,9 +103,14 @@ if(CONFIG_ARCH_KERNEL_STACK)
|
|||
endif()
|
||||
|
||||
if(CONFIG_ARCH_ADDRENV)
|
||||
list(APPEND SRCS arm64_addrenv.c arm64_pgalloc.c arm64_addrenv_perms.c)
|
||||
list(APPEND SRCS arm64_addrenv_utils.c arm64_addrenv_shm.c)
|
||||
list(APPEND SRCS arm64_addrenv_pgmap.c)
|
||||
if(CONFIG_ARCH_USE_MMU)
|
||||
list(APPEND SRCS arm64_addrenv_mmu.c arm64_pgalloc.c arm64_addrenv_perms.c)
|
||||
list(APPEND SRCS arm64_addrenv_utils.c arm64_addrenv_shm.c)
|
||||
list(APPEND SRCS arm64_addrenv_pgmap.c)
|
||||
elseif(CONFIG_ARCH_USE_MPU)
|
||||
list(APPEND SRCS arm64_addrenv_mpu.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_STACK_DYNAMIC)
|
||||
list(APPEND SRCS arm64_addrenv_ustack.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -112,8 +112,14 @@ CMN_CSRCS += arm64_addrenv_kstack.c
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
||||
CMN_CSRCS += arm64_addrenv.c arm64_pgalloc.c arm64_addrenv_perms.c
|
||||
|
||||
ifeq ($(CONFIG_ARCH_USE_MMU),y)
|
||||
CMN_CSRCS += arm64_addrenv_mmu.c arm64_pgalloc.c arm64_addrenv_perms.c
|
||||
CMN_CSRCS += arm64_addrenv_utils.c arm64_addrenv_shm.c arm64_addrenv_pgmap.c
|
||||
else ifeq ($(CONFIG_ARCH_USE_MPU),y)
|
||||
CMN_CSRCS += arm64_addrenv_mpu.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACK_DYNAMIC),y)
|
||||
CMN_CSRCS += arm64_addrenv_ustack.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#include <nuttx/addrenv.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "addrenv.h"
|
||||
#include "arm64_internal.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_addrenv.c
|
||||
* arch/arm64/src/common/arm64_addrenv_mmu.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
|
@ -84,6 +84,10 @@
|
|||
# error "This module is intended to be used with CONFIG_BUILD_KERNEL"
|
||||
#endif
|
||||
|
||||
#if CONFIG_MM_PGSIZE != 4096
|
||||
# error Only pages sizes of 4096 are currently supported (CONFIG_ARCH_ADDRENV)
|
||||
#endif
|
||||
|
||||
/* Entries per PGT */
|
||||
|
||||
#define ENTRIES_PER_PGT (MMU_PAGE_ENTRIES)
|
||||
432
arch/arm64/src/common/arm64_addrenv_mpu.c
Normal file
432
arch/arm64/src/common/arm64_addrenv_mpu.c
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_addrenv_mpu.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Address Environment Interfaces
|
||||
*
|
||||
* Low-level interfaces used in binfmt/ to instantiate tasks with address
|
||||
* environments. These interfaces all operate on type arch_addrenv_t which
|
||||
* is an abstract representation of a task group's address environment and
|
||||
* must be defined in arch/arch.h if CONFIG_ARCH_ADDRENV is defined.
|
||||
*
|
||||
* up_addrenv_create - Create an address environment
|
||||
* up_addrenv_destroy - Destroy an address environment.
|
||||
* up_addrenv_vtext - Returns the virtual base address of the .text
|
||||
* address environment
|
||||
* up_addrenv_vdata - Returns the virtual base address of the .bss/.data
|
||||
* address environment
|
||||
* up_addrenv_heapsize - Returns the size of the initial heap allocation.
|
||||
* up_addrenv_select - Instantiate an address environment
|
||||
* up_addrenv_clone - Copy an address environment from one location to
|
||||
* another.
|
||||
*
|
||||
* Higher-level interfaces used by the tasking logic. These interfaces are
|
||||
* used by the functions in sched/ and all operate on the thread which whose
|
||||
* group been assigned an address environment by up_addrenv_clone().
|
||||
*
|
||||
* up_addrenv_attach - Clone the address environment assigned to one TCB
|
||||
* to another. This operation is done when a pthread
|
||||
* is created that share's the same group address
|
||||
* environment.
|
||||
* up_addrenv_detach - Release the thread's reference to an address
|
||||
* environment when a task/thread exits.
|
||||
*
|
||||
* If CONFIG_ARCH_KERNEL_STACK is selected, then each user process will have
|
||||
* two stacks: (1) a large (and possibly dynamic) user stack and (2) a
|
||||
* smaller kernel stack. However, this option is *required* if both
|
||||
* CONFIG_BUILD_KERNEL and CONFIG_LIBC_EXECFUNCS are selected. Why? Because
|
||||
* when we instantiate and initialize the address environment of the new
|
||||
* user process, we will temporarily lose the address environment of the old
|
||||
* user process, including its stack contents. The kernel C logic will crash
|
||||
* immediately with no valid stack in place.
|
||||
*
|
||||
* If CONFIG_ARCH_KERNEL_STACK=y is selected then the platform specific
|
||||
* code must export these additional interfaces:
|
||||
*
|
||||
* up_addrenv_kstackalloc - Create a stack in the kernel address
|
||||
* environment
|
||||
* up_addrenv_kstackfree - Destroy the kernel stack.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/cache.h>
|
||||
#include <nuttx/tls.h>
|
||||
#include <nuttx/mm/mm.h>
|
||||
|
||||
#include "arm64_mpu.h"
|
||||
#include "sched/sched.h"
|
||||
#include "group/group.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_create
|
||||
*
|
||||
* Description:
|
||||
* This function is called when a new task is created in order to
|
||||
* instantiate an address environment for the new task group.
|
||||
* up_addrenv_create() is essentially the allocator of the physical
|
||||
* memory for the new task.
|
||||
*
|
||||
* Input Parameters:
|
||||
* textsize - The size (in bytes) of the .text address environment needed
|
||||
* by the task. This region may be read/execute only.
|
||||
* datasize - The size (in bytes) of the .data/.bss address environment
|
||||
* needed by the task. This region may be read/write only. NOTE: The
|
||||
* actual size of the data region that is allocated will include a
|
||||
* OS private reserved region at the beginning. The size of the
|
||||
* private, reserved region is give by ARCH_DATA_RESERVE_SIZE.
|
||||
* heapsize - The initial size (in bytes) of the heap address environment
|
||||
* needed by the task. This region may be read/write only.
|
||||
* addrenv - The location to return the representation of the task address
|
||||
* environment.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize,
|
||||
arch_addrenv_t *addrenv)
|
||||
{
|
||||
binfo("addrenv=%p textsize=%lu datasize=%lu heapsize=%lu\n",
|
||||
addrenv,
|
||||
(unsigned long)textsize,
|
||||
(unsigned long)datasize,
|
||||
(unsigned long)heapsize);
|
||||
|
||||
DEBUGASSERT(addrenv);
|
||||
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_destroy
|
||||
*
|
||||
* Description:
|
||||
* This function is called when a final thread leaves the task group and
|
||||
* the task group is destroyed. This function then destroys the defunct
|
||||
* address environment, releasing the underlying physical memory.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - The address environment to be destroyed.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_destroy(arch_addrenv_t *addrenv)
|
||||
{
|
||||
binfo("addrenv=%p\n", addrenv);
|
||||
DEBUGASSERT(addrenv);
|
||||
|
||||
/* Implement it later */
|
||||
|
||||
memset(addrenv, 0, sizeof(arch_addrenv_t));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_vtext
|
||||
*
|
||||
* Description:
|
||||
* Return the virtual address associated with the newly create .text
|
||||
* address environment. This function is used by the binary loaders in
|
||||
* order get an address that can be used to initialize the new task.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - The representation of the task address environment previously
|
||||
* returned by up_addrenv_create.
|
||||
* vtext - The location to return the virtual address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_vtext(arch_addrenv_t *addrenv, void **vtext)
|
||||
{
|
||||
DEBUGASSERT(addrenv && vtext);
|
||||
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_vdata
|
||||
*
|
||||
* Description:
|
||||
* Return the virtual address associated with the newly create .text
|
||||
* address environment. This function is used by the binary loaders in
|
||||
* order get an address that can be used to initialize the new task.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - The representation of the task address environment previously
|
||||
* returned by up_addrenv_create.
|
||||
* textsize - For some implementations, the text and data will be saved
|
||||
* in the same memory region (read/write/execute) and, in this case,
|
||||
* the virtual address of the data just lies at this offset into the
|
||||
* common region.
|
||||
* vdata - The location to return the virtual address.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_vdata(arch_addrenv_t *addrenv, uintptr_t textsize,
|
||||
void **vdata)
|
||||
{
|
||||
DEBUGASSERT(addrenv && vdata);
|
||||
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_select
|
||||
*
|
||||
* Description:
|
||||
* After an address environment has been established for a task group (via
|
||||
* up_addrenv_create(). This function may be called to instantiate
|
||||
* that address environment in the virtual address space. this might be
|
||||
* necessary, for example, to load the code for the task group from a file
|
||||
* or to access address environment private data.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - The representation of the task address environment previously
|
||||
* returned by up_addrenv_create.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_select(const arch_addrenv_t *addrenv)
|
||||
{
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_coherent
|
||||
*
|
||||
* Description:
|
||||
* Flush D-Cache and invalidate I-Cache in preparation for a change in
|
||||
* address environments. This should immediately precede a call to
|
||||
* up_addrenv_select();
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - Describes the address environment to be made coherent.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_coherent(const arch_addrenv_t *addrenv)
|
||||
{
|
||||
DEBUGASSERT(addrenv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_clone
|
||||
*
|
||||
* Description:
|
||||
* Duplicate an address environment. This does not copy the underlying
|
||||
* memory, only the representation that can be used to instantiate that
|
||||
* memory as an address environment.
|
||||
*
|
||||
* Input Parameters:
|
||||
* src - The address environment to be copied.
|
||||
* dest - The location to receive the copied address environment.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_clone(const arch_addrenv_t *src,
|
||||
arch_addrenv_t *dest)
|
||||
{
|
||||
binfo("src=%p dest=%p\n", src, dest);
|
||||
DEBUGASSERT(src && dest);
|
||||
|
||||
/* Just copy the address environment from the source to the destination */
|
||||
|
||||
memcpy(dest, src, sizeof(arch_addrenv_t));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_attach
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the core scheduler logic when a thread
|
||||
* is created that needs to share the address environment of its task
|
||||
* group.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ptcb - The tcb of the parent task.
|
||||
* tcb - The tcb of the thread needing the address environment.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_attach(struct tcb_s *ptcb, struct tcb_s *tcb)
|
||||
{
|
||||
binfo("parent=%p tcb=%p\n", ptcb, tcb);
|
||||
|
||||
/* Nothing needs to be done in this implementation */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_detach
|
||||
*
|
||||
* Description:
|
||||
* This function is called when a task or thread exits in order to release
|
||||
* its reference to an address environment. The address environment,
|
||||
* however, should persist until up_addrenv_destroy() is called when the
|
||||
* task group is itself destroyed. Any resources unique to this thread
|
||||
* may be destroyed now.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - The TCB of the task or thread whose the address environment will
|
||||
* be released.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_detach(struct tcb_s *tcb)
|
||||
{
|
||||
binfo("tcb=%p\n", tcb);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_mprot
|
||||
*
|
||||
* Description:
|
||||
* Modify access rights to an address range.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addrenv - The address environment to be modified.
|
||||
* addr - Base address of the region.
|
||||
* len - Size of the region.
|
||||
* prot - Access right flags.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_mprot(arch_addrenv_t *addrenv, uintptr_t addr, size_t len,
|
||||
int prot)
|
||||
{
|
||||
/* Nothing needs to be done */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_STACK_PROTECT
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_ustackswitch
|
||||
*
|
||||
* Description:
|
||||
* After an address environment has been established for a task's stack
|
||||
* (via up_addrenv_ustackalloc(). This function may be called to
|
||||
* instantiate that address environment in the virtual address space.
|
||||
* This is a necessary step before each context switch to the newly created
|
||||
* thread (including the initial thread startup).
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - The TCB of the thread with the stack address environment to be
|
||||
* instantiated.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_ustackswitch(struct tcb_s *tcb)
|
||||
{
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
# ifdef CONFIG_ARCH_KSTACK_PROTECT
|
||||
/****************************************************************************
|
||||
* Name: up_addrenv_kstackswitch
|
||||
*
|
||||
* Description:
|
||||
* After an address environment has been established for a task's stack
|
||||
* (via up_addrenv_kstackswitch(). This function may be called to
|
||||
* instantiate that address environment in the virtual address space.
|
||||
* This is a necessary step before each context switch to the newly created
|
||||
* thread (including the initial thread startup).
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - The TCB of the thread with the stack address environment to be
|
||||
* instantiated.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_addrenv_kstackswitch(struct tcb_s *tcb)
|
||||
{
|
||||
/* Implement it later */
|
||||
|
||||
return OK;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
|
@ -43,7 +43,6 @@
|
|||
#include <nuttx/power/pm.h>
|
||||
#include <arch/chip/chip.h>
|
||||
|
||||
#include "addrenv.h"
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "chip.h"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <nuttx/sched.h>
|
||||
#include <nuttx/addrenv.h>
|
||||
|
||||
#include "addrenv.h"
|
||||
#include "arch/irq.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "arm64_fatal.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue