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 | |
| 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>
| -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 | ||
