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

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _ASM_PGALLOC_H
  2. #define _ASM_PGALLOC_H
  3. /* The usual comment is "Caches aren't brain-dead on the <architecture>".
  4.  * Unfortunately, that doesn't apply to PA-RISC. */
  5. #include <asm/processor.h>
  6. #include <asm/fixmap.h>
  7. #include <linux/threads.h>
  8. #include <asm/pgtable.h>
  9. #include <asm/cache.h>
  10. /* Internal use D/I cache flushing routines... */
  11. /* XXX: these functions must not access memory between f[di]ce instructions. */
  12. static inline void __flush_dcache_range(unsigned long start, unsigned long size)
  13. {
  14. #if 0
  15. register unsigned long count = (size / L1_CACHE_BYTES);
  16. register unsigned long loop = cache_info.dc_loop;
  17. register unsigned long i, j;
  18. if (size > 64 * 1024) {
  19. /* Just punt and clear the whole damn thing */
  20. flush_data_cache();
  21. return;
  22. }
  23. for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)
  24. for(j = 0; j < loop; j++)
  25. fdce(start);
  26. #else
  27. flush_data_cache();
  28. #endif
  29. }
  30. static inline void __flush_icache_range(unsigned long start, unsigned long size)
  31. {
  32. #if 0
  33. register unsigned long count = (size / L1_CACHE_BYTES);
  34. register unsigned long loop = cache_info.ic_loop;
  35. register unsigned long i, j;
  36. if (size > 64 * 1024) {
  37. /* Just punt and clear the whole damn thing */
  38. flush_instruction_cache();
  39. return;
  40. }
  41. for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)
  42. for(j = 0; j < loop; j++)
  43. fice(start);
  44. #else
  45. flush_instruction_cache();
  46. #endif
  47. }
  48. static inline void
  49. flush_kernel_dcache_range(unsigned long start, unsigned long size)
  50. {
  51. register unsigned long end = start + size;
  52. register unsigned long i;
  53. start &= ~(L1_CACHE_BYTES - 1);
  54. for (i = start; i < end; i += L1_CACHE_BYTES) {
  55. kernel_fdc(i);
  56. }
  57. asm volatile("sync" : : );
  58. asm volatile("syncdma" : : );
  59. }
  60. extern void __flush_page_to_ram(unsigned long address);
  61. #define flush_cache_all() flush_all_caches()
  62. #define flush_cache_mm(foo) flush_all_caches()
  63. #if 0
  64. /* This is how I think the cache flushing should be done -- mrw */
  65. extern inline void flush_cache_mm(struct mm_struct *mm) {
  66. if (mm == current->mm) {
  67. flush_user_dcache_range(mm->start_data, mm->end_data);
  68. flush_user_icache_range(mm->start_code, mm->end_code);
  69. } else {
  70. flush_other_dcache_range(mm->context, mm->start_data, mm->end_data);
  71. flush_other_icache_range(mm->context, mm->start_code, mm->end_code);
  72. }
  73. }
  74. #endif
  75. #define flush_cache_range(mm, start, end) do { 
  76.                 __flush_dcache_range(start, (unsigned long)end - (unsigned long)start); 
  77.                 __flush_icache_range(start, (unsigned long)end - (unsigned long)start); 
  78. } while(0)
  79. #define flush_cache_page(vma, vmaddr) do { 
  80.                 __flush_dcache_range(vmaddr, PAGE_SIZE); 
  81.                 __flush_icache_range(vmaddr, PAGE_SIZE); 
  82. } while(0)
  83. #define flush_page_to_ram(page)
  84.         __flush_page_to_ram((unsigned long)page_address(page))
  85. #define flush_icache_range(start, end) 
  86.         __flush_icache_range(start, end - start)
  87. #define flush_icache_page(vma, page) 
  88. __flush_icache_range(page_address(page), PAGE_SIZE)
  89. #define flush_dcache_page(page) 
  90. __flush_dcache_range(page_address(page), PAGE_SIZE)
  91. /* TLB flushing routines.... */
  92. extern void flush_data_tlb(void);
  93. extern void flush_instruction_tlb(void);
  94. #define flush_tlb() do { 
  95.         flush_data_tlb(); 
  96. flush_instruction_tlb(); 
  97. } while(0);
  98. #define flush_tlb_all()  flush_tlb() /* XXX p[id]tlb */
  99. extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
  100. {
  101. }
  102.  
  103. static inline void flush_instruction_tlb_range(unsigned long start,
  104. unsigned long size)
  105. {
  106. #if 0
  107. register unsigned long count = (size / PAGE_SIZE);
  108. register unsigned long loop = cache_info.it_loop;
  109. register unsigned long i, j;
  110. for(i = 0; i <= count; i++, start += PAGE_SIZE)
  111. for(j = 0; j < loop; j++)
  112. pitlbe(start);
  113. #else
  114. flush_instruction_tlb();
  115. #endif
  116. }
  117. static inline void flush_data_tlb_range(unsigned long start,
  118. unsigned long size)
  119. {
  120. #if 0
  121. register unsigned long count = (size / PAGE_SIZE);
  122. register unsigned long loop = cache_info.dt_loop;
  123. register unsigned long i, j;
  124. for(i = 0; i <= count; i++, start += PAGE_SIZE)
  125. for(j = 0; j < loop; j++)
  126. pdtlbe(start);
  127. #else
  128. flush_data_tlb();
  129. #endif
  130. }
  131. static inline void __flush_tlb_range(unsigned long space, unsigned long start,
  132.        unsigned long size)
  133. {
  134. unsigned long old_sr1;
  135. if(!size)
  136. return;
  137. old_sr1 = mfsp(1);
  138. mtsp(space, 1);
  139. flush_data_tlb_range(start, size);
  140. flush_instruction_tlb_range(start, size);
  141. mtsp(old_sr1, 1);
  142. }
  143. extern void __flush_tlb_space(unsigned long space);
  144. static inline void flush_tlb_mm(struct mm_struct *mm)
  145. {
  146. #if 0
  147. __flush_tlb_space(mm->context);
  148. #else
  149. flush_tlb();
  150. #endif
  151. }
  152. static inline void flush_tlb_page(struct vm_area_struct *vma,
  153. unsigned long addr)
  154. {
  155. __flush_tlb_range(vma->vm_mm->context, addr, PAGE_SIZE);
  156. }
  157. static inline void flush_tlb_range(struct mm_struct *mm,
  158. unsigned long start, unsigned long end)
  159. {
  160. __flush_tlb_range(mm->context, start, end - start);
  161. }
  162. /*
  163.  * NOTE: Many of the below macros use PT_NLEVELS because
  164.  *       it is convenient that PT_NLEVELS == LOG2(pte size in bytes),
  165.  *       i.e. we use 3 level page tables when we use 8 byte pte's
  166.  *       (for 64 bit) and 2 level page tables when we use 4 byte pte's
  167.  */
  168. #ifdef __LP64__
  169. #define PT_NLEVELS 3
  170. #define PT_INITIAL 4 /* Number of initial page tables */
  171. #else
  172. #define PT_NLEVELS 2
  173. #define PT_INITIAL 2 /* Number of initial page tables */
  174. #endif
  175. /* Definitions for 1st level */
  176. #define PGDIR_SHIFT  (PAGE_SHIFT + (PT_NLEVELS - 1)*(PAGE_SHIFT - PT_NLEVELS))
  177. #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
  178. #define PGDIR_MASK (~(PGDIR_SIZE-1))
  179. #define PTRS_PER_PGD    (1UL << (PAGE_SHIFT - PT_NLEVELS))
  180. #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
  181. /* Definitions for 2nd level */
  182. #define PMD_SHIFT       (PAGE_SHIFT + (PAGE_SHIFT - PT_NLEVELS))
  183. #define PMD_SIZE (1UL << PMD_SHIFT)
  184. #define PMD_MASK (~(PMD_SIZE-1))
  185. #if PT_NLEVELS == 3
  186. #define PTRS_PER_PMD    (1UL << (PAGE_SHIFT - PT_NLEVELS))
  187. #else
  188. #define PTRS_PER_PMD    1
  189. #endif
  190. /* Definitions for 3rd level */
  191. #define PTRS_PER_PTE    (1UL << (PAGE_SHIFT - PT_NLEVELS))
  192. #define get_pgd_fast get_pgd_slow
  193. #define free_pgd_fast free_pgd_slow
  194. extern __inline__ pgd_t *get_pgd_slow(void)
  195. {
  196. extern unsigned long gateway_pgd_offset;
  197. extern unsigned long gateway_pgd_entry;
  198. pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
  199. if (ret) {
  200.     memset (ret, 0, PTRS_PER_PGD * sizeof(pgd_t));
  201.     /* Install HP-UX and Linux gateway page translations */
  202.     pgd_val(*(ret + gateway_pgd_offset)) = gateway_pgd_entry;
  203. }
  204. return ret;
  205. }
  206. extern __inline__ void free_pgd_slow(pgd_t *pgd)
  207. {
  208. free_page((unsigned long)pgd);
  209. }
  210. #if PT_NLEVELS == 3
  211. /* Three Level Page Table Support for pmd's */
  212. extern __inline__ pmd_t *get_pmd_fast(void)
  213. {
  214. return NULL; /* la la */
  215. }
  216. #if 0
  217. extern __inline__ void free_pmd_fast(pmd_t *pmd)
  218. {
  219. }
  220. #else
  221. #define free_pmd_fast free_pmd_slow
  222. #endif
  223. extern __inline__ pmd_t *get_pmd_slow(void)
  224. {
  225. pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
  226. if (pmd)
  227. clear_page(pmd);
  228. return pmd;
  229. }
  230. extern __inline__ void free_pmd_slow(pmd_t *pmd)
  231. {
  232. free_page((unsigned long)pmd);
  233. }
  234. extern void __bad_pgd(pgd_t *pgd);
  235. extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
  236. {
  237. address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
  238. if (pgd_none(*pgd))
  239. goto getnew;
  240. if (pgd_bad(*pgd))
  241. goto fix;
  242. return (pmd_t *) pgd_page(*pgd) + address;
  243. getnew:
  244. {
  245. pmd_t *page = get_pmd_fast();
  246. if (!page)
  247. page = get_pmd_slow();
  248. if (page) {
  249. if (pgd_none(*pgd)) {
  250.     pgd_val(*pgd) = _PAGE_TABLE + __pa((unsigned long)page);
  251.     return page + address;
  252. }
  253. else
  254.     free_pmd_fast(page);
  255. }
  256. else {
  257. return NULL;
  258. }
  259. }
  260. fix:
  261. __bad_pgd(pgd);
  262. return NULL;
  263. }
  264. #else
  265. /* Two Level Page Table Support for pmd's */
  266. extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
  267. {
  268. return (pmd_t *) pgd;
  269. }
  270. extern inline void free_pmd_fast(pmd_t * pmd)
  271. {
  272. }
  273. #endif
  274. extern __inline__ pte_t *get_pte_fast(void)
  275. {
  276. return NULL; /* la la */
  277. }
  278. #if 0
  279. extern __inline__ void free_pte_fast(pte_t *pte)
  280. {
  281. }
  282. #else
  283. #define free_pte_fast free_pte_slow
  284. #endif
  285. extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
  286. extern __inline__ void free_pte_slow(pte_t *pte)
  287. {
  288. free_page((unsigned long)pte);
  289. }
  290. #define pmd_alloc_kernel pmd_alloc
  291. #define pte_alloc_kernel pte_alloc
  292. #define pte_free(pte) free_pte_fast(pte)
  293. #define pmd_free(pmd)           free_pmd_fast(pmd)
  294. #define pgd_free(pgd) free_pgd_fast(pgd)
  295. #define pgd_alloc(mm) get_pgd_fast()
  296. extern void __bad_pmd(pmd_t *pmd);
  297. extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  298. {
  299. address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  300. if (pmd_none(*pmd))
  301. goto getnew;
  302. if (pmd_bad(*pmd))
  303. goto fix;
  304. return (pte_t *) pmd_page(*pmd) + address;
  305. getnew:
  306. {
  307. pte_t *page = get_pte_fast();
  308. if (!page)
  309. return get_pte_slow(pmd, address);
  310. pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)page);
  311. return page + address;
  312. }
  313. fix:
  314. __bad_pmd(pmd);
  315. return NULL;
  316. }
  317. extern int do_check_pgt_cache(int, int);
  318. #endif