pgalloc.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _I386_PGALLOC_H
  2. #define _I386_PGALLOC_H
  3. #include <linux/config.h>
  4. #include <asm/processor.h>
  5. #include <asm/fixmap.h>
  6. #include <linux/threads.h>
  7. #define pgd_quicklist (current_cpu_data.pgd_quick)
  8. #define pmd_quicklist (current_cpu_data.pmd_quick)
  9. #define pte_quicklist (current_cpu_data.pte_quick)
  10. #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
  11. #define pmd_populate(mm, pmd, pte) 
  12. set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
  13. /*
  14.  * Allocate and free page tables.
  15.  */
  16. #if defined (CONFIG_X86_PAE)
  17. /*
  18.  * We can't include <linux/slab.h> here, thus these uglinesses.
  19.  */
  20. struct kmem_cache_s;
  21. extern struct kmem_cache_s *pae_pgd_cachep;
  22. extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
  23. extern void kmem_cache_free(struct kmem_cache_s *, void *);
  24. static inline pgd_t *get_pgd_slow(void)
  25. {
  26. int i;
  27. pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
  28. if (pgd) {
  29. for (i = 0; i < USER_PTRS_PER_PGD; i++) {
  30. unsigned long pmd = __get_free_page(GFP_KERNEL);
  31. if (!pmd)
  32. goto out_oom;
  33. clear_page(pmd);
  34. set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
  35. }
  36. memcpy(pgd + USER_PTRS_PER_PGD,
  37. swapper_pg_dir + USER_PTRS_PER_PGD,
  38. (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
  39. }
  40. return pgd;
  41. out_oom:
  42. for (i--; i >= 0; i--)
  43. free_page((unsigned long)__va(pgd_val(pgd[i])-1));
  44. kmem_cache_free(pae_pgd_cachep, pgd);
  45. return NULL;
  46. }
  47. #else
  48. static inline pgd_t *get_pgd_slow(void)
  49. {
  50. pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
  51. if (pgd) {
  52. memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
  53. memcpy(pgd + USER_PTRS_PER_PGD,
  54. swapper_pg_dir + USER_PTRS_PER_PGD,
  55. (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
  56. }
  57. return pgd;
  58. }
  59. #endif /* CONFIG_X86_PAE */
  60. static inline pgd_t *get_pgd_fast(void)
  61. {
  62. unsigned long *ret;
  63. if ((ret = pgd_quicklist) != NULL) {
  64. pgd_quicklist = (unsigned long *)(*ret);
  65. ret[0] = 0;
  66. pgtable_cache_size--;
  67. } else
  68. ret = (unsigned long *)get_pgd_slow();
  69. return (pgd_t *)ret;
  70. }
  71. static inline void free_pgd_fast(pgd_t *pgd)
  72. {
  73. *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
  74. pgd_quicklist = (unsigned long *) pgd;
  75. pgtable_cache_size++;
  76. }
  77. static inline void free_pgd_slow(pgd_t *pgd)
  78. {
  79. #if defined(CONFIG_X86_PAE)
  80. int i;
  81. for (i = 0; i < USER_PTRS_PER_PGD; i++)
  82. free_page((unsigned long)__va(pgd_val(pgd[i])-1));
  83. kmem_cache_free(pae_pgd_cachep, pgd);
  84. #else
  85. free_page((unsigned long)pgd);
  86. #endif
  87. }
  88. static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
  89. {
  90. pte_t *pte;
  91. pte = (pte_t *) __get_free_page(GFP_KERNEL);
  92. if (pte)
  93. clear_page(pte);
  94. return pte;
  95. }
  96. static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
  97. unsigned long address)
  98. {
  99. unsigned long *ret;
  100. if ((ret = (unsigned long *)pte_quicklist) != NULL) {
  101. pte_quicklist = (unsigned long *)(*ret);
  102. ret[0] = ret[1];
  103. pgtable_cache_size--;
  104. }
  105. return (pte_t *)ret;
  106. }
  107. static inline void pte_free_fast(pte_t *pte)
  108. {
  109. *(unsigned long *)pte = (unsigned long) pte_quicklist;
  110. pte_quicklist = (unsigned long *) pte;
  111. pgtable_cache_size++;
  112. }
  113. static __inline__ void pte_free_slow(pte_t *pte)
  114. {
  115. free_page((unsigned long)pte);
  116. }
  117. #define pte_free(pte) pte_free_slow(pte)
  118. #define pgd_free(pgd) free_pgd_slow(pgd)
  119. #define pgd_alloc(mm) get_pgd_fast()
  120. /*
  121.  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  122.  * inside the pgd, so has no extra memory associated with it.
  123.  * (In the PAE case we free the pmds as part of the pgd.)
  124.  */
  125. #define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); })
  126. #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
  127. #define pmd_free_slow(x) do { } while (0)
  128. #define pmd_free_fast(x) do { } while (0)
  129. #define pmd_free(x) do { } while (0)
  130. #define pgd_populate(mm, pmd, pte) BUG()
  131. extern int do_check_pgt_cache(int, int);
  132. /*
  133.  * TLB flushing:
  134.  *
  135.  *  - flush_tlb() flushes the current mm struct TLBs
  136.  *  - flush_tlb_all() flushes all processes TLBs
  137.  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  138.  *  - flush_tlb_page(vma, vmaddr) flushes one page
  139.  *  - flush_tlb_range(mm, start, end) flushes a range of pages
  140.  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  141.  *
  142.  * ..but the i386 has somewhat limited tlb flushing capabilities,
  143.  * and page-granular flushes are available only on i486 and up.
  144.  */
  145. #ifndef CONFIG_SMP
  146. #define flush_tlb() __flush_tlb()
  147. #define flush_tlb_all() __flush_tlb_all()
  148. #define local_flush_tlb() __flush_tlb()
  149. static inline void flush_tlb_mm(struct mm_struct *mm)
  150. {
  151. if (mm == current->active_mm)
  152. __flush_tlb();
  153. }
  154. static inline void flush_tlb_page(struct vm_area_struct *vma,
  155. unsigned long addr)
  156. {
  157. if (vma->vm_mm == current->active_mm)
  158. __flush_tlb_one(addr);
  159. }
  160. static inline void flush_tlb_range(struct mm_struct *mm,
  161. unsigned long start, unsigned long end)
  162. {
  163. if (mm == current->active_mm)
  164. __flush_tlb();
  165. }
  166. #else
  167. #include <asm/smp.h>
  168. #define local_flush_tlb() 
  169. __flush_tlb()
  170. extern void flush_tlb_all(void);
  171. extern void flush_tlb_current_task(void);
  172. extern void flush_tlb_mm(struct mm_struct *);
  173. extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
  174. #define flush_tlb() flush_tlb_current_task()
  175. static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, unsigned long end)
  176. {
  177. flush_tlb_mm(mm);
  178. }
  179. #define TLBSTATE_OK 1
  180. #define TLBSTATE_LAZY 2
  181. struct tlb_state
  182. {
  183. struct mm_struct *active_mm;
  184. int state;
  185. };
  186. extern struct tlb_state cpu_tlbstate[NR_CPUS];
  187. #endif
  188. static inline void flush_tlb_pgtables(struct mm_struct *mm,
  189.       unsigned long start, unsigned long end)
  190. {
  191. /* i386 does not keep any page table caches in TLB */
  192. }
  193. #endif /* _I386_PGALLOC_H */