1 #include <linux/kernel.h> 2 3 #include <asm/cputype.h> 4 #include <asm/pgalloc.h> 5 #include <asm/pgtable.h> 6 7 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, 8 unsigned long prot) 9 { 10 pmd_t *pmd = pmd_offset(pud, 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 19 static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, 20 unsigned long prot) 21 { 22 pud_t *pud = pud_offset(pgd, addr); 23 unsigned long next; 24 25 do { 26 next = pud_addr_end(addr, end); 27 idmap_add_pmd(pud, addr, next, prot); 28 } while (pud++, addr = next, addr != end); 29 } 30 31 void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) 32 { 33 unsigned long prot, next; 34 35 prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; 36 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) 37 prot |= PMD_BIT4; 38 39 pgd += pgd_index(addr); 40 do { 41 next = pgd_addr_end(addr, end); 42 idmap_add_pud(pgd, addr, next, prot); 43 } while (pgd++, addr = next, addr != end); 44 } 45 46 #ifdef CONFIG_SMP 47 static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end) 48 { 49 pmd_t *pmd = pmd_offset(pud, addr); 50 pmd_clear(pmd); 51 } 52 53 static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end) 54 { 55 pud_t *pud = pud_offset(pgd, addr); 56 unsigned long next; 57 58 do { 59 next = pud_addr_end(addr, end); 60 idmap_del_pmd(pud, addr, next); 61 } while (pud++, addr = next, addr != end); 62 } 63 64 void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) 65 { 66 unsigned long next; 67 68 pgd += pgd_index(addr); 69 do { 70 next = pgd_addr_end(addr, end); 71 idmap_del_pud(pgd, addr, next); 72 } while (pgd++, addr = next, addr != end); 73 } 74 #endif 75 76 /* 77 * In order to soft-boot, we need to insert a 1:1 mapping in place of 78 * the user-mode pages. This will then ensure that we have predictable 79 * results when turning the mmu off 80 */ 81 void setup_mm_for_reboot(char mode) 82 { 83 /* 84 * We need to access to user-mode page tables here. For kernel threads 85 * we don't have any user-mode mappings so we use the context that we 86 * "borrowed". 87 */ 88 identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE); 89 local_flush_tlb_all(); 90 } 91