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