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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  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) 2001-2002 Silicon Graphics, Inc. All rights reserved.
  8.  *
  9.  */
  10. #include <linux/kernel.h>
  11. #include <asm/pgalloc.h>
  12. #include <asm/sn/arch.h>
  13. #include <asm/sn/sn_cpuid.h>
  14. #include <asm/sn/sn1/synergy.h>
  15. #include <asm/delay.h>
  16. #ifndef MB
  17. #define MB (1024*1024)
  18. #endif
  19. /*
  20.  * Lock for protecting SYN_TAG_DISABLE_WAY.
  21.  * Consider making this a per-FSB lock. 
  22.  */
  23. static spinlock_t flush_lock = SPIN_LOCK_UNLOCKED;
  24. /**
  25.  * sn_flush_all_caches - flush a range of addresses from all caches (incl. L4)
  26.  * @flush_addr: identity mapped region 7 address to start flushing
  27.  * @bytes: number of bytes to flush
  28.  *
  29.  * Flush a range of addresses from all caches including L4.  All addresses 
  30.  * fully or partially contained within @flush_addr to @flush_addr + @bytes 
  31.  * are flushed from the all caches.
  32.  */
  33. void
  34. sn_flush_all_caches(long flush_addr, long bytes)
  35. {
  36. ulong  addr, baddr, eaddr, bitbucket;
  37. int way, alias;
  38. /*
  39.  * Because of the way synergy implements "fc", this flushes the
  40.  * data from all caches on all cpus & L4's on OTHER FSBs. It also
  41.  * flushes both cpus on the local FSB. It does NOT flush it from 
  42.  * the local FSB.
  43.  */
  44. flush_icache_range(flush_addr, flush_addr+bytes);
  45. /*
  46.  * Memory DIMMs are a minimum of 256MB and start on 256MB
  47.  * boundaries. Convert the start address to an address
  48.  * that is between +0MB & +128 of the same DIMM. 
  49.  * Then add 8MB to skip the uncached MinState areas if the address
  50.  * is on the master node.
  51.  */
  52. if (bytes > SYNERGY_L4_BYTES_PER_WAY)
  53. bytes = SYNERGY_L4_BYTES_PER_WAY;
  54. baddr = TO_NODE(smp_physical_node_id(), PAGE_OFFSET + (flush_addr & (128*MB-1)) + 8*MB); 
  55. eaddr = (baddr+bytes+SYNERGY_BLOCK_SIZE-1) & ~(SYNERGY_BLOCK_SIZE-1);
  56. baddr = baddr & ~(SYNERGY_BLOCK_SIZE-1);
  57. /*
  58.  * Now flush the local synergy.
  59.  */
  60. spin_lock(&flush_lock);
  61. for(way=0; way<SYNERGY_L4_WAYS; way++) {
  62. WRITE_LOCAL_SYNERGY_REG(SYN_TAG_DISABLE_WAY, 0xffL ^ (1L<<way));
  63. mb();
  64. for(alias=0; alias < 9; alias++)
  65. for(addr=baddr; addr<eaddr; addr+=SYNERGY_BLOCK_SIZE)
  66. bitbucket = *(volatile ulong *)(addr+alias*8*MB);
  67. mb();
  68. }
  69. WRITE_LOCAL_SYNERGY_REG(SYN_TAG_DISABLE_WAY, 0);
  70. spin_unlock(&flush_lock);
  71. }