Merge remote-tracking branch 's5p/for-next'
[linux-2.6/next.git] / arch / arm / mm / idmap.c
blob24e06555bee49d51b525b0cbb2677f396c663d37
1 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3 #include <linux/kernel.h>
5 #include <asm/cputype.h>
6 #include <asm/pgalloc.h>
7 #include <asm/pgtable.h>
9 #ifdef CONFIG_ARM_LPAE
10 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
11 unsigned long prot)
13 pmd_t *pmd;
14 unsigned long next;
16 if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) {
17 pmd = pmd_alloc_one(NULL, addr);
18 if (!pmd) {
19 pr_warning("Failed to allocate identity pmd.\n");
20 return;
22 pud_populate(NULL, pud, pmd);
23 pmd += pmd_index(addr);
24 } else
25 pmd = pmd_offset(pud, addr);
27 do {
28 next = pmd_addr_end(addr, end);
29 *pmd = __pmd((addr & PMD_MASK) | prot);
30 flush_pmd_entry(pmd);
31 } while (pmd++, addr = next, addr != end);
33 #else /* !CONFIG_ARM_LPAE */
34 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
35 unsigned long prot)
37 pmd_t *pmd = pmd_offset(pud, addr);
39 addr = (addr & PMD_MASK) | prot;
40 pmd[0] = __pmd(addr);
41 addr += SECTION_SIZE;
42 pmd[1] = __pmd(addr);
43 flush_pmd_entry(pmd);
45 #endif /* CONFIG_ARM_LPAE */
47 static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
48 unsigned long prot)
50 pud_t *pud = pud_offset(pgd, addr);
51 unsigned long next;
53 do {
54 next = pud_addr_end(addr, end);
55 idmap_add_pmd(pud, addr, next, prot);
56 } while (pud++, addr = next, addr != end);
59 void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
61 unsigned long prot, next;
63 prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
64 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
65 prot |= PMD_BIT4;
67 pgd += pgd_index(addr);
68 do {
69 next = pgd_addr_end(addr, end);
70 idmap_add_pud(pgd, addr, next, prot);
71 } while (pgd++, addr = next, addr != end);
74 #ifdef CONFIG_SMP
75 static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end)
77 pmd_t *pmd;
79 if (pud_none_or_clear_bad(pud))
80 return;
81 pmd = pmd_offset(pud, addr);
82 pmd_clear(pmd);
85 static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end)
87 pud_t *pud = pud_offset(pgd, addr);
88 unsigned long next;
90 do {
91 next = pud_addr_end(addr, end);
92 idmap_del_pmd(pud, addr, next);
93 } while (pud++, addr = next, addr != end);
96 void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
98 unsigned long next;
100 pgd += pgd_index(addr);
101 do {
102 next = pgd_addr_end(addr, end);
103 idmap_del_pud(pgd, addr, next);
104 } while (pgd++, addr = next, addr != end);
106 #endif
109 * In order to soft-boot, we need to insert a 1:1 mapping in place of
110 * the user-mode pages. This will then ensure that we have predictable
111 * results when turning the mmu off
113 void setup_mm_for_reboot(char mode)
116 * We need to access to user-mode page tables here. For kernel threads
117 * we don't have any user-mode mappings so we use the context that we
118 * "borrowed".
120 identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE);
121 local_flush_tlb_all();