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 8682321d0c5b6de9c14851db8dd12d4754ed0f74 Author: p-szafonimateusz <[email protected]> AuthorDate: Thu Jun 20 08:43:53 2024 +0200 arch/x86_64: addrenv support Add addrenv support for x86_64. For now we support mapping on PT level, so PD, PDT and PML4 are static Signed-off-by: p-szafonimateusz <[email protected]> --- arch/x86_64/Kconfig | 2 + arch/x86_64/include/arch.h | 51 ++ arch/x86_64/include/intel64/arch.h | 5 + arch/x86_64/src/common/CMakeLists.txt | 4 + arch/x86_64/src/common/Make.defs | 4 + arch/x86_64/src/common/x86_64_addrenv.c | 791 +++++++++++++++++++++ .../arch.h => src/common/x86_64_addrenv_perms.c} | 65 +- arch/x86_64/src/intel64/intel64_head.S | 2 +- 8 files changed, 889 insertions(+), 35 deletions(-) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4a8458bd77..3ed07ee723 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -18,6 +18,8 @@ config ARCH_INTEL64 bool "Intel x86_64" select ARCH_HAVE_MMU select ARCH_USE_MMU + select ARCH_HAVE_ADDRENV + select ARCH_NEED_ADDRENV_MAPPING select ARCH_HAVE_TICKLESS select ARCH_HAVE_STACKCHECK select ARCH_HAVE_RNG diff --git a/arch/x86_64/include/arch.h b/arch/x86_64/include/arch.h index 40c5b06728..86b9c8a2b2 100644 --- a/arch/x86_64/include/arch.h +++ b/arch/x86_64/include/arch.h @@ -31,6 +31,8 @@ #include <nuttx/config.h> +#include <sys/types.h> + /* Include chip-specific definitions */ # include <arch/chip/arch.h> @@ -45,6 +47,17 @@ * Pre-processor Definitions ****************************************************************************/ +/* 4 levels of page table. + * NOTE: in this implementation: + * PTL4 index = 0 + * PDPT index = 1 + * PD index = 2 + * PT index = 3 + */ + +#define ARCH_PGT_MAX_LEVELS 4 +#define ARCH_SPGTS (ARCH_PGT_MAX_LEVELS - 1) + /**************************************************************************** * Inline functions ****************************************************************************/ @@ -53,6 +66,44 @@ * Public Types ****************************************************************************/ +#ifdef CONFIG_ARCH_ADDRENV +#ifndef __ASSEMBLY__ + +/* The task group resources are retained in a single structure, task_group_s + * that is defined in the header file nuttx/include/nuttx/sched.h. The type + * arch_addrenv_t must be defined by platform specific logic in + * nuttx/arch/<architecture>/include/arch.h. + */ + +struct arch_addrenv_s +{ + /* Physical addresses of the static page tables here, these + * are allocated when a task is created: + * + * spgtables[0] - PML4 + * spgtables[1] - PDPT + * spgtables[2] - PD + * PT - dynamic allocation + */ + + uintptr_t spgtables[ARCH_SPGTS]; + + /* The text, data, heap bases and heap size here */ + + uintptr_t textvbase; + uintptr_t datavbase; + uintptr_t heapvbase; + size_t heapsize; + + /* The page directory root (pml4) is stored in CR3 register */ + + uintptr_t cr3; +}; + +typedef struct arch_addrenv_s arch_addrenv_t; +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_ARCH_ADDRENV */ + /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/arch/x86_64/include/intel64/arch.h b/arch/x86_64/include/intel64/arch.h index 8be9273e3e..8a41ae9285 100644 --- a/arch/x86_64/include/intel64/arch.h +++ b/arch/x86_64/include/intel64/arch.h @@ -173,6 +173,11 @@ #define HUGE_PAGE_SIZE (0x200000) # define HUGE_PAGE_MASK (~(HUGE_PAGE_SIZE - 1)) +/* Kernel mapping - lower 1GB maps to 4GB-5GB */ + +#define X86_PDPT_KERNEL_MAP (X86_PAGE_GLOBAL | X86_PAGE_WR | \ + X86_PAGE_PRESENT | X86_PAGE_HUGE) + /* CPUID Leaf Definitions */ #define X86_64_CPUID_VENDOR 0x00 diff --git a/arch/x86_64/src/common/CMakeLists.txt b/arch/x86_64/src/common/CMakeLists.txt index 600a643f05..79ba14789f 100644 --- a/arch/x86_64/src/common/CMakeLists.txt +++ b/arch/x86_64/src/common/CMakeLists.txt @@ -45,4 +45,8 @@ if(CONFIG_ARCH_USE_MMU) list(APPEND SRCS x86_64_mmu.c) endif() +if(CONFIG_ARCH_ADDRENV) + list(APPEND SRCS x86_64_addrenv.c x86_64_addrenv_perms.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 97756c9e91..ccf8bee3ac 100644 --- a/arch/x86_64/src/common/Make.defs +++ b/arch/x86_64/src/common/Make.defs @@ -36,3 +36,7 @@ endif ifeq ($(CONFIG_ARCH_USE_MMU),y) CMN_CSRCS += x86_64_mmu.c endif + +ifeq ($(CONFIG_ARCH_ADDRENV),y) +CMN_CSRCS += x86_64_addrenv.c x86_64_addrenv_perms.c +endif diff --git a/arch/x86_64/src/common/x86_64_addrenv.c b/arch/x86_64/src/common/x86_64_addrenv.c new file mode 100644 index 0000000000..4d2cc30fa3 --- /dev/null +++ b/arch/x86_64/src/common/x86_64_addrenv.c @@ -0,0 +1,791 @@ +/**************************************************************************** + * arch/x86_64/src/common/x86_64_addrenv.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 address + * environment. + * up_addrenv_detach - Release the threads reference to an address + * environment when a task/thread exits. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/addrenv.h> +#include <nuttx/arch.h> +#include <nuttx/compiler.h> +#include <nuttx/irq.h> +#include <nuttx/pgalloc.h> + +#include <nuttx/spinlock.h> + +#include "addrenv.h" +#include "pgalloc.h" +#include "x86_64_mmu.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_RAM_VSTART must be properly configured */ + +#if CONFIG_RAM_VSTART != 0x100000000 +# error CONFIG_RAM_VSTART != 0x100000000 +#endif + +/* For now we support mapping on PT level, so PD, PDT and PML4 are static. + * Bit mask for PT is 0x001ff000. + */ + +#if (((CONFIG_ARCH_TEXT_VBASE & 0xffffffffffe00000) != \ + (CONFIG_ARCH_DATA_VBASE & 0xffffffffffe00000)) || \ + ((CONFIG_ARCH_TEXT_VBASE & 0xffffffffffe00000) != \ + (CONFIG_ARCH_HEAP_VBASE & 0xffffffffffe00000))) +# error VBASE address must use the same PML4, PDT adn PD +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: map_spgtables + * + * Description: + * Map vaddr to the static page tables. + * + * Input Parameters: + * addrenv - Describes the address environment + * + ****************************************************************************/ + +static void map_spgtables(arch_addrenv_t *addrenv, uintptr_t vaddr) +{ + int i; + uintptr_t prev; + + /* Start from PML4 */ + + prev = x86_64_pgvaddr(addrenv->spgtables[0]); + + /* No mapping yet, create it */ + + for (i = 0; i < (ARCH_SPGTS - 1); i++) + { + uintptr_t next = addrenv->spgtables[i + 1]; + mmu_ln_setentry(i, prev, next, vaddr, MMU_UPGT_FLAGS); + prev = x86_64_pgvaddr(next); + } +} + +/**************************************************************************** + * Name: create_spgtables + * + * Description: + * Create the static page tables. Allocate memory for them and connect them + * together. + * + * Input Parameters: + * addrenv - Describes the address environment + * + * Returned value: + * Amount of pages created on success; a negated errno value on failure + * + ****************************************************************************/ + +static int create_spgtables(arch_addrenv_t *addrenv) +{ + int i; + uintptr_t paddr; + + for (i = 0; i < ARCH_SPGTS; i++) + { + paddr = mm_pgalloc(1); + if (!paddr) + { + return -ENOMEM; + } + + /* Wipe the memory and assign it */ + + x86_64_pgwipe(paddr); + addrenv->spgtables[i] = paddr; + } + + /* Flush the data cache, so the changes are committed to memory */ + + SP_DMB(); + return i; +} + +/**************************************************************************** + * Name: copy_kernel_mappings + * + * Description: + * Copy kernel mappings to address environment. Expects that the user page + * table does not contain any mappings yet (as they will be wiped). + * + * Input Parameters: + * addrenv - Describes the address environment. The page tables must exist + * at this point. + * + * Returned value: + * None + * + ****************************************************************************/ + +static void copy_kernel_mappings(arch_addrenv_t *addrenv) +{ + uintptr_t *pdpt = (uintptr_t *)x86_64_pgvaddr(addrenv->spgtables[1]); + + /* Kernel mapping - lower 1GB maps to 4GB-5GB */ + + pdpt[4] = X86_PDPT_KERNEL_MAP; +} + +/**************************************************************************** + * Name: create_region + * + * Description: + * Map a single region of memory to MMU. Assumes that the static page + * tables exist. Allocates the final level page tables and commits the + * region memory to physical memory. + * + * Input Parameters: + * addrenv - Describes the address environment + * vaddr - Base virtual address for the mapping + * size - Size of the region in bytes + * mmuflags - MMU flags to use + * + * Returned value: + * Amount of pages created on success; a negated errno value on failure + * + ****************************************************************************/ + +static int x86_64_create_region(arch_addrenv_t *addrenv, uintptr_t vaddr, + size_t size, uint32_t mmuflags) +{ + uintptr_t ptlast; + uintptr_t ptprev; + uintptr_t paddr; + uint32_t ptlevel; + int npages; + int nmapped; + int i; + int j; + + /* Only one entry in PML4 supported now */ + + DEBUGASSERT(vaddr + size < 0x8000000000); + + nmapped = 0; + npages = MM_NPAGES(size); + + /* The last static page level is PD */ + + ptprev = x86_64_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); + ptlevel = ARCH_SPGTS - 1; + + if (npages == 0) + { + return 0; + } + + /* Create mappings for the lower level tables */ + + map_spgtables(addrenv, vaddr); + + /* Begin allocating memory for the page tables */ + + for (i = 0; i < npages; i += X86_MMU_ENTRIES_PER_PGT) + { + /* Get the current final level entry (PT) corresponding to this vaddr */ + + paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr)); + if (!paddr) + { + /* Nothing yet, allocate one page for final level page table */ + + paddr = mm_pgalloc(1); + if (!paddr) + { + return -ENOMEM; + } + + /* Map the page table to the prior level */ + + mmu_ln_setentry(ptlevel, ptprev, paddr, vaddr, MMU_UPGT_FLAGS); + + /* This is then used to map the final level */ + + x86_64_pgwipe(paddr); + } + + ptlast = x86_64_pgvaddr(paddr); + + /* Then allocate memory for the region data */ + + for (j = X86_MMU_VADDR_INDEX(vaddr, ptlevel); + j < X86_MMU_ENTRIES_PER_PGT && nmapped < size; + j++) + { + paddr = mm_pgalloc(1); + if (!paddr) + { + return -ENOMEM; + } + + /* Wipe the physical page memory */ + + x86_64_pgwipe(paddr); + + /* Then map the virtual address to the physical address (12 bit) */ + + mmu_ln_setentry(ptlevel + 1, ptlast, paddr, vaddr, mmuflags); + nmapped += MM_PGSIZE; + vaddr += MM_PGSIZE; + } + } + + /* Flush the data cache, so the changes are committed to memory */ + + SP_DMB(); + return npages; +} + +/**************************************************************************** + * Name: vaddr_is_shm + * + * Description: + * Check if a vaddr is part of the SHM area + * + * Input Parameters: + * vaddr - Virtual address to check + * + * Returned value: + * true if it is; false if not + * + ****************************************************************************/ + +static inline bool vaddr_is_shm(uintptr_t vaddr) +{ + /* Not supported yet */ + + UNUSED(vaddr); + return false; +} + +/**************************************************************************** + * 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) +{ + uintptr_t resvbase; + uintptr_t resvsize; + uintptr_t textbase; + uintptr_t database; + uintptr_t heapbase; + int ret; + + DEBUGASSERT(addrenv); + + /* Initialize the address environment structure to all zeroes */ + + memset(addrenv, 0, sizeof(arch_addrenv_t)); + + /* Create the static page tables */ + + ret = create_spgtables(addrenv); + if (ret < 0) + { + serr("ERROR: Failed to create static page tables\n"); + goto errout; + } + + /* Map the kernel memory for the user */ + + copy_kernel_mappings(addrenv); + + /* Calculate the base addresses for convenience */ + +#if (CONFIG_ARCH_TEXT_VBASE != 0x0) && (CONFIG_ARCH_HEAP_VBASE != 0x0) + resvbase = CONFIG_ARCH_DATA_VBASE; + resvsize = ARCH_DATA_RESERVE_SIZE; + textbase = CONFIG_ARCH_TEXT_VBASE; + database = resvbase + MM_PGALIGNUP(resvsize); + heapbase = CONFIG_ARCH_HEAP_VBASE; +#else + resvbase = ARCH_ADDRENV_VBASE; + resvsize = ARCH_DATA_RESERVE_SIZE; + textbase = resvbase + MM_PGALIGNUP(resvsize); + database = textbase + MM_PGALIGNUP(textsize); + heapbase = database + MM_PGALIGNUP(datasize); +#endif + + /* Map the reserved area */ + + ret = x86_64_create_region(addrenv, resvbase, resvsize, MMU_UDATA_FLAGS); + if (ret < 0) + { + berr("ERROR: Failed to create reserved region: %d\n", ret); + goto errout; + } + + /* Map each region in turn */ + + ret = x86_64_create_region(addrenv, textbase, textsize, MMU_UTEXT_FLAGS); + if (ret < 0) + { + berr("ERROR: Failed to create .text region: %d\n", ret); + goto errout; + } + + ret = x86_64_create_region(addrenv, database, datasize, MMU_UDATA_FLAGS); + if (ret < 0) + { + berr("ERROR: Failed to create .bss/.data region: %d\n", ret); + goto errout; + } + + ret = x86_64_create_region(addrenv, heapbase, heapsize, MMU_UDATA_FLAGS); + if (ret < 0) + { + berr("ERROR: Failed to create heap region: %d\n", ret); + goto errout; + } + + /* Save the heap base and initial size allocated. These will be needed when + * the heap data structures are initialized. + */ + + addrenv->heapvbase = heapbase; + addrenv->heapsize = (size_t)ret << MM_PGSHIFT; + + /* Save the text base */ + + addrenv->textvbase = textbase; + + /* Save the data base */ + + addrenv->datavbase = database; + + /* Provide the cr3 value for context switch - point to PLT4 table */ + + addrenv->cr3 = mmu_cr3_reg(addrenv->spgtables[0], 0); + + /* When all is set and done, flush the data caches */ + + SP_DSB(); + SP_DMB(); + + return OK; + +errout: + up_addrenv_destroy(addrenv); + return ret; +} + +/**************************************************************************** + * 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) +{ + /* Recursively destroy it all, need to table walk */ + + uintptr_t *ptprev; + uintptr_t *ptlast; + uintptr_t paddr; + uintptr_t vaddr; + size_t pgsize; + int i; + int j; + + DEBUGASSERT(addrenv); + + /* Make sure the caches are flushed before doing this */ + + SP_DSB(); + SP_DMB(); + + /* Things start from the beginning of the user virtual memory */ + + vaddr = ARCH_ADDRENV_VBASE; + pgsize = X86_MMU_PAGE_SIZE; + + /* First destroy the allocated memory and the final level page table */ + + ptprev = (uintptr_t *)x86_64_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); + if (ptprev) + { + for (i = 0; i < X86_MMU_ENTRIES_PER_PGT; i++, vaddr += pgsize) + { + ptlast = (uintptr_t *)x86_64_pgvaddr(mmu_pte_to_paddr(ptprev[i])); + if (ptlast) + { + if (!vaddr_is_shm(vaddr)) + { + /* Free the allocated pages, but not from SHM area */ + + for (j = 0; j < X86_MMU_ENTRIES_PER_PGT; j++) + { + paddr = mmu_pte_to_paddr(ptlast[j]); + if (paddr) + { + mm_pgfree(paddr, 1); + } + } + } + + /* Regardless, free the page table itself */ + + mm_pgfree(x86_64_pgpaddr((uintptr_t)ptlast), 1); + } + } + } + + /* Then destroy the static tables */ + + for (i = 0; i < ARCH_SPGTS; i++) + { + paddr = addrenv->spgtables[i]; + if (paddr) + { + mm_pgfree(paddr, 1); + } + } + + /* When all is set and done, flush the caches */ + + SP_DSB(); + SP_DMB(); + + 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); + *vtext = (void *)addrenv->textvbase; + 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); + *vdata = (void *)addrenv->datavbase; + return OK; +} + +/**************************************************************************** + * Name: up_addrenv_vheap + * + * Description: + * Return the heap virtual address associated with the newly created + * 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. + * vheap - The location to return the virtual address. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int up_addrenv_vheap(const arch_addrenv_t *addrenv, void **vheap) +{ + DEBUGASSERT(addrenv && vheap); + *vheap = (void *)addrenv->heapvbase; + return OK; +} +#endif + +/**************************************************************************** + * Name: up_addrenv_heapsize + * + * Description: + * Return the initial heap allocation size. That is the amount of memory + * allocated by up_addrenv_create() when the heap memory region was first + * created. This may or may not differ from the heapsize parameter that + * was passed to up_addrenv_create() + * + * Input Parameters: + * addrenv - The representation of the task address environment previously + * returned by up_addrenv_create. + * + * Returned Value: + * The initial heap size allocated is returned on success; a negated + * errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +ssize_t up_addrenv_heapsize(const arch_addrenv_t *addrenv) +{ + DEBUGASSERT(addrenv); + return (ssize_t)addrenv->heapsize; +} +#endif + +/**************************************************************************** + * Name: up_addrenv_select + * + * Description: + * After an address environment has been established for a task (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 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) +{ + DEBUGASSERT(addrenv && addrenv->cr3); + set_cr3(addrenv->cr3); + 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) +{ + /* Nothing needs to be done */ + + 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) +{ + DEBUGASSERT(src && dest); + 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) +{ + /* There is nothing that needs to be done */ + + 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) +{ + /* There is nothing that needs to be done */ + + return OK; +} diff --git a/arch/x86_64/include/arch.h b/arch/x86_64/src/common/x86_64_addrenv_perms.c similarity index 69% copy from arch/x86_64/include/arch.h copy to arch/x86_64/src/common/x86_64_addrenv_perms.c index 40c5b06728..cdd5f000f7 100644 --- a/arch/x86_64/include/arch.h +++ b/arch/x86_64/src/common/x86_64_addrenv_perms.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/x86_64/include/arch.h + * arch/x86_64/src/common/x86_64_addrenv_perms.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,60 +18,57 @@ * ****************************************************************************/ -/* This file should never be included directly but, rather, only indirectly - * through arch/arch.h - */ - -#ifndef __ARCH_X86_64_INCLUDE_ARCH_H -#define __ARCH_X86_64_INCLUDE_ARCH_H - /**************************************************************************** * Included Files ****************************************************************************/ #include <nuttx/config.h> -/* Include chip-specific definitions */ - -# include <arch/chip/arch.h> - -/* Include architecture-specific definitions */ +#include <errno.h> +#include <assert.h> -#ifdef CONFIG_ARCH_INTEL64 -# include <arch/intel64/arch.h> -#endif +#include <nuttx/addrenv.h> +#include <nuttx/arch.h> +#include <nuttx/pgalloc.h> /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** - * Inline functions - ****************************************************************************/ - -/**************************************************************************** - * Public Types + * Private Functions ****************************************************************************/ /**************************************************************************** - * Public Data + * Public Functions ****************************************************************************/ /**************************************************************************** - * Public Function Prototypes + * 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. + * ****************************************************************************/ -#ifdef __cplusplus -#define EXTERN extern "C" -extern "C" +int up_addrenv_mprot(arch_addrenv_t *addrenv, uintptr_t addr, size_t len, + int prot) { -#else -#define EXTERN extern -#endif + /* Nothing needs to be done */ -#undef EXTERN -#ifdef __cplusplus -} -#endif + UNUSED(addrenv); + UNUSED(addr); + UNUSED(len); + UNUSED(prot); -#endif /* __ARCH_X86_64_INCLUDE_ARCH_H */ + return OK; +} diff --git a/arch/x86_64/src/intel64/intel64_head.S b/arch/x86_64/src/intel64/intel64_head.S index 54f63f3b5b..ba773a47fb 100644 --- a/arch/x86_64/src/intel64/intel64_head.S +++ b/arch/x86_64/src/intel64/intel64_head.S @@ -276,7 +276,7 @@ start64_init: * This creates maps the lower 1GB to 4GB~5GB */ lea g_pdpt_low, %edi - mov $(X86_PAGE_GLOBAL | X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_HUGE), %eax + mov $(X86_PDPT_KERNEL_MAP), %eax mov $0x4, %ecx mov %eax, 0(%edi, %ecx, X86_PAGE_ENTRY_SIZE)
