pgalloc.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * arch/arm/include/asm/pgalloc.h
  4. *
  5. * Copyright (C) 2000-2001 Russell King
  6. */
  7. #ifndef _ASMARM_PGALLOC_H
  8. #define _ASMARM_PGALLOC_H
  9. #include <linux/pagemap.h>
  10. #include <asm/domain.h>
  11. #include <asm/pgtable-hwdef.h>
  12. #include <asm/processor.h>
  13. #include <asm/cacheflush.h>
  14. #include <asm/tlbflush.h>
  15. #ifdef CONFIG_MMU
  16. #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
  17. #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
  18. #ifdef CONFIG_ARM_LPAE
  19. #define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
  20. static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
  21. {
  22. set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
  23. }
  24. #else /* !CONFIG_ARM_LPAE */
  25. #define PGD_SIZE (PAGE_SIZE << 2)
  26. /*
  27. * Since we have only two-level page tables, these are trivial
  28. */
  29. #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
  30. #define pmd_free(mm, pmd) do { } while (0)
  31. #ifdef CONFIG_KASAN
  32. /* The KASan core unconditionally calls pud_populate() on all architectures */
  33. #define pud_populate(mm,pmd,pte) do { } while (0)
  34. #else
  35. #define pud_populate(mm,pmd,pte) BUG()
  36. #endif
  37. #endif /* CONFIG_ARM_LPAE */
  38. extern pgd_t *pgd_alloc(struct mm_struct *mm);
  39. extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
  40. static inline void clean_pte_table(pte_t *pte)
  41. {
  42. clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE);
  43. }
  44. /*
  45. * Allocate one PTE table.
  46. *
  47. * This actually allocates two hardware PTE tables, but we wrap this up
  48. * into one table thus:
  49. *
  50. * +------------+
  51. * | Linux pt 0 |
  52. * +------------+
  53. * | Linux pt 1 |
  54. * +------------+
  55. * | h/w pt 0 |
  56. * +------------+
  57. * | h/w pt 1 |
  58. * +------------+
  59. */
  60. #define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
  61. #define __HAVE_ARCH_PTE_ALLOC_ONE
  62. #define __HAVE_ARCH_PGD_FREE
  63. #include <asm-generic/pgalloc.h>
  64. static inline pte_t *
  65. pte_alloc_one_kernel(struct mm_struct *mm)
  66. {
  67. pte_t *pte = __pte_alloc_one_kernel(mm);
  68. if (pte)
  69. clean_pte_table(pte);
  70. return pte;
  71. }
  72. #ifdef CONFIG_HIGHPTE
  73. #define PGTABLE_HIGHMEM __GFP_HIGHMEM
  74. #else
  75. #define PGTABLE_HIGHMEM 0
  76. #endif
  77. static inline pgtable_t
  78. pte_alloc_one(struct mm_struct *mm)
  79. {
  80. struct page *pte;
  81. pte = __pte_alloc_one(mm, GFP_PGTABLE_USER | PGTABLE_HIGHMEM);
  82. if (!pte)
  83. return NULL;
  84. if (!PageHighMem(pte))
  85. clean_pte_table(page_address(pte));
  86. return pte;
  87. }
  88. static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
  89. pmdval_t prot)
  90. {
  91. pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
  92. pmdp[0] = __pmd(pmdval);
  93. #ifndef CONFIG_ARM_LPAE
  94. pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
  95. #endif
  96. flush_pmd_entry(pmdp);
  97. }
  98. /*
  99. * Populate the pmdp entry with a pointer to the pte. This pmd is part
  100. * of the mm address space.
  101. *
  102. * Ensure that we always set both PMD entries.
  103. */
  104. static inline void
  105. pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
  106. {
  107. /*
  108. * The pmd must be loaded with the physical address of the PTE table
  109. */
  110. __pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE);
  111. }
  112. static inline void
  113. pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
  114. {
  115. extern pmdval_t user_pmd_table;
  116. pmdval_t prot;
  117. if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE))
  118. prot = user_pmd_table;
  119. else
  120. prot = _PAGE_USER_TABLE;
  121. __pmd_populate(pmdp, page_to_phys(ptep), prot);
  122. }
  123. #endif /* CONFIG_MMU */
  124. #endif