diff options
author | kato <kato@FreeBSD.org> | 1998-10-06 13:16:29 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1998-10-06 13:16:29 +0000 |
commit | 5c811970f93597f910f75c2df6a06a262c02984f (patch) | |
tree | 15b2411727db7060104658127a54dd17de6e7b9a /sys/amd64/amd64/initcpu.c | |
parent | f37c35755da9a0f27e648ac1ffc453524689aac6 (diff) | |
download | FreeBSD-src-5c811970f93597f910f75c2df6a06a262c02984f.zip FreeBSD-src-5c811970f93597f910f75c2df6a06a262c02984f.tar.gz |
- Implement enabling write allocate on AMD K5/K6/K6-2 cpus.
The code was originaly contributed by Kelly Yancey
<kbyanc@freedomnet.com> in PR i386/6269 and revised by Akio Morita
<amorita@meadow.scphys.kyoto-u.ac.jp> and me. Test was performed by
Akio Morita and Toshiomi Moriki <moriki@db.is.kyushu-u.ac.jp>.
- Fix stylistic bug in identcpu.c.
- Update copyright in initcpu.c
- Fix typo in LINT.
PR: 6269 and 6270
Diffstat (limited to 'sys/amd64/amd64/initcpu.c')
-rw-r--r-- | sys/amd64/amd64/initcpu.c | 126 |
1 files changed, 123 insertions, 3 deletions
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 3849299..9f1f2a9 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) KATO Takenori, 1997. + * Copyright (c) KATO Takenori, 1997, 1998. * * All rights reserved. Unpublished rights reserved under the copyright * laws of Japan. @@ -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.12 1998/02/04 03:47:14 eivind Exp $ + * $Id: initcpu.c,v 1.13 1998/05/16 14:38:10 kato Exp $ */ #include "opt_cpu.h" @@ -41,6 +41,11 @@ #include <machine/specialreg.h> void initializecpu(void); +#if defined(I586_CPU) && defined(CPU_WT_ALLOC) +void enable_K5_wt_alloc(void); +void enable_K6_wt_alloc(void); +#endif + #ifdef I486_CPU static void init_5x86(void); static void init_bluelightning(void); @@ -439,7 +444,7 @@ static void init_ppro(void) { #ifndef SMP - quad_t apicbase; + u_int64_t apicbase; /* * Local APIC should be diabled in UP kernel. @@ -533,6 +538,121 @@ initializecpu(void) #endif /* PC98 && !UPGRADE_CPU_HW_CACHE */ } +#if defined(I586_CPU) && defined(CPU_WT_ALLOC) +/* + * Enable write allocate feature of AMD processors. + * Following two functions require the Maxmem variable being set. + */ +void +enable_K5_wt_alloc(void) +{ + u_int64_t msr; + + /* + * Write allocate is supported only on models 1, 2, and 3, with + * a stepping of 4 or greater. + */ + if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) { + disable_intr(); + msr = rdmsr(0x83); /* HWCR */ + wrmsr(0x83, msr & !(0x10)); + + /* + * We have to tell the chip where the top of memory is, + * since video cards could have frame bufferes there, + * memory-mapped I/O could be there, etc. + */ + if(Maxmem > 0) + msr = Maxmem / 16; + else + msr = 0; + msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE; +#ifdef PC98 + if (!(inb(0x43b) & 4)) { + wrmsr(0x86, 0x0ff00f0); + msr |= AMD_WT_ALLOC_PRE; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + wrmsr(0x86, 0x0ff00f0); + msr |= AMD_WT_ALLOC_PRE; +#endif + wrmsr(0x85, msr); + + msr=rdmsr(0x83); + wrmsr(0x83, msr|0x10); /* enable write allocate */ + + enable_intr(); + } +} + +void +enable_K6_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 / 256; + else + size = 0; + size = (size + 3) / 4; + + /* Limit is 508M bytes. */ + if (size > 127) + size = 127; + whcr = rdmsr(0xc0000082); + whcr &= ~0x00feLL; + whcr |= (size << 1); + +#ifdef PC98 + if (whcr & 0x00feLL) { + /* + * If bit 2 of port 0x43b is 0, disable wrte allocate for the + * 15-16M range. + */ + if (!(inb(0x43b) & 4)) + whcr &= ~0x0001LL; + else + whcr |= 0x0001LL; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + whcr &= 0x00feLL; +#endif + wrmsr(0x0c0000082, whcr); + + write_eflags(eflags); + enable_intr(); +} +#endif /* I585_CPU && CPU_WT_ALLOC */ + #include "opt_ddb.h" #ifdef DDB #include <ddb/ddb.h> |