pgtable.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  4. *
  5. * Derived from MIPS:
  6. * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle
  7. * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
  8. */
  9. #ifndef _ASM_PGTABLE_H
  10. #define _ASM_PGTABLE_H
  11. #include <linux/compiler.h>
  12. #include <asm/addrspace.h>
  13. #include <asm/asm.h>
  14. #include <asm/page.h>
  15. #include <asm/pgtable-bits.h>
  16. #if CONFIG_PGTABLE_LEVELS == 2
  17. #include <asm-generic/pgtable-nopmd.h>
  18. #elif CONFIG_PGTABLE_LEVELS == 3
  19. #include <asm-generic/pgtable-nopud.h>
  20. #else
  21. #include <asm-generic/pgtable-nop4d.h>
  22. #endif
  23. #if CONFIG_PGTABLE_LEVELS == 2
  24. #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG))
  25. #elif CONFIG_PGTABLE_LEVELS == 3
  26. #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG))
  27. #define PMD_SIZE (1UL << PMD_SHIFT)
  28. #define PMD_MASK (~(PMD_SIZE-1))
  29. #define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT - PTRLOG))
  30. #elif CONFIG_PGTABLE_LEVELS == 4
  31. #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG))
  32. #define PMD_SIZE (1UL << PMD_SHIFT)
  33. #define PMD_MASK (~(PMD_SIZE-1))
  34. #define PUD_SHIFT (PMD_SHIFT + (PAGE_SHIFT - PTRLOG))
  35. #define PUD_SIZE (1UL << PUD_SHIFT)
  36. #define PUD_MASK (~(PUD_SIZE-1))
  37. #define PGDIR_SHIFT (PUD_SHIFT + (PAGE_SHIFT - PTRLOG))
  38. #endif
  39. #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
  40. #define PGDIR_MASK (~(PGDIR_SIZE-1))
  41. #ifdef CONFIG_32BIT
  42. #define VA_BITS 32
  43. #else
  44. #define VA_BITS (PGDIR_SHIFT + (PAGE_SHIFT - PTRLOG))
  45. #endif
  46. #define PTRS_PER_PGD (PAGE_SIZE >> PTRLOG)
  47. #if CONFIG_PGTABLE_LEVELS > 3
  48. #define PTRS_PER_PUD (PAGE_SIZE >> PTRLOG)
  49. #endif
  50. #if CONFIG_PGTABLE_LEVELS > 2
  51. #define PTRS_PER_PMD (PAGE_SIZE >> PTRLOG)
  52. #endif
  53. #define PTRS_PER_PTE (PAGE_SIZE >> PTRLOG)
  54. #ifdef CONFIG_32BIT
  55. #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
  56. #else
  57. #define USER_PTRS_PER_PGD ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1)
  58. #endif
  59. #ifndef __ASSEMBLER__
  60. #include <linux/mm_types.h>
  61. #include <linux/mmzone.h>
  62. #include <asm/fixmap.h>
  63. #include <asm/sparsemem.h>
  64. struct mm_struct;
  65. struct vm_area_struct;
  66. /*
  67. * ZERO_PAGE is a global shared page that is always zero; used
  68. * for zero-mapped memory areas etc..
  69. */
  70. extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
  71. #define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
  72. #ifdef CONFIG_32BIT
  73. #define VMALLOC_START (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE))
  74. #define VMALLOC_END (FIXADDR_START - (2 * PAGE_SIZE))
  75. #endif
  76. #ifdef CONFIG_64BIT
  77. #define MODULES_VADDR (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE))
  78. #define MODULES_END (MODULES_VADDR + SZ_256M)
  79. #ifdef CONFIG_KFENCE
  80. #define KFENCE_AREA_SIZE (((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 + 2) * PAGE_SIZE)
  81. #else
  82. #define KFENCE_AREA_SIZE 0
  83. #endif
  84. #define VMALLOC_START MODULES_END
  85. #ifndef CONFIG_KASAN
  86. #define VMALLOC_END \
  87. (vm_map_base + \
  88. min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, (1UL << cpu_vabits)) - PMD_SIZE - VMEMMAP_SIZE - KFENCE_AREA_SIZE)
  89. #else
  90. #define VMALLOC_END \
  91. (vm_map_base + \
  92. min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, (1UL << cpu_vabits) / 2) - PMD_SIZE - VMEMMAP_SIZE - KFENCE_AREA_SIZE)
  93. #endif
  94. #define vmemmap ((struct page *)((VMALLOC_END + PMD_SIZE) & PMD_MASK))
  95. #define VMEMMAP_END ((unsigned long)vmemmap + VMEMMAP_SIZE - 1)
  96. #define KFENCE_AREA_START (VMEMMAP_END + 1)
  97. #define KFENCE_AREA_END (KFENCE_AREA_START + KFENCE_AREA_SIZE - 1)
  98. #endif
  99. #define ptep_get(ptep) READ_ONCE(*(ptep))
  100. #define pmdp_get(pmdp) READ_ONCE(*(pmdp))
  101. #define pte_ERROR(e) \
  102. pr_err("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
  103. #ifndef __PAGETABLE_PMD_FOLDED
  104. #define pmd_ERROR(e) \
  105. pr_err("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
  106. #endif
  107. #ifndef __PAGETABLE_PUD_FOLDED
  108. #define pud_ERROR(e) \
  109. pr_err("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
  110. #endif
  111. #define pgd_ERROR(e) \
  112. pr_err("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
  113. extern pte_t invalid_pte_table[PTRS_PER_PTE];
  114. #ifndef __PAGETABLE_PUD_FOLDED
  115. typedef struct { unsigned long pud; } pud_t;
  116. #define pud_val(x) ((x).pud)
  117. #define __pud(x) ((pud_t) { (x) })
  118. extern pud_t invalid_pud_table[PTRS_PER_PUD];
  119. /*
  120. * Empty pgd/p4d entries point to the invalid_pud_table.
  121. */
  122. static inline int p4d_none(p4d_t p4d)
  123. {
  124. return p4d_val(p4d) == (unsigned long)invalid_pud_table;
  125. }
  126. static inline int p4d_bad(p4d_t p4d)
  127. {
  128. return p4d_val(p4d) & ~PAGE_MASK;
  129. }
  130. static inline int p4d_present(p4d_t p4d)
  131. {
  132. return p4d_val(p4d) != (unsigned long)invalid_pud_table;
  133. }
  134. static inline pud_t *p4d_pgtable(p4d_t p4d)
  135. {
  136. return (pud_t *)p4d_val(p4d);
  137. }
  138. static inline void set_p4d(p4d_t *p4d, p4d_t p4dval)
  139. {
  140. WRITE_ONCE(*p4d, p4dval);
  141. }
  142. static inline void p4d_clear(p4d_t *p4dp)
  143. {
  144. set_p4d(p4dp, __p4d((unsigned long)invalid_pud_table));
  145. }
  146. #define p4d_phys(p4d) PHYSADDR(p4d_val(p4d))
  147. #define p4d_page(p4d) (pfn_to_page(p4d_phys(p4d) >> PAGE_SHIFT))
  148. #endif
  149. #ifndef __PAGETABLE_PMD_FOLDED
  150. typedef struct { unsigned long pmd; } pmd_t;
  151. #define pmd_val(x) ((x).pmd)
  152. #define __pmd(x) ((pmd_t) { (x) })
  153. extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
  154. /*
  155. * Empty pud entries point to the invalid_pmd_table.
  156. */
  157. static inline int pud_none(pud_t pud)
  158. {
  159. return pud_val(pud) == (unsigned long)invalid_pmd_table;
  160. }
  161. static inline int pud_bad(pud_t pud)
  162. {
  163. return pud_val(pud) & ~PAGE_MASK;
  164. }
  165. static inline int pud_present(pud_t pud)
  166. {
  167. return pud_val(pud) != (unsigned long)invalid_pmd_table;
  168. }
  169. static inline pmd_t *pud_pgtable(pud_t pud)
  170. {
  171. return (pmd_t *)pud_val(pud);
  172. }
  173. static inline void set_pud(pud_t *pud, pud_t pudval)
  174. {
  175. WRITE_ONCE(*pud, pudval);
  176. }
  177. static inline void pud_clear(pud_t *pudp)
  178. {
  179. set_pud(pudp, __pud((unsigned long)invalid_pmd_table));
  180. }
  181. #define pud_phys(pud) PHYSADDR(pud_val(pud))
  182. #define pud_page(pud) (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
  183. #endif
  184. /*
  185. * Empty pmd entries point to the invalid_pte_table.
  186. */
  187. static inline int pmd_none(pmd_t pmd)
  188. {
  189. return pmd_val(pmd) == (unsigned long)invalid_pte_table;
  190. }
  191. static inline int pmd_bad(pmd_t pmd)
  192. {
  193. return (pmd_val(pmd) & ~PAGE_MASK);
  194. }
  195. static inline int pmd_present(pmd_t pmd)
  196. {
  197. if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
  198. return !!(pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PRESENT_INVALID));
  199. return pmd_val(pmd) != (unsigned long)invalid_pte_table;
  200. }
  201. static inline void set_pmd(pmd_t *pmd, pmd_t pmdval)
  202. {
  203. WRITE_ONCE(*pmd, pmdval);
  204. }
  205. static inline void pmd_clear(pmd_t *pmdp)
  206. {
  207. set_pmd(pmdp, __pmd((unsigned long)invalid_pte_table));
  208. }
  209. #define pmd_phys(pmd) PHYSADDR(pmd_val(pmd))
  210. #ifndef CONFIG_TRANSPARENT_HUGEPAGE
  211. #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
  212. #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  213. #define pmd_page_vaddr(pmd) pmd_val(pmd)
  214. extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd);
  215. #define pte_page(x) pfn_to_page(pte_pfn(x))
  216. #define pte_pfn(x) ((unsigned long)(((x).pte & _PFN_MASK) >> PFN_PTE_SHIFT))
  217. #define pfn_pte(pfn, prot) __pte(((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot))
  218. #define pfn_pmd(pfn, prot) __pmd(((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot))
  219. /*
  220. * Initialize a new pgd / pud / pmd table with invalid pointers.
  221. */
  222. extern void pgd_init(void *addr);
  223. extern void pud_init(void *addr);
  224. #define pud_init pud_init
  225. extern void pmd_init(void *addr);
  226. #define pmd_init pmd_init
  227. extern void kernel_pte_init(void *addr);
  228. #define kernel_pte_init kernel_pte_init
  229. /*
  230. * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
  231. * are !pte_none() && !pte_present().
  232. *
  233. * Format of 32bit swap PTEs:
  234. *
  235. * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  236. * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  237. * <------------ offset -------------> E <- type -> <-- zeroes -->
  238. *
  239. * E is the exclusive marker that is not stored in swap entries.
  240. * The zero'ed bits include _PAGE_PRESENT.
  241. *
  242. * Format of 64bit swap PTEs:
  243. *
  244. * 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3
  245. * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
  246. * <--------------------------- offset ---------------------------
  247. *
  248. * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  249. * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  250. * --------------> E <--- type ---> <---------- zeroes ---------->
  251. *
  252. * E is the exclusive marker that is not stored in swap entries.
  253. * The zero'ed bits include _PAGE_PRESENT and _PAGE_PROTNONE.
  254. */
  255. #define __SWP_TYPE_BITS (IS_ENABLED(CONFIG_32BIT) ? 5 : 7)
  256. #define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1)
  257. #define __SWP_TYPE_SHIFT (IS_ENABLED(CONFIG_32BIT) ? 8 : 16)
  258. #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT + 1)
  259. static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
  260. {
  261. pte_t pte;
  262. pte_val(pte) = ((type & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT) | (offset << __SWP_OFFSET_SHIFT);
  263. return pte;
  264. }
  265. #define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
  266. #define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT)
  267. #define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) })
  268. #define __swp_entry_to_pte(x) __pte((x).val)
  269. #define __swp_entry_to_pmd(x) __pmd((x).val | _PAGE_HUGE)
  270. #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
  271. #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) })
  272. static inline bool pte_swp_exclusive(pte_t pte)
  273. {
  274. return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
  275. }
  276. static inline pte_t pte_swp_mkexclusive(pte_t pte)
  277. {
  278. pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;
  279. return pte;
  280. }
  281. static inline pte_t pte_swp_clear_exclusive(pte_t pte)
  282. {
  283. pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE;
  284. return pte;
  285. }
  286. #define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL))
  287. #define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
  288. #define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC)
  289. static inline void set_pte(pte_t *ptep, pte_t pteval)
  290. {
  291. WRITE_ONCE(*ptep, pteval);
  292. #ifdef CONFIG_SMP
  293. if (pte_val(pteval) & _PAGE_GLOBAL)
  294. DBAR(0b11000); /* o_wrw = 0b11000 */
  295. #endif
  296. }
  297. static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
  298. {
  299. pte_t pte = ptep_get(ptep);
  300. pte_val(pte) &= _PAGE_GLOBAL;
  301. set_pte(ptep, pte);
  302. }
  303. #define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1)
  304. #define PMD_T_LOG2 (__builtin_ffs(sizeof(pmd_t)) - 1)
  305. #define PTE_T_LOG2 (__builtin_ffs(sizeof(pte_t)) - 1)
  306. extern pgd_t swapper_pg_dir[];
  307. extern pgd_t invalid_pg_dir[];
  308. /*
  309. * The following only work if pte_present() is true.
  310. * Undefined behaviour if not..
  311. */
  312. static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
  313. static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
  314. static inline int pte_dirty(pte_t pte) { return pte_val(pte) & (_PAGE_DIRTY | _PAGE_MODIFIED); }
  315. static inline pte_t pte_mkold(pte_t pte)
  316. {
  317. pte_val(pte) &= ~_PAGE_ACCESSED;
  318. return pte;
  319. }
  320. static inline pte_t pte_mkyoung(pte_t pte)
  321. {
  322. pte_val(pte) |= _PAGE_ACCESSED;
  323. return pte;
  324. }
  325. static inline pte_t pte_mkclean(pte_t pte)
  326. {
  327. pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_MODIFIED);
  328. return pte;
  329. }
  330. static inline pte_t pte_mkdirty(pte_t pte)
  331. {
  332. pte_val(pte) |= _PAGE_MODIFIED;
  333. if (pte_val(pte) & _PAGE_WRITE)
  334. pte_val(pte) |= _PAGE_DIRTY;
  335. return pte;
  336. }
  337. static inline pte_t pte_mkwrite_novma(pte_t pte)
  338. {
  339. pte_val(pte) |= _PAGE_WRITE;
  340. if (pte_val(pte) & _PAGE_MODIFIED)
  341. pte_val(pte) |= _PAGE_DIRTY;
  342. return pte;
  343. }
  344. static inline pte_t pte_wrprotect(pte_t pte)
  345. {
  346. pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
  347. return pte;
  348. }
  349. static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE; }
  350. static inline pte_t pte_mkhuge(pte_t pte)
  351. {
  352. pte_val(pte) |= _PAGE_HUGE;
  353. return pte;
  354. }
  355. #if defined(CONFIG_ARCH_HAS_PTE_SPECIAL)
  356. static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
  357. static inline pte_t pte_mkspecial(pte_t pte) { pte_val(pte) |= _PAGE_SPECIAL; return pte; }
  358. #endif /* CONFIG_ARCH_HAS_PTE_SPECIAL */
  359. #define pte_accessible pte_accessible
  360. static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
  361. {
  362. if (pte_val(a) & _PAGE_PRESENT)
  363. return true;
  364. if ((pte_val(a) & _PAGE_PROTNONE) &&
  365. atomic_read(&mm->tlb_flush_pending))
  366. return true;
  367. return false;
  368. }
  369. static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  370. {
  371. if (pte_val(pte) & _PAGE_DIRTY)
  372. pte_val(pte) |= _PAGE_MODIFIED;
  373. return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
  374. (pgprot_val(newprot) & ~_PAGE_CHG_MASK));
  375. }
  376. extern void __update_tlb(struct vm_area_struct *vma,
  377. unsigned long address, pte_t *ptep);
  378. static inline void update_mmu_cache_range(struct vm_fault *vmf,
  379. struct vm_area_struct *vma, unsigned long address,
  380. pte_t *ptep, unsigned int nr)
  381. {
  382. for (;;) {
  383. __update_tlb(vma, address, ptep);
  384. if (--nr == 0)
  385. break;
  386. address += PAGE_SIZE;
  387. ptep++;
  388. }
  389. }
  390. #define update_mmu_cache(vma, addr, ptep) \
  391. update_mmu_cache_range(NULL, vma, addr, ptep, 1)
  392. #define update_mmu_tlb_range(vma, addr, ptep, nr) \
  393. update_mmu_cache_range(NULL, vma, addr, ptep, nr)
  394. static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
  395. unsigned long address, pmd_t *pmdp)
  396. {
  397. __update_tlb(vma, address, (pte_t *)pmdp);
  398. }
  399. static inline unsigned long pmd_pfn(pmd_t pmd)
  400. {
  401. return (pmd_val(pmd) & _PFN_MASK) >> PFN_PTE_SHIFT;
  402. }
  403. #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  404. /* We don't have hardware dirty/accessed bits, generic_pmdp_establish is fine.*/
  405. #define pmdp_establish generic_pmdp_establish
  406. static inline int pmd_trans_huge(pmd_t pmd)
  407. {
  408. return !!(pmd_val(pmd) & _PAGE_HUGE) && pmd_present(pmd);
  409. }
  410. static inline pmd_t pmd_mkhuge(pmd_t pmd)
  411. {
  412. pmd_val(pmd) = (pmd_val(pmd) & ~(_PAGE_GLOBAL)) |
  413. ((pmd_val(pmd) & _PAGE_GLOBAL) << (_PAGE_HGLOBAL_SHIFT - _PAGE_GLOBAL_SHIFT));
  414. pmd_val(pmd) |= _PAGE_HUGE;
  415. return pmd;
  416. }
  417. #define pmd_write pmd_write
  418. static inline int pmd_write(pmd_t pmd)
  419. {
  420. return !!(pmd_val(pmd) & _PAGE_WRITE);
  421. }
  422. static inline pmd_t pmd_mkwrite_novma(pmd_t pmd)
  423. {
  424. pmd_val(pmd) |= _PAGE_WRITE;
  425. if (pmd_val(pmd) & _PAGE_MODIFIED)
  426. pmd_val(pmd) |= _PAGE_DIRTY;
  427. return pmd;
  428. }
  429. static inline pmd_t pmd_wrprotect(pmd_t pmd)
  430. {
  431. pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
  432. return pmd;
  433. }
  434. #define pmd_dirty pmd_dirty
  435. static inline int pmd_dirty(pmd_t pmd)
  436. {
  437. return !!(pmd_val(pmd) & (_PAGE_DIRTY | _PAGE_MODIFIED));
  438. }
  439. static inline pmd_t pmd_mkclean(pmd_t pmd)
  440. {
  441. pmd_val(pmd) &= ~(_PAGE_DIRTY | _PAGE_MODIFIED);
  442. return pmd;
  443. }
  444. static inline pmd_t pmd_mkdirty(pmd_t pmd)
  445. {
  446. pmd_val(pmd) |= _PAGE_MODIFIED;
  447. if (pmd_val(pmd) & _PAGE_WRITE)
  448. pmd_val(pmd) |= _PAGE_DIRTY;
  449. return pmd;
  450. }
  451. #define pmd_young pmd_young
  452. static inline int pmd_young(pmd_t pmd)
  453. {
  454. return !!(pmd_val(pmd) & _PAGE_ACCESSED);
  455. }
  456. static inline pmd_t pmd_mkold(pmd_t pmd)
  457. {
  458. pmd_val(pmd) &= ~_PAGE_ACCESSED;
  459. return pmd;
  460. }
  461. static inline pmd_t pmd_mkyoung(pmd_t pmd)
  462. {
  463. pmd_val(pmd) |= _PAGE_ACCESSED;
  464. return pmd;
  465. }
  466. static inline struct page *pmd_page(pmd_t pmd)
  467. {
  468. if (pmd_trans_huge(pmd))
  469. return pfn_to_page(pmd_pfn(pmd));
  470. return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
  471. }
  472. static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
  473. {
  474. if (pmd_val(pmd) & _PAGE_DIRTY)
  475. pmd_val(pmd) |= _PAGE_MODIFIED;
  476. return __pmd((pmd_val(pmd) & _HPAGE_CHG_MASK) |
  477. (pgprot_val(newprot) & ~_HPAGE_CHG_MASK));
  478. }
  479. static inline pmd_t pmd_mkinvalid(pmd_t pmd)
  480. {
  481. pmd_val(pmd) |= _PAGE_PRESENT_INVALID;
  482. pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY | _PAGE_PROTNONE);
  483. return pmd;
  484. }
  485. /*
  486. * The generic version pmdp_huge_get_and_clear uses a version of pmd_clear() with a
  487. * different prototype.
  488. */
  489. #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
  490. static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
  491. unsigned long address, pmd_t *pmdp)
  492. {
  493. pmd_t old = pmdp_get(pmdp);
  494. pmd_clear(pmdp);
  495. return old;
  496. }
  497. #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  498. #ifdef CONFIG_NUMA_BALANCING
  499. static inline long pte_protnone(pte_t pte)
  500. {
  501. return (pte_val(pte) & _PAGE_PROTNONE);
  502. }
  503. static inline long pmd_protnone(pmd_t pmd)
  504. {
  505. return (pmd_val(pmd) & _PAGE_PROTNONE);
  506. }
  507. #endif /* CONFIG_NUMA_BALANCING */
  508. #define pmd_leaf(pmd) ((pmd_val(pmd) & _PAGE_HUGE) != 0)
  509. #define pud_leaf(pud) ((pud_val(pud) & _PAGE_HUGE) != 0)
  510. /*
  511. * We provide our own get_unmapped area to cope with the virtual aliasing
  512. * constraints placed on us by the cache architecture.
  513. */
  514. #define HAVE_ARCH_UNMAPPED_AREA
  515. #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
  516. #endif /* !__ASSEMBLER__ */
  517. #endif /* _ASM_PGTABLE_H */