diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-21 06:48:16 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-22 06:05:34 -0500 |
commit | af3813d6a5bf8d0f71b23d3ce458fa5f9916c6b7 (patch) | |
tree | 701ed00ea1e781ae758318c81b051f23ed9956fa /arch | |
parent | 614dd0585f376a25c638abbed9c5fbd21d7baece (diff) |
ARM: pgtable: use conventional page table code for identity mappings
Remove some knowledge of our 2-level page table layout from the
identity mapping code - we assume that a step size of PGDIR_SIZE will
allow us to step over all entries. While this is true today, it won't
be true in the near future.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mm/idmap.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 034124d1272d..57299446f787 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -4,33 +4,49 @@ | |||
4 | #include <asm/pgalloc.h> | 4 | #include <asm/pgalloc.h> |
5 | #include <asm/pgtable.h> | 5 | #include <asm/pgtable.h> |
6 | 6 | ||
7 | static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
8 | unsigned long prot) | ||
9 | { | ||
10 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
11 | |||
12 | addr = (addr & PMD_MASK) | prot; | ||
13 | pmd[0] = __pmd(addr); | ||
14 | addr += SECTION_SIZE; | ||
15 | pmd[1] = __pmd(addr); | ||
16 | flush_pmd_entry(pmd); | ||
17 | } | ||
18 | |||
7 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | 19 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) |
8 | { | 20 | { |
9 | unsigned long prot; | 21 | unsigned long prot, next; |
10 | 22 | ||
11 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; | 23 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; |
12 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | 24 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) |
13 | prot |= PMD_BIT4; | 25 | prot |= PMD_BIT4; |
14 | 26 | ||
15 | for (addr &= PGDIR_MASK; addr < end;) { | 27 | pgd += pgd_index(addr); |
16 | pmd_t *pmd = pmd_offset(pgd + pgd_index(addr), addr); | 28 | do { |
17 | pmd[0] = __pmd(addr | prot); | 29 | next = pgd_addr_end(addr, end); |
18 | addr += SECTION_SIZE; | 30 | idmap_add_pmd(pgd, addr, next, prot); |
19 | pmd[1] = __pmd(addr | prot); | 31 | } while (pgd++, addr = next, addr != end); |
20 | addr += SECTION_SIZE; | ||
21 | flush_pmd_entry(pmd); | ||
22 | } | ||
23 | } | 32 | } |
24 | 33 | ||
25 | #ifdef CONFIG_SMP | 34 | #ifdef CONFIG_SMP |
35 | static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
36 | { | ||
37 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
38 | pmd_clear(pmd); | ||
39 | } | ||
40 | |||
26 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | 41 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) |
27 | { | 42 | { |
28 | for (addr &= PGDIR_MASK; addr < end; addr += PGDIR_SIZE) { | 43 | unsigned long next; |
29 | pmd_t *pmd = pmd_offset(pgd + pgd_index(addr), addr); | 44 | |
30 | pmd[0] = __pmd(0); | 45 | pgd += pgd_index(addr); |
31 | pmd[1] = __pmd(0); | 46 | do { |
32 | clean_pmd_entry(pmd); | 47 | next = pgd_addr_end(addr, end); |
33 | } | 48 | idmap_del_pmd(pgd, addr, next); |
49 | } while (pgd++, addr = next, addr != end); | ||
34 | } | 50 | } |
35 | #endif | 51 | #endif |
36 | 52 | ||