From kbyanc@www2.freedomnet.com  Thu Sep 10 20:55:48 1998
Received: from freedomnet.com (freedomnet.com [198.240.104.3])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id UAA03532
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 10 Sep 1998 20:55:46 -0700 (PDT)
          (envelope-from kbyanc@www2.freedomnet.com)
Received: from www2.freedomnet.com (www2.freedomnet.com [198.240.104.14])
	by freedomnet.com (8.8.7/8.8.7/antispam) with ESMTP id XAA15375
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 10 Sep 1998 23:50:50 -0400 (EDT)
Received: (from root@localhost)
	by www2.freedomnet.com (8.9.0.Beta5/8.9.0.Beta5) id XAA02014;
	Thu, 10 Sep 1998 23:58:54 -0400 (EDT)
Message-Id: <199809110358.XAA02014@www2.freedomnet.com>
Date: Thu, 10 Sep 1998 23:58:54 -0400 (EDT)
From: kbyanc@freedomnet.com
Reply-To: kbyanc@freedomnet.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: New (fixed) AMD processor detection patch (with write allocate feature)
X-Send-Pr-Version: 3.2

>Number:         7890
>Category:       i386
>Synopsis:       New (fixed) AMD processor detection patch (with write allocate feature)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Sep 10 21:00:01 PDT 1998
>Closed-Date:    Fri Oct 9 23:18:26 PDT 1998
>Last-Modified:  Fri Oct  9 23:19:20 PDT 1998
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: gnats-admin->freebsd-bugs 
Responsible-Changed-By: steve 
Responsible-Changed-When: Fri Sep 18 22:01:52 PDT 1998 
Responsible-Changed-Why:  
Misfiled PR. 
State-Changed-From-To: open->closed 
State-Changed-By: kato 
State-Changed-When: Fri Oct 9 23:18:26 PDT 1998 
State-Changed-Why:  
AMD write allocate has been supported in current. 
>Unformatted:
AMD processors' write allocate feature. Previous version did not detect new AMD K6-2
processors nor properly enabled the write allocate feature (I uploaded the wrong patch :( )
New kernel option was also added to enable the write allocate support: CPU_AMD_WT_ALLOC
(options CPU_AMD_WT_ALLOC).
  AMD lists write allocate as experimental and only supported on K6 processors with the 
following BIOS revisions:
     Award - Compile dates of March 1, 1997 or later 
     AMI - CPU Module 3.31 or later 
     Phoenix - Version 4.0 
         Release 6.0 or Release 5.1 w/build dates 4/7/97 or later. 

 patch follows...


diff -c -r ./i386/identcpu.c /sys/i386/i386/identcpu.c
*** ./i386/identcpu.c	Thu Sep 10 23:19:41 1998
--- /sys/i386/i386/identcpu.c	Thu Sep 10 23:29:27 1998
***************
*** 95,100 ****
--- 95,103 ----
  	{ "Cyrix 6x86MX",	CPUCLASS_686 },		/* CPU_M2 */
  	{ "NexGen 586",		CPUCLASS_386 },		/* CPU_NX586 (XXX) */
  	{ "Cyrix 486S/DX",	CPUCLASS_486 },		/* CPU_CY486DX */
+ 	{ "AMD K5",		CPUCLASS_586 },		/* CPU_AMDK5 */
+ 	{ "AMD K6",		CPUCLASS_586 },		/* CPU_AMDK6 */
+ 	{ "AMD K6-2",		CPUCLASS_586 },		/* CPU_AMDK62 */
  };
  
  static void
***************
*** 227,232 ****
--- 230,241 ----
  		case 0x560:
  			strcat(cpu_model, "K6");
  			break;
+ 		case 0x570:
+ 			strcat(cpu_model, "K6 266 (model 1)");
+ 			break;
+ 		case 0x580:
+ 			strcat(cpu_model, "K6-2 w/3DNow!");
+ 			break;
  		default:
  			strcat(cpu_model, "Unknown");
  			break;
***************
*** 437,443 ****
  			 * to check that all CPUs >= Pentium have a TSC and
  			 * MSRs.
  			 */
! 			printf("\n  Features=0x%b", cpu_feature, 
  			"\020"
  			"\001FPU"
  			"\002VME"
--- 446,452 ----
  			 * to check that all CPUs >= Pentium have a TSC and
  			 * MSRs.
  			 */
! 			printf("\n  Features=0x%b", cpu_feature,
  			"\020"
  			"\001FPU"
  			"\002VME"
***************
*** 585,591 ****
  
  	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
--- 594,600 ----
  
  	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
***************
*** 735,744 ****
  			}
  		}
  	}
  }
  
  /*
!  * 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
--- 744,767 ----
  			}
  		}
  	}
+ 	else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+ 		switch (cpu_id & 0xff0) {
+ 		case 0x500:
+ 		case 0x510:
+ 		case 0x520:
+ 		case 0x530: cpu = CPU_AMDK5;
+ 			    break;
+ 		case 0x560:
+ 		case 0x570: cpu = CPU_AMDK6;
+                 	    break;
+ 		case 0x580: cpu = CPU_AMDK62;
+ 			    break;
+ 		}
+ 	}
  }
  
  /*
!  * 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
***************
*** 762,768 ****
  }
  
  static void
! print_AMD_info(void) 
  {
  	u_long regs[4];
  
--- 785,791 ----
  }
  
  static void
! print_AMD_info(void)
  {
  	u_long regs[4];
  
Only in /sys/i386/i386: identcpu.c.orig
Only in /sys/i386/i386: in_cksum.c
diff -c -r ./i386/initcpu.c /sys/i386/i386/initcpu.c
*** ./i386/initcpu.c	Thu Sep 10 23:19:41 1998
--- /sys/i386/i386/initcpu.c	Fri Apr 10 15:31:19 1998
***************
*** 52,61 ****
--- 52,134 ----
  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);
  #endif
  
+ #ifdef I586_CPU
+ /* support for AMD write allocate function added by Kelly Yancey,
+    kbyanc@freedomnet.com 4/10/98
+ */
+ /* bit definitions for 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 */
+ 
+ static void init_amdK5(void)
+ {
+ 	u_long	msr;
+ #ifdef CPU_AMD_WT_ALLOC
+ /* enable write allocate on AMD processors that support it */
+ /* AMD K5, Model 1, 2, and 3 Stepping 4 or higher all support it per
+    AMD Write Allocate Application Note: http://www.amd.com/K6/k6docs/pdf/21326c.pdf
+ */
+ 	if(((cpu_id & 0xF0) > 0) &&  /* check the model number (K6 is technically model 6, but we
+ 					have already identified this as a K5 so that's moot */
+ 	  ((cpu_id & 0x0F) > 4)) {   /* make sure the stepping is at least 4 */
+ 		disable_intr();
+ 		msr=rdmsr(0x83);     /* AMD Hardware Configuration Register */
+ 		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; /* load the msr with the high 16 bits of the top of physical memory */
+ 		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();
+ 	}
+ #endif
+ }
+ 
+ static void init_amdK6(void)
+ {
+ 	u_long	eflags;
+ #ifdef CPU_AMD_WT_ALLOC
+ /* enable write allocate on AMD processors that support it */
+ /* AMD K6, Model 1 Stepping 4 or higher all support it per
+    AMD Write Allocate Application Note: http://www.amd.com/K6/k6docs/pdf/21326c.pdf
+ */
+ 	if((cpu_id & 0xFF) > 0x60) {   /* we already know it is a K6, just check the stepping
+ 					 (later models appear to support write allocate no matter
+ 					 what the stepping) */
+ 		eflags = read_eflags();
+ 		disable_intr();
+ 		wbinvd();			/* the K6 requires us to invalidate the cache */
+ 		wrmsr(0x0C0000082, ((Maxmem>>9)&0x0FE)|0x100);/* K6 uses a limit measured in 4M blocks (we convert from pages).
+ 							 we also make sure that 9-63 are 0 and that we disable
+ 							 write allocate for the 15-16M range */
+ 		write_eflags(eflags);
+ 		enable_intr();
+ 	}
+ #endif
+ }
+ #endif /* I586_CPU */
+ 
+ 
  #ifdef I486_CPU
  /*
   * IBM Blue Lightning
***************
*** 462,467 ****
--- 535,548 ----
  		init_6x86();
  		break;
  #endif /* I486_CPU */
+ #ifdef I586_CPU
+ 	case CPU_AMDK5:
+ 		init_amdK5();
+ 		break;
+ 	case CPU_AMDK6:
+ 		init_amdK6();
+ 		break;
+ #endif /* I586_CPU */
  #ifdef I686_CPU
  	case CPU_M2:
  		init_6x86MX();
diff -c -r ./include/cputypes.h /sys/i386/include/cputypes.h
*** ./include/cputypes.h	Thu Sep 10 23:19:50 1998
--- /sys/i386/include/cputypes.h	Thu Sep 10 23:21:50 1998
***************
*** 58,61 ****
--- 58,64 ----
  #define	CPU_M2		11	/* Cyrix M2 (aka enhanced 6x86 with MMX */
  #define CPU_NX586	12	/* NexGen (now AMD) 586 */
  #define	CPU_CY486DX	13	/* Cyrix 486S/DX/DX2/DX4 */
+ #define CPU_AMDK5	14	/* AMD K5 */
+ #define CPU_AMDK6	15	/* AMD K6 with MMX */
+ #define CPU_AMDK62	16	/* AMD K6-2 with MMX, 3D-Now!, superfunk.... */
  #endif /* _MACHINE_CPUTYPES_H_ */
