pgalloc.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #ifndef _X86_64_PGALLOC_H
  2. #define _X86_64_PGALLOC_H
  3. #include <asm/pda.h>
  4. #include <linux/threads.h>
  5. #include <linux/mm.h>
  6. #include <linux/quicklist.h>
  7. #define QUICK_PGD 0 /* We preserve special mappings over free */
  8. #define QUICK_PT 1 /* Other page table pages that are zero on free */
  9. #define pmd_populate_kernel(mm, pmd, pte) \
  10. set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
  11. #define pud_populate(mm, pud, pmd) \
  12. set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
  13. #define pgd_populate(mm, pgd, pud) \
  14. set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)))
  15. static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
  16. {
  17. set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
  18. }
  19. static inline void pmd_free(pmd_t *pmd)
  20. {
  21. BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
  22. quicklist_free(QUICK_PT, NULL, pmd);
  23. }
  24. static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
  25. {
  26. return (pmd_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
  27. }
  28. static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
  29. {
  30. return (pud_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
  31. }
  32. static inline void pud_free (pud_t *pud)
  33. {
  34. BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
  35. quicklist_free(QUICK_PT, NULL, pud);
  36. }
  37. static inline void pgd_list_add(pgd_t *pgd)
  38. {
  39. struct page *page = virt_to_page(pgd);
  40. spin_lock(&pgd_lock);
  41. list_add(&page->lru, &pgd_list);
  42. spin_unlock(&pgd_lock);
  43. }
  44. static inline void pgd_list_del(pgd_t *pgd)
  45. {
  46. struct page *page = virt_to_page(pgd);
  47. spin_lock(&pgd_lock);
  48. list_del(&page->lru);
  49. spin_unlock(&pgd_lock);
  50. }
  51. static inline void pgd_ctor(void *x)
  52. {
  53. unsigned boundary;
  54. pgd_t *pgd = x;
  55. struct page *page = virt_to_page(pgd);
  56. /*
  57. * Copy kernel pointers in from init.
  58. */
  59. boundary = pgd_index(__PAGE_OFFSET);
  60. memcpy(pgd + boundary,
  61. init_level4_pgt + boundary,
  62. (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
  63. spin_lock(&pgd_lock);
  64. list_add(&page->lru, &pgd_list);
  65. spin_unlock(&pgd_lock);
  66. }
  67. static inline void pgd_dtor(void *x)
  68. {
  69. pgd_t *pgd = x;
  70. struct page *page = virt_to_page(pgd);
  71. spin_lock(&pgd_lock);
  72. list_del(&page->lru);
  73. spin_unlock(&pgd_lock);
  74. }
  75. static inline pgd_t *pgd_alloc(struct mm_struct *mm)
  76. {
  77. pgd_t *pgd = (pgd_t *)quicklist_alloc(QUICK_PGD,
  78. GFP_KERNEL|__GFP_REPEAT, pgd_ctor);
  79. return pgd;
  80. }
  81. static inline void pgd_free(pgd_t *pgd)
  82. {
  83. BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
  84. quicklist_free(QUICK_PGD, pgd_dtor, pgd);
  85. }
  86. static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
  87. {
  88. return (pte_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
  89. }
  90. static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
  91. {
  92. void *p = (void *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL);
  93. if (!p)
  94. return NULL;
  95. return virt_to_page(p);
  96. }
  97. /* Should really implement gc for free page table pages. This could be
  98. done with a reference count in struct page. */
  99. static inline void pte_free_kernel(pte_t *pte)
  100. {
  101. BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
  102. quicklist_free(QUICK_PT, NULL, pte);
  103. }
  104. static inline void pte_free(struct page *pte)
  105. {
  106. quicklist_free_page(QUICK_PT, NULL, pte);
  107. }
  108. #define __pte_free_tlb(tlb,pte) quicklist_free_page(QUICK_PT, NULL,(pte))
  109. #define __pmd_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x))
  110. #define __pud_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x))
  111. static inline void check_pgt_cache(void)
  112. {
  113. quicklist_trim(QUICK_PGD, pgd_dtor, 25, 16);
  114. quicklist_trim(QUICK_PT, NULL, 25, 16);
  115. }
  116. #endif /* _X86_64_PGALLOC_H */