forked from openbmc/linux
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The virtual memory layout is described in Documentation/arm64/memory.txt. This patch adds the MMU definitions for the 4KB and 64KB translation table configurations. The SECTION_SIZE is 2MB with 4KB page and 512MB with 64KB page configuration. PHYS_OFFSET is calculated at run-time and stored in a variable (no run-time code patching at this stage). On the current implementation, both user and kernel address spaces are 512G (39-bit) each with a maximum of 256G for the RAM linear mapping. Linux uses 3 levels of translation tables with the 4K page configuration and 2 levels with the 64K configuration. Extending the memory space beyond 39-bit with the 4K pages or 42-bit with 64K pages requires an additional level of translation tables. The SPARSEMEM configuration is global to all AArch64 platforms and allows for 1GB sections with SPARSEMEM_VMEMMAP enabled by default. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Tony Lindgren <tony@atomide.com> Acked-by: Nicolas Pitre <nico@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
- Loading branch information
Showing
10 changed files
with
912 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
Memory Layout on AArch64 Linux | ||
============================== | ||
|
||
Author: Catalin Marinas <catalin.marinas@arm.com> | ||
Date : 20 February 2012 | ||
|
||
This document describes the virtual memory layout used by the AArch64 | ||
Linux kernel. The architecture allows up to 4 levels of translation | ||
tables with a 4KB page size and up to 3 levels with a 64KB page size. | ||
|
||
AArch64 Linux uses 3 levels of translation tables with the 4KB page | ||
configuration, allowing 39-bit (512GB) virtual addresses for both user | ||
and kernel. With 64KB pages, only 2 levels of translation tables are | ||
used but the memory layout is the same. | ||
|
||
User addresses have bits 63:39 set to 0 while the kernel addresses have | ||
the same bits set to 1. TTBRx selection is given by bit 63 of the | ||
virtual address. The swapper_pg_dir contains only kernel (global) | ||
mappings while the user pgd contains only user (non-global) mappings. | ||
The swapper_pgd_dir address is written to TTBR1 and never written to | ||
TTBR0. | ||
|
||
|
||
AArch64 Linux memory layout: | ||
|
||
Start End Size Use | ||
----------------------------------------------------------------------- | ||
0000000000000000 0000007fffffffff 512GB user | ||
|
||
ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc | ||
|
||
ffffffbbfffd0000 ffffffbcfffdffff 64KB [guard page] | ||
|
||
ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O space | ||
|
||
ffffffbbffff0000 ffffffbcffffffff 64KB [guard page] | ||
|
||
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap | ||
|
||
ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap] | ||
|
||
ffffffbffc000000 ffffffbfffffffff 64MB modules | ||
|
||
ffffffc000000000 ffffffffffffffff 256GB memory | ||
|
||
|
||
Translation table lookup with 4KB pages: | ||
|
||
+--------+--------+--------+--------+--------+--------+--------+--------+ | ||
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| | ||
+--------+--------+--------+--------+--------+--------+--------+--------+ | ||
| | | | | | | ||
| | | | | v | ||
| | | | | [11:0] in-page offset | ||
| | | | +-> [20:12] L3 index | ||
| | | +-----------> [29:21] L2 index | ||
| | +---------------------> [38:30] L1 index | ||
| +-------------------------------> [47:39] L0 index (not used) | ||
+-------------------------------------------------> [63] TTBR0/1 | ||
|
||
|
||
Translation table lookup with 64KB pages: | ||
|
||
+--------+--------+--------+--------+--------+--------+--------+--------+ | ||
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| | ||
+--------+--------+--------+--------+--------+--------+--------+--------+ | ||
| | | | | | ||
| | | | v | ||
| | | | [15:0] in-page offset | ||
| | | +----------> [28:16] L3 index | ||
| | +--------------------------> [41:29] L2 index (only 38:29 used) | ||
| +-------------------------------> [47:42] L1 index (not used) | ||
+-------------------------------------------------> [63] TTBR0/1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
* Based on arch/arm/include/asm/memory.h | ||
* | ||
* Copyright (C) 2000-2002 Russell King | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
* Note: this file should not be included by non-asm/.h files | ||
*/ | ||
#ifndef __ASM_MEMORY_H | ||
#define __ASM_MEMORY_H | ||
|
||
#include <linux/compiler.h> | ||
#include <linux/const.h> | ||
#include <linux/types.h> | ||
#include <asm/sizes.h> | ||
|
||
/* | ||
* Allow for constants defined here to be used from assembly code | ||
* by prepending the UL suffix only with actual C code compilation. | ||
*/ | ||
#define UL(x) _AC(x, UL) | ||
|
||
/* | ||
* PAGE_OFFSET - the virtual address of the start of the kernel image. | ||
* VA_BITS - the maximum number of bits for virtual addresses. | ||
* TASK_SIZE - the maximum size of a user space task. | ||
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. | ||
* The module space lives between the addresses given by TASK_SIZE | ||
* and PAGE_OFFSET - it must be within 128MB of the kernel text. | ||
*/ | ||
#define PAGE_OFFSET UL(0xffffffc000000000) | ||
#define MODULES_END (PAGE_OFFSET) | ||
#define MODULES_VADDR (MODULES_END - SZ_64M) | ||
#define VA_BITS (39) | ||
#define TASK_SIZE_64 (UL(1) << VA_BITS) | ||
|
||
#ifdef CONFIG_COMPAT | ||
#define TASK_SIZE_32 UL(0x100000000) | ||
#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ | ||
TASK_SIZE_32 : TASK_SIZE_64) | ||
#else | ||
#define TASK_SIZE TASK_SIZE_64 | ||
#endif /* CONFIG_COMPAT */ | ||
|
||
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4)) | ||
|
||
#if TASK_SIZE_64 > MODULES_VADDR | ||
#error Top of 64-bit user space clashes with start of module space | ||
#endif | ||
|
||
/* | ||
* Physical vs virtual RAM address space conversion. These are | ||
* private definitions which should NOT be used outside memory.h | ||
* files. Use virt_to_phys/phys_to_virt/__pa/__va instead. | ||
*/ | ||
#define __virt_to_phys(x) (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET)) | ||
#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET)) | ||
|
||
/* | ||
* Convert a physical address to a Page Frame Number and back | ||
*/ | ||
#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) | ||
#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) | ||
|
||
/* | ||
* Convert a page to/from a physical address | ||
*/ | ||
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) | ||
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) | ||
|
||
/* | ||
* Memory types available. | ||
*/ | ||
#define MT_DEVICE_nGnRnE 0 | ||
#define MT_DEVICE_nGnRE 1 | ||
#define MT_DEVICE_GRE 2 | ||
#define MT_NORMAL_NC 3 | ||
#define MT_NORMAL 4 | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
extern phys_addr_t memstart_addr; | ||
/* PHYS_OFFSET - the physical address of the start of memory. */ | ||
#define PHYS_OFFSET ({ memstart_addr; }) | ||
|
||
/* | ||
* PFNs are used to describe any physical page; this means | ||
* PFN 0 == physical address 0. | ||
* | ||
* This is the PFN of the first RAM page in the kernel | ||
* direct-mapped view. We assume this is the first page | ||
* of RAM in the mem_map as well. | ||
*/ | ||
#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) | ||
|
||
/* | ||
* Note: Drivers should NOT use these. They are the wrong | ||
* translation for translating DMA addresses. Use the driver | ||
* DMA support - see dma-mapping.h. | ||
*/ | ||
static inline phys_addr_t virt_to_phys(const volatile void *x) | ||
{ | ||
return __virt_to_phys((unsigned long)(x)); | ||
} | ||
|
||
static inline void *phys_to_virt(phys_addr_t x) | ||
{ | ||
return (void *)(__phys_to_virt(x)); | ||
} | ||
|
||
/* | ||
* Drivers should NOT use these either. | ||
*/ | ||
#define __pa(x) __virt_to_phys((unsigned long)(x)) | ||
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) | ||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | ||
|
||
/* | ||
* virt_to_page(k) convert a _valid_ virtual address to struct page * | ||
* virt_addr_valid(k) indicates whether a virtual address is valid | ||
*/ | ||
#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET | ||
|
||
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ | ||
((void *)(kaddr) < (void *)high_memory)) | ||
|
||
#endif | ||
|
||
#include <asm-generic/memory_model.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
#ifndef __ASM_MMU_H | ||
#define __ASM_MMU_H | ||
|
||
typedef struct { | ||
unsigned int id; | ||
raw_spinlock_t id_lock; | ||
void *vdso; | ||
} mm_context_t; | ||
|
||
#define ASID(mm) ((mm)->context.id & 0xffff) | ||
|
||
extern void paging_init(void); | ||
extern void setup_mm_for_reboot(void); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
#ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H | ||
#define __ASM_PGTABLE_2LEVEL_HWDEF_H | ||
|
||
/* | ||
* With LPAE and 64KB pages, there are 2 levels of page tables. Each level has | ||
* 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not | ||
* used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each | ||
* entry representing 512MB. The user and kernel address spaces are limited to | ||
* 512GB and therefore we only use 1024 entries in the PGD. | ||
*/ | ||
#define PTRS_PER_PTE 8192 | ||
#define PTRS_PER_PGD 1024 | ||
|
||
/* | ||
* PGDIR_SHIFT determines the size a top-level page table entry can map. | ||
*/ | ||
#define PGDIR_SHIFT 29 | ||
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) | ||
#define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
|
||
/* | ||
* section address mask and size definitions. | ||
*/ | ||
#define SECTION_SHIFT 29 | ||
#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) | ||
#define SECTION_MASK (~(SECTION_SIZE-1)) | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
#ifndef __ASM_PGTABLE_2LEVEL_TYPES_H | ||
#define __ASM_PGTABLE_2LEVEL_TYPES_H | ||
|
||
typedef u64 pteval_t; | ||
typedef u64 pgdval_t; | ||
typedef pgdval_t pmdval_t; | ||
|
||
#undef STRICT_MM_TYPECHECKS | ||
|
||
#ifdef STRICT_MM_TYPECHECKS | ||
|
||
/* | ||
* These are used to make use of C type-checking.. | ||
*/ | ||
typedef struct { pteval_t pte; } pte_t; | ||
typedef struct { pgdval_t pgd; } pgd_t; | ||
typedef struct { pteval_t pgprot; } pgprot_t; | ||
|
||
#define pte_val(x) ((x).pte) | ||
#define pgd_val(x) ((x).pgd) | ||
#define pgprot_val(x) ((x).pgprot) | ||
|
||
#define __pte(x) ((pte_t) { (x) } ) | ||
#define __pgd(x) ((pgd_t) { (x) } ) | ||
#define __pgprot(x) ((pgprot_t) { (x) } ) | ||
|
||
#else /* !STRICT_MM_TYPECHECKS */ | ||
|
||
typedef pteval_t pte_t; | ||
typedef pgdval_t pgd_t; | ||
typedef pteval_t pgprot_t; | ||
|
||
#define pte_val(x) (x) | ||
#define pgd_val(x) (x) | ||
#define pgprot_val(x) (x) | ||
|
||
#define __pte(x) (x) | ||
#define __pgd(x) (x) | ||
#define __pgprot(x) (x) | ||
|
||
#endif /* STRICT_MM_TYPECHECKS */ | ||
|
||
#include <asm-generic/pgtable-nopmd.h> | ||
|
||
#endif /* __ASM_PGTABLE_2LEVEL_TYPES_H */ |
Oops, something went wrong.