Subject: some mips3 mips_machdep.c changes to chew on.
To: None <port-mips@netbsd.org>
From: Chris G. Demetriou <cgd@sibyte.com>
List: port-mips
Date: 06/20/2000 14:56:43
here are some changes I just went through and made to the
mips_machdep.c mips3 cache configuration, printing, and
sanity-checking code.

* change 'two way' to more general associativity, and make it separate
for I and D.  (and corresponding changes to print fns.)

* adjusted mips_CacheAliasMask calculation (for greater and
potentially different I and D assoc.)

* #if defined(MIPS3) sanity checks only done if actually on >= mips3
cpu.

* cache op sanity checks done differently based on whether or not the
2way cache ops are being used.  (the way that's selected is
... Special.)  These sanity checks need to be sanity-checked.  I don't
think I understand how the old sanity check:

!       if (mips3_L1TwoWayCache &&
!           (mips_L1ICacheLSize < 32 || mips_L1DCacheLSize < 32)) {
                /*
!                * current implementation of mips3_FlushCache(),
!                * mips3_FlushICache(), mips3_FlushDCache() and
!                * mips3_HitFlushDCache() assume that
!                * if the CPU has two way L1 cache, line size >= 32.

was correct, unless you were also using the 2way cache functions.  If
you were using the non-2way cache functions, and had a 2-way cache,
you were going to lose with all but the mips3_FlushCache op, correct?


These changes need sanity-checking, and need testing on actual mips3
hardware which uses both types (direct, 2-way) of cache fns.  (I've
compiled them, at least.  8-)

comments also appreciated, but i'll be at usenix from this evening
until friday, and don't plan to check mail.



chris
===================================================================
Index: locore_mips3.S
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/locore_mips3.S,v
retrieving revision 1.36
diff -c -r1.36 locore_mips3.S
*** locore_mips3.S	2000/06/20 02:57:17	1.36
--- locore_mips3.S	2000/06/20 21:09:49
***************
*** 2611,2621 ****
   * The variables below are used to communicate the cache handling
   * to higher-level software.
   */
- 	.sdata
- 
- 	.globl	_C_LABEL(mips3_L1TwoWayCache)
- _C_LABEL(mips3_L1TwoWayCache):
- 	.word	0
  
  	.data
  
--- 2611,2616 ----
Index: mips_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/mips_machdep.c,v
retrieving revision 1.90
diff -c -r1.90 mips_machdep.c
*** mips_machdep.c	2000/06/17 06:38:25	1.90
--- mips_machdep.c	2000/06/20 21:09:49
***************
*** 109,114 ****
--- 109,118 ----
  int mips_num_tlb_entries;
  
  #ifdef MIPS3
+ int	mips3_L1_ICache_Assoc;	/* ways-1; 0 is direct mapped, 1 is 2-way */
+ int	mips3_L1_DCache_Assoc;	/* ways-1; 0 is direct mapped, 1 is 2-way */
+ /* XXX secondary cache associativity!!! */
+ 
  u_int	mips_L2CacheSize;
  int	mips_L2CacheIsSnooping;	/* Set if L2 cache snoops uncached writes */
  int	mips_L2CacheMixed;
***************
*** 378,406 ****
  	case MIPS_R4000:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1TwoWayCache = 0;
  		break;
  	case MIPS_R4100:
  		cpu_arch = 3;
  		mips_num_tlb_entries = 32;
! 		mips3_L1TwoWayCache = 0;
  		break;
  	case MIPS_R4300:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS_R4300_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1TwoWayCache = 0;
  		break;
  	case MIPS_R4600:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1TwoWayCache = 1;
  		/* disable interrupt while cacheflush to workaround the bug */
  		break;
  #ifdef ENABLE_MIPS_R4700 /* ID conflict */
  	case MIPS_R4700:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1TwoWayCache = 1;
  		break;
  #endif
  #ifndef ENABLE_MIPS_R3NKK /* ID conflict */
--- 382,415 ----
  	case MIPS_R4000:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1_ICache_Assoc = 0;
! 		mips3_L1_DCache_Assoc = 0;
  		break;
  	case MIPS_R4100:
  		cpu_arch = 3;
  		mips_num_tlb_entries = 32;
! 		mips3_L1_ICache_Assoc = 0;
! 		mips3_L1_DCache_Assoc = 0;
  		break;
  	case MIPS_R4300:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS_R4300_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1_ICache_Assoc = 0;
! 		mips3_L1_DCache_Assoc = 0;
  		break;
  	case MIPS_R4600:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1_ICache_Assoc = 1;
! 		mips3_L1_DCache_Assoc = 1;
  		/* disable interrupt while cacheflush to workaround the bug */
  		break;
  #ifdef ENABLE_MIPS_R4700 /* ID conflict */
  	case MIPS_R4700:
  		cpu_arch = 3;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1_ICache_Assoc = 1;
! 		mips3_L1_DCache_Assoc = 1;
  		break;
  #endif
  #ifndef ENABLE_MIPS_R3NKK /* ID conflict */
***************
*** 409,422 ****
  	case MIPS_RM5200:
  		cpu_arch = 4;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1TwoWayCache = 1;
  		break;
  
  	case MIPS_R10000:
  	case MIPS_R12000:
  		cpu_arch = 4;
  		mips_num_tlb_entries = 64;
! 		mips3_L1TwoWayCache = 1;
  		break;
  #endif /* MIPS3 */
  
--- 418,433 ----
  	case MIPS_RM5200:
  		cpu_arch = 4;
  		mips_num_tlb_entries = MIPS3_TLB_NUM_TLB_ENTRIES;
! 		mips3_L1_ICache_Assoc = 1;
! 		mips3_L1_DCache_Assoc = 1;
  		break;
  
  	case MIPS_R10000:
  	case MIPS_R12000:
  		cpu_arch = 4;
  		mips_num_tlb_entries = 64;
! 		mips3_L1_ICache_Assoc = 1;
! 		mips3_L1_DCache_Assoc = 1;
  		break;
  #endif /* MIPS3 */
  
***************
*** 573,591 ****
  #endif
  #ifdef MIPS3
  	if (cpu_arch >= 3) {
! 		printf("L1 cache: %dKB/%dB instruction, %dKB/%dB data",
! 		    mips_L1ICacheSize / 1024, mips_L1ICacheLSize,
  		    mips_L1DCacheSize / 1024, mips_L1DCacheLSize);
! 		if (mips3_L1TwoWayCache) {
! 			printf(", two way set associative");
! 			/* One less alias bit with 2 way cache. */
! 			mips_CacheAliasMask =
! 				((mips_L1DCacheSize/2) - 1) & ~(NBPG - 1);
! 		}
  		else
! 			printf(", direct mapped");
  		printf("\n");
! 		printf("cpu0: ");
  		if (!mips_L2CachePresent) {
  			printf("No L2 cache");
  		}
--- 584,616 ----
  #endif
  #ifdef MIPS3
  	if (cpu_arch >= 3) {
! 		printf("L1 instruction cache: %dKB/%dB, ",
! 		    mips_L1ICacheSize / 1024, mips_L1ICacheLSize);
! 		if (mips3_L1_ICache_Assoc)
! 			printf("%d way set associative",
! 			    mips3_L1_ICache_Assoc + 1);
! 		else
! 			printf("direct mapped");
! 		printf("\n");
! 		printf("cpu0: ");			/* XXX */
! 		printf("L1 data cache: %dKB/%dB, ",
  		    mips_L1DCacheSize / 1024, mips_L1DCacheLSize);
! 		if (mips3_L1_DCache_Assoc)
! 			printf("%d way set associative",
! 			    mips3_L1_DCache_Assoc + 1);
  		else
! 			printf("direct mapped");
  		printf("\n");
! 		printf("cpu0: ");			/* XXX */
! 
! 		/*
! 		 * XXX only worry about d-cache (writes)?  how about
! 		 * XXX secondary?
! 		 */
! 		mips_CacheAliasMask =
! 		    imax(mips_L1ICacheSize / mips3_L1_ICache_Assoc,
! 		      mips_L1DCacheSize / mips3_L1_DCache_Assoc) & ~(NBPG - 1);
! 
  		if (!mips_L2CachePresent) {
  			printf("No L2 cache");
  		}
***************
*** 606,647 ****
  
  #ifdef MIPS3
  	/*
! 	 * sanity check.
  	 * good place to do this is mips_vector_init(),
  	 * but printf() doesn't work in it.
  	 */
  #if !defined(MIPS3_L2CACHE_ABSENT)
! 	if (cpu_arch >= 3 && !mips_L2CachePresent) {
! 		printf("This kernel doesn't work without L2 cache.\n"
! 		    "Please add \"options MIPS3_L2CACHE_ABSENT\" "
! 		    "to the kernel config file.\n");
! 		cpu_reboot(RB_HALT, NULL);
! 	}
  #endif
! 	if (mips3_L1TwoWayCache &&
! 	    (mips_L1ICacheLSize < 32 || mips_L1DCacheLSize < 32)) {
  		/*
! 		 * current implementation of mips3_FlushCache(),
! 		 * mips3_FlushICache(), mips3_FlushDCache() and
! 		 * mips3_HitFlushDCache() assume that
! 		 * if the CPU has two way L1 cache, line size >= 32.
  		 */
! 		printf("L1 cache: two way, but Inst/Data line size = %d/%d\n",
! 		    mips_L1ICacheLSize, mips_L1DCacheLSize);
! 		printf("Please fix implementation of mips3_*Flush*Cache\n");
! 		cpu_reboot(RB_HALT, NULL);
! 	}
! 	if (mips_L2CachePresent && mips_L2CacheLSize < 32) {
  		/*
! 		 * current implementation of mips3_FlushCache(),
! 		 * mips3_FlushDCache() and mips3_HitFlushDCache() assume
! 		 * that if the CPU has L2 cache, line size >= 32.
  		 */
! 		printf("L2 cache line size = %d\n", mips_L2CacheLSize);
! 		printf("Please fix implementation of mips3_*Flush*Cache\n");
! 		cpu_reboot(RB_HALT, NULL);
  	}
! #endif
  	/* XXX cache sizes for MIPS1? */
  	/* XXX hardware mcclock CPU-speed computation */
  }
--- 631,704 ----
  
  #ifdef MIPS3
  	/*
! 	 * sanity checks on cache parameters.
  	 * good place to do this is mips_vector_init(),
  	 * but printf() doesn't work in it.
  	 */
+ 	if (cpu_arch >= 3) {
  #if !defined(MIPS3_L2CACHE_ABSENT)
! 		if (!mips_L2CachePresent) {
! 			printf("This kernel doesn't work without L2 cache.\n"
! 		    	"Please add \"options MIPS3_L2CACHE_ABSENT\" "
! 		    	"to the kernel config file.\n");
! 			cpu_reboot(RB_HALT, NULL);
! 		}
  #endif
! #ifdef MIPS3_5200	/* XXX SEE COMMENT BELOW */
! 	/*
! 	 * XXX the MIPS3_5200 option -- and only the MIPS3_5200 option --
! 	 * XXX selects between the one-way and two-way cache ops.
! 	 */
  		/*
! 		 * 2-way cache ops (other than FlushCache) won't
! 		 * work properly for caches with greater number of ways.
! 		 * (they'll should be fine with less, though wasteful).
  		 */
! 		if (mips3_L1_ICache_Assoc > 1 || mips3_L1_DCache_Assoc > 1) {
! 			printf("cache associativity not supported by "
! 			    "2-way cache flush implementation.\n");
! 			cpu_reboot(RB_HALT, NULL);
! 		}
! 
  		/*
! 		 * 2-way cache ops assume line size of at least 32 for
! 		 * primary I, primary D, and secondary (D).
  		 */
! 		if (mips_L1ICacheLSize < 32 || mips_L1DCacheLSize < 32 ||
! 		    (mips_L2CachePresent && mips_L2CacheLSize < 32)) {
! 			printf("cache parameters not supported by "
! 			    "2way cache implementation.\n");
! 			printf("Please fix implementation of "
! 			    "mips3_*Flush*Cache_2way\n");
! 			cpu_reboot(RB_HALT, NULL);
! 		}
! #else /* !MIPS3_5200 */
! 		/*
! 		 * direct mapped cache ops (other than FlushCache) won't
! 		 * work properly for associative caches.
! 		 */
! 		if (mips3_L1_ICache_Assoc > 0 || mips3_L1_DCache_Assoc > 0) {
! 			printf("cache associativity not supported by "
! 			    "direct-mapped cache flush implementation.\n");
! 			cpu_reboot(RB_HALT, NULL);
! 		}
! 
! 		/*
! 		 * direct-mapped cache ops assume line size of at least
! 		 * 16 for primary I and primary D, and of at least 32
! 		 * for secondary (D).
! 		 */
! 		if (mips_L1ICacheLSize < 16 || mips_L1DCacheLSize < 16 ||
! 		    (mips_L2CachePresent && mips_L2CacheLSize < 32)) {
! 			printf("cache parameters not supported by "
! 			    "direct-mapped cache flush implementation.\n");
! 			printf("Please fix implementation of "
! 			    "mips3_*Flush*Cache\n");
! 			cpu_reboot(RB_HALT, NULL);
! 		}
! #endif /* MIPS3_5200 */
  	}
! #endif /* MIPS3 */
  	/* XXX cache sizes for MIPS1? */
  	/* XXX hardware mcclock CPU-speed computation */
  }