c-sb1.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

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, 2001 Broadcom Corporation
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version 2
  9.  * of the License, or (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  */
  20. #include <linux/config.h>
  21. #include <linux/init.h>
  22. #include <asm/mmu_context.h>
  23. #include <asm/bootinfo.h>
  24. #include <asm/cacheops.h>
  25. #include <asm/cpu.h>
  26. #include <asm/uaccess.h>
  27. /* These are probed at ld_mmu time */
  28. static unsigned int icache_size;
  29. static unsigned int dcache_size;
  30. static unsigned int icache_line_size;
  31. static unsigned int dcache_line_size;
  32. static unsigned int icache_index_mask;
  33. static unsigned int icache_assoc;
  34. static unsigned int dcache_assoc;
  35. static unsigned int icache_sets;
  36. static unsigned int dcache_sets;
  37. void pgd_init(unsigned long page)
  38. {
  39. unsigned long *p = (unsigned long *) page;
  40. int i;
  41. for (i = 0; i < USER_PTRS_PER_PGD; i+=8) {
  42. p[i + 0] = (unsigned long) invalid_pte_table;
  43. p[i + 1] = (unsigned long) invalid_pte_table;
  44. p[i + 2] = (unsigned long) invalid_pte_table;
  45. p[i + 3] = (unsigned long) invalid_pte_table;
  46. p[i + 4] = (unsigned long) invalid_pte_table;
  47. p[i + 5] = (unsigned long) invalid_pte_table;
  48. p[i + 6] = (unsigned long) invalid_pte_table;
  49. p[i + 7] = (unsigned long) invalid_pte_table;
  50. }
  51. }
  52. /*
  53.  * The dcache is fully coherent to the system, with one
  54.  * big caveat:  the instruction stream.  In other words,
  55.  * if we miss in the icache, and have dirty data in the
  56.  * L1 dcache, then we'll go out to memory (or the L2) and
  57.  * get the not-as-recent data.
  58.  *
  59.  * So the only time we have to flush the dcache is when
  60.  * we're flushing the icache.  Since the L2 is fully
  61.  * coherent to everything, including I/O, we never have
  62.  * to flush it
  63.  */
  64. static void sb1_flush_cache_all(void)
  65. {
  66. }
  67. static void local_sb1___flush_cache_all(void)
  68. {
  69. /*
  70.  * Haven't worried too much about speed here; given that we're flushing
  71.  * the icache, the time to invalidate is dwarfed by the time it's going
  72.  * to take to refill it.  Register usage:
  73.  *
  74.  * $1 - moving cache index
  75.  * $2 - set count
  76.  */
  77. __asm__ __volatile__ (
  78. ".set push                  n"
  79. ".set noreorder             n"
  80. ".set noat                  n"
  81. ".set mips4                 n"
  82. "     move   $1, %2         n" /* Start at index 0 */
  83. "1:   cache  %3, 0($1)      n" /* WB/Invalidate this index */
  84. "     addiu  %1, %1, -1     n" /* Decrement loop count */
  85. "     bnez   %1, 1b         n" /* loop test */
  86. "      addu   $1, $1, %0    n" /* Next address */
  87. ".set pop                   n"
  88. :
  89. : "r" (dcache_line_size), "r" (dcache_sets * dcache_assoc),
  90.   "r" (KSEG0), "i" (Index_Writeback_Inv_D));
  91. __asm__ __volatile__ (
  92. ".set push                  n"
  93. ".set noreorder             n"
  94. ".set mips2                 n"
  95. "sync                       n"
  96. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* Bug 1384 */
  97. "sync                       n"
  98. #endif
  99. ".set pop                   n");
  100. __asm__ __volatile__ (
  101. ".set push                  n"
  102. ".set noreorder             n"
  103. ".set noat                  n"
  104. ".set mips4                 n"
  105. "     move   $1, %2         n" /* Start at index 0 */
  106. "1:   cache  %3, 0($1)       n" /* Invalidate this index */
  107. "     addiu  %1, %1, -1     n" /* Decrement loop count */
  108. "     bnez   %1, 1b         n" /* loop test */
  109. "      addu   $1, $1, %0    n" /* Next address */
  110. ".set pop                   n"
  111. :
  112. : "r" (icache_line_size), "r" (icache_sets * icache_assoc),
  113.   "r" (KSEG0), "i" (Index_Invalidate_I));
  114. }
  115. #ifdef CONFIG_SMP
  116. extern void sb1___flush_cache_all_ipi(void *ignored);
  117. asm("sb1___flush_cache_all_ipi = local_sb1___flush_cache_all");
  118. static void sb1___flush_cache_all(void)
  119. {
  120. smp_call_function(sb1___flush_cache_all_ipi, 0, 1, 1);
  121. local_sb1___flush_cache_all();
  122. }
  123. #else
  124. extern void sb1___flush_cache_all(void);
  125. asm("sb1___flush_cache_all = local_sb1___flush_cache_all");
  126. #endif
  127. /*
  128.  * When flushing a range in the icache, we have to first writeback
  129.  * the dcache for the same range, so new ifetches will see any
  130.  * data that was dirty in the dcache.
  131.  *
  132.  * The start/end arguments are expected to be Kseg addresses.
  133.  */
  134. static void local_sb1_flush_icache_range(unsigned long start, unsigned long end)
  135. {
  136. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  137. unsigned long flags;
  138. local_irq_save(flags);
  139. #endif
  140. __asm__ __volatile__ (
  141. ".set push                  n"
  142. ".set noreorder             n"
  143. ".set noat                  n"
  144. ".set mips4                 n"
  145. "     move   $1, %0         n"
  146. "1:                         n"
  147. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  148. ".align 3                   n"
  149. "     lw     $0,   0($1)    n" /* Bug 1370, 1368            */
  150. "     sync                  n"
  151. #endif
  152. "     cache  %3, 0($1)      n" /* Hit-WB{,-inval} this address */
  153. "     bne    $1, %1, 1b     n" /* loop test */
  154. "      addu  $1, $1, %2     n" /* next line */
  155. ".set pop                   n"
  156. :
  157. : "r" (start  & ~(dcache_line_size - 1)),
  158.   "r" ((end - 1) & ~(dcache_line_size - 1)),
  159.   "r" (dcache_line_size),
  160. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  161.   "i" (Hit_Writeback_Inv_D)
  162. #else
  163.   "i" (Hit_Writeback_D)
  164. #endif
  165. );
  166. __asm__ __volatile__ (
  167. ".set push                  n"
  168. ".set noreorder             n"
  169. ".set mips2                 n"
  170. "sync                       n"
  171. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* Bug 1384 */
  172. "sync                       n"
  173. #endif
  174. ".set pop                   n");
  175. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  176. local_irq_restore(flags);
  177. #endif
  178. __asm__ __volatile__ (
  179. ".set push                  n"
  180. ".set noreorder             n"
  181. ".set noat                  n"
  182. ".set mips4                 n"
  183. "     move   $1, %0         n"
  184. ".align 3                   n"
  185. "1:   cache  %3, (0<<13)($1) n" /* Index-inval this address */
  186. "     cache  %3, (1<<13)($1) n" /* Index-inval this address */
  187. "     cache  %3, (2<<13)($1) n" /* Index-inval this address */
  188. "     cache  %3, (3<<13)($1) n" /* Index-inval this address */
  189. "     bne    $1, %1, 1b     n" /* loop test */
  190. "      addu  $1, $1, %2     n" /* next line */
  191. ".set pop                   n"
  192. :
  193. : "r" (start & ~(icache_line_size - 1)),
  194.   "r" ((end - 1) & ~(icache_line_size - 1)),
  195.   "r" (icache_line_size),
  196.   "i" (Index_Invalidate_I));
  197. }
  198. #ifdef CONFIG_SMP
  199. struct flush_icache_range_args {
  200. unsigned long start;
  201. unsigned long end;
  202. };
  203. static void sb1_flush_icache_range_ipi(void *info)
  204. {
  205. struct flush_icache_range_args *args = info;
  206. local_sb1_flush_icache_range(args->start, args->end);
  207. }
  208. void sb1_flush_icache_range(unsigned long start, unsigned long end)
  209. {
  210. struct flush_icache_range_args args;
  211. args.start = start;
  212. args.end = end;
  213. smp_call_function(sb1_flush_icache_range_ipi, &args, 1, 1);
  214. local_sb1_flush_icache_range(start, end);
  215. }
  216. #else
  217. void sb1_flush_icache_range(unsigned long start, unsigned long end);
  218. asm("sb1_flush_icache_range = local_sb1_flush_icache_range");
  219. #endif
  220. /*
  221.  * If there's no context yet, or the page isn't executable, no icache flush
  222.  * is needed
  223.  */
  224. static void sb1_flush_icache_page(struct vm_area_struct *vma,
  225. struct page *page)
  226. {
  227. if (!(vma->vm_flags & VM_EXEC))
  228. return;
  229. /*
  230.  * We're not sure of the virtual address(es) involved here, so
  231.  * conservatively flush the entire caches on all processors
  232.  * (ouch).
  233.  */
  234. sb1___flush_cache_all();
  235. }
  236. static inline void protected_flush_icache_line(unsigned long addr)
  237. {
  238. __asm__ __volatile__(
  239. "    .set push                n"
  240. "    .set noreorder           n"
  241. "    .set mips4               n"
  242. "1:  cache %1, (%0)           n"
  243. "2:  .set pop                 n"
  244. "    .section __ex_table,"a"n"
  245. "     .word  1b, 2b          n"
  246. "     .previous"
  247. :
  248. : "r" (addr),
  249.   "i" (Hit_Invalidate_I));
  250. }
  251. static inline void protected_writeback_dcache_line(unsigned long addr)
  252. {
  253. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  254. /* Have to be sure the TLB entry exists for the cache op,
  255.    so we have to be sure that nothing happens in between the
  256.    lw and the cache op
  257. */
  258. unsigned long flags;
  259. local_irq_save(flags);
  260. #endif
  261. __asm__ __volatile__(
  262. "    .set push                n"
  263. "    .set noreorder           n"
  264. "    .set mips4               n"
  265. "1:                           n"
  266. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  267. "     lw    $0,   (%0)        n"
  268. "     sync                  n"
  269. #endif
  270. "     cache  %1, 0(%0)    n" /* Hit-WB{-inval} this address */
  271. /* XXX: should be able to do this after both dcache cache
  272.    ops, but there's no guarantee that this will be inlined,
  273.    and the pass1 restriction checker can't detect syncs
  274.    following cache ops except in the following basic block.
  275. */
  276. "     sync                    n"
  277. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* Bug 1384 */
  278. "     sync                    n"
  279. #endif
  280. "2:  .set pop                 n"
  281. "    .section __ex_table,"a"n"
  282. "     .word  1b, 2b          n"
  283. "     .previous"
  284. :
  285. : "r" (addr),
  286. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  287.   "i" (Hit_Writeback_Inv_D)
  288. #else
  289.   "i" (Hit_Writeback_D)
  290. #endif
  291.   );
  292. #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  293. local_irq_restore(flags);
  294. #endif
  295. }
  296. /*
  297.  * A signal trampoline must fit into a single cacheline.
  298.  */
  299. static void local_sb1_flush_cache_sigtramp(unsigned long addr)
  300. {
  301. unsigned long daddr, iaddr;
  302. daddr = addr & ~(dcache_line_size - 1);
  303. protected_writeback_dcache_line(daddr);
  304. iaddr = addr & ~(icache_line_size - 1);
  305. protected_flush_icache_line(iaddr);
  306. }
  307. #ifdef CONFIG_SMP
  308. static void sb1_flush_cache_sigtramp_ipi(void *info)
  309. {
  310. unsigned long iaddr = (unsigned long) info;
  311. iaddr = iaddr & ~(icache_line_size - 1);
  312. protected_flush_icache_line(iaddr);
  313. }
  314. static void sb1_flush_cache_sigtramp(unsigned long addr)
  315. {
  316. unsigned long tmp;
  317. /*
  318.  * Flush the local dcache, then load the instruction back into a
  319.  * register.  That will make sure that any remote CPU also has
  320.  * written back it's data cache to memory.
  321.  */
  322. local_sb1_flush_cache_sigtramp(addr);
  323. __get_user(tmp, (unsigned long *)addr);
  324. smp_call_function(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1);
  325. }
  326. #else
  327. void sb1_flush_cache_sigtramp(unsigned long addr);
  328. asm("sb1_flush_cache_sigtramp = local_sb1_flush_cache_sigtramp");
  329. #endif
  330. static void sb1_flush_icache_all(void)
  331. {
  332. /*
  333.  * Haven't worried too much about speed here; given that we're flushing
  334.  * the icache, the time to invalidate is dwarfed by the time it's going
  335.  * to take to refill it.  Register usage:
  336.  *
  337.  * $1 - moving cache index
  338.  * $2 - set count
  339.  */
  340. __asm__ __volatile__ (
  341. ".set push                  n"
  342. ".set noreorder             n"
  343. ".set noat                  n"
  344. ".set mips4                 n"
  345. "     move   $1, %2         n" /* Start at index 0 */
  346. "1:   cache  %3, 0($1)      n" /* Invalidate this index */
  347. "     addiu  %1, %1, -1     n" /* Decrement loop count */
  348. "     bnez   %1, 1b         n" /* loop test */
  349. "      addu   $1, $1, %0    n" /* Next address */
  350. ".set pop                   n"
  351. :
  352. : "r" (icache_line_size), "r" (icache_sets * icache_assoc),
  353.   "r" (KSEG0), "i" (Index_Invalidate_I));
  354. }
  355. /*
  356.  * Anything that just flushes dcache state can be ignored, as we're always
  357.  * coherent in dcache space.  This is just a dummy function that all the
  358.  * nop'ed routines point to
  359.  */
  360. static void sb1_nop(void)
  361. {
  362. }
  363. /*
  364.  * This only needs to make sure stores done up to this
  365.  * point are visible to other agents outside the CPU.  Given
  366.  * the coherent nature of the ZBbus, all that's required here is
  367.  * a sync to make sure the data gets out to the caches and is
  368.  * visible to an arbitrary A Phase from an external agent
  369.  *
  370.  * Actually, I'm not even sure that's necessary; the semantics
  371.  * of this function aren't clear.  If it's supposed to serve as
  372.  * a memory barrier, this is needed.  If it's only meant to
  373.  * prevent data from being invisible to non-cpu memory accessors
  374.  * for some indefinite period of time (e.g. in a non-coherent
  375.  * dcache) then this function would be a complete nop.
  376.  */
  377. static void sb1_flush_page_to_ram(struct page *page)
  378. {
  379. __asm__ __volatile__(
  380. "     sync  n"  /* Short pipe */
  381. :::"memory");
  382. }
  383. /*
  384.  *  Cache set values (from the mips64 spec)
  385.  * 0 - 64
  386.  * 1 - 128
  387.  * 2 - 256
  388.  * 3 - 512
  389.  * 4 - 1024
  390.  * 5 - 2048
  391.  * 6 - 4096
  392.  * 7 - Reserved
  393.  */
  394. static unsigned int decode_cache_sets(unsigned int config_field)
  395. {
  396. if (config_field == 7) {
  397. /* JDCXXX - Find a graceful way to abort. */
  398. return 0;
  399. }
  400. return (1<<(config_field + 6));
  401. }
  402. /*
  403.  *  Cache line size values (from the mips64 spec)
  404.  * 0 - No cache present.
  405.  * 1 - 4 bytes
  406.  * 2 - 8 bytes
  407.  * 3 - 16 bytes
  408.  * 4 - 32 bytes
  409.  * 5 - 64 bytes
  410.  * 6 - 128 bytes
  411.  * 7 - Reserved
  412.  */
  413. static unsigned int decode_cache_line_size(unsigned int config_field)
  414. {
  415. if (config_field == 0) {
  416. return 0;
  417. } else if (config_field == 7) {
  418. /* JDCXXX - Find a graceful way to abort. */
  419. return 0;
  420. }
  421. return (1<<(config_field + 1));
  422. }
  423. /*
  424.  * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs)
  425.  *
  426.  * 24:22 Icache sets per way
  427.  * 21:19 Icache line size
  428.  * 18:16 Icache Associativity
  429.  * 15:13 Dcache sets per way
  430.  * 12:10 Dcache line size
  431.  * 9:7   Dcache Associativity
  432.  */
  433. static __init void probe_cache_sizes(void)
  434. {
  435. u32 config1;
  436. config1 = read_mips32_cp0_config1();
  437. icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7);
  438. dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7);
  439. icache_sets = decode_cache_sets((config1 >> 22) & 0x7);
  440. dcache_sets = decode_cache_sets((config1 >> 13) & 0x7);
  441. icache_assoc = ((config1 >> 16) & 0x7) + 1;
  442. dcache_assoc = ((config1 >> 7) & 0x7) + 1;
  443. icache_size = icache_line_size * icache_sets * icache_assoc;
  444. dcache_size = dcache_line_size * dcache_sets * dcache_assoc;
  445. icache_index_mask = (icache_sets - 1) * icache_line_size;
  446. }
  447. /*
  448.  * This is called from loadmmu.c.  We have to set up all the
  449.  * memory management function pointers, as well as initialize
  450.  * the caches and tlbs
  451.  */
  452. void ld_mmu_sb1(void)
  453. {
  454. probe_cache_sizes();
  455. _clear_page = sb1_clear_page;
  456. _copy_page = sb1_copy_page;
  457. _flush_cache_all = sb1_flush_cache_all;
  458. ___flush_cache_all = sb1___flush_cache_all;
  459. _flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop;
  460. _flush_cache_range = (void *) sb1_nop;
  461. _flush_page_to_ram = sb1_flush_page_to_ram;
  462. _flush_icache_page = sb1_flush_icache_page;
  463. _flush_icache_range = sb1_flush_icache_range;
  464. /* None of these are needed for the sb1 */
  465. _flush_cache_page = (void *) sb1_nop;
  466. _flush_cache_sigtramp = sb1_flush_cache_sigtramp;
  467. _flush_icache_all = sb1_flush_icache_all;
  468. change_cp0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
  469. flush_cache_all();
  470. }