idmap.c 2.1 KB

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