-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arm64: MMU fault handling and page table management
This patch adds support for the handling of the MMU faults (exception entry code introduced by a previous patch) and page table management. The user translation table is pointed to by TTBR0 and the kernel one (swapper_pg_dir) by TTBR1. There is no translation information shared or address space overlapping between user and kernel page tables. 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
Catalin Marinas
committed
Sep 17, 2012
1 parent
c1cc155
commit 1d18c47
Showing
8 changed files
with
965 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,67 @@ | ||
/* | ||
* Based on arch/arm/include/asm/page.h | ||
* | ||
* Copyright (C) 1995-2003 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/>. | ||
*/ | ||
#ifndef __ASM_PAGE_H | ||
#define __ASM_PAGE_H | ||
|
||
/* PAGE_SHIFT determines the page size */ | ||
#ifdef CONFIG_ARM64_64K_PAGES | ||
#define PAGE_SHIFT 16 | ||
#else | ||
#define PAGE_SHIFT 12 | ||
#endif | ||
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) | ||
#define PAGE_MASK (~(PAGE_SIZE-1)) | ||
|
||
/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
#define __HAVE_ARCH_GATE_AREA 1 | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#ifdef CONFIG_ARM64_64K_PAGES | ||
#include <asm/pgtable-2level-types.h> | ||
#else | ||
#include <asm/pgtable-3level-types.h> | ||
#endif | ||
|
||
extern void __cpu_clear_user_page(void *p, unsigned long user); | ||
extern void __cpu_copy_user_page(void *to, const void *from, | ||
unsigned long user); | ||
extern void copy_page(void *to, const void *from); | ||
extern void clear_page(void *to); | ||
|
||
#define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) | ||
#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) | ||
|
||
typedef struct page *pgtable_t; | ||
|
||
#ifdef CONFIG_HAVE_ARCH_PFN_VALID | ||
extern int pfn_valid(unsigned long); | ||
#endif | ||
|
||
#include <asm/memory.h> | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#define VM_DATA_DEFAULT_FLAGS \ | ||
(((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ | ||
VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
|
||
#include <asm-generic/getorder.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,113 @@ | ||
/* | ||
* Based on arch/arm/include/asm/pgalloc.h | ||
* | ||
* Copyright (C) 2000-2001 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/>. | ||
*/ | ||
#ifndef __ASM_PGALLOC_H | ||
#define __ASM_PGALLOC_H | ||
|
||
#include <asm/pgtable-hwdef.h> | ||
#include <asm/processor.h> | ||
#include <asm/cacheflush.h> | ||
#include <asm/tlbflush.h> | ||
|
||
#define check_pgt_cache() do { } while (0) | ||
|
||
#ifndef CONFIG_ARM64_64K_PAGES | ||
|
||
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
{ | ||
return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); | ||
} | ||
|
||
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
{ | ||
BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); | ||
free_page((unsigned long)pmd); | ||
} | ||
|
||
static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
{ | ||
set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); | ||
} | ||
|
||
#endif /* CONFIG_ARM64_64K_PAGES */ | ||
|
||
extern pgd_t *pgd_alloc(struct mm_struct *mm); | ||
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | ||
|
||
#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) | ||
|
||
static inline pte_t * | ||
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | ||
{ | ||
return (pte_t *)__get_free_page(PGALLOC_GFP); | ||
} | ||
|
||
static inline pgtable_t | ||
pte_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
{ | ||
struct page *pte; | ||
|
||
pte = alloc_pages(PGALLOC_GFP, 0); | ||
if (pte) | ||
pgtable_page_ctor(pte); | ||
|
||
return pte; | ||
} | ||
|
||
/* | ||
* Free a PTE table. | ||
*/ | ||
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
{ | ||
if (pte) | ||
free_page((unsigned long)pte); | ||
} | ||
|
||
static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
{ | ||
pgtable_page_dtor(pte); | ||
__free_page(pte); | ||
} | ||
|
||
static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | ||
pmdval_t prot) | ||
{ | ||
set_pmd(pmdp, __pmd(pte | prot)); | ||
} | ||
|
||
/* | ||
* Populate the pmdp entry with a pointer to the pte. This pmd is part | ||
* of the mm address space. | ||
*/ | ||
static inline void | ||
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | ||
{ | ||
/* | ||
* The pmd must be loaded with the physical address of the PTE table | ||
*/ | ||
__pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE); | ||
} | ||
|
||
static inline void | ||
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | ||
{ | ||
__pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE); | ||
} | ||
#define pmd_pgtable(pmd) pmd_page(pmd) | ||
|
||
#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,34 @@ | ||
/* | ||
* Based on arch/arm/mm/copypage.c | ||
* | ||
* Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved. | ||
* 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/>. | ||
*/ | ||
|
||
#include <linux/mm.h> | ||
|
||
#include <asm/page.h> | ||
#include <asm/cacheflush.h> | ||
|
||
void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) | ||
{ | ||
copy_page(kto, kfrom); | ||
__flush_dcache_area(kto, PAGE_SIZE); | ||
} | ||
|
||
void __cpu_clear_user_page(void *kaddr, unsigned long vaddr) | ||
{ | ||
clear_page(kaddr); | ||
} |
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,17 @@ | ||
/* | ||
* Based on arch/arm/mm/extable.c | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/uaccess.h> | ||
|
||
int fixup_exception(struct pt_regs *regs) | ||
{ | ||
const struct exception_table_entry *fixup; | ||
|
||
fixup = search_exception_tables(instruction_pointer(regs)); | ||
if (fixup) | ||
regs->pc = fixup->fixup; | ||
|
||
return fixup != NULL; | ||
} |
Oops, something went wrong.