From owner-freebsd-current Wed Dec 23 20:56:01 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id UAA07376 for freebsd-current-outgoing; Wed, 23 Dec 1998 20:56:01 -0800 (PST) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from janus.syracuse.net (janus.syracuse.net [205.232.47.15]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id UAA07338 for ; Wed, 23 Dec 1998 20:55:59 -0800 (PST) (envelope-from green@unixhelp.org) Received: from localhost (green@localhost) by janus.syracuse.net (8.8.8/8.8.7) with ESMTP id XAA29514 for ; Wed, 23 Dec 1998 23:55:54 -0500 (EST) Date: Wed, 23 Dec 1998 23:55:54 -0500 (EST) From: Brian Feldman X-Sender: green@janus.syracuse.net To: current@FreeBSD.ORG Subject: K6-2 (3?) CPU_WT_ALLOC Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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. A patch follows in cleartext and encoded forms. Brian Feldman _ __ ___ ___ ___ green@unixhelp.org _ __ ___ | _ ) __| \ http://www.freebsd.org/ _ __ ___ ____ | _ \__ \ |) | FreeBSD: The Power to Serve! _ __ ___ ____ _____ |___/___/___/ --- src/sys/i386/conf/options.i386.orig Wed Dec 23 20:36:45 1998 +++ src/sys/i386/conf/options.i386 Wed Dec 23 20:36:56 1998 @@ -57,6 +57,7 @@ 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 --- src/sys/i386/i386/identcpu.c.orig Mon Dec 21 23:12:18 1998 +++ src/sys/i386/i386/identcpu.c Wed Dec 23 20:30:39 1998 @@ -68,6 +68,7 @@ #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 @@ 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,18 +863,28 @@ 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; } --- src/sys/i386/i386/initcpu.c.orig Mon Dec 21 23:01:26 1998 +++ src/sys/i386/i386/initcpu.c Wed Dec 23 19:53:10 1998 @@ -44,6 +44,7 @@ #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 @@ 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 @@ if (!(inb(0x43b) & 4)) whcr &= ~0x0001LL; else +#endif whcr |= 0x0001LL; } #else @@ -644,7 +647,68 @@ * 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); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message