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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  3.  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
  4.  * Copyright (C) 2000 Sibyte
  5.  * 
  6.  * Written by Justin Carlson (carlson@sibyte.com)
  7.  *
  8.  *
  9.  * This program is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License
  11.  * as published by the Free Software Foundation; either version 2
  12.  * of the License, or (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  * 
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.  */ 
  23. /*
  24.  * In this entire file, I'm not sure what the role of the L2 on the sb1250 
  25.  * is.  Since it is coherent to the system, we should never need to flush
  26.  * it...right?...right???  -JDC
  27.  */
  28. #include <asm/mmu_context.h>
  29. /* These are probed at ld_mmu time */
  30. static unsigned int icache_size;
  31. static unsigned int dcache_size;
  32. static unsigned int icache_line_size;
  33. static unsigned int dcache_line_size;
  34. static unsigned int icache_assoc;
  35. static unsigned int dcache_assoc;
  36. static unsigned int icache_sets;
  37. static unsigned int dcache_sets;
  38. static unsigned int tlb_entries;
  39. void pgd_init(unsigned long page)
  40. {
  41. unsigned long *p = (unsigned long *) page;
  42. int i;
  43. for (i = 0; i < USER_PTRS_PER_PGD; i+=8) {
  44. p[i + 0] = (unsigned long) invalid_pte_table;
  45. p[i + 1] = (unsigned long) invalid_pte_table;
  46. p[i + 2] = (unsigned long) invalid_pte_table;
  47. p[i + 3] = (unsigned long) invalid_pte_table;
  48. p[i + 4] = (unsigned long) invalid_pte_table;
  49. p[i + 5] = (unsigned long) invalid_pte_table;
  50. p[i + 6] = (unsigned long) invalid_pte_table;
  51. p[i + 7] = (unsigned long) invalid_pte_table;
  52. }
  53. }
  54. void flush_tlb_all(void)
  55. {
  56. unsigned long flags;
  57. unsigned long old_ctx;
  58. int entry;
  59. __save_and_cli(flags);
  60. /* Save old context and create impossible VPN2 value */
  61. old_ctx = (get_entryhi() & 0xff);
  62. set_entrylo0(0);
  63. set_entrylo1(0);
  64. for (entry = 0; entry < tlb_entries; entry++) {
  65. set_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry);
  66. set_index(entry);
  67. tlb_write_indexed();
  68. }
  69. set_entryhi(old_ctx);
  70. __restore_flags(flags);
  71. }
  72. /* These are the functions hooked by the memory management function pointers */
  73. static void sb1_clear_page(void *page)
  74. {
  75. /* JDCXXX - This should be bottlenecked by the write buffer, but these
  76.    things tend to be mildly unpredictable...should check this on the
  77.    performance model */
  78. /* We prefetch 4 lines ahead.  We're also "cheating" slightly here...
  79.    since we know we're on an SB1, we force the assembler to take 
  80.    64-bit operands to speed things up */
  81. __asm__ __volatile__(
  82. ".set push                  n"
  83. ".set noreorder             n"
  84. ".set noat                  n"
  85. ".set mips4                 n"
  86. "     addiu     $1, %0, %2  n"  /* Calculate the end of the page to clear */
  87. "     pref       5,  0(%0)  n"  /* Prefetch the first 4 lines */
  88. "     pref       5, 32(%0)  n"  
  89. "     pref       5, 64(%0)  n"  
  90. "     pref       5, 96(%0)  n"  
  91. "1:   sd        $0,  0(%0)  n"  /* Throw out a cacheline of 0's */
  92. "     sd        $0,  8(%0)  n"
  93. "     sd        $0, 16(%0)  n"
  94. "     sd        $0, 24(%0)  n"
  95. "     pref       5,128(%0)  n"  /* Prefetch 4 lines ahead     */
  96. "     bne       $1, %0, 1b  n"
  97. "     addiu     %0, %0, 32  n"  /* Next cacheline (This instruction better be short piped!) */
  98. ".set pop                   n"
  99. :"=r" (page)
  100. :"0" (page),
  101.  "I" (PAGE_SIZE-32)
  102. :"$1","memory");
  103. }
  104. static void sb1_copy_page(void *to, void *from)
  105. {
  106. /* This should be optimized in assembly...can't use ld/sd, though,
  107.  * because the top 32 bits could be nuked if we took an interrupt
  108.  * during the routine.  And this is not a good place to be cli()'ing
  109.  */
  110. /* The pref's used here are using "streaming" hints, which cause the
  111.  * copied data to be kicked out of the cache sooner.  A page copy often
  112.  * ends up copying a lot more data than is commonly used, so this seems
  113.  * to make sense in terms of reducing cache pollution, but I've no real
  114.  * performance data to back this up
  115.  */ 
  116. __asm__ __volatile__(
  117. ".set push                  n"
  118. ".set noreorder             n"
  119. ".set noat                  n"
  120. ".set mips4                 n"
  121. "     addiu     $1, %0, %4  n"  /* Calculate the end of the page to copy */
  122. "     pref       4,  0(%0)  n"  /* Prefetch the first 3 lines to be read and copied */
  123. "     pref       5,  0(%1)  n"  
  124. "     pref       4, 32(%0)  n"  
  125. "     pref       5, 32(%1)  n"  
  126. "     pref       4, 64(%0)  n"  
  127. "     pref       5, 64(%1)  n"  
  128. "1:   lw        $2,  0(%0)  n"  /* Block copy a cacheline */
  129. "     lw        $3,  4(%0)  n"
  130. "     lw        $4,  8(%0)  n"
  131. "     lw        $5, 12(%0)  n"
  132. "     lw        $6, 16(%0)  n"
  133. "     lw        $7, 20(%0)  n"
  134. "     lw        $8, 24(%0)  n"
  135. "     lw        $9, 28(%0)  n"
  136. "     pref       4, 96(%0)  n"  /* Prefetch ahead         */
  137. "     pref       5, 96(%1)  n"
  138. "     sw        $2,  0(%1)  n"  
  139. "     sw        $3,  4(%1)  n"
  140. "     sw        $4,  8(%1)  n"
  141. "     sw        $5, 12(%1)  n"
  142. "     sw        $6, 16(%1)  n"
  143. "     sw        $7, 20(%1)  n"
  144. "     sw        $8, 24(%1)  n"
  145. "     sw        $9, 28(%1)  n"
  146. "     addiu     %1, %1, 32  n"  /* Next cacheline */
  147. "     nop                   n"  /* Force next add to short pipe */
  148. "     nop                   n"  /* Force next add to short pipe */
  149. "     bne       $1, %0, 1b  n"
  150. "     addiu     %0, %0, 32  n"  /* Next cacheline */
  151. ".set pop                   n" 
  152. :"=r" (to),
  153. "=r" (from)
  154. :
  155. "0" (from),
  156. "1" (to),
  157. "I" (PAGE_SIZE-32)
  158. :"$1","$2","$3","$4","$5","$6","$7","$8","$9","memory");
  159. /*
  160. unsigned long *src = from;
  161. unsigned long *dest = to;
  162. unsigned long *target = (unsigned long *) (((unsigned long)src) + PAGE_SIZE);
  163. while (src != target) {
  164. *dest++ = *src++;
  165. }
  166. */
  167. }
  168. /*
  169.  * The dcache is fully coherent to the system, with one
  170.  * big caveat:  the instruction stream.  In other words,
  171.  * if we miss in the icache, and have dirty data in the
  172.  * L1 dcache, then we'll go out to memory (or the L2) and
  173.  * get the not-as-recent data.
  174.  * 
  175.  * So the only time we have to flush the dcache is when
  176.  * we're flushing the icache.  Since the L2 is fully
  177.  * coherent to everything, including I/O, we never have
  178.  * to flush it
  179.  */
  180. static void sb1_flush_cache_all(void)
  181. {
  182. /*
  183.  * Haven't worried too much about speed here; given that we're flushing
  184.  * the icache, the time to invalidate is dwarfed by the time it's going
  185.  * to take to refill it.  Register usage:
  186.  * 
  187.  * $1 - moving cache index
  188.  * $2 - set count
  189.  */
  190. if (icache_sets) { 
  191. __asm__ __volatile__ (
  192. ".set push                  n"
  193. ".set noreorder             n"
  194. ".set noat                  n"
  195. ".set mips4                 n"
  196. "     move   $1, %2         n" /* Start at index 0 */
  197.                         "1:   cache  0, 0($1)       n" /* Invalidate this index */
  198. "     addiu  %1, %1, -1     n" /* Decrement loop count */
  199. "     bnez   %1, 1b         n" /* loop test */
  200. "     addu   $1, $1, %0     n" /* Next address JDCXXX - Should be short piped */
  201. ".set pop                   n"
  202. ::"r" (icache_line_size),
  203. "r" (icache_sets * icache_assoc),
  204. "r" (KSEG0)
  205. :"$1");
  206. }
  207. if (dcache_sets) {
  208. __asm__ __volatile__ (
  209. ".set push                  n"
  210. ".set noreorder             n"
  211. ".set noat                  n"
  212. ".set mips4                 n"
  213. "     move   $1, %2         n" /* Start at index 0 */
  214.                         "1:   cache  0x1, 0($1)     n" /* WB/Invalidate this index */
  215. "     addiu  %1, %1, -1     n" /* Decrement loop count */
  216. "     bnez   %1, 1b         n" /* loop test */
  217. "     addu   $1, $1, %0     n" /* Next address JDCXXX - Should be short piped */
  218. ".set pop                   n"
  219. ::"r" (dcache_line_size),
  220. "r" (dcache_sets * dcache_assoc),
  221. "r" (KSEG0)
  222. :"$1");
  223. }
  224. }
  225. /*
  226.  * When flushing a range in the icache, we have to first writeback
  227.  * the dcache for the same range, so new ifetches will see any
  228.  * data that was dirty in the dcache
  229.  */
  230. static void sb1_flush_icache_range(unsigned long start, unsigned long end)
  231. {
  232. /* JDCXXX - Implement me! */
  233. sb1_flush_cache_all();
  234. }
  235. static void sb1_flush_cache_mm(struct mm_struct *mm)
  236. {
  237. /* Don't need to do this, as the dcache is physically tagged */
  238. }
  239. static void sb1_flush_cache_range(struct mm_struct *mm, 
  240.   unsigned long start,
  241.   unsigned long end)
  242. {
  243. /* Don't need to do this, as the dcache is physically tagged */
  244. }
  245. static void sb1_flush_cache_sigtramp(unsigned long page)
  246. {
  247. /* JDCXXX - Implement me! */
  248. sb1_flush_cache_all();
  249. }
  250. /*
  251.  * This only needs to make sure stores done up to this
  252.  * point are visible to other agents outside the CPU.  Given 
  253.  * the coherent nature of the ZBus, all that's required here is 
  254.  * a sync to make sure the data gets out to the caches and is
  255.  * visible to an arbitrary A Phase from an external agent 
  256.  *   
  257.  * Actually, I'm not even sure that's necessary; the semantics
  258.  * of this function aren't clear.  If it's supposed to serve as
  259.  * a memory barrier, this is needed.  If it's only meant to 
  260.  * prevent data from being invisible to non-cpu memory accessors
  261.  * for some indefinite period of time (e.g. in a non-coherent 
  262.  * dcache) then this function would be a complete nop.
  263.  */
  264. static void sb1_flush_page_to_ram(struct page *page)
  265. {
  266. __asm__ __volatile__(
  267. "     sync  n"  /* Short pipe */
  268. :::"memory");
  269. }
  270. /* Cribbed from the r2300 code */
  271. static void sb1_flush_cache_page(struct vm_area_struct *vma,
  272.   unsigned long page)
  273. {
  274. sb1_flush_cache_all();
  275. #if 0
  276. struct mm_struct *mm = vma->vm_mm;
  277. unsigned long physpage;
  278. /* No icache flush needed without context; */
  279. if (mm->context == 0) 
  280. return;  
  281. /* No icache flush needed if the page isn't executable */
  282. if (!(vma->vm_flags & VM_EXEC))
  283. return;
  284. physpage = (unsigned long) page_address(page);
  285. if (physpage)
  286. sb1_flush_icache_range(physpage, physpage + PAGE_SIZE);
  287. #endif
  288. }
  289. /*
  290.  *  Cache set values (from the mips64 spec)
  291.  * 0 - 64
  292.  * 1 - 128
  293.  * 2 - 256
  294.  * 3 - 512
  295.  * 4 - 1024
  296.  * 5 - 2048
  297.  * 6 - 4096
  298.  * 7 - Reserved
  299.  */
  300. static unsigned int decode_cache_sets(unsigned int config_field)
  301. {
  302. if (config_field == 7) {
  303. /* JDCXXX - Find a graceful way to abort. */
  304. return 0;
  305. return (1<<(config_field + 6));
  306. }
  307. /*
  308.  *  Cache line size values (from the mips64 spec)
  309.  * 0 - No cache present.
  310.  * 1 - 4 bytes
  311.  * 2 - 8 bytes
  312.  * 3 - 16 bytes
  313.  * 4 - 32 bytes
  314.  * 5 - 64 bytes
  315.  * 6 - 128 bytes
  316.  * 7 - Reserved
  317.  */
  318. static unsigned int decode_cache_line_size(unsigned int config_field)
  319. {
  320. if (config_field == 0) {
  321. return 0;
  322. } else if (config_field == 7) {
  323. /* JDCXXX - Find a graceful way to abort. */
  324. return 0;
  325. return (1<<(config_field + 1));
  326. }
  327. /*
  328.  * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs)
  329.  *
  330.  * 24:22 Icache sets per way
  331.  * 21:19 Icache line size
  332.  * 18:16 Icache Associativity
  333.  * 15:13 Dcache sets per way
  334.  * 12:10 Dcache line size
  335.  * 9:7   Dcache Associativity
  336.  */
  337. static void probe_cache_sizes(void)
  338. {
  339. u32 config1;
  340. __asm__ __volatile__(
  341. ".set push                  n"
  342. ".set mips64                n"
  343. "     mfc0    %0, $16, 1    n"  /* Get config1 register */
  344. ".set pop                   n"
  345. :"=r" (config1));
  346. icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7);
  347. dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7);
  348. icache_sets = decode_cache_sets((config1 >> 22) & 0x7);
  349. dcache_sets = decode_cache_sets((config1 >> 13) & 0x7);
  350.         icache_assoc = ((config1 >> 16) & 0x7) + 1;
  351. dcache_assoc = ((config1 >> 7) & 0x7) + 1;
  352. icache_size = icache_line_size * icache_sets * icache_assoc;
  353. dcache_size = dcache_line_size * dcache_sets * dcache_assoc;
  354. tlb_entries = ((config1 >> 25) & 0x3f) + 1;
  355. }
  356. /* This is called from loadmmu.c.  We have to set up all the
  357.    memory management function pointers, as well as initialize
  358.    the caches and tlbs */
  359. void ld_mmu_sb1(void)
  360. {
  361. probe_cache_sizes();
  362. _clear_page = sb1_clear_page;
  363. _copy_page = sb1_copy_page;
  364. _flush_cache_all = sb1_flush_cache_all;
  365. _flush_cache_mm = sb1_flush_cache_mm;
  366. _flush_cache_range = sb1_flush_cache_range;
  367. _flush_cache_page = sb1_flush_cache_page;
  368. _flush_cache_sigtramp = sb1_flush_cache_sigtramp;
  369. _flush_page_to_ram = sb1_flush_page_to_ram;
  370. _flush_icache_page = sb1_flush_cache_page;
  371. _flush_icache_range = sb1_flush_icache_range;
  372. /*
  373.  * JDCXXX I'm not sure whether these are necessary: is this the right 
  374.  * place to initialize the tlb?  If it is, why is it done 
  375.  * at this level instead of as common code in loadmmu()?
  376.  */
  377. flush_cache_all();
  378. flush_tlb_all();
  379. /* Turn on caching in kseg0 */
  380. set_cp0_config(CONF_CM_CMASK, 0);
  381. }