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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1999 Helge Deller (07-13-1999)
  8.  * Copyright (C) 1999 SuSE GmbH Nuernberg
  9.  * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
  10.  *
  11.  * Cache and TLB management
  12.  *
  13.  */
  14.  
  15. #include <linux/init.h>
  16. #include <linux/kernel.h>
  17. #include <linux/mm.h>
  18. #include <asm/pdc.h>
  19. #include <asm/cache.h>
  20. #include <asm/system.h>
  21. #include <asm/page.h>
  22. #include <asm/pgalloc.h>
  23. struct pdc_cache_info cache_info;
  24. #ifndef __LP64__
  25. static struct pdc_btlb_info btlb_info;
  26. #endif
  27. void __flush_page_to_ram(unsigned long address)
  28. {
  29. __flush_dcache_range(address, PAGE_SIZE);
  30. __flush_icache_range(address, PAGE_SIZE);
  31. }
  32. void flush_data_cache(void)
  33. {
  34. register unsigned long base   = cache_info.dc_base;
  35. register unsigned long count  = cache_info.dc_count;
  36. register unsigned long loop   = cache_info.dc_loop;
  37. register unsigned long stride = cache_info.dc_stride;
  38. register unsigned long addr;
  39. register long i, j;
  40. for(i=0,addr=base; i<count; i++,addr+=stride)
  41. for(j=0; j<loop; j++)
  42. fdce(addr);
  43. }
  44. static inline void flush_data_tlb_space(void)
  45. {
  46. unsigned long base   = cache_info.dt_off_base;
  47. unsigned long count  = cache_info.dt_off_count;
  48. unsigned long stride = cache_info.dt_off_stride;
  49. unsigned long loop   = cache_info.dt_loop;
  50. unsigned long addr;
  51. long i,j;
  52. for(i=0,addr=base; i<count; i++,addr+=stride)
  53. for(j=0; j<loop; j++)
  54. pdtlbe(addr);
  55. }
  56. void flush_data_tlb(void)
  57. {
  58. unsigned long base   = cache_info.dt_sp_base;
  59. unsigned long count  = cache_info.dt_sp_count;
  60. unsigned long stride = cache_info.dt_sp_stride;
  61. unsigned long space;
  62. unsigned long old_sr1;
  63. long i;
  64. old_sr1 = mfsp(1);
  65. for(i=0,space=base; i<count; i++, space+=stride) {
  66. mtsp(space,1);
  67. flush_data_tlb_space();
  68. }
  69. mtsp(old_sr1, 1);
  70. }
  71. static inline void flush_instruction_tlb_space(void)
  72. {
  73. unsigned long base   = cache_info.it_off_base;
  74. unsigned long count  = cache_info.it_off_count;
  75. unsigned long stride = cache_info.it_off_stride;
  76. unsigned long loop   = cache_info.it_loop;
  77. unsigned long addr;
  78. long i,j;
  79. for(i=0,addr=base; i<count; i++,addr+=stride)
  80. for(j=0; j<loop; j++)
  81. pitlbe(addr);
  82. }
  83. void flush_instruction_tlb(void)
  84. {
  85. unsigned long base   = cache_info.it_sp_base;
  86. unsigned long count  = cache_info.it_sp_count;
  87. unsigned long stride = cache_info.it_sp_stride;
  88. unsigned long space;
  89. unsigned long old_sr1;
  90. unsigned int i;
  91. old_sr1 = mfsp(1);
  92. for(i=0,space=base; i<count; i++, space+=stride) {
  93. mtsp(space,1);
  94. flush_instruction_tlb_space();
  95. }
  96. mtsp(old_sr1, 1);
  97. }
  98. void __flush_tlb_space(unsigned long space)
  99. {
  100. unsigned long old_sr1;
  101. old_sr1 = mfsp(1);
  102. mtsp(space, 1);
  103. flush_data_tlb_space();
  104. flush_instruction_tlb_space();
  105. mtsp(old_sr1, 1);
  106. }
  107. void flush_instruction_cache(void)
  108. {
  109. register unsigned long base   = cache_info.ic_base;
  110. register unsigned long count  = cache_info.ic_count;
  111. register unsigned long loop   = cache_info.ic_loop;
  112. register unsigned long stride = cache_info.ic_stride;
  113. register unsigned long addr;
  114. register long i, j;
  115. unsigned long old_sr1;
  116. old_sr1 = mfsp(1);
  117. mtsp(0,1);
  118. /*
  119.  * Note: fice instruction has 3 bit space field, so one must
  120.  *       be specified (otherwise you are justing using whatever
  121.  *       happens to be in sr0).
  122.  */
  123. for(i=0,addr=base; i<count; i++,addr+=stride)
  124. for(j=0; j<loop; j++)
  125. fice(addr);
  126. mtsp(old_sr1, 1);
  127. }
  128. /* not yet ... fdc() needs to be implemented in cache.h !
  129. void flush_datacache_range( unsigned int base, unsigned int end )
  130. {
  131.     register long offset,offset_add;
  132.     offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) * 
  133.     cache_info.dc_conf.cc_line ) << 4;
  134.     for (offset=base; offset<=end; offset+=offset_add)
  135. fdc(space,offset);
  136.     fdc(space,end);
  137. }
  138. */
  139. /* flushes code and data-cache */
  140. void flush_all_caches(void)
  141. {
  142. flush_instruction_cache();
  143. flush_data_cache();
  144. flush_instruction_tlb();
  145. flush_data_tlb();
  146. asm volatile("sync");
  147. asm volatile("syncdma");
  148. asm volatile("sync");
  149. }
  150. int get_cache_info(char *buffer)
  151. {
  152. char *p = buffer;
  153. p += sprintf(p, "I-cachett: %ld KBn", 
  154. cache_info.ic_size/1024 );
  155. p += sprintf(p, "D-cachett: %ld KB (%s)%sn", 
  156. cache_info.dc_size/1024,
  157. (cache_info.dc_conf.cc_wt ? "WT":"WB"),
  158. (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
  159. );
  160. p += sprintf(p, "ITLB entriest: %ldn" "DTLB entriest: %ld%sn",
  161. cache_info.it_size,
  162. cache_info.dt_size,
  163. cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
  164. );
  165. #ifndef __LP64__
  166. /* BTLB - Block TLB */
  167. if (btlb_info.max_size==0) {
  168. p += sprintf(p, "BTLBtt: not supportedn" );
  169. } else {
  170. p += sprintf(p, 
  171. "BTLB fixedt: max. %d pages, pagesize=%d (%dMB)n"
  172. "BTLB fix-entr.t: %d instruction, %d data (%d combined)n"
  173. "BTLB var-entr.t: %d instruction, %d data (%d combined)n",
  174. btlb_info.max_size, (int)4096,
  175. btlb_info.max_size>>8,
  176. btlb_info.fixed_range_info.num_i,
  177. btlb_info.fixed_range_info.num_d,
  178. btlb_info.fixed_range_info.num_comb, 
  179. btlb_info.variable_range_info.num_i,
  180. btlb_info.variable_range_info.num_d,
  181. btlb_info.variable_range_info.num_comb
  182. );
  183. }
  184. #endif
  185. return p - buffer;
  186. }
  187. void __init 
  188. cache_init(void)
  189. {
  190. if(pdc_cache_info(&cache_info)<0)
  191. panic("cache_init: pdc_cache_info failed");
  192. #if 0
  193. printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %dn",
  194.     cache_info.ic_size,
  195.     cache_info.dc_size,
  196.     cache_info.it_size,
  197.     sizeof (struct pdc_cache_info) / sizeof (long),
  198.     sizeof (struct pdc_cache_cf)
  199. );
  200. #endif
  201. #ifndef __LP64__
  202. if(pdc_btlb_info(&btlb_info)<0) {
  203. memset(&btlb_info, 0, sizeof btlb_info);
  204. }
  205. #endif
  206. }