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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * r4kcache.h: Inline assembly cache operations.
  3.  *
  4.  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  5.  *
  6.  * FIXME: Handle split L2 caches.
  7.  */
  8. #ifndef _MIPS_R4KCACHE_H
  9. #define _MIPS_R4KCACHE_H
  10. #include <asm/asm.h>
  11. #include <asm/cacheops.h>
  12. static inline void flush_icache_line_indexed(unsigned long addr)
  13. {
  14. __asm__ __volatile__(
  15. ".set noreordernt"
  16. ".set mips3nt"
  17. "cache %1, (%0)nt"
  18. ".set mips0nt"
  19. ".set reorder"
  20. :
  21. : "r" (addr),
  22.   "i" (Index_Invalidate_I));
  23. }
  24. static inline void flush_dcache_line_indexed(unsigned long addr)
  25. {
  26. __asm__ __volatile__(
  27. ".set noreordernt"
  28. ".set mips3nt"
  29. "cache %1, (%0)nt"
  30. ".set mips0nt"
  31. ".set reorder"
  32. :
  33. : "r" (addr),
  34.   "i" (Index_Writeback_Inv_D));
  35. }
  36. static inline void flush_scache_line_indexed(unsigned long addr)
  37. {
  38. __asm__ __volatile__(
  39. ".set noreordernt"
  40. ".set mips3nt"
  41. "cache %1, (%0)nt"
  42. ".set mips0nt"
  43. ".set reorder"
  44. :
  45. : "r" (addr),
  46.   "i" (Index_Writeback_Inv_SD));
  47. }
  48. static inline void flush_icache_line(unsigned long addr)
  49. {
  50. __asm__ __volatile__(
  51. ".set noreordernt"
  52. ".set mips3nt"
  53. "cache %1, (%0)nt"
  54. ".set mips0nt"
  55. ".set reorder"
  56. :
  57. : "r" (addr),
  58.   "i" (Hit_Invalidate_I));
  59. }
  60. static inline void flush_dcache_line(unsigned long addr)
  61. {
  62. __asm__ __volatile__(
  63. ".set noreordernt"
  64. ".set mips3nt"
  65. "cache %1, (%0)nt"
  66. ".set mips0nt"
  67. ".set reorder"
  68. :
  69. : "r" (addr),
  70.   "i" (Hit_Writeback_Inv_D));
  71. }
  72. static inline void invalidate_dcache_line(unsigned long addr)
  73. {
  74. __asm__ __volatile__(
  75. ".set noreordernt"
  76. ".set mips3nt"
  77. "cache %1, (%0)nt"
  78. ".set mips0nt"
  79. ".set reorder"
  80. :
  81. : "r" (addr),
  82.   "i" (Hit_Invalidate_D));
  83. }
  84. static inline void invalidate_scache_line(unsigned long addr)
  85. {
  86. __asm__ __volatile__(
  87. ".set noreordernt"
  88. ".set mips3nt"
  89. "cache %1, (%0)nt"
  90. ".set mips0nt"
  91. ".set reorder"
  92. :
  93. : "r" (addr),
  94.   "i" (Hit_Invalidate_SD));
  95. }
  96. static inline void flush_scache_line(unsigned long addr)
  97. {
  98. __asm__ __volatile__(
  99. ".set noreordernt"
  100. ".set mips3nt"
  101. "cache %1, (%0)nt"
  102. ".set mips0nt"
  103. ".set reorder"
  104. :
  105. : "r" (addr),
  106.   "i" (Hit_Writeback_Inv_SD));
  107. }
  108. /*
  109.  * The next two are for badland addresses like signal trampolines.
  110.  */
  111. static inline void protected_flush_icache_line(unsigned long addr)
  112. {
  113. __asm__ __volatile__(
  114. ".set noreordernt"
  115. ".set mips3n"
  116. "1:tcache %1,(%0)n"
  117. "2:t.set mips0nt"
  118. ".set reordernt"
  119. ".sectiont__ex_table,"a"nt"
  120. STR(PTR)"t1b,2bnt"
  121. ".previous"
  122. :
  123. : "r" (addr),
  124.   "i" (Hit_Invalidate_I));
  125. }
  126. static inline void protected_writeback_dcache_line(unsigned long addr)
  127. {
  128. __asm__ __volatile__(
  129. ".set noreordernt"
  130. ".set mips3n"
  131. "1:tcache %1,(%0)n"
  132. "2:t.set mips0nt"
  133. ".set reordernt"
  134. ".sectiont__ex_table,"a"nt"
  135. STR(PTR)"t1b,2bnt"
  136. ".previous"
  137. :
  138. : "r" (addr),
  139.   "i" (Hit_Writeback_D));
  140. }
  141. #define cache16_unroll32(base,op)
  142. __asm__ __volatile__("
  143. .set noreorder;
  144. .set mips3;
  145. cache %1, 0x000(%0); cache %1, 0x010(%0);
  146. cache %1, 0x020(%0); cache %1, 0x030(%0);
  147. cache %1, 0x040(%0); cache %1, 0x050(%0);
  148. cache %1, 0x060(%0); cache %1, 0x070(%0);
  149. cache %1, 0x080(%0); cache %1, 0x090(%0);
  150. cache %1, 0x0a0(%0); cache %1, 0x0b0(%0);
  151. cache %1, 0x0c0(%0); cache %1, 0x0d0(%0);
  152. cache %1, 0x0e0(%0); cache %1, 0x0f0(%0);
  153. cache %1, 0x100(%0); cache %1, 0x110(%0);
  154. cache %1, 0x120(%0); cache %1, 0x130(%0);
  155. cache %1, 0x140(%0); cache %1, 0x150(%0);
  156. cache %1, 0x160(%0); cache %1, 0x170(%0);
  157. cache %1, 0x180(%0); cache %1, 0x190(%0);
  158. cache %1, 0x1a0(%0); cache %1, 0x1b0(%0);
  159. cache %1, 0x1c0(%0); cache %1, 0x1d0(%0);
  160. cache %1, 0x1e0(%0); cache %1, 0x1f0(%0);
  161. .set mips0;
  162. .set reorder"
  163. :
  164. : "r" (base),
  165.   "i" (op));
  166. static inline void blast_dcache16(void)
  167. {
  168. unsigned long start = KSEG0;
  169. unsigned long end = (start + dcache_size);
  170. while(start < end) {
  171. cache16_unroll32(start,Index_Writeback_Inv_D);
  172. start += 0x200;
  173. }
  174. }
  175. static inline void blast_dcache16_wayLSB(void)
  176. {
  177. unsigned long start = KSEG0;
  178. unsigned long end = (start + mips_cpu.dcache.sets * mips_cpu.dcache.linesz);
  179. int way;
  180. while(start < end) {
  181. /* LSB of VA select the way */
  182. for (way = 0; way < mips_cpu.dcache.ways; way++)
  183. cache16_unroll32(start|way,Index_Writeback_Inv_D);
  184. start += 0x200;
  185. }
  186. }
  187. static inline void blast_dcache16_page(unsigned long page)
  188. {
  189. unsigned long start = page;
  190. unsigned long end = (start + PAGE_SIZE);
  191. while(start < end) {
  192. cache16_unroll32(start,Hit_Writeback_Inv_D);
  193. start += 0x200;
  194. }
  195. }
  196. static inline void blast_dcache16_page_indexed(unsigned long page)
  197. {
  198. unsigned long start = page;
  199. unsigned long end = (start + PAGE_SIZE);
  200. while(start < end) {
  201. cache16_unroll32(start,Index_Writeback_Inv_D);
  202. start += 0x200;
  203. }
  204. }
  205. static inline void blast_dcache16_page_indexed_wayLSB(unsigned long page)
  206. {
  207. unsigned long start = page;
  208. unsigned long end = (start + PAGE_SIZE);
  209. int way;
  210. while(start < end) {
  211. /* LSB of VA select the way */
  212. for (way = 0; way < mips_cpu.dcache.ways; way++)
  213. cache16_unroll32(start|way,Index_Writeback_Inv_D);
  214. start += 0x200;
  215. }
  216. }
  217. static inline void blast_icache16(void)
  218. {
  219. unsigned long start = KSEG0;
  220. unsigned long end = (start + icache_size);
  221. while(start < end) {
  222. cache16_unroll32(start,Index_Invalidate_I);
  223. start += 0x200;
  224. }
  225. }
  226. static inline void blast_icache16_wayLSB(void)
  227. {
  228. unsigned long start = KSEG0;
  229. unsigned long end = (start + mips_cpu.icache.sets * mips_cpu.icache.linesz);
  230. int way;
  231. while(start < end) {
  232. /* LSB of VA select the way */
  233. for (way = 0; way < mips_cpu.icache.ways; way++)
  234. cache16_unroll32(start|way,Index_Invalidate_I);
  235. start += 0x200;
  236. }
  237. }
  238. static inline void blast_icache16_page(unsigned long page)
  239. {
  240. unsigned long start = page;
  241. unsigned long end = (start + PAGE_SIZE);
  242. while(start < end) {
  243. cache16_unroll32(start,Hit_Invalidate_I);
  244. start += 0x200;
  245. }
  246. }
  247. static inline void blast_icache16_page_indexed(unsigned long page)
  248. {
  249. unsigned long start = page;
  250. unsigned long end = (start + PAGE_SIZE);
  251. while(start < end) {
  252. cache16_unroll32(start,Index_Invalidate_I);
  253. start += 0x200;
  254. }
  255. }
  256. static inline void blast_scache16(void)
  257. {
  258. unsigned long start = KSEG0;
  259. unsigned long end = KSEG0 + scache_size;
  260. while(start < end) {
  261. cache16_unroll32(start,Index_Writeback_Inv_SD);
  262. start += 0x200;
  263. }
  264. }
  265. static inline void blast_scache16_page(unsigned long page)
  266. {
  267. unsigned long start = page;
  268. unsigned long end = page + PAGE_SIZE;
  269. while(start < end) {
  270. cache16_unroll32(start,Hit_Writeback_Inv_SD);
  271. start += 0x200;
  272. }
  273. }
  274. static inline void blast_scache16_page_indexed(unsigned long page)
  275. {
  276. unsigned long start = page;
  277. unsigned long end = page + PAGE_SIZE;
  278. while(start < end) {
  279. cache16_unroll32(start,Index_Writeback_Inv_SD);
  280. start += 0x200;
  281. }
  282. }
  283. #define cache32_unroll32(base,op)
  284. __asm__ __volatile__("
  285. .set noreorder;
  286. .set mips3;
  287. cache %1, 0x000(%0); cache %1, 0x020(%0);
  288. cache %1, 0x040(%0); cache %1, 0x060(%0);
  289. cache %1, 0x080(%0); cache %1, 0x0a0(%0);
  290. cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);
  291. cache %1, 0x100(%0); cache %1, 0x120(%0);
  292. cache %1, 0x140(%0); cache %1, 0x160(%0);
  293. cache %1, 0x180(%0); cache %1, 0x1a0(%0);
  294. cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);
  295. cache %1, 0x200(%0); cache %1, 0x220(%0);
  296. cache %1, 0x240(%0); cache %1, 0x260(%0);
  297. cache %1, 0x280(%0); cache %1, 0x2a0(%0);
  298. cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);
  299. cache %1, 0x300(%0); cache %1, 0x320(%0);
  300. cache %1, 0x340(%0); cache %1, 0x360(%0);
  301. cache %1, 0x380(%0); cache %1, 0x3a0(%0);
  302. cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);
  303. .set mips0;
  304. .set reorder"
  305. :
  306. : "r" (base),
  307.   "i" (op));
  308. static inline void blast_dcache32(void)
  309. {
  310. unsigned long start = KSEG0;
  311. unsigned long end = (start + dcache_size);
  312. while(start < end) {
  313. cache32_unroll32(start,Index_Writeback_Inv_D);
  314. start += 0x400;
  315. }
  316. }
  317. static inline void blast_dcache32_wayLSB(void)
  318. {
  319. unsigned long start = KSEG0;
  320. unsigned long end = (start + mips_cpu.dcache.sets * mips_cpu.dcache.linesz);
  321. int way;
  322. while(start < end) {
  323. /* LSB of VA select the way */
  324. for (way = 0; way < mips_cpu.dcache.ways; way++)
  325. cache32_unroll32(start|way,Index_Writeback_Inv_D);
  326. start += 0x400;
  327. }
  328. }
  329. /*
  330.  * Call this function only with interrupts disabled or R4600 V2.0 may blow
  331.  * up on you.
  332.  *
  333.  * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D,
  334.  * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only
  335.  * operate correctly if the internal data cache refill buffer is empty.  These
  336.  * CACHE instructions should be separated from any potential data cache miss
  337.  * by a load instruction to an uncached address to empty the response buffer."
  338.  * (Revision 2.0 device errata from IDT available on http://www.idt.com/
  339.  * in .pdf format.)
  340.  */
  341. static inline void blast_dcache32_page(unsigned long page)
  342. {
  343. unsigned long start = page;
  344. unsigned long end = (start + PAGE_SIZE);
  345. /*
  346.  * Sigh ... workaround for R4600 v1.7 bug.  Explanation see above.
  347.  */
  348. *(volatile unsigned long *)KSEG1;
  349. __asm__ __volatile__("nop;nop;nop;nop");
  350. while(start < end) {
  351. cache32_unroll32(start,Hit_Writeback_Inv_D);
  352. start += 0x400;
  353. }
  354. }
  355. static inline void blast_dcache32_page_indexed(unsigned long page)
  356. {
  357. unsigned long start = page;
  358. unsigned long end = (start + PAGE_SIZE);
  359. while(start < end) {
  360. cache32_unroll32(start,Index_Writeback_Inv_D);
  361. start += 0x400;
  362. }
  363. }
  364. static inline void blast_dcache32_page_indexed_wayLSB(unsigned long page)
  365. {
  366. unsigned long start = page;
  367. unsigned long end = (start + PAGE_SIZE);
  368. int way;
  369. while(start < end) {
  370. /* LSB of VA select the way */
  371. for (way = 0; way < mips_cpu.dcache.ways; way++)
  372. cache32_unroll32(start|way,Index_Writeback_Inv_D);
  373. start += 0x400;
  374. }
  375. }
  376. static inline void blast_icache32(void)
  377. {
  378. unsigned long start = KSEG0;
  379. unsigned long end = (start + icache_size);
  380. while(start < end) {
  381. cache32_unroll32(start,Index_Invalidate_I);
  382. start += 0x400;
  383. }
  384. }
  385. static inline void blast_icache32_wayLSB(void)
  386. {
  387. unsigned long start = KSEG0;
  388. unsigned long end = (start + mips_cpu.icache.sets * mips_cpu.icache.linesz);
  389. int way;
  390. while(start < end) {
  391. /* LSB of VA select the way */
  392. for (way = 0; way < mips_cpu.icache.ways; way++)
  393. cache32_unroll32(start|way,Index_Invalidate_I);
  394. start += 0x400;
  395. }
  396. }
  397. static inline void blast_icache32_page(unsigned long page)
  398. {
  399. unsigned long start = page;
  400. unsigned long end = (start + PAGE_SIZE);
  401. while(start < end) {
  402. cache32_unroll32(start,Hit_Invalidate_I);
  403. start += 0x400;
  404. }
  405. }
  406. static inline void blast_icache32_page_indexed(unsigned long page)
  407. {
  408. unsigned long start = page;
  409. unsigned long end = (start + PAGE_SIZE);
  410. while(start < end) {
  411. cache32_unroll32(start,Index_Invalidate_I);
  412. start += 0x400;
  413. }
  414. }
  415. static inline void blast_scache32(void)
  416. {
  417. unsigned long start = KSEG0;
  418. unsigned long end = KSEG0 + scache_size;
  419. while(start < end) {
  420. cache32_unroll32(start,Index_Writeback_Inv_SD);
  421. start += 0x400;
  422. }
  423. }
  424. static inline void blast_scache32_page(unsigned long page)
  425. {
  426. unsigned long start = page;
  427. unsigned long end = page + PAGE_SIZE;
  428. while(start < end) {
  429. cache32_unroll32(start,Hit_Writeback_Inv_SD);
  430. start += 0x400;
  431. }
  432. }
  433. static inline void blast_scache32_page_indexed(unsigned long page)
  434. {
  435. unsigned long start = page;
  436. unsigned long end = page + PAGE_SIZE;
  437. while(start < end) {
  438. cache32_unroll32(start,Index_Writeback_Inv_SD);
  439. start += 0x400;
  440. }
  441. }
  442. #define cache64_unroll32(base,op)
  443. __asm__ __volatile__("
  444. .set noreorder;
  445. .set mips3;
  446. cache %1, 0x000(%0); cache %1, 0x040(%0);
  447. cache %1, 0x080(%0); cache %1, 0x0c0(%0);
  448. cache %1, 0x100(%0); cache %1, 0x140(%0);
  449. cache %1, 0x180(%0); cache %1, 0x1c0(%0);
  450. cache %1, 0x200(%0); cache %1, 0x240(%0);
  451. cache %1, 0x280(%0); cache %1, 0x2c0(%0);
  452. cache %1, 0x300(%0); cache %1, 0x340(%0);
  453. cache %1, 0x380(%0); cache %1, 0x3c0(%0);
  454. cache %1, 0x400(%0); cache %1, 0x440(%0);
  455. cache %1, 0x480(%0); cache %1, 0x4c0(%0);
  456. cache %1, 0x500(%0); cache %1, 0x540(%0);
  457. cache %1, 0x580(%0); cache %1, 0x5c0(%0);
  458. cache %1, 0x600(%0); cache %1, 0x640(%0);
  459. cache %1, 0x680(%0); cache %1, 0x6c0(%0);
  460. cache %1, 0x700(%0); cache %1, 0x740(%0);
  461. cache %1, 0x780(%0); cache %1, 0x7c0(%0);
  462. .set mips0;
  463. .set reorder"
  464. :
  465. : "r" (base),
  466.   "i" (op));
  467. static inline void blast_scache64(void)
  468. {
  469. unsigned long start = KSEG0;
  470. unsigned long end = KSEG0 + scache_size;
  471. while(start < end) {
  472. cache64_unroll32(start,Index_Writeback_Inv_SD);
  473. start += 0x800;
  474. }
  475. }
  476. static inline void blast_scache64_page(unsigned long page)
  477. {
  478. unsigned long start = page;
  479. unsigned long end = page + PAGE_SIZE;
  480. while(start < end) {
  481. cache64_unroll32(start,Hit_Writeback_Inv_SD);
  482. start += 0x800;
  483. }
  484. }
  485. static inline void blast_scache64_page_indexed(unsigned long page)
  486. {
  487. unsigned long start = page;
  488. unsigned long end = page + PAGE_SIZE;
  489. while(start < end) {
  490. cache64_unroll32(start,Index_Writeback_Inv_SD);
  491. start += 0x800;
  492. }
  493. }
  494. #define cache128_unroll32(base,op)
  495. __asm__ __volatile__("
  496. .set noreorder;
  497. .set mips3;
  498. cache %1, 0x000(%0); cache %1, 0x080(%0);
  499. cache %1, 0x100(%0); cache %1, 0x180(%0);
  500. cache %1, 0x200(%0); cache %1, 0x280(%0);
  501. cache %1, 0x300(%0); cache %1, 0x380(%0);
  502. cache %1, 0x400(%0); cache %1, 0x480(%0);
  503. cache %1, 0x500(%0); cache %1, 0x580(%0);
  504. cache %1, 0x600(%0); cache %1, 0x680(%0);
  505. cache %1, 0x700(%0); cache %1, 0x780(%0);
  506. cache %1, 0x800(%0); cache %1, 0x880(%0);
  507. cache %1, 0x900(%0); cache %1, 0x980(%0);
  508. cache %1, 0xa00(%0); cache %1, 0xa80(%0);
  509. cache %1, 0xb00(%0); cache %1, 0xb80(%0);
  510. cache %1, 0xc00(%0); cache %1, 0xc80(%0);
  511. cache %1, 0xd00(%0); cache %1, 0xd80(%0);
  512. cache %1, 0xe00(%0); cache %1, 0xe80(%0);
  513. cache %1, 0xf00(%0); cache %1, 0xf80(%0);
  514. .set mips0;
  515. .set reorder"
  516. :
  517. : "r" (base),
  518.   "i" (op));
  519. static inline void blast_scache128(void)
  520. {
  521. unsigned long start = KSEG0;
  522. unsigned long end = KSEG0 + scache_size;
  523. while(start < end) {
  524. cache128_unroll32(start,Index_Writeback_Inv_SD);
  525. start += 0x1000;
  526. }
  527. }
  528. static inline void blast_scache128_page(unsigned long page)
  529. {
  530. cache128_unroll32(page,Hit_Writeback_Inv_SD);
  531. }
  532. static inline void blast_scache128_page_indexed(unsigned long page)
  533. {
  534. cache128_unroll32(page,Index_Writeback_Inv_SD);
  535. }
  536. #endif /* !(_MIPS_R4KCACHE_H) */