diff options
author | msmith <msmith@FreeBSD.org> | 1998-12-27 23:23:26 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1998-12-27 23:23:26 +0000 |
commit | 7d69874701ab8fb7883fed77b6d23f1328fbb6e0 (patch) | |
tree | 0e60ef6169cbebe7c704506df6a10e2f17b83418 /sys | |
parent | 4a9f4655409a70d5a5fab4ac14d3eee37332e2f0 (diff) | |
download | FreeBSD-src-7d69874701ab8fb7883fed77b6d23f1328fbb6e0.zip FreeBSD-src-7d69874701ab8fb7883fed77b6d23f1328fbb6e0.tar.gz |
From the submitter:
CPU_WT_ALLOC does not work correctly for K6-2s of model 8+ and
probably K6-3s (when they appear on the market soon). In addition,
print_AMD_info() incorrectly printfs write allocation's size. I've
fixed them, so they now Do The Right Thing, and added a
"NO_MEMORY_HOLE" option to easily allow 15-16mb range handling for us
K6 and K6-2 users.
Submitted by: Brian Feldman <green@unixhelp.org>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/identcpu.c | 25 | ||||
-rw-r--r-- | sys/amd64/amd64/initcpu.c | 70 | ||||
-rw-r--r-- | sys/conf/NOTES | 6 | ||||
-rw-r--r-- | sys/conf/options.i386 | 3 | ||||
-rw-r--r-- | sys/i386/conf/LINT | 6 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 6 | ||||
-rw-r--r-- | sys/i386/conf/options.i386 | 3 | ||||
-rw-r--r-- | sys/i386/i386/identcpu.c | 25 | ||||
-rw-r--r-- | sys/i386/i386/initcpu.c | 70 |
9 files changed, 191 insertions, 23 deletions
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index 9b6d722..64972ec 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id: identcpu.c,v 1.52 1998/10/06 13:16:23 kato Exp $ + * $Id: identcpu.c,v 1.53 1998/12/05 16:30:55 kato Exp $ */ #include "opt_cpu.h" @@ -68,6 +68,7 @@ void earlysetcpuclass(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); +void enable_K6_2_wt_alloc(void); #endif void panicifcpuunsupported(void); static void identifycyrix(void); @@ -291,9 +292,11 @@ printcpuinfo(void) if ((cpu_id & 0xf00) == 0x500) { if (((cpu_id & 0x0f0) > 0) && ((cpu_id & 0x0f0) < 0x60) - && ((cpu_id & 0x00f) > 3)) { + && ((cpu_id & 0x00f) > 3)) enable_K5_wt_alloc(); - } else if ((cpu_id & 0x0f0) > 0x50) + else if ((cpu_id & 0x0f0) > 0x70) + enable_K6_2_wt_alloc(); + else if ((cpu_id & 0x0f0) > 0x50) enable_K6_wt_alloc(); } #endif @@ -860,19 +863,29 @@ print_AMD_info(void) switch (cpu_id & 0xFF0) { case 0x560: /* K6 0.35u */ case 0x570: /* K6 0.25u */ - case 0x580: /* K6-2 */ - case 0x590: /* K6-3 */ amd_whcr = rdmsr(0xc0000082); if (!(amd_whcr & 0x00fe)) { printf("Write Allocate Disable\n"); } else { printf("Write Allocate Enable Limit: %dM bytes\n", - (u_int32_t)(amd_whcr & 0x00fe) * 2); + (u_int32_t)(amd_whcr & 0x00fe) * 4); printf("Write Allocate 15-16M bytes: %s\n", (amd_whcr & 0x0001) ? "Enable" : "Disable"); printf("Hardware Write Allocate Control: %s\n", (amd_whcr & 0x0100) ? "Enable" : "Disable"); } break; + case 0x580: /* K6-2 */ + case 0x590: /* K6-3 */ + amd_whcr = rdmsr(0xc0000082); + if (!(amd_whcr & (0x3ff << 22))) { + printf("Write Allocate Disable\n"); + } else { + printf("Write Allocate Enable Limit: %dM bytes\n", + (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); + printf("Write Allocate 15-16M bytes: %s\n", + (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); + } + break; } } diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 9fb8008..330f9ef 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: initcpu.c,v 1.14 1998/10/06 13:16:23 kato Exp $ + * $Id: initcpu.c,v 1.15 1998/12/14 06:16:13 dillon Exp $ */ #include "opt_cpu.h" @@ -44,6 +44,7 @@ void initializecpu(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); +void enable_K6_2_wt_alloc(void); #endif #ifdef I486_CPU @@ -628,8 +629,9 @@ enable_K6_wt_alloc(void) whcr &= ~0x00feLL; whcr |= (size << 1); -#ifdef PC98 +#if defined(PC98) || defined(NO_MEMORY_HOLE) if (whcr & 0x00feLL) { +#ifdef PC98 /* * If bit 2 of port 0x43b is 0, disable wrte allocate for the * 15-16M range. @@ -637,6 +639,7 @@ enable_K6_wt_alloc(void) if (!(inb(0x43b) & 4)) whcr &= ~0x0001LL; else +#endif whcr |= 0x0001LL; } #else @@ -644,7 +647,68 @@ enable_K6_wt_alloc(void) * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ - whcr &= 0x00feLL; + whcr &= ~0x0001LL; +#endif + wrmsr(0x0c0000082, whcr); + + write_eflags(eflags); + enable_intr(); +} + +void +enable_K6_2_wt_alloc(void) +{ + quad_t size; + u_int64_t whcr; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + wbinvd(); + +#ifdef CPU_DISABLE_CACHE + /* + * Certain K6-2 box becomes unstable when write allocation is + * enabled. + */ + /* + * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), + * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. + * All other bits in TR12 have no effect on the processer's operation. + * The I/O Trap Restart function (bit 9 of TR12) is always enabled + * on the AMD-K6. + */ + wrmsr(0x0000000e, (u_int64_t)0x0008); +#endif + /* Don't assume that memory size is aligned with 4M. */ + if (Maxmem > 0) + size = ((Maxmem >> 8) + 3) >> 2; + else + size = 0; + + /* Limit is 4092M bytes. */ + size &= 0x3ff; + whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22); + +#if defined(PC98) || defined(NO_MEMORY_HOLE) + if (whcr & (0x3ffLL << 22)) { +#ifdef PC98 + /* + * If bit 2 of port 0x43b is 0, disable wrte allocate for the + * 15-16M range. + */ + if (!(inb(0x43b) & 4)) + whcr &= ~(1LL << 16); + else +#endif + whcr |= 1LL << 16; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + whcr &= ~(1LL << 16); #endif wrmsr(0x0c0000082, whcr); diff --git a/sys/conf/NOTES b/sys/conf/NOTES index ba4d97b..165501e 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ +# $Id: LINT,v 1.521 1998/12/27 21:46:55 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -178,6 +178,10 @@ cpu "I686_CPU" # aka Pentium Pro(tm) # executed. This should be included for ALL kernels that won't run # on a Pentium. # +# NO_MEMORY_HOLE is an optimisation for systems with AMD K6 processors +# which indicates that the 15-16MB range is *definitely* not being +# occupied by an ISA memory hole. +# # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should not be used becasue of CPU bugs. # These options may crash your system. diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index 4604c9a..3a706ab 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.98 1998/12/27 14:21:08 sos Exp $ +# $Id: options.i386,v 1.99 1998/12/27 21:46:55 phk Exp $ DISABLE_PSE IDE_DELAY @@ -56,6 +56,7 @@ CPU_UPGRADE_HW_CACHE opt_cpu.h CPU_WT_ALLOC opt_cpu.h CYRIX_CACHE_WORKS opt_cpu.h CYRIX_CACHE_REALLY_WORKS opt_cpu.h +NO_MEMORY_HOLE opt_cpu.h # The CPU type affects the endian conversion functions all over the kernel. I386_CPU opt_global.h diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index ba4d97b..165501e 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ +# $Id: LINT,v 1.521 1998/12/27 21:46:55 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -178,6 +178,10 @@ cpu "I686_CPU" # aka Pentium Pro(tm) # executed. This should be included for ALL kernels that won't run # on a Pentium. # +# NO_MEMORY_HOLE is an optimisation for systems with AMD K6 processors +# which indicates that the 15-16MB range is *definitely* not being +# occupied by an ISA memory hole. +# # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should not be used becasue of CPU bugs. # These options may crash your system. diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index ba4d97b..165501e 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ +# $Id: LINT,v 1.521 1998/12/27 21:46:55 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -178,6 +178,10 @@ cpu "I686_CPU" # aka Pentium Pro(tm) # executed. This should be included for ALL kernels that won't run # on a Pentium. # +# NO_MEMORY_HOLE is an optimisation for systems with AMD K6 processors +# which indicates that the 15-16MB range is *definitely* not being +# occupied by an ISA memory hole. +# # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should not be used becasue of CPU bugs. # These options may crash your system. diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386 index 4604c9a..3a706ab 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.98 1998/12/27 14:21:08 sos Exp $ +# $Id: options.i386,v 1.99 1998/12/27 21:46:55 phk Exp $ DISABLE_PSE IDE_DELAY @@ -56,6 +56,7 @@ CPU_UPGRADE_HW_CACHE opt_cpu.h CPU_WT_ALLOC opt_cpu.h CYRIX_CACHE_WORKS opt_cpu.h CYRIX_CACHE_REALLY_WORKS opt_cpu.h +NO_MEMORY_HOLE opt_cpu.h # The CPU type affects the endian conversion functions all over the kernel. I386_CPU opt_global.h diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index 9b6d722..64972ec 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id: identcpu.c,v 1.52 1998/10/06 13:16:23 kato Exp $ + * $Id: identcpu.c,v 1.53 1998/12/05 16:30:55 kato Exp $ */ #include "opt_cpu.h" @@ -68,6 +68,7 @@ void earlysetcpuclass(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); +void enable_K6_2_wt_alloc(void); #endif void panicifcpuunsupported(void); static void identifycyrix(void); @@ -291,9 +292,11 @@ printcpuinfo(void) if ((cpu_id & 0xf00) == 0x500) { if (((cpu_id & 0x0f0) > 0) && ((cpu_id & 0x0f0) < 0x60) - && ((cpu_id & 0x00f) > 3)) { + && ((cpu_id & 0x00f) > 3)) enable_K5_wt_alloc(); - } else if ((cpu_id & 0x0f0) > 0x50) + else if ((cpu_id & 0x0f0) > 0x70) + enable_K6_2_wt_alloc(); + else if ((cpu_id & 0x0f0) > 0x50) enable_K6_wt_alloc(); } #endif @@ -860,19 +863,29 @@ print_AMD_info(void) switch (cpu_id & 0xFF0) { case 0x560: /* K6 0.35u */ case 0x570: /* K6 0.25u */ - case 0x580: /* K6-2 */ - case 0x590: /* K6-3 */ amd_whcr = rdmsr(0xc0000082); if (!(amd_whcr & 0x00fe)) { printf("Write Allocate Disable\n"); } else { printf("Write Allocate Enable Limit: %dM bytes\n", - (u_int32_t)(amd_whcr & 0x00fe) * 2); + (u_int32_t)(amd_whcr & 0x00fe) * 4); printf("Write Allocate 15-16M bytes: %s\n", (amd_whcr & 0x0001) ? "Enable" : "Disable"); printf("Hardware Write Allocate Control: %s\n", (amd_whcr & 0x0100) ? "Enable" : "Disable"); } break; + case 0x580: /* K6-2 */ + case 0x590: /* K6-3 */ + amd_whcr = rdmsr(0xc0000082); + if (!(amd_whcr & (0x3ff << 22))) { + printf("Write Allocate Disable\n"); + } else { + printf("Write Allocate Enable Limit: %dM bytes\n", + (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); + printf("Write Allocate 15-16M bytes: %s\n", + (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); + } + break; } } diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c index 9fb8008..330f9ef 100644 --- a/sys/i386/i386/initcpu.c +++ b/sys/i386/i386/initcpu.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: initcpu.c,v 1.14 1998/10/06 13:16:23 kato Exp $ + * $Id: initcpu.c,v 1.15 1998/12/14 06:16:13 dillon Exp $ */ #include "opt_cpu.h" @@ -44,6 +44,7 @@ void initializecpu(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); +void enable_K6_2_wt_alloc(void); #endif #ifdef I486_CPU @@ -628,8 +629,9 @@ enable_K6_wt_alloc(void) whcr &= ~0x00feLL; whcr |= (size << 1); -#ifdef PC98 +#if defined(PC98) || defined(NO_MEMORY_HOLE) if (whcr & 0x00feLL) { +#ifdef PC98 /* * If bit 2 of port 0x43b is 0, disable wrte allocate for the * 15-16M range. @@ -637,6 +639,7 @@ enable_K6_wt_alloc(void) if (!(inb(0x43b) & 4)) whcr &= ~0x0001LL; else +#endif whcr |= 0x0001LL; } #else @@ -644,7 +647,68 @@ enable_K6_wt_alloc(void) * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ - whcr &= 0x00feLL; + whcr &= ~0x0001LL; +#endif + wrmsr(0x0c0000082, whcr); + + write_eflags(eflags); + enable_intr(); +} + +void +enable_K6_2_wt_alloc(void) +{ + quad_t size; + u_int64_t whcr; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + wbinvd(); + +#ifdef CPU_DISABLE_CACHE + /* + * Certain K6-2 box becomes unstable when write allocation is + * enabled. + */ + /* + * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), + * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. + * All other bits in TR12 have no effect on the processer's operation. + * The I/O Trap Restart function (bit 9 of TR12) is always enabled + * on the AMD-K6. + */ + wrmsr(0x0000000e, (u_int64_t)0x0008); +#endif + /* Don't assume that memory size is aligned with 4M. */ + if (Maxmem > 0) + size = ((Maxmem >> 8) + 3) >> 2; + else + size = 0; + + /* Limit is 4092M bytes. */ + size &= 0x3ff; + whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22); + +#if defined(PC98) || defined(NO_MEMORY_HOLE) + if (whcr & (0x3ffLL << 22)) { +#ifdef PC98 + /* + * If bit 2 of port 0x43b is 0, disable wrte allocate for the + * 15-16M range. + */ + if (!(inb(0x43b) & 4)) + whcr &= ~(1LL << 16); + else +#endif + whcr |= 1LL << 16; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + whcr &= ~(1LL << 16); #endif wrmsr(0x0c0000082, whcr); |