pgalloc.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  4. *
  5. * vineetg: June 2011
  6. * -"/proc/meminfo | grep PageTables" kept on increasing
  7. * Recently added pgtable dtor was not getting called.
  8. *
  9. * vineetg: May 2011
  10. * -Variable pg-sz means that Page Tables could be variable sized themselves
  11. * So calculate it based on addr traversal split [pgd-bits:pte-bits:xxx]
  12. * -Page Table size capped to max 1 to save memory - hence verified.
  13. * -Since these deal with constants, gcc compile-time optimizes them.
  14. *
  15. * vineetg: Nov 2010
  16. * -Added pgtable ctor/dtor used for pgtable mem accounting
  17. *
  18. * vineetg: April 2010
  19. * -Switched pgtable_t from being struct page * to unsigned long
  20. * =Needed so that Page Table allocator (pte_alloc_one) is not forced to
  21. * deal with struct page. That way in future we can make it allocate
  22. * multiple PG Tbls in one Page Frame
  23. * =sweet side effect is avoiding calls to ugly page_address( ) from the
  24. * pg-tlb allocator sub-sys (pte_alloc_one, ptr_free, pmd_populate)
  25. *
  26. * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  27. */
  28. #ifndef _ASM_ARC_PGALLOC_H
  29. #define _ASM_ARC_PGALLOC_H
  30. #include <linux/mm.h>
  31. #include <linux/log2.h>
  32. #include <asm-generic/pgalloc.h>
  33. static inline void
  34. pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
  35. {
  36. /*
  37. * The cast to long below is OK in 32-bit PAE40 regime with long long pte
  38. * Despite "wider" pte, the pte table needs to be in non-PAE low memory
  39. * as all higher levels can only hold long pointers.
  40. *
  41. * The cast itself is needed given simplistic definition of set_pmd()
  42. */
  43. set_pmd(pmd, __pmd((unsigned long)pte));
  44. }
  45. static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte_page)
  46. {
  47. set_pmd(pmd, __pmd((unsigned long)page_address(pte_page)));
  48. }
  49. static inline pgd_t *pgd_alloc(struct mm_struct *mm)
  50. {
  51. pgd_t *ret = (pgd_t *) __get_free_page(GFP_KERNEL);
  52. if (ret) {
  53. int num, num2;
  54. num = USER_PTRS_PER_PGD + USER_KERNEL_GUTTER / PGDIR_SIZE;
  55. memzero(ret, num * sizeof(pgd_t));
  56. num2 = VMALLOC_SIZE / PGDIR_SIZE;
  57. memcpy(ret + num, swapper_pg_dir + num, num2 * sizeof(pgd_t));
  58. memzero(ret + num + num2,
  59. (PTRS_PER_PGD - num - num2) * sizeof(pgd_t));
  60. }
  61. return ret;
  62. }
  63. #if CONFIG_PGTABLE_LEVELS > 3
  64. static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
  65. {
  66. set_p4d(p4dp, __p4d((unsigned long)pudp));
  67. }
  68. #define __pud_free_tlb(tlb, pmd, addr) pud_free((tlb)->mm, pmd)
  69. #endif
  70. #if CONFIG_PGTABLE_LEVELS > 2
  71. static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
  72. {
  73. set_pud(pudp, __pud((unsigned long)pmdp));
  74. }
  75. #define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
  76. #endif
  77. #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
  78. #endif /* _ASM_ARC_PGALLOC_H */