From 8b64dc003ee975c82389785cc9647d0030f65143 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 7 Sep 2014 19:25:30 -0600 Subject: [PATCH] SAMA5D4-EK: In kernel build with address environment, need logic to map user virtual addresses to physical addresses, and vice versa --- arch/arm/src/armv7-a/mmu.h | 3 +- arch/arm/src/sama5/sam_allocateheap.c | 2 +- arch/arm/src/sama5/sam_memories.c | 33 ++++++++ arch/arm/src/sama5/sam_memories.h | 2 +- arch/arm/src/sama5/sam_pgalloc.c | 116 +++++++++++++++++++++++++- arch/arm/src/sama5/sam_pgalloc.h | 97 +++++++++++++++++++++ 6 files changed, 247 insertions(+), 6 deletions(-) create mode 100644 arch/arm/src/sama5/sam_pgalloc.h diff --git a/arch/arm/src/armv7-a/mmu.h b/arch/arm/src/armv7-a/mmu.h index 258a9d206f..59bc056a21 100644 --- a/arch/arm/src/armv7-a/mmu.h +++ b/arch/arm/src/armv7-a/mmu.h @@ -609,7 +609,8 @@ /* Mapped section size */ -#define SECTION_SIZE (1 << 20) /* 1Mb */ +#define SECTION_SHIFT (20) +#define SECTION_SIZE (1 << SECTION_SHIFT) /* 1Mb */ #define SECTION_MASK (SECTION_SIZE - 1) /* The Cortex-A5 supports two translation table base address registers. In diff --git a/arch/arm/src/sama5/sam_allocateheap.c b/arch/arm/src/sama5/sam_allocateheap.c index 5cff278aa5..9ece85b414 100644 --- a/arch/arm/src/sama5/sam_allocateheap.c +++ b/arch/arm/src/sama5/sam_allocateheap.c @@ -195,7 +195,7 @@ #endif /* The heap space in the primary memory region is added automatically when - * up_allocate heap is called. So if the memory region is the primary region, + * up_allocate_heap is called. So if the memory region is the primary region, * it should not be added to the heap (again). */ diff --git a/arch/arm/src/sama5/sam_memories.c b/arch/arm/src/sama5/sam_memories.c index 0c215bed04..231545ed55 100644 --- a/arch/arm/src/sama5/sam_memories.c +++ b/arch/arm/src/sama5/sam_memories.c @@ -43,7 +43,10 @@ #include #include +#include + #include "chip.h" +#include "sam_pgalloc.h" #include "sam_memories.h" /**************************************************************************** @@ -901,6 +904,21 @@ uintptr_t sam_physramaddr(uintptr_t virtramaddr) } #endif +#ifdef CONFIG_ARCH_ADDRENV + /* Check if the virtual address lies in the user data area and, if so + * get the mapping to the physical address in the page pool. + */ + + else + { + uintptr_t paddr = sam_physpgaddr(virtramaddr); + if (paddr != 0) + { + return paddr; + } + } +#endif + /* We will not get here unless we are called with an invalid or * unsupported RAM address. Special case the NULL address. */ @@ -1019,6 +1037,21 @@ uintptr_t sam_virtramaddr(uintptr_t physramaddr) } #endif +#ifdef CONFIG_ARCH_ADDRENV + /* Check if the physical address lies in the page pool and, if so + * get the mapping to the virtual address in the user data area. + */ + + else + { + uintptr_t vaddr = sam_virtpgaddr(physramaddr); + if (vaddr != 0) + { + return vaddr; + } + } +#endif + /* We will not get here unless we are called with an invalid or * unsupported RAM address. Special case the NULL address. */ diff --git a/arch/arm/src/sama5/sam_memories.h b/arch/arm/src/sama5/sam_memories.h index 308b06c138..249331cbf5 100644 --- a/arch/arm/src/sama5/sam_memories.h +++ b/arch/arm/src/sama5/sam_memories.h @@ -99,7 +99,7 @@ uintptr_t sam_physramaddr(uintptr_t vramaddr); * Name: sam_virtramaddr * * Description: - * Give the phsical address of a RAM memory location, return the virtual + * Give the physical address of a RAM memory location, return the virtual * address of that location. * ****************************************************************************/ diff --git a/arch/arm/src/sama5/sam_pgalloc.c b/arch/arm/src/sama5/sam_pgalloc.c index ba344c645a..b09c6cf62f 100644 --- a/arch/arm/src/sama5/sam_pgalloc.c +++ b/arch/arm/src/sama5/sam_pgalloc.c @@ -41,16 +41,22 @@ #include #include +#include #include +#include #include #include "chip.h" +#include "mmu.h" +#include "cache.h" + +#include "sam_pgalloc.h" #ifdef CONFIG_MM_PGALLOC /**************************************************************************** - * Private Definitions + * Pre-processor Definitions ****************************************************************************/ /* Currently, page cache memory must be allocated in DRAM. There are other * possibilities, but the logic in this file will have to extended in order @@ -89,7 +95,7 @@ * Public Functions ****************************************************************************/ - /**************************************************************************** +/**************************************************************************** * Name: up_allocate_pgheap * * Description: @@ -104,9 +110,113 @@ void up_allocate_pgheap(FAR void **heap_start, size_t *heap_size) { DEBUGASSERT(heap_start && heap_size); - *heap_start = (FAR void *)((uintptr_t)SAM_DDRCS_VSECTION + + *heap_start = (FAR void *)((uintptr_t)SAM_DDRCS_PSECTION + CONFIG_SAMA5_DDRCS_PGHEAP_OFFSET); *heap_size = CONFIG_SAMA5_DDRCS_PGHEAP_SIZE; } +/**************************************************************************** + * Name: sam_physpgaddr + * + * Description: + * Check if the virtual address lies in the user data area and, if so + * get the mapping to the physical address in the page pool. + * + ****************************************************************************/ + +uintptr_t sam_physpgaddr(uintptr_t vaddr) +{ + FAR uint32_t *l2table; + uint32_t l1entry; + uintptr_t paddr; + int index; + + /* Check if this address is within the range of the virtualized .bss/.data, + * heap, or stack regions. + */ + + if ((vaddr >= CONFIG_ARCH_TEXT_VBASE && vaddr < ARCH_TEXT_VEND) || + (vaddr >= CONFIG_ARCH_DATA_VBASE && vaddr < ARCH_DATA_VEND) || + (vaddr >= CONFIG_ARCH_HEAP_VBASE && vaddr < ARCH_HEAP_VEND) || + (vaddr >= CONFIG_ARCH_STACK_VBASE && vaddr < ARCH_STACK_VEND)) + { + /* Yes.. Get Level 1 page table entry corresponding to this virtual + * address. + */ + + l1entry = mmu_l1_getentry(vaddr); + if ((l1entry & PMD_TYPE_MASK) == PMD_TYPE_PTE) + { + /* Get the physical address of the level 2 page table from level 1 + * page table entry. + */ + + paddr = ((uintptr_t)l1entry & PMD_PTE_PADDR_MASK); + + /* Extract the virtual address of the base of level 2 page table */ + + l2table = (FAR uint32_t *)sam_virtpgaddr(paddr); + if (l2table) + { + /* Invalidate D-Cache line containing this virtual address so that + * we re-read from physical memory + */ + + index = (vaddr & SECTION_MASK) >> MM_PGSHIFT; + arch_invalidate_dcache((uintptr_t)&l2table[index], + (uintptr_t)&l2table[index] + sizeof(uint32_t)); + + /* Get the Level 2 page table entry corresponding to this virtual + * address. Extract the physical address of the page containing + * the mapping of the virtual address. + */ + + paddr = ((uintptr_t)l2table[index] & PTE_SMALL_PADDR_MASK); + + /* Add the correct offset and return the physical address + * corresponding to the virtual address. + */ + + return paddr + (vaddr & MM_PGMASK); + } + } + } + + /* No mapping available */ + + return 0; +} + +/**************************************************************************** + * Name: sam_virtpgaddr + * + * Description: + * Check if the physical address lies in the page pool and, if so + * get the mapping to the virtual address in the user data area. + * + ****************************************************************************/ + +uintptr_t sam_virtpgaddr(uintptr_t paddr) +{ + uintptr_t poolstart; + uintptr_t poolend; + + /* REVISIT: Not implemented correctly. The reverse lookup from physical + * to virtual. This will return a kernel accessible virtual address, but + * not an address usable by the user code. + * + * The correct solutions is complex and, perhaps, will never be needed. + */ + + poolstart = ((uintptr_t)SAM_DDRCS_PSECTION + CONFIG_SAMA5_DDRCS_PGHEAP_OFFSET); + poolend = poolstart + CONFIG_SAMA5_DDRCS_PGHEAP_SIZE; + + if (paddr >= poolstart && paddr < poolend) + { + return paddr - SAM_DDRCS_PSECTION + SAM_DDRCS_VSECTION; + } + + return 0; +} + #endif /* CONFIG_MM_PGALLOC */ diff --git a/arch/arm/src/sama5/sam_pgalloc.h b/arch/arm/src/sama5/sam_pgalloc.h new file mode 100644 index 0000000000..5d43568eb9 --- /dev/null +++ b/arch/arm/src/sama5/sam_pgalloc.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * arch/arm/src/sama5/sam_pgalloc.h + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMA5_SAM_PGALLOC_H +#define __ARCH_ARM_SRC_SAMA5_SAM_PGALLOC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_MM_PGALLOC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: sam_physpgaddr + * + * Description: + * Check if the virtual address lies in the user data area and, if so + * get the mapping to the physical address in the page pool. + * + ****************************************************************************/ + +uintptr_t sam_physpgaddr(uintptr_t vaddr); + +/**************************************************************************** + * Name: sam_virtpgaddr + * + * Description: + * Check if the physical address lies in the page pool and, if so + * get the mapping to the virtual address in the user data area. + * + ****************************************************************************/ + +uintptr_t sam_virtpgaddr(uintptr_t paddr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_MM_PGALLOC */ +#endif /* __ARCH_ARM_SRC_SAMA5_SAM_PGALLOC_H */