NetBSD Problem Report #38480

From tls@rek.tjls.com  Mon Apr 21 18:50:15 2008
Return-Path: <tls@rek.tjls.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id 71E1863B293
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 21 Apr 2008 18:50:15 +0000 (UTC)
Message-Id: <20080421184833.2FCDD49ABF@claw.hvg.tjls.com>
Date: Mon, 21 Apr 2008 14:48:33 -0400 (EDT)
From: tls@NetBSD.ORG
Reply-To: tls@NetBSD.oRG
To: gnats-bugs@gnats.NetBSD.org
Subject: x86 MTRR code makes invalid assumption of 8 variable MTRRs
X-Send-Pr-Version: 3.95

>Number:         38480
>Category:       port-amd64
>Synopsis:       x86 MTRR code makes invalid assumption of 8 variable MTRRs
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    port-amd64-maintainer
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 21 18:55:00 +0000 2008
>Closed-Date:    Fri Nov 06 22:44:02 +0000 2009
>Last-Modified:  Thu Jun 06 07:15:01 +0000 2013
>Originator:     tls@NetBSD.oRG
>Release:        NetBSD 4.99.58
>Organization:
	The NetBSD Foundation
>Environment:
System: NetBSD claw 4.99.58 NetBSD 4.99.58 (GENERIC) #1: Wed Apr 9 01:06:27 EDT 2008 tls@claw:/usr/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
	On a 2 socket SuperMicro X7DCL motherboard with two 4-core Xeon E5405
	processors, an amd64 INSTALL or GENERIC kernel panics in cpu_init
	for the boot processor.  This panic occurs because it receives a
	protection fault on the rdmsr() for the 8th variable MTRR for the
	CPU; this fault is not handled, though rdmsr() is defined to give
	a protection fault on any attempt to read an invalid MSR.

	It appears that on this CPU, as configured by this motherboard's
	BIOS, only 7 (not 8) variable MTRRs can be used by the OS (at
	least in 64 bit mode, possibly in 32 bit mode as well).  Supposedly
	this CPU family has a new (third?) MTRR type available which may,
	though the BIOS has been configured to disable it, be what is
	consuming the last variable MTRR.

	Evidently, though all prior Intel CPUs have actually had 8 MTRRs
	and some other manufacturers' CPU families are defined to have 8
	MTRRs (e.g. VIA/Centaur), Intel has never specified that 8 MTRRs
	will be present.  Rather, the OS is supposed to read the MTRR
	config register and mask the returned value with 0xff to obtain
	the number of variable-size MTRRs available for use.

	We can't do this because we use fixed size arrays to index the
	hardware MTRRs.  We need to adjust that.  Also, Linux code seems
	to believe that AMD CPUs have only 2 variable MTRRs but I think
	this actually applies only to K6 generation CPUs and is already
	handled by our i386 specific MTRR code.

	If I knew how to find the fixed MTRRs with an arbitrary number of
	variable MTRRs present, I think this would be a reasonably simple
	fix -- but I don't know that and don't have time to find the
	right Intel document today, thus this PR.  If someone else has
	it handy, I can provide access to my system which exhibits this
	problem for quick testing.

>How-To-Repeat:
	Try to boot a NetBSD/amd64 kernel on a SuperMicro X7DCL-3 or
	X7DCL-I motherboard with BIOS revision 1.0 and two Intel Xeon
	E5405 2.0GHz quad-core processors.  Boom.
>Fix:
	Removing options MTRR from the kernel config leaves the system
	working reasonably well, though I doubt it'd make X happy (I
	could care less about X).

>Release-Note:

>Audit-Trail:
From: Thor Lancelot Simon <tls@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/38480 CVS commit: src/sys/arch/amd64
Date: Mon, 21 Apr 2008 19:06:43 +0000 (UTC)

 Module Name:	src
 Committed By:	tls
 Date:		Mon Apr 21 19:06:43 UTC 2008

 Modified Files:
 	src/sys/arch/amd64/amd64: netbsd32_machdep.c
 	src/sys/arch/amd64/conf: INSTALL

 Log Message:
 Work around PR38480 by making it possible to omit options MTRR from
 amd64 INSTALL kernels -- and doing so.  At least you can now get an
 INSTALL kernel onto a box with this odd MTRR configuration to debug it.


 To generate a diff of this commit:
 cvs rdiff -r1.48 -r1.49 src/sys/arch/amd64/amd64/netbsd32_machdep.c
 cvs rdiff -r1.78 -r1.79 src/sys/arch/amd64/conf/INSTALL

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Andrew Doran <ad@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: port-amd64/38480: x86 MTRR code makes invalid assumption of 8 variable MTRRs
Date: Tue, 22 Apr 2008 20:47:11 +0100

 On Mon, Apr 21, 2008 at 06:55:00PM +0000, tls@NetBSD.ORG wrote:

 > 	will be present.  Rather, the OS is supposed to read the MTRR
 > 	config register and mask the returned value with 0xff to obtain
 > 	the number of variable-size MTRRs available for use.

 Do you have a reference for that?

 Andrew

From: Thor Lancelot Simon <tls@rek.tjls.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: port-amd64/38480: x86 MTRR code makes invalid assumption of 8 variable MTRRs
Date: Tue, 22 Apr 2008 16:03:07 -0400

 On Tue, Apr 22, 2008 at 07:50:02PM +0000, Andrew Doran wrote:
 >  
 >  > 	will be present.  Rather, the OS is supposed to read the MTRR
 >  > 	config register and mask the returned value with 0xff to obtain
 >  > 	the number of variable-size MTRRs available for use.
 >  
 >  Do you have a reference for that?

 At this point, allow me to lamely indicate that it's what the Linux code,
 which works on this platform, does... but I did find a reference to it
 in an Intel document yesterday -- I'll try to find it again.

From: Thor Lancelot Simon <tls@rek.tjls.com>
To: gnats-bugs@NetBSD.org
Cc: port-amd64-maintainer@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org, tls@NetBSD.ORG, ad@netbsd.org
Subject: Re: port-amd64/38480: x86 MTRR code makes invalid assumption of 8 variable MTRRs
Date: Sat, 26 Apr 2008 10:05:51 -0400

 On Tue, Apr 22, 2008 at 07:50:02PM +0000, Andrew Doran wrote:
 >
 >  Do you have a reference for that?

 http://lkml.org/lkml/2005/9/28/323 refers to two Intel "Specification
 Updates", 30240216 for 64-bit mode and 30235221 for 32-bit mode, but
 I can't seem to fetch them from Intel's site right now.

 -- 
   Thor Lancelot Simon	                                     tls@rek.tjls.com

   "The inconsistency is startling, though admittedly, if consistency is to
    be abandoned or transcended, there is no problem."	      - Noam Chomsky

From: Thor Lancelot Simon <tls@rek.tjls.com>
To: gnats-bugs@NetBSD.org
Cc: port-amd64-maintainer@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org, tls@NetBSD.ORG, ad@netbsd.org
Subject: Re: port-amd64/38480: x86 MTRR code makes invalid assumption of 8 variable MTRRs
Date: Sat, 26 Apr 2008 11:02:26 -0400

 This is -- obliquely -- described in the architecture manual, part 3A,
 (Intel document 253668) chapter 10, section 10.11.  This section has
 clearly been repeatedly revised -- it's got typos, and references to
 it in other parts of the document sometimes get the section number
 wrong...

 Now, watch out!  Evidently, newer processors -- such as the one I have --
 are not really, quite, "Pentium 4, Intel Xeon, and P6 family processors"
 in this regard, as you might guess from the fact that many other datasheets
 and spec updates on the Intel site break out the Core and subsequent
 processors separately (e.g. there's a whole separate set of spec updates
 for "800 Mhz bus Xeon" processors); clearly, there are processors out there,
 made by Intel, where "the IA32_MTRRCAP MSR always contains the value 508H"
 is not so, and I've got one.

 It looks like it should always be safe to read (and rely on) VCNT; but
 assuming there are always 8 is no longer safe.

 Anyway, 10.11.1 "MTRR Feature Identification" says:

 The availability of the MTRR feature is model-specific. Software can determine
 if MTRRs are supported on a processor by executing the CPUID instruction and
 reading the state of the MTRR flag (bit 12) in the feature information
 register (EDX).

 If the MTRR flag is set (indicating that the processor implements MTRRs),
 additional information about MTRRs can be obtained from the 64-bit
 IA32_MTRRCAP MSR (named MTRRcap MSR for the P6 family processors). The
 IA32_MTRRCAP MSR is a read-only MSR that can be read with the RDMSR
 instruction. Figure 10-4 shows the contents of the IA32_MTRRCAP MSR. The
 functions of the flags and field in this register are as follows:

 *	VCNT (variable range registers count) field, bits 0 through 7 --
 		Indicates the number of variable ranges implemented on the
 		processor. The Pentium 4, Intel Xeon, and P6 family processors
 		have eight pairs of MTRRs for setting up eight variable ranges.

 *	FIX (fixed range registers supported) flag, bit 8 -- Fixed
 		range MTRRs (IA32_MTRR_FIX64K_00000 through
 		IA32_MTRR_FIX4K_0F8000) are supported when set; no fixed
 		range registers are supported when clear.

 *	WC (write combining) flag, bit 10 -- The write-combining
 	(WC) memory type is supported when set; the WC type is not
 	supported when clear.

 Bit 9 and bits 11 through 63 in the IA32_MTRRCAP MSR are reserved.
 If software attempts to write to the IA32_MTRRCAP MSR, a general-protection
 exception (#GP) is generated.

 For the Pentium 4, Intel Xeon, and P6 family processors, the IA32_MTRRCAP MSR
 always contains the value 508H.

From: matthew green <mrg@eterna.com.au>
To: gnats-bugs@NetBSD.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
    netbsd-bugs@netbsd.org, tls@NetBSD.ORG, ad@netbsd.org
Subject: re: port-amd64/38480
Date: Mon, 30 Jun 2008 05:58:14 +1000

 this lame patch makes this problem go away for me, but it only papers over
 the general problem, and works for MTRR VCNT < 8 case that now exists in
 the real hardware.

 i haven't tested this on real intel hardware (i don't have any that don't
 have this problem i can easily reboot) so it would be great if someone
 else tested this patch on an older intel cpu (i686-class, please :-)


 andy, OK to commit this given it works?  this PR can be decreased in
 priority and i686_mtrr.c will need more work for >8 VCNT to properly
 close it, but for now this lets my system actually work.


 .mrg.

 Index: include/mtrr.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/x86/include/mtrr.h,v
 retrieving revision 1.3
 diff -p -r1.3 mtrr.h
 *** include/mtrr.h	28 Apr 2008 20:23:40 -0000	1.3
 --- include/mtrr.h	29 Jun 2008 19:53:43 -0000
 ***************
 *** 36,42 ****
   #define MTRR_I686_FIXED_IDX16K	1
   #define MTRR_I686_FIXED_IDX4K	3

 ! #define MTRR_I686_NVAR		8

   #define MTRR_I686_64K_START		0x00000
   #define MTRR_I686_16K_START		0x80000
 --- 36,42 ----
   #define MTRR_I686_FIXED_IDX16K	1
   #define MTRR_I686_FIXED_IDX4K	3

 ! #define MTRR_I686_NVAR_MAX	8	/* could be upto 255? */

   #define MTRR_I686_64K_START		0x00000
   #define MTRR_I686_16K_START		0x80000
 Index: x86/mtrr_i686.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/x86/x86/mtrr_i686.c,v
 retrieving revision 1.17
 diff -p -r1.17 mtrr_i686.c
 *** x86/mtrr_i686.c	12 May 2008 14:41:07 -0000	1.17
 --- x86/mtrr_i686.c	29 Jun 2008 19:53:43 -0000
 *************** mtrr_raw[] = {
 *** 96,104 ****
 --- 96,106 ----
   	{ MSR_MTRRfix4K_F0000, 0 },
   	{ MSR_MTRRfix4K_F8000, 0 },
   	{ MSR_MTRRdefType, 0 },
 + 
   };

   static const int nmtrr_raw = sizeof(mtrr_raw)/sizeof(mtrr_raw[0]);
 + static int i686_mtrr_vcnt = 0;

   static struct mtrr_state *mtrr_var_raw;
   static struct mtrr_state *mtrr_fixed_raw;
 *************** i686_mtrr_reload(int synch)
 *** 229,234 ****
 --- 231,238 ----
   	for (i = 0; i < nmtrr_raw; i++) {
   		uint64_t val = mtrr_raw[i].msrval;
   		uint32_t addr = mtrr_raw[i].msraddr;
 + 		if (addr == 0)
 + 			continue;
   		if (addr == MSR_MTRRdefType)
   			val &= ~MTRR_I686_ENABLE_MASK;
   		wrmsr(addr, val);
 *************** i686_mtrr_init_first(void)
 *** 294,302 ****
   {
   	int i;

 - 	for (i = 0; i < nmtrr_raw; i++)
 - 		mtrr_raw[i].msrval = rdmsr(mtrr_raw[i].msraddr);
   	i686_mtrr_cap = rdmsr(MSR_MTRRcap);
   #if 0
   	mtrr_dump("init mtrr");
   #endif
 --- 298,320 ----
   {
   	int i;

   	i686_mtrr_cap = rdmsr(MSR_MTRRcap);
 + 	i686_mtrr_vcnt = i686_mtrr_cap & MTRR_I686_CAP_VCNT_MASK;
 + 
 + 	if (i686_mtrr_vcnt > MTRR_I686_NVAR_MAX)
 + 		printf("\%s: FIXME: more than 8 mtrr's\n", __FILE__);
 + 	else if (i686_mtrr_vcnt < MTRR_I686_NVAR_MAX) {
 + 		for (i = MTRR_I686_NVAR_MAX - i686_mtrr_vcnt; i; i--) {
 + 			mtrr_raw[16 - (i*2)].msraddr = 0;
 + 			mtrr_raw[17 - (i*2)].msraddr = 0;
 + 		}
 + 	}
 + 
 + 	for (i = 0; i < nmtrr_raw; i++)
 + 		if (mtrr_raw[i].msraddr)
 + 			mtrr_raw[i].msrval = rdmsr(mtrr_raw[i].msraddr);
 + 		else
 + 			mtrr_raw[i].msrval = 0;
   #if 0
   	mtrr_dump("init mtrr");
   #endif
 *************** i686_mtrr_init_first(void)
 *** 308,319 ****
   		panic("can't allocate fixed MTRR array");

   	mtrr_var = (struct mtrr *)
 ! 	    malloc(MTRR_I686_NVAR * sizeof (struct mtrr), M_TEMP, M_NOWAIT);
   	if (mtrr_var == NULL)
   		panic("can't allocate variable MTRR array");

   	mtrr_var_raw = &mtrr_raw[0];
 ! 	mtrr_fixed_raw = &mtrr_raw[MTRR_I686_NVAR * 2];
   	mtrr_funcs = &i686_mtrr_funcs;

   	i686_raw2soft();
 --- 326,337 ----
   		panic("can't allocate fixed MTRR array");

   	mtrr_var = (struct mtrr *)
 ! 	    malloc(i686_mtrr_vcnt * sizeof (struct mtrr), M_TEMP, M_NOWAIT);
   	if (mtrr_var == NULL)
   		panic("can't allocate variable MTRR array");

   	mtrr_var_raw = &mtrr_raw[0];
 ! 	mtrr_fixed_raw = &mtrr_raw[MTRR_I686_NVAR_MAX * 2];
   	mtrr_funcs = &i686_mtrr_funcs;

   	i686_raw2soft();
 *************** i686_raw2soft(void)
 *** 326,332 ****
   	struct mtrr *mtrrp;
   	uint64_t base, mask;

 ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
   		mtrrp = &mtrr_var[i];
   		memset(mtrrp, 0, sizeof *mtrrp);
   		mask = mtrr_var_raw[i * 2 + 1].msrval;
 --- 344,350 ----
   	struct mtrr *mtrrp;
   	uint64_t base, mask;

 ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
   		mtrrp = &mtrr_var[i];
   		memset(mtrrp, 0, sizeof *mtrrp);
   		mask = mtrr_var_raw[i * 2 + 1].msrval;
 *************** i686_soft2raw(void)
 *** 391,397 ****
   	uint64_t val;
   	struct mtrr *mtrrp;

 ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
   		mtrrp = &mtrr_var[i];
   		mtrr_var_raw[i * 2].msrval = mtrr_base_value(mtrrp);
   		mtrr_var_raw[i * 2 + 1].msrval = mtrr_mask_value(mtrrp);
 --- 409,415 ----
   	uint64_t val;
   	struct mtrr *mtrrp;

 ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
   		mtrrp = &mtrr_var[i];
   		mtrr_var_raw[i * 2].msrval = mtrr_base_value(mtrrp);
   		mtrr_var_raw[i * 2 + 1].msrval = mtrr_mask_value(mtrrp);
 *************** i686_mtrr_setone(struct mtrr *mtrrp, str
 *** 588,594 ****
   	low = mtrrp->base;
   	high = low + mtrrp->len;
   	freep = NULL;
 ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
   		if (!(mtrr_var[i].flags & MTRR_VALID)) {
   			freep = &mtrr_var[i];
   			continue;
 --- 606,612 ----
   	low = mtrrp->base;
   	high = low + mtrrp->len;
   	freep = NULL;
 ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
   		if (!(mtrr_var[i].flags & MTRR_VALID)) {
   			freep = &mtrr_var[i];
   			continue;
 *************** i686_mtrr_clean(struct proc *p)
 *** 631,637 ****
   			mtrr_fixed[i].flags &= ~MTRR_PRIVATE;
   	}

 ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
   		if ((mtrr_var[i].flags & MTRR_PRIVATE) &&
   		    (mtrr_var[i].owner == p->p_pid))
   			mtrr_var[i].flags &= ~(MTRR_PRIVATE | MTRR_VALID);
 --- 649,655 ----
   			mtrr_fixed[i].flags &= ~MTRR_PRIVATE;
   	}

 ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
   		if ((mtrr_var[i].flags & MTRR_PRIVATE) &&
   		    (mtrr_var[i].owner == p->p_pid))
   			mtrr_var[i].flags &= ~(MTRR_PRIVATE | MTRR_VALID);
 *************** i686_mtrr_set(struct mtrr *mtrrp, int *n
 *** 646,652 ****
   	int i, error;
   	struct mtrr mtrr;

 ! 	if (*n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR)) {
   		*n = 0;
   		return EINVAL;
   	}
 --- 664,670 ----
   	int i, error;
   	struct mtrr mtrr;

 ! 	if (*n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) {
   		*n = 0;
   		return EINVAL;
   	}
 *************** i686_mtrr_get(struct mtrr *mtrrp, int *n
 *** 678,684 ****
   	int idx, i, error;

   	if (mtrrp == NULL) {
 ! 		*n = MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR;
   		return 0;
   	}

 --- 696,702 ----
   	int idx, i, error;

   	if (mtrrp == NULL) {
 ! 		*n = MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX;
   		return 0;
   	}

 *************** i686_mtrr_get(struct mtrr *mtrrp, int *n
 *** 698,704 ****
   		return error;
   	}

 ! 	for (i = 0; i < MTRR_I686_NVAR && idx < *n; idx++, i++) {
   		if (flags & MTRR_GETSET_USER) {
   			error = copyout(&mtrr_var[i], &mtrrp[idx],
   					sizeof *mtrrp);
 --- 716,722 ----
   		return error;
   	}

 ! 	for (i = 0; i < i686_mtrr_vcnt && idx < *n; idx++, i++) {
   		if (flags & MTRR_GETSET_USER) {
   			error = copyout(&mtrr_var[i], &mtrrp[idx],
   					sizeof *mtrrp);

From: Andrew Doran <ad@netbsd.org>
To: matthew green <mrg@eterna.com.au>
Cc: gnats-bugs@NetBSD.org, kern-bug-people@netbsd.org,
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, tls@NetBSD.ORG
Subject: Re: port-amd64/38480
Date: Tue, 1 Jul 2008 10:43:56 +0000

 On Mon, Jun 30, 2008 at 05:58:14AM +1000, matthew green wrote:

 > this lame patch makes this problem go away for me, but it only papers over
 > the general problem, and works for MTRR VCNT < 8 case that now exists in
 > the real hardware.
 > 
 > i haven't tested this on real intel hardware (i don't have any that don't
 > have this problem i can easily reboot) so it would be great if someone
 > else tested this patch on an older intel cpu (i686-class, please :-)
 > 
 > 
 > andy, OK to commit this given it works?  this PR can be decreased in
 > priority and i686_mtrr.c will need more work for >8 VCNT to properly
 > close it, but for now this lets my system actually work.

 If it works for you, please commit.

 Thanks,
 Andrew

 > 
 > .mrg.
 > 
 > Index: include/mtrr.h
 > ===================================================================
 > RCS file: /cvsroot/src/sys/arch/x86/include/mtrr.h,v
 > retrieving revision 1.3
 > diff -p -r1.3 mtrr.h
 > *** include/mtrr.h	28 Apr 2008 20:23:40 -0000	1.3
 > --- include/mtrr.h	29 Jun 2008 19:53:43 -0000
 > ***************
 > *** 36,42 ****
 >   #define MTRR_I686_FIXED_IDX16K	1
 >   #define MTRR_I686_FIXED_IDX4K	3
 >   
 > ! #define MTRR_I686_NVAR		8
 >   
 >   #define MTRR_I686_64K_START		0x00000
 >   #define MTRR_I686_16K_START		0x80000
 > --- 36,42 ----
 >   #define MTRR_I686_FIXED_IDX16K	1
 >   #define MTRR_I686_FIXED_IDX4K	3
 >   
 > ! #define MTRR_I686_NVAR_MAX	8	/* could be upto 255? */
 >   
 >   #define MTRR_I686_64K_START		0x00000
 >   #define MTRR_I686_16K_START		0x80000
 > Index: x86/mtrr_i686.c
 > ===================================================================
 > RCS file: /cvsroot/src/sys/arch/x86/x86/mtrr_i686.c,v
 > retrieving revision 1.17
 > diff -p -r1.17 mtrr_i686.c
 > *** x86/mtrr_i686.c	12 May 2008 14:41:07 -0000	1.17
 > --- x86/mtrr_i686.c	29 Jun 2008 19:53:43 -0000
 > *************** mtrr_raw[] = {
 > *** 96,104 ****
 > --- 96,106 ----
 >   	{ MSR_MTRRfix4K_F0000, 0 },
 >   	{ MSR_MTRRfix4K_F8000, 0 },
 >   	{ MSR_MTRRdefType, 0 },
 > + 
 >   };
 >   
 >   static const int nmtrr_raw = sizeof(mtrr_raw)/sizeof(mtrr_raw[0]);
 > + static int i686_mtrr_vcnt = 0;
 >   
 >   static struct mtrr_state *mtrr_var_raw;
 >   static struct mtrr_state *mtrr_fixed_raw;
 > *************** i686_mtrr_reload(int synch)
 > *** 229,234 ****
 > --- 231,238 ----
 >   	for (i = 0; i < nmtrr_raw; i++) {
 >   		uint64_t val = mtrr_raw[i].msrval;
 >   		uint32_t addr = mtrr_raw[i].msraddr;
 > + 		if (addr == 0)
 > + 			continue;
 >   		if (addr == MSR_MTRRdefType)
 >   			val &= ~MTRR_I686_ENABLE_MASK;
 >   		wrmsr(addr, val);
 > *************** i686_mtrr_init_first(void)
 > *** 294,302 ****
 >   {
 >   	int i;
 >   
 > - 	for (i = 0; i < nmtrr_raw; i++)
 > - 		mtrr_raw[i].msrval = rdmsr(mtrr_raw[i].msraddr);
 >   	i686_mtrr_cap = rdmsr(MSR_MTRRcap);
 >   #if 0
 >   	mtrr_dump("init mtrr");
 >   #endif
 > --- 298,320 ----
 >   {
 >   	int i;
 >   
 >   	i686_mtrr_cap = rdmsr(MSR_MTRRcap);
 > + 	i686_mtrr_vcnt = i686_mtrr_cap & MTRR_I686_CAP_VCNT_MASK;
 > + 
 > + 	if (i686_mtrr_vcnt > MTRR_I686_NVAR_MAX)
 > + 		printf("\%s: FIXME: more than 8 mtrr's\n", __FILE__);
 > + 	else if (i686_mtrr_vcnt < MTRR_I686_NVAR_MAX) {
 > + 		for (i = MTRR_I686_NVAR_MAX - i686_mtrr_vcnt; i; i--) {
 > + 			mtrr_raw[16 - (i*2)].msraddr = 0;
 > + 			mtrr_raw[17 - (i*2)].msraddr = 0;
 > + 		}
 > + 	}
 > + 
 > + 	for (i = 0; i < nmtrr_raw; i++)
 > + 		if (mtrr_raw[i].msraddr)
 > + 			mtrr_raw[i].msrval = rdmsr(mtrr_raw[i].msraddr);
 > + 		else
 > + 			mtrr_raw[i].msrval = 0;
 >   #if 0
 >   	mtrr_dump("init mtrr");
 >   #endif
 > *************** i686_mtrr_init_first(void)
 > *** 308,319 ****
 >   		panic("can't allocate fixed MTRR array");
 >   
 >   	mtrr_var = (struct mtrr *)
 > ! 	    malloc(MTRR_I686_NVAR * sizeof (struct mtrr), M_TEMP, M_NOWAIT);
 >   	if (mtrr_var == NULL)
 >   		panic("can't allocate variable MTRR array");
 >   
 >   	mtrr_var_raw = &mtrr_raw[0];
 > ! 	mtrr_fixed_raw = &mtrr_raw[MTRR_I686_NVAR * 2];
 >   	mtrr_funcs = &i686_mtrr_funcs;
 >   
 >   	i686_raw2soft();
 > --- 326,337 ----
 >   		panic("can't allocate fixed MTRR array");
 >   
 >   	mtrr_var = (struct mtrr *)
 > ! 	    malloc(i686_mtrr_vcnt * sizeof (struct mtrr), M_TEMP, M_NOWAIT);
 >   	if (mtrr_var == NULL)
 >   		panic("can't allocate variable MTRR array");
 >   
 >   	mtrr_var_raw = &mtrr_raw[0];
 > ! 	mtrr_fixed_raw = &mtrr_raw[MTRR_I686_NVAR_MAX * 2];
 >   	mtrr_funcs = &i686_mtrr_funcs;
 >   
 >   	i686_raw2soft();
 > *************** i686_raw2soft(void)
 > *** 326,332 ****
 >   	struct mtrr *mtrrp;
 >   	uint64_t base, mask;
 >   
 > ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
 >   		mtrrp = &mtrr_var[i];
 >   		memset(mtrrp, 0, sizeof *mtrrp);
 >   		mask = mtrr_var_raw[i * 2 + 1].msrval;
 > --- 344,350 ----
 >   	struct mtrr *mtrrp;
 >   	uint64_t base, mask;
 >   
 > ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
 >   		mtrrp = &mtrr_var[i];
 >   		memset(mtrrp, 0, sizeof *mtrrp);
 >   		mask = mtrr_var_raw[i * 2 + 1].msrval;
 > *************** i686_soft2raw(void)
 > *** 391,397 ****
 >   	uint64_t val;
 >   	struct mtrr *mtrrp;
 >   
 > ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
 >   		mtrrp = &mtrr_var[i];
 >   		mtrr_var_raw[i * 2].msrval = mtrr_base_value(mtrrp);
 >   		mtrr_var_raw[i * 2 + 1].msrval = mtrr_mask_value(mtrrp);
 > --- 409,415 ----
 >   	uint64_t val;
 >   	struct mtrr *mtrrp;
 >   
 > ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
 >   		mtrrp = &mtrr_var[i];
 >   		mtrr_var_raw[i * 2].msrval = mtrr_base_value(mtrrp);
 >   		mtrr_var_raw[i * 2 + 1].msrval = mtrr_mask_value(mtrrp);
 > *************** i686_mtrr_setone(struct mtrr *mtrrp, str
 > *** 588,594 ****
 >   	low = mtrrp->base;
 >   	high = low + mtrrp->len;
 >   	freep = NULL;
 > ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
 >   		if (!(mtrr_var[i].flags & MTRR_VALID)) {
 >   			freep = &mtrr_var[i];
 >   			continue;
 > --- 606,612 ----
 >   	low = mtrrp->base;
 >   	high = low + mtrrp->len;
 >   	freep = NULL;
 > ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
 >   		if (!(mtrr_var[i].flags & MTRR_VALID)) {
 >   			freep = &mtrr_var[i];
 >   			continue;
 > *************** i686_mtrr_clean(struct proc *p)
 > *** 631,637 ****
 >   			mtrr_fixed[i].flags &= ~MTRR_PRIVATE;
 >   	}
 >   
 > ! 	for (i = 0; i < MTRR_I686_NVAR; i++) {
 >   		if ((mtrr_var[i].flags & MTRR_PRIVATE) &&
 >   		    (mtrr_var[i].owner == p->p_pid))
 >   			mtrr_var[i].flags &= ~(MTRR_PRIVATE | MTRR_VALID);
 > --- 649,655 ----
 >   			mtrr_fixed[i].flags &= ~MTRR_PRIVATE;
 >   	}
 >   
 > ! 	for (i = 0; i < i686_mtrr_vcnt; i++) {
 >   		if ((mtrr_var[i].flags & MTRR_PRIVATE) &&
 >   		    (mtrr_var[i].owner == p->p_pid))
 >   			mtrr_var[i].flags &= ~(MTRR_PRIVATE | MTRR_VALID);
 > *************** i686_mtrr_set(struct mtrr *mtrrp, int *n
 > *** 646,652 ****
 >   	int i, error;
 >   	struct mtrr mtrr;
 >   
 > ! 	if (*n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR)) {
 >   		*n = 0;
 >   		return EINVAL;
 >   	}
 > --- 664,670 ----
 >   	int i, error;
 >   	struct mtrr mtrr;
 >   
 > ! 	if (*n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) {
 >   		*n = 0;
 >   		return EINVAL;
 >   	}
 > *************** i686_mtrr_get(struct mtrr *mtrrp, int *n
 > *** 678,684 ****
 >   	int idx, i, error;
 >   
 >   	if (mtrrp == NULL) {
 > ! 		*n = MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR;
 >   		return 0;
 >   	}
 >   
 > --- 696,702 ----
 >   	int idx, i, error;
 >   
 >   	if (mtrrp == NULL) {
 > ! 		*n = MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX;
 >   		return 0;
 >   	}
 >   
 > *************** i686_mtrr_get(struct mtrr *mtrrp, int *n
 > *** 698,704 ****
 >   		return error;
 >   	}
 >   
 > ! 	for (i = 0; i < MTRR_I686_NVAR && idx < *n; idx++, i++) {
 >   		if (flags & MTRR_GETSET_USER) {
 >   			error = copyout(&mtrr_var[i], &mtrrp[idx],
 >   					sizeof *mtrrp);
 > --- 716,722 ----
 >   		return error;
 >   	}
 >   
 > ! 	for (i = 0; i < i686_mtrr_vcnt && idx < *n; idx++, i++) {
 >   		if (flags & MTRR_GETSET_USER) {
 >   			error = copyout(&mtrr_var[i], &mtrrp[idx],
 >   					sizeof *mtrrp);

From: matthew green <mrg@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/38480 CVS commit: src/sys/arch/x86
Date: Tue,  1 Jul 2008 15:27:34 +0000 (UTC)

 Module Name:	src
 Committed By:	mrg
 Date:		Tue Jul  1 15:27:34 UTC 2008

 Modified Files:
 	src/sys/arch/x86/include: mtrr.h
 	src/sys/arch/x86/x86: mtrr_i686.c

 Log Message:
 hack around PR#38480:

 - rename MTRR_I686_NVAR to MTRR_I686_NVAR_MAX, still set to 8
 - store mtrr VCNT value into i686_mtrr_vcnt.  if it is less than 8,
   zero out the relevant parts of mtrr_raw[].msraddr
 - replace all usage of MTRR_I686_NVAR with either i686_mtrr_vcnt or
   with MTRR_I686_NVAR_MAX as appropriate
 - in i686_mtrr_reload() and mtrr_init_first() don't use mtrr_raw[]
   addresses of 0

 still needs a bunch of reworking to handle VCNT > 8 case.


 To generate a diff of this commit:
 cvs rdiff -r1.3 -r1.4 src/sys/arch/x86/include/mtrr.h
 cvs rdiff -r1.17 -r1.18 src/sys/arch/x86/x86/mtrr_i686.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Manuel Bouyer <bouyer@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/38480 CVS commit: [netbsd-4] src/sys/arch/x86
Date: Wed, 20 Aug 2008 19:37:23 +0000 (UTC)

 Module Name:	src
 Committed By:	bouyer
 Date:		Wed Aug 20 19:37:23 UTC 2008

 Modified Files:
 	src/sys/arch/x86/include [netbsd-4]: mtrr.h
 	src/sys/arch/x86/x86 [netbsd-4]: mtrr_i686.c

 Log Message:
 Pull up following revision(s) (requested by sborrill in ticket #1173):
 	sys/arch/x86/include/mtrr.h: revision 1.4
 	sys/arch/x86/x86/mtrr_i686.c: revision 1.18
 hack around PR#38480:
 - rename MTRR_I686_NVAR to MTRR_I686_NVAR_MAX, still set to 8
 - store mtrr VCNT value into i686_mtrr_vcnt.  if it is less than 8,
    zero out the relevant parts of mtrr_raw[].msraddr
 - replace all usage of MTRR_I686_NVAR with either i686_mtrr_vcnt or
    with MTRR_I686_NVAR_MAX as appropriate
 - in i686_mtrr_reload() and mtrr_init_first() don't use mtrr_raw[]
    addresses of 0
 still needs a bunch of reworking to handle VCNT > 8 case.


 To generate a diff of this commit:
 cvs rdiff -r1.2 -r1.2.52.1 src/sys/arch/x86/include/mtrr.h
 cvs rdiff -r1.8.2.1 -r1.8.2.2 src/sys/arch/x86/x86/mtrr_i686.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Manuel Bouyer <bouyer@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/38480 CVS commit: [netbsd-4] src/sys/arch
Date: Tue, 18 Nov 2008 22:33:28 +0000 (UTC)

 Module Name:	src
 Committed By:	bouyer
 Date:		Tue Nov 18 22:33:28 UTC 2008

 Modified Files:
 	src/sys/arch/amd64/amd64 [netbsd-4]: netbsd32_machdep.c
 	src/sys/arch/x86/include [netbsd-4]: mtrr.h
 	src/sys/arch/x86/x86 [netbsd-4]: mtrr_i686.c

 Log Message:
 Pull up following revision(s) (requested by sborrill in ticket #1173):
 	sys/arch/x86/include/mtrr.h: revision 1.4
 	sys/arch/amd64/amd64/netbsd32_machdep.c: revision 1.54
 	sys/arch/x86/x86/mtrr_i686.c: revision 1.18
 hack around PR#38480:
 - rename MTRR_I686_NVAR to MTRR_I686_NVAR_MAX, still set to 8
 - store mtrr VCNT value into i686_mtrr_vcnt.  if it is less than 8,
    zero out the relevant parts of mtrr_raw[].msraddr
 - replace all usage of MTRR_I686_NVAR with either i686_mtrr_vcnt or
    with MTRR_I686_NVAR_MAX as appropriate
 - in i686_mtrr_reload() and mtrr_init_first() don't use mtrr_raw[]
    addresses of 0
 still needs a bunch of reworking to handle VCNT > 8 case.
 Ensure optional MTRR sections are built if MTRR is enabled (missing
 Fix build due to changes in revision 1.4 of sys/arch/x86/include/mtrr.h


 To generate a diff of this commit:
 cvs rdiff -r1.30.2.1 -r1.30.2.2 src/sys/arch/amd64/amd64/netbsd32_machdep.c
 cvs rdiff -r1.2.52.2 -r1.2.52.3 src/sys/arch/x86/include/mtrr.h
 cvs rdiff -r1.8.2.3 -r1.8.2.4 src/sys/arch/x86/x86/mtrr_i686.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: dsl@NetBSD.org
State-Changed-When: Fri, 06 Nov 2009 22:44:02 +0000
State-Changed-Why:
Fix applied and pulled up to netbsd 4.
Maybe this will rear its ugly head again in the future.


From: "SAITOH Masanobu" <msaitoh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/38480 CVS commit: src/sys/arch/amd64/conf
Date: Thu, 6 Jun 2013 07:11:18 +0000

 Module Name:	src
 Committed By:	msaitoh
 Date:		Thu Jun  6 07:11:18 UTC 2013

 Modified Files:
 	src/sys/arch/amd64/conf: INSTALL

 Log Message:
 Fix compile error. PR#38480 was correctly fixed in 2009, it's ok to remove
 "no options MTRR"


 To generate a diff of this commit:
 cvs rdiff -u -r1.88 -r1.89 src/sys/arch/amd64/conf/INSTALL

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.