From owner-FreeBSD-tech-jp@jp.freebsd.org  Thu Oct  1 22:53:00 1998
Received: (from daemon@localhost)
	by jaz.jp.freebsd.org (8.9.1+3.1W/8.7.3) id WAA16730;
	Thu, 1 Oct 1998 22:53:00 +0900 (JST)
	(envelope-from owner-FreeBSD-tech-jp@jp.FreeBSD.org)
Received: from gneiss.eps.nagoya-u.ac.jp (gneiss.eps.nagoya-u.ac.jp [133.6.124.148])
	by jaz.jp.freebsd.org (8.9.1+3.1W/8.7.3) with ESMTP id WAA16722
	for <FreeBSD-tech-jp@jp.freebsd.org>; Thu, 1 Oct 1998 22:52:57 +0900 (JST)
	(envelope-from kato@ganko.eps.nagoya-u.ac.jp)
Received: from localhost (localhost [127.0.0.1])
	by gneiss.eps.nagoya-u.ac.jp (8.9.1/3.7W) with ESMTP id WAA00413
	for <FreeBSD-tech-jp@jp.freebsd.org>; Thu, 1 Oct 1998 22:52:56 +0900 (JST)
To: FreeBSD-tech-jp@jp.freebsd.org
From: KATO Takenori <kato@ganko.eps.nagoya-u.ac.jp>
X-Mailer: Mew version 1.92.4 on Emacs 19.28 / Mule 2.3 (SUETSUMUHANA)
X-PGP-Fingerprint: 03 72 85 36 62 46 23 03  52 B1 10 22 44 10 0D 9E
Mime-Version: 1.0
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
Message-Id: <19981001225256W.kato@gneiss.eps.nagoya-u.ac.jp>
Date: Thu, 01 Oct 1998 22:52:56 +0900
X-Dispatcher: imput version 971024
Lines: 258
Reply-To: FreeBSD-tech-jp@jp.freebsd.org
Precedence: bulk
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+980914
X-Sequence: FreeBSD-tech-jp 1747
Subject: [FreeBSD-tech-jp 1747] AMD K5/K6/K6-2 Write Allocation patch
Errors-To: owner-FreeBSD-tech-jp@jp.freebsd.org
Sender: owner-FreeBSD-tech-jp@jp.freebsd.org

$B2CF#!wL>Bg4d9[$G$9!%(B

AMD K5/K6/K6-2$B$N(BWrite Allocation$B$r%5%]!<%H$9$k$?$a$N%Q%C%A$r:n$j$^$7$?!%(B
$B$I$J$?$+%F%9%H$7$F$b$i$($^$;$s$+!)(B

$B%Q%C%A$O!$(B3.0-current$BMQ$G$9!%(B

---------- BEGIN ----------
*** sys/i386/conf/options.i386.ORIG	Thu Oct  1 03:17:43 1998
--- sys/i386/conf/options.i386	Thu Oct  1 03:18:35 1998
***************
*** 46,51 ****
--- 46,52 ----
  CLK_USE_TSC_CALIBRATION		opt_clock.h
  
  NO_F00F_HACK			opt_cpu.h
+ CPU_AMD_WT_ALLOC		opt_cpu.h
  CPU_BLUELIGHTNING_FPU_OP_CACHE	opt_cpu.h
  CPU_BLUELIGHTNING_3X		opt_cpu.h
  CPU_BTB_EN			opt_cpu.h
***************
*** 54,59 ****
--- 55,61 ----
  CPU_FASTER_5X86_FPU		opt_cpu.h
  CPU_I486_ON_386			opt_cpu.h
  CPU_IORT			opt_cpu.h
+ CPU_K6_DISABLE_L1		opt_cpu.h
  CPU_LOOP_EN			opt_cpu.h
  CPU_RSTK_EN			opt_cpu.h
  CPU_SUSP_HLT			opt_cpu.h
*** sys/i386/i386/identcpu.c.ORIG	Thu Oct  1 02:38:40 1998
--- sys/i386/i386/identcpu.c	Thu Oct  1 03:52:26 1998
***************
*** 273,278 ****
--- 273,284 ----
  		case 0x560:
  			strcat(cpu_model, "K6");
  			break;
+ 		case 0x570:
+ 			strcat(cpu_model, "K6 266 (model 1)");
+ 			break;
+ 		case 0x580:
+ 			strcat(cpu_model, "K6-2");
+ 			break;
  		default:
  			strcat(cpu_model, "Unknown");
  			break;
***************
*** 488,494 ****
  			 * to check that all CPUs >= Pentium have a TSC and
  			 * MSRs.
  			 */
! 			printf("\n  Features=0x%b", cpu_feature, 
  			"\020"
  			"\001FPU"
  			"\002VME"
--- 494,500 ----
  			 * to check that all CPUs >= Pentium have a TSC and
  			 * MSRs.
  			 */
! 			printf("\n  Features=0x%b", cpu_feature,
  			"\020"
  			"\001FPU"
  			"\002VME"
***************
*** 636,642 ****
  
  	trap_by_rdmsr = 0;
  
! 	/* 
  	 * Cyrix 486-class CPU does not support rdmsr instruction.
  	 * The rdmsr instruction generates invalid opcode fault, and exception
  	 * will be trapped by bluetrap6() on Cyrix 486-class CPU.  The
--- 642,648 ----
  
  	trap_by_rdmsr = 0;
  
! 	/*
  	 * Cyrix 486-class CPU does not support rdmsr instruction.
  	 * The rdmsr instruction generates invalid opcode fault, and exception
  	 * will be trapped by bluetrap6() on Cyrix 486-class CPU.  The
***************
*** 792,798 ****
  }
  
  /*
!  * This routine is called specifically to set up cpu_class before 
   * startrtclock() uses it.  Probably this should be rearranged so that
   * startrtclock() doesn't need to run until after identifycpu() has been
   * called.  Another alternative formulation would be for this routine
--- 798,804 ----
  }
  
  /*
!  * This routine is called specifically to set up cpu_class before
   * startrtclock() uses it.  Probably this should be rearranged so that
   * startrtclock() doesn't need to run until after identifycpu() has been
   * called.  Another alternative formulation would be for this routine
***************
*** 816,822 ****
  }
  
  static void
! print_AMD_info(void) 
  {
  	u_int regs[4];
  
--- 822,828 ----
  }
  
  static void
! print_AMD_info(void)
  {
  	u_int regs[4];
  
*** sys/i386/include/specialreg.h.ORIG	Thu Oct  1 02:52:52 1998
--- sys/i386/include/specialreg.h	Thu Oct  1 02:50:25 1998
***************
*** 258,263 ****
--- 258,268 ----
  #define	RCR_WT	0x10	/* Write-through. */
  #define	RCR_NLB	0x20	/* LBA# pin is not asserted. */
  
+ /* AMD Write Allocate Top-Of-Memory and Control Register */
+ #define	AMD_WT_ALLOC_TME	0x40000	/* top-of-memory enable */
+ #define	AMD_WT_ALLOC_PRE	0x20000	/* programmable range enable */
+ #define	AMD_WT_ALLOC_FRE	0x10000	/* fixed (A0000-FFFFF) range enable */
+ 
  
  #ifndef LOCORE
  static __inline u_char
*** sys/i386/i386/initcpu.c.ORIG	Thu Oct  1 02:38:02 1998
--- sys/i386/i386/initcpu.c	Thu Oct  1 03:56:10 1998
***************
*** 52,57 ****
--- 52,62 ----
  static void init_6x86(void);
  #endif /* I486_CPU */
  
+ #ifdef I586_CPU
+ static void	init_amdk5(void);
+ static void	init_amdk6(void);
+ #endif
+ 
  #ifdef I686_CPU
  static void	init_6x86MX(void);
  static void	init_ppro(void);
***************
*** 435,440 ****
--- 440,518 ----
  	write_eflags(eflags);
  }
  
+ #ifdef I586_CPU
+ static void
+ init_amdk5(void)
+ {
+ #ifdef CPU_AMD_WT_ALLOC
+ 	u_long	msr;
+ 
+ 	/*
+ 	 * Make sure the stepping is at least 4.
+ 	 */
+ 	if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 4)) {
+ 		disable_intr();
+ 		msr = rdmsr(0x83);
+ 		wrmsr(0x83, msr&!(0x10));
+ 
+ 		/*
+ 		 *  Now set the programmable range to include the 15M-16M
+ 		 * range for compatibility with hardware that memory-maps
+ 		 * this range.
+ 		 */
+ 		wrmsr(0x86, 0x0ff00f0);
+ 		/*
+ 		 * now we are going to set the Top-Of-Memory Enable and
+ 		 * Fixed-Memory Enable bits in the Write Allocate register
+ 		 * on the AMD. We also have to tell the chip where the top
+ 		 * of memory is. (We don't want to write-allocate past the
+ 		 * top of memory because video cards could have frame
+ 		 * buffers there, memory-mapped I/O could be there, etc.
+ 		 */
+ 		msr=Maxmem>>PAGE_SHIFT<<16;
+ 		wrmsr(0x85, AMD_WT_ALLOC_TME|AMD_WT_ALLOC_PRE|AMD_WT_ALLOC_FRE|msr);
+ 		rdmsr(0x85);
+ 		msr=rdmsr(0x83);
+ 		wrmsr(0x83, msr|0x10); /* enable write allocate */
+ 		enable_intr();
+ 		printf("Write allocation enabled\n");
+ 	}
+ #endif
+ }
+ 
+ static void
+ init_amdk6(void)
+ {
+ #ifdef CPU_AMD_WT_ALLOC
+ 	u_long	eflags;
+ 
+ 	if ((cpu_id & 0xff) > 0x60) {
+ 		eflags = read_eflags();
+ 		disable_intr();
+ 		wbinvd();
+ 		/*
+ 		 * K6 uses a limit measured in 4M blocks (we convert from
+ 		 * pages).  we also make sure that 8-63 are 0 and that we
+ 		 * disable write allocate for the 15-16M range.
+ 		 */
+ 		wrmsr(0x0c0000082, (Maxmem>>9)&0x0fe);
+ 		write_eflags(eflags);
+ 		enable_intr();
+ 		printf("Write allocation enabled.\n");
+ 	}
+ #endif
+ 
+ 	/*
+ 	 * Certain K6-2 box becomes unstable when write allocation is
+ 	 * enabled.
+ 	 */
+ #ifdef CPU_K6_DISABLE_L1
+ 	wrmsr(0x0000000e, (u_int64_t)0x0008);
+ 	printf("L1 cache disabled.\n");
+ #endif
+ }
+ #endif /* I585_CPU */
+ 
  static void
  init_ppro(void)
  {
***************
*** 478,483 ****
--- 556,580 ----
  		init_6x86();
  		break;
  #endif /* I486_CPU */
+ #ifdef I585_CPU
+ 	case CPU_585:
+ 		if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+ 			switch (cpu_id & 0xff0) {
+ 			case 0x500:
+ 			case 0x510:
+ 			case 0x520:
+ 			case 0x530:
+ 				init_amdk5();
+ 				break;
+ 			case 0x560:
+ 			case 0x570:
+ 			case 0x580:		/* XXX K6-2 */
+ 				init_amdk6();
+ 				break;
+ 			}
+ 		}
+ 		break;
+ #endif
  #ifdef I686_CPU
  	case CPU_M2:
  		init_6x86MX();
---------- END ----------
