# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # sys/drivers/mtrr # sys/drivers/mtrr/Makefile # sys/drivers/mtrr/compat.h # sys/drivers/mtrr/cpufunc.h # sys/drivers/mtrr/cputypes.h # sys/drivers/mtrr/i686_mem.c # sys/drivers/mtrr/k6_mem.c # sys/drivers/mtrr/kprotos.h # sys/drivers/mtrr/memrange.h # sys/drivers/mtrr/mtrr.4 # sys/drivers/mtrr/mtrr.c # sys/drivers/mtrr/mtrr.cfg # sys/drivers/mtrr/mtrr.man # sys/drivers/mtrr/specialreg.h # sys/drivers/mtrr/support.S # echo c - sys/drivers/mtrr mkdir -p sys/drivers/mtrr > /dev/null 2>&1 echo x - sys/drivers/mtrr/Makefile sed 's/^X//' >sys/drivers/mtrr/Makefile << 'END-of-sys/drivers/mtrr/Makefile' X#************************************************************ X# X# $XFree86: xc/programs/Xserver/hw/xfree86/etc/MTRR-Lynx.shar,v 1.1 1999/12/08 06:10:11 dawes Exp $ X# X#************************************************************ X XLYNXVER := $(shell uname -r | cut -c1,3,5) X Xifeq "240" "$(LYNXVER)" Xabort :: X @echo "This driver will not work on LynxOS version earlier than 2.5.0" X @exit 1 Xendif X XUSR_HFILES=/usr/include/sys/memrange.h X XFILES = mtrrdrvr.o XHFILES = compat.h kprotos.h \ X cpufunc.h cputypes.h specialreg.h \ X $(USR_HFILES) X XLIBRARY= drivers X XDFILES = mtrr.x support.x i686_mem.x k6_mem.x XDOBJS=$(DFILES:.x=.o) X Xifneq "240" "$(LYNXVER)" Xinclude ../../OBJ_RULES Xendif X Xifneq "386" "$(PROCESSOR)" Xabort :: X @echo "This driver will only work on LynxOS x86" X @exit 1 Xendif X XDRV_LD=$(KERN_LD) Xifeq "250" "$(LYNXVER)" XDRV_LD=$(NEW_GCC_LD) Xendif X XSPECIAL_INCLUDES = XSPECIAL_CFLAGS = -DKERNEL -D__NO_INCLUDE_WARN__ -Wall -Wunused XASFLAGS=-DLOCORE X X%.o: %.S X $(ansi_compile) $(ASFLAGS) $(OPTIMIZE) X Xinstall all :: $(ALL_LIBRARIES) X Xclean: X $(RM) $(FILES) $(DOBJS) X Xclobber: clean X X$(DOBJS) : $(HFILES) X Xmtrrdrvr.o : $(DOBJS) X $(DRV_LD) -r -o $@ $(DOBJS) X X# X# automatically copy user include files in place X# X$(USR_HFILES) : memrange.h X install -c -u 0 -g 0 -m 0444 memrange.h $(ENV_PREFIX)/usr/include/sys X Xinstall :: mtrr.4 X install -c -u 0 -g 0 -m 0444 mtrr.4 $(ENV_PREFIX)/usr/man/cat4 X Xmtrr.4 : mtrr.man X groff -mandoc -Tascii mtrr.man > mtrr.4 END-of-sys/drivers/mtrr/Makefile echo x - sys/drivers/mtrr/compat.h sed 's/^X//' >sys/drivers/mtrr/compat.h << 'END-of-sys/drivers/mtrr/compat.h' X/* X * Copyright 1999 by Thomas Mueller X * X * Permission to use, copy, modify, distribute, and sell this software and its X * documentation for any purpose is hereby granted without fee, provided that X * the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the names of the above listed copyright holder(s) X * not be used in advertising or publicity pertaining to distribution of X * the software without specific, written prior permission. The above listed X * copyright holder(s) make(s) no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X */ X X#ifndef __compat_h X#define __compat_h X X#include X X#define __STRING(x) #x /* stringify without expanding x */ X#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ X X#include X X#ifndef min X#define min(a,b) MIN(a,b) X#endif X X#ifdef NEED_PCI_COMPAT X#include "pci_compat.h" X#endif X X#ifdef NEED_KERNEL_UIO X#include X/* flags for uiomove() missing from sys/uio.h X * X * uiomove() will only be present with TCP/IP X * included in the kernel! X */ X X/* Segment flag values. */ Xenum uio_seg { X UIO_USERSPACE, /* from user data space */ X UIO_SYSSPACE, /* from system space */ X UIO_USERISPACE /* from user I space */ X}; X X#undef UIO_READ X#undef UIO_WRITE X Xenum uio_rw { UIO_READ, UIO_WRITE }; X X/* X * struct uio as it lokks in the kernel. X * I guess it'd be better to use a replacement for X * uiomove as well. one never knows how the kernel X * structure looks like.... X */ X#define uio kernel_uio X Xstruct kernel_uio { X struct iovec *uio_iov; X int uio_iovcnt; X off_t uio_offset; X int uio_resid; X enum uio_seg uio_segflg; X enum uio_rw uio_rw; X struct pentry *uio_procp; X}; X Xextern int uiomove _AP((caddr_t, int, struct uio *)); X#endif X X/* X * LynxOS doesn't have vm_offset_t X */ Xtypedef unsigned int vm_offset_t; Xtypedef unsigned int vm_size_t; X X X#ifndef bootverbose X#define bootverbose (0) X#endif X X#define printf kkprintf X#define sprintf ksprintf X#define copyin(user, kern, len) bcopy(user, kern, len) X#define copyout(kern, user, len) bcopy(kern, user, len) X#define DELAY(x) usec_delay(x) X#define hz tickspersec Xextern void usec_delay _AP((unsigned long)); X Xextern int tickspersec; Xextern void microtime _AP((struct timeval *)); X X#define PZERO 22 X#define PRIMASK 0x0ff X#define PCATCH 0x100 Xextern int tsleep _AP((int *sema, int flag, char *name, int ticks)); X/* careful with this one ... */ X#define wakeup(x) ssignal(x) X X#define PAGE_SIZE PAGESIZE X#define vtophys(x) ((unsigned long)(get_phys((long)x) - PHYSBASE + DRAMBASE)) X#define btoc(x) (((unsigned)(x)+PAGE_OFFSET_MASK)>>PAGESHIFT) X X#define IO_NDELAY FNDELAY X#define ERESTART 0 /* usually we don't do this */ X X/* device driver entry points */ X Xtypedef int d_open_t _AP((void *, int devno, struct file *)); Xtypedef int d_close_t _AP((void *, struct file *)); Xtypedef int d_read_t _AP((void *, struct file *, char *, int)); Xtypedef int d_write_t _AP((void *, struct file *, char *, int)); Xtypedef int d_select_t _AP((void *, struct file *, int, struct sel *)); Xtypedef int d_ioctl_t _AP((void *, struct file *f, int cmd, char *arg)); Xtypedef char *d_install_t _AP((void *)); Xtypedef int d_uninstall_t _AP((void *)); X/* not really a device driver entry point on LynxOS (yet?) */ Xtypedef int d_mmap_t _AP((void *, vm_offset_t)); X X#define powerof2(x) ((((x)-1)&(x))==0) X#include X X#endif END-of-sys/drivers/mtrr/compat.h echo x - sys/drivers/mtrr/cpufunc.h sed 's/^X//' >sys/drivers/mtrr/cpufunc.h << 'END-of-sys/drivers/mtrr/cpufunc.h' X/*- X * Copyright (c) 1993 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.85.2.1 1999/08/29 16:06:26 peter Exp $ X */ X X/* X * Functions to provide access to special i386 instructions. X */ X X#ifndef _MACHINE_CPUFUNC_H_ X#define _MACHINE_CPUFUNC_H_ X X#define readb(va) (*(volatile u_int8_t *) (va)) X#define readw(va) (*(volatile u_int16_t *) (va)) X#define readl(va) (*(volatile u_int32_t *) (va)) X X#define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) X#define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) X#define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) X X#ifdef __GNUC__ X X#ifdef SMP X#include /* XXX */ X#endif X X#ifdef SWTCH_OPTIM_STATS Xextern int tlb_flush_count; /* XXX */ X#endif X Xstatic __inline void Xbreakpoint(void) X{ X __asm __volatile("int $3"); X} X Xstatic __inline void Xdisable_intr(void) X{ X __asm __volatile("cli" : : : "memory"); X#ifdef SMP X MPINTR_LOCK(); X#endif X} X Xstatic __inline void Xenable_intr(void) X{ X#ifdef SMP X MPINTR_UNLOCK(); X#endif X __asm __volatile("sti"); X} X X#define HAVE_INLINE_FFS X Xstatic __inline int Xffs(int mask) X{ X int result; X /* X * bsfl turns out to be not all that slow on 486's. It can beaten X * using a binary search to reduce to 4 bits and then a table lookup, X * but only if the code is inlined and in the cache, and the code X * is quite large so inlining it probably busts the cache. X * X * Note that gcc-2's builtin ffs would be used if we didn't declare X * this inline or turn off the builtin. The builtin is faster but X * broken in gcc-2.4.5 and slower but working in gcc-2.5 and 2.6. X */ X __asm __volatile("testl %0,%0; je 1f; bsfl %0,%0; incl %0; 1:" X : "=r" (result) : "0" (mask)); X return (result); X} X X#define HAVE_INLINE_FLS X Xstatic __inline int Xfls(int mask) X{ X int result; X __asm __volatile("testl %0,%0; je 1f; bsrl %0,%0; incl %0; 1:" X : "=r" (result) : "0" (mask)); X return (result); X} X X#if __GNUC__ < 2 X X#define inb(port) inbv(port) X#define outb(port, data) outbv(port, data) X X#else /* __GNUC >= 2 */ X X/* X * The following complications are to get around gcc not having a X * constraint letter for the range 0..255. We still put "d" in the X * constraint because "i" isn't a valid constraint when the port X * isn't constant. This only matters for -O0 because otherwise X * the non-working version gets optimized away. X * X * Use an expression-statement instead of a conditional expression X * because gcc-2.6.0 would promote the operands of the conditional X * and produce poor code for "if ((inb(var) & const1) == const2)". X * X * The unnecessary test `(port) < 0x10000' is to generate a warning if X * the `port' has type u_short or smaller. Such types are pessimal. X * This actually only works for signed types. The range check is X * careful to avoid generating warnings. X */ X#define inb(port) __extension__ ({ \ X u_char _data; \ X if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ X && (port) < 0x10000) \ X _data = inbc(port); \ X else \ X _data = inbv(port); \ X _data; }) X X#define outb(port, data) ( \ X __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ X && (port) < 0x10000 \ X ? outbc(port, data) : outbv(port, data)) X Xstatic __inline u_char Xinbc(u_int port) X{ X u_char data; X X __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); X return (data); X} X Xstatic __inline void Xoutbc(u_int port, u_char data) X{ X __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port))); X} X X#endif /* __GNUC <= 2 */ X Xstatic __inline u_char Xinbv(u_int port) X{ X u_char data; X /* X * We use %%dx and not %1 here because i/o is done at %dx and not at X * %edx, while gcc generates inferior code (movw instead of movl) X * if we tell it to load (u_short) port. X */ X __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); X return (data); X} X Xstatic __inline u_int Xinl(u_int port) X{ X u_int data; X X __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); X return (data); X} X Xstatic __inline void Xinsb(u_int port, void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; insb" X : "=D" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port) X : "memory"); X} X Xstatic __inline void Xinsw(u_int port, void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; insw" X : "=D" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port) X : "memory"); X} X Xstatic __inline void Xinsl(u_int port, void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; insl" X : "=D" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port) X : "memory"); X} X Xstatic __inline void Xinvd(void) X{ X __asm __volatile("invd"); X} X X#if defined(SMP) && defined(KERNEL) X X/* X * When using APIC IPI's, invlpg() is not simply the invlpg instruction X * (this is a bug) and the inlining cost is prohibitive since the call X * executes into the IPI transmission system. X */ Xvoid invlpg __P((u_int addr)); Xvoid invltlb __P((void)); X Xstatic __inline void Xcpu_invlpg(void *addr) X{ X __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); X} X Xstatic __inline void Xcpu_invltlb(void) X{ X u_int temp; X /* X * This should be implemented as load_cr3(rcr3()) when load_cr3() X * is inlined. X */ X __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp) X : : "memory"); X#if defined(SWTCH_OPTIM_STATS) X ++tlb_flush_count; X#endif X} X X#else /* !(SMP && KERNEL) */ X Xstatic __inline void Xinvlpg(u_int addr) X{ X __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); X} X Xstatic __inline void Xinvltlb(void) X{ X u_int temp; X /* X * This should be implemented as load_cr3(rcr3()) when load_cr3() X * is inlined. X */ X __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp) X : : "memory"); X#ifdef SWTCH_OPTIM_STATS X ++tlb_flush_count; X#endif X} X X#endif /* SMP && KERNEL */ X Xstatic __inline u_short Xinw(u_int port) X{ X u_short data; X X __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port)); X return (data); X} X Xstatic __inline u_int Xloadandclear(u_int *addr) X{ X u_int result; X X __asm __volatile("xorl %0,%0; xchgl %1,%0" X : "=&r" (result) : "m" (*addr)); X return (result); X} X Xstatic __inline void Xoutbv(u_int port, u_char data) X{ X u_char al; X /* X * Use an unnecessary assignment to help gcc's register allocator. X * This make a large difference for gcc-1.40 and a tiny difference X * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for X * best results. gcc-2.6.0 can't handle this. X */ X al = data; X __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); X} X Xstatic __inline void Xoutl(u_int port, u_int data) X{ X /* X * outl() and outw() aren't used much so we haven't looked at X * possible micro-optimizations such as the unnecessary X * assignment for them. X */ X __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); X} X Xstatic __inline void Xoutsb(u_int port, const void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; outsb" X : "=S" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port)); X} X Xstatic __inline void Xoutsw(u_int port, const void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; outsw" X : "=S" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port)); X} X Xstatic __inline void Xoutsl(u_int port, const void *addr, size_t cnt) X{ X __asm __volatile("cld; rep; outsl" X : "=S" (addr), "=c" (cnt) X : "0" (addr), "1" (cnt), "d" (port)); X} X Xstatic __inline void Xoutw(u_int port, u_short data) X{ X __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port)); X} X Xstatic __inline u_int Xrcr2(void) X{ X u_int data; X X __asm __volatile("movl %%cr2,%0" : "=r" (data)); X return (data); X} X Xstatic __inline u_int Xread_eflags(void) X{ X u_int ef; X X __asm __volatile("pushfl; popl %0" : "=r" (ef)); X return (ef); X} X Xstatic __inline u_int64_t Xrdmsr(u_int msr) X{ X u_int64_t rv; X X __asm __volatile(".byte 0x0f, 0x32" : "=A" (rv) : "c" (msr)); X return (rv); X} X Xstatic __inline u_int64_t Xrdpmc(u_int pmc) X{ X u_int64_t rv; X X __asm __volatile(".byte 0x0f, 0x33" : "=A" (rv) : "c" (pmc)); X return (rv); X} X Xstatic __inline u_int64_t Xrdtsc(void) X{ X u_int64_t rv; X X __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv)); X return (rv); X} X Xstatic __inline void Xsetbits(volatile u_int *addr, u_int bits) X{ X __asm __volatile( X#ifdef SMP X "lock; " X#endif X "orl %1,%0" : "=m" (*addr) : "ir" (bits)); X} X Xstatic __inline void Xwbinvd(void) X{ X __asm __volatile("wbinvd"); X} X Xstatic __inline void Xwrite_eflags(u_int ef) X{ X __asm __volatile("pushl %0; popfl" : : "r" (ef)); X} X Xstatic __inline void Xwrmsr(u_int msr, u_int64_t newval) X{ X __asm __volatile(".byte 0x0f, 0x30" : : "A" (newval), "c" (msr)); X} X X#else /* !__GNUC__ */ X Xint breakpoint __P((void)); Xvoid disable_intr __P((void)); Xvoid enable_intr __P((void)); Xu_char inb __P((u_int port)); Xu_int inl __P((u_int port)); Xvoid insb __P((u_int port, void *addr, size_t cnt)); Xvoid insl __P((u_int port, void *addr, size_t cnt)); Xvoid insw __P((u_int port, void *addr, size_t cnt)); Xvoid invd __P((void)); Xvoid invlpg __P((u_int addr)); Xvoid invltlb __P((void)); Xu_short inw __P((u_int port)); Xu_int loadandclear __P((u_int *addr)); Xvoid outb __P((u_int port, u_char data)); Xvoid outl __P((u_int port, u_int data)); Xvoid outsb __P((u_int port, void *addr, size_t cnt)); Xvoid outsl __P((u_int port, void *addr, size_t cnt)); Xvoid outsw __P((u_int port, void *addr, size_t cnt)); Xvoid outw __P((u_int port, u_short data)); Xu_int rcr2 __P((void)); Xu_int64_t rdmsr __P((u_int msr)); Xu_int64_t rdpmc __P((u_int pmc)); Xu_int64_t rdtsc __P((void)); Xu_int read_eflags __P((void)); Xvoid setbits __P((volatile u_int *addr, u_int bits)); Xvoid wbinvd __P((void)); Xvoid write_eflags __P((u_int ef)); Xvoid wrmsr __P((u_int msr, u_int64_t newval)); X X#endif /* __GNUC__ */ X Xvoid load_cr0 __P((u_int cr0)); Xvoid load_cr3 __P((u_int cr3)); Xvoid load_cr4 __P((u_int cr4)); Xvoid ltr __P((u_short sel)); Xu_int rcr0 __P((void)); Xu_int rcr3 __P((void)); Xu_int rcr4 __P((void)); X X#endif /* !_MACHINE_CPUFUNC_H_ */ END-of-sys/drivers/mtrr/cpufunc.h echo x - sys/drivers/mtrr/cputypes.h sed 's/^X//' >sys/drivers/mtrr/cputypes.h << 'END-of-sys/drivers/mtrr/cputypes.h' X/* X * Copyright (c) 1993 Christopher G. Demetriou X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. The name of the author may not be used to endorse or promote products X * derived from this software without specific prior written permission X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. X * X * $FreeBSD: src/sys/i386/include/cputypes.h,v 1.11.2.2 1999/08/29 16:06:26 peter Exp $ X */ X X#ifndef _MACHINE_CPUTYPES_H_ X#define _MACHINE_CPUTYPES_H_ X X/* X * Classes of processor. X */ X#define CPUCLASS_286 0 X#define CPUCLASS_386 1 X#define CPUCLASS_486 2 X#define CPUCLASS_586 3 X#define CPUCLASS_686 4 X X/* X * Kinds of processor. X */ X#define CPU_286 0 /* Intel 80286 */ X#define CPU_386SX 1 /* Intel 80386SX */ X#define CPU_386 2 /* Intel 80386DX */ X#define CPU_486SX 3 /* Intel 80486SX */ X#define CPU_486 4 /* Intel 80486DX */ X#define CPU_586 5 /* Intel P.....m (I hate lawyers; it's TM) */ X#define CPU_486DLC 6 /* Cyrix 486DLC */ X#define CPU_686 7 /* Pentium Pro */ X#define CPU_M1SC 8 /* Cyrix M1sc (aka 5x86) */ X#define CPU_M1 9 /* Cyrix M1 (aka 6x86) */ X#define CPU_BLUE 10 /* IBM BlueLighting CPU */ X#define CPU_M2 11 /* Cyrix M2 (aka enhanced 6x86 with MMX */ X#define CPU_NX586 12 /* NexGen (now AMD) 586 */ X#define CPU_CY486DX 13 /* Cyrix 486S/DX/DX2/DX4 */ X#define CPU_PII 14 /* Intel Pentium II */ X#define CPU_PIII 15 /* Intel Pentium III */ X X#ifndef LOCORE Xstruct cpu_nameclass { X char *cpu_name; X int cpu_class; X}; X Xextern int cpu; Xextern int cpu_class; X#endif X X#endif /* !_MACHINE_CPUTYPES_H_ */ END-of-sys/drivers/mtrr/cputypes.h echo x - sys/drivers/mtrr/i686_mem.c sed 's/^X//' >sys/drivers/mtrr/i686_mem.c << 'END-of-sys/drivers/mtrr/i686_mem.c' X/*- X * Copyright (c) 1999 Michael Smith X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD: src/sys/i386/i386/i686_mem.c,v 1.8 1999/10/12 22:53:05 green Exp $ X */ X X#ifndef __Lynx__ X#include "opt_smp.h" X#endif X X#include X#include X#ifndef __Lynx__ X#include X#include X#else X#include X#include X#include X#include X#include X#include X#endif X#include X X#ifndef __Lynx__ X#include X#include X#else X#include "kprotos.h" X#include "compat.h" X Xextern u_int cpu_feature; Xextern u_int cpu_high; Xextern u_int cpu_id; Xextern char cpu_vendor[]; X#include X#endif X X#ifdef SMP X#include X#endif X X/* X * i686 memory range operations X * X * This code will probably be impenetrable without reference to the X * Intel Pentium Pro documentation. X */ X Xstatic char *mem_owner_bios = "BIOS"; X X#define MR686_FIXMTRR (1<<0) X X#define mrwithin(mr, a) \ X (((a) >= (mr)->mr_base) && ((a) < ((mr)->mr_base + (mr)->mr_len))) X#define mroverlap(mra, mrb) \ X (mrwithin(mra, mrb->mr_base) || mrwithin(mrb, mra->mr_base)) X X#define mrvalid(base, len) \ X ((!(base & ((1 << 12) - 1))) && /* base is multiple of 4k */ \ X ((len) >= (1 << 12)) && /* length is >= 4k */ \ X powerof2((len)) && /* ... and power of two */ \ X !((base) & ((len) - 1))) /* range is not discontiuous */ X X#define mrcopyflags(curr, new) (((curr) & ~MDF_ATTRMASK) | ((new) & MDF_ATTRMASK)) X Xstatic void i686_mrinit(struct mem_range_softc *sc); Xstatic int i686_mrset(struct mem_range_softc *sc, X struct mem_range_desc *mrd, X int *arg); Xstatic void i686_mrAPinit(struct mem_range_softc *sc); X Xstatic struct mem_range_ops i686_mrops = { X i686_mrinit, X i686_mrset, X i686_mrAPinit X}; X X/* XXX for AP startup hook */ Xstatic u_int64_t mtrrcap, mtrrdef; X Xstatic struct mem_range_desc *mem_range_match(struct mem_range_softc *sc, X struct mem_range_desc *mrd); Xstatic void i686_mrfetch(struct mem_range_softc *sc); Xstatic int i686_mtrrtype(int flags); Xstatic void i686_mrstore(struct mem_range_softc *sc); Xstatic void i686_mrstoreone(void *arg); Xstatic struct mem_range_desc *i686_mtrrfixsearch(struct mem_range_softc *sc, X u_int64_t addr); Xstatic int i686_mrsetlow(struct mem_range_softc *sc, X struct mem_range_desc *mrd, X int *arg); Xstatic int i686_mrsetvariable(struct mem_range_softc *sc, X struct mem_range_desc *mrd, X int *arg); X X/* i686 MTRR type to memory range type conversion */ Xstatic int i686_mtrrtomrt[] = { X MDF_UNCACHEABLE, X MDF_WRITECOMBINE, X 0, X 0, X MDF_WRITETHROUGH, X MDF_WRITEPROTECT, X MDF_WRITEBACK X}; X X/* X * i686 MTRR conflict matrix for overlapping ranges X * X * Specifically, this matrix allows writeback and uncached ranges X * to overlap (the overlapped region is uncached). The array index X * is the translated i686 code for the flags (because they map well). X */ Xstatic int i686_mtrrconflict[] = { X MDF_WRITECOMBINE | MDF_WRITETHROUGH | MDF_WRITEPROTECT, X MDF_ATTRMASK, X 0, X 0, X MDF_ATTRMASK, X MDF_ATTRMASK, X MDF_WRITECOMBINE | MDF_WRITETHROUGH | MDF_WRITEPROTECT X}; X X/* X * Look for an exactly-matching range. X */ Xstatic struct mem_range_desc * Xmem_range_match(struct mem_range_softc *sc, struct mem_range_desc *mrd) X{ X struct mem_range_desc *cand; X int i; X X for (i = 0, cand = sc->mr_desc; i < sc->mr_ndesc; i++, cand++) X if ((cand->mr_base == mrd->mr_base) && X (cand->mr_len == mrd->mr_len)) X return(cand); X return(NULL); X} X X/* X * Fetch the current mtrr settings from the current CPU (assumed to all X * be in sync in the SMP case). Note that if we are here, we assume X * that MTRRs are enabled, and we may or may not have fixed MTRRs. X */ Xstatic void Xi686_mrfetch(struct mem_range_softc *sc) X{ X struct mem_range_desc *mrd; X u_int64_t msrv; X int i, j, msr; X X mrd = sc->mr_desc; X X /* Get fixed-range MTRRs */ X if (sc->mr_cap & MR686_FIXMTRR) { X msr = MSR_MTRR64kBase; X for (i = 0; i < (MTRR_N64K / 8); i++, msr++) { X msrv = rdmsr(msr); X for (j = 0; j < 8; j++, mrd++) { X mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | X i686_mtrrtomrt[msrv & 0xff] | X MDF_ACTIVE; X if (mrd->mr_owner[0] == 0) X strcpy(mrd->mr_owner, mem_owner_bios); X msrv = msrv >> 8; X } X } X msr = MSR_MTRR16kBase; X for (i = 0; i < (MTRR_N16K / 8); i++, msr++) { X msrv = rdmsr(msr); X for (j = 0; j < 8; j++, mrd++) { X mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | X i686_mtrrtomrt[msrv & 0xff] | X MDF_ACTIVE; X if (mrd->mr_owner[0] == 0) X strcpy(mrd->mr_owner, mem_owner_bios); X msrv = msrv >> 8; X } X } X msr = MSR_MTRR4kBase; X for (i = 0; i < (MTRR_N4K / 8); i++, msr++) { X msrv = rdmsr(msr); X for (j = 0; j < 8; j++, mrd++) { X mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | X i686_mtrrtomrt[msrv & 0xff] | X MDF_ACTIVE; X if (mrd->mr_owner[0] == 0) X strcpy(mrd->mr_owner, mem_owner_bios); X msrv = msrv >> 8; X } X } X } X X /* Get remainder which must be variable MTRRs */ X msr = MSR_MTRRVarBase; X for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) { X msrv = rdmsr(msr); X mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | X i686_mtrrtomrt[msrv & 0xff]; X mrd->mr_base = msrv & 0x0000000ffffff000LL; X msrv = rdmsr(msr + 1); X mrd->mr_flags = (msrv & 0x800) ? X (mrd->mr_flags | MDF_ACTIVE) : X (mrd->mr_flags & ~MDF_ACTIVE); X /* Compute the range from the mask. Ick. */ X mrd->mr_len = (~(msrv & 0x0000000ffffff000LL) & 0x0000000fffffffffLL) + 1; X if (!mrvalid(mrd->mr_base, mrd->mr_len)) X mrd->mr_flags |= MDF_BOGUS; X /* If unclaimed and active, must be the BIOS */ X if ((mrd->mr_flags & MDF_ACTIVE) && (mrd->mr_owner[0] == 0)) X strcpy(mrd->mr_owner, mem_owner_bios); X } X} X X/* X * Return the MTRR memory type matching a region's flags X */ Xstatic int Xi686_mtrrtype(int flags) X{ X int i; X X flags &= MDF_ATTRMASK; X X for (i = 0; i < (sizeof(i686_mtrrtomrt) / sizeof(i686_mtrrtomrt[0])); i++) { X if (i686_mtrrtomrt[i] == 0) X continue; X if (flags == i686_mtrrtomrt[i]) X return(i); X } X return(-1); X} X X/* X * Update running CPU(s) MTRRs to match the ranges in the descriptor X * list. X * X * XXX Must be called with interrupts enabled. X */ Xstatic void Xi686_mrstore(struct mem_range_softc *sc) X{ X#ifdef SMP X /* X * We should use all_but_self_ipi() to call other CPUs into a X * locking gate, then call a target function to do this work. X * The "proper" solution involves a generalised locking gate X * implementation, not ready yet. X */ X smp_rendezvous(NULL, i686_mrstoreone, NULL, (void *)sc); X#else X disable_intr(); /* disable interrupts */ X i686_mrstoreone((void *)sc); X enable_intr(); X#endif X} X X/* X * Update the current CPU's MTRRs with those represented in the X * descriptor list. Note that we do this wholesale rather than X * just stuffing one entry; this is simpler (but slower, of course). X */ Xstatic void Xi686_mrstoreone(void *arg) X{ X struct mem_range_softc *sc = (struct mem_range_softc *)arg; X struct mem_range_desc *mrd; X u_int64_t msrv; X int i, j, msr; X u_int cr4save; X X mrd = sc->mr_desc; X X cr4save = rcr4(); /* save cr4 */ X if (cr4save & CR4_PGE) X load_cr4(cr4save & ~CR4_PGE); X load_cr0((rcr0() & ~CR0_NW) | CR0_CD); /* disable caches (CD = 1, NW = 0) */ X wbinvd(); /* flush caches, TLBs */ X wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) & ~0x800); /* disable MTRRs (E = 0) */ X X /* Set fixed-range MTRRs */ X if (sc->mr_cap & MR686_FIXMTRR) { X msr = MSR_MTRR64kBase; X for (i = 0; i < (MTRR_N64K / 8); i++, msr++) { X msrv = 0; X for (j = 7; j >= 0; j--) { X msrv = msrv << 8; X msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff); X } X wrmsr(msr, msrv); X mrd += 8; X } X msr = MSR_MTRR16kBase; X for (i = 0; i < (MTRR_N16K / 8); i++, msr++) { X msrv = 0; X for (j = 7; j >= 0; j--) { X msrv = msrv << 8; X msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff); X } X wrmsr(msr, msrv); X mrd += 8; X } X msr = MSR_MTRR4kBase; X for (i = 0; i < (MTRR_N4K / 8); i++, msr++) { X msrv = 0; X for (j = 7; j >= 0; j--) { X msrv = msrv << 8; X msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff); X } X wrmsr(msr, msrv); X mrd += 8; X } X } X X /* Set remainder which must be variable MTRRs */ X msr = MSR_MTRRVarBase; X for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) { X /* base/type register */ X if (mrd->mr_flags & MDF_ACTIVE) { X msrv = mrd->mr_base & 0x0000000ffffff000LL; X msrv |= (i686_mtrrtype(mrd->mr_flags) & 0xff); X } else { X msrv = 0; X } X wrmsr(msr, msrv); X X /* mask/active register */ X if (mrd->mr_flags & MDF_ACTIVE) { X msrv = 0x800 | (~(mrd->mr_len - 1) & 0x0000000ffffff000LL); X } else { X msrv = 0; X } X wrmsr(msr + 1, msrv); X } X wbinvd(); /* flush caches, TLBs */ X wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) | 0x800); /* restore MTRR state */ X load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* enable caches CD = 0 and NW = 0 */ X load_cr4(cr4save); /* restore cr4 */ X} X X/* X * Hunt for the fixed MTRR referencing (addr) X */ Xstatic struct mem_range_desc * Xi686_mtrrfixsearch(struct mem_range_softc *sc, u_int64_t addr) X{ X struct mem_range_desc *mrd; X int i; X X for (i = 0, mrd = sc->mr_desc; i < (MTRR_N64K + MTRR_N16K + MTRR_N4K); i++, mrd++) X if ((addr >= mrd->mr_base) && (addr < (mrd->mr_base + mrd->mr_len))) X return(mrd); X return(NULL); X} X X/* X * Try to satisfy the given range request by manipulating the fixed MTRRs that X * cover low memory. X * X * Note that we try to be generous here; we'll bloat the range out to the X * next higher/lower boundary to avoid the consumer having to know too much X * about the mechanisms here. X * X * XXX note that this will have to be updated when we start supporting "busy" ranges. X */ Xstatic int Xi686_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) X{ X struct mem_range_desc *first_md, *last_md, *curr_md; X X /* range check */ X if (((first_md = i686_mtrrfixsearch(sc, mrd->mr_base)) == NULL) || X ((last_md = i686_mtrrfixsearch(sc, mrd->mr_base + mrd->mr_len - 1)) == NULL)) X return(EINVAL); X X /* set flags, clear set-by-firmware flag */ X for (curr_md = first_md; curr_md <= last_md; curr_md++) { X curr_md->mr_flags = mrcopyflags(curr_md->mr_flags & ~MDF_FIRMWARE, mrd->mr_flags); X bcopy(mrd->mr_owner, curr_md->mr_owner, sizeof(mrd->mr_owner)); X } X X return(0); X} X X X/* X * Modify/add a variable MTRR to satisfy the request. X * X * XXX needs to be updated to properly support "busy" ranges. X */ Xstatic int Xi686_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) X{ X struct mem_range_desc *curr_md, *free_md; X int i; X X /* X * Scan the currently active variable descriptors, look for X * one we exactly match (straight takeover) and for possible X * accidental overlaps. X * Keep track of the first empty variable descriptor in case we X * can't perform a takeover. X */ X i = (sc->mr_cap & MR686_FIXMTRR) ? MTRR_N64K + MTRR_N16K + MTRR_N4K : 0; X curr_md = sc->mr_desc + i; X free_md = NULL; X for (; i < sc->mr_ndesc; i++, curr_md++) { X if (curr_md->mr_flags & MDF_ACTIVE) { X /* exact match? */ X if ((curr_md->mr_base == mrd->mr_base) && X (curr_md->mr_len == mrd->mr_len)) { X /* whoops, owned by someone */ X if (curr_md->mr_flags & MDF_BUSY) X return(EBUSY); X /* Ok, just hijack this entry */ X free_md = curr_md; X break; X } X /* non-exact overlap ? */ X if (mroverlap(curr_md, mrd)) { X /* between conflicting region types? */ X if ((i686_mtrrconflict[i686_mtrrtype(curr_md->mr_flags)] & mrd->mr_flags) || X (i686_mtrrconflict[i686_mtrrtype(mrd->mr_flags)] & curr_md->mr_flags)) X return(EINVAL); X } X } else if (free_md == NULL) { X free_md = curr_md; X } X } X /* got somewhere to put it? */ X if (free_md == NULL) X return(ENOSPC); X X /* Set up new descriptor */ X free_md->mr_base = mrd->mr_base; X free_md->mr_len = mrd->mr_len; X free_md->mr_flags = mrcopyflags(MDF_ACTIVE, mrd->mr_flags); X bcopy(mrd->mr_owner, free_md->mr_owner, sizeof(mrd->mr_owner)); X return(0); X} X X/* X * Handle requests to set memory range attributes by manipulating MTRRs. X * X */ Xstatic int Xi686_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) X{ X struct mem_range_desc *targ; X int error = 0; X X switch(*arg) { X case MEMRANGE_SET_UPDATE: X /* make sure that what's being asked for is even possible at all */ X if (!mrvalid(mrd->mr_base, mrd->mr_len) || X (i686_mtrrtype(mrd->mr_flags & MDF_ATTRMASK) == -1)) X return(EINVAL); X X#define FIXTOP ((MTRR_N64K * 0x10000) + (MTRR_N16K * 0x4000) + (MTRR_N4K * 0x1000)) X X /* are the "low memory" conditions applicable? */ X if ((sc->mr_cap & MR686_FIXMTRR) && X ((mrd->mr_base + mrd->mr_len) <= FIXTOP)) { X if ((error = i686_mrsetlow(sc, mrd, arg)) != 0) X return(error); X } else { X /* it's time to play with variable MTRRs */ X if ((error = i686_mrsetvariable(sc, mrd, arg)) != 0) X return(error); X } X break; X X case MEMRANGE_SET_REMOVE: X if ((targ = mem_range_match(sc, mrd)) == NULL) X return(ENOENT); X if (targ->mr_flags & MDF_FIXACTIVE) X return(EPERM); X if (targ->mr_flags & MDF_BUSY) X return(EBUSY); X targ->mr_flags &= ~MDF_ACTIVE; X targ->mr_owner[0] = 0; X break; X X default: X return(EOPNOTSUPP); X } X X /* update the hardware */ X i686_mrstore(sc); X i686_mrfetch(sc); /* refetch to see where we're at */ X return(0); X} X X/* X * Work out how many ranges we support, initialise storage for them, X * fetch the initial settings. X */ Xstatic void Xi686_mrinit(struct mem_range_softc *sc) X{ X struct mem_range_desc *mrd; X int nmdesc = 0; X int i; X X mtrrcap = rdmsr(MSR_MTRRcap); X mtrrdef = rdmsr(MSR_MTRRdefType); X X /* For now, bail out if MTRRs are not enabled */ X if (!(mtrrdef & 0x800)) { X if (bootverbose) X printf("CPU supports MTRRs but not enabled\n"); X return; X } X nmdesc = mtrrcap & 0xff; X if (bootverbose) X printf("Pentium Pro MTRR support enabled\n"); X X /* If fixed MTRRs supported and enabled */ X if ((mtrrcap & 0x100) && (mtrrdef & 0x400)) { X sc->mr_cap = MR686_FIXMTRR; X nmdesc += MTRR_N64K + MTRR_N16K + MTRR_N4K; X } X X#ifndef __Lynx__ X sc->mr_desc = X (struct mem_range_desc *)malloc(nmdesc * sizeof(struct mem_range_desc), X M_MEMDESC, M_WAITOK); X#else X sc->mr_desc = X (struct mem_range_desc *)sysbrk(nmdesc * sizeof(struct mem_range_desc)); X#endif X bzero(sc->mr_desc, nmdesc * sizeof(struct mem_range_desc)); X sc->mr_ndesc = nmdesc; X X mrd = sc->mr_desc; X X /* Populate the fixed MTRR entries' base/length */ X if (sc->mr_cap & MR686_FIXMTRR) { X for (i = 0; i < MTRR_N64K; i++, mrd++) { X mrd->mr_base = i * 0x10000; X mrd->mr_len = 0x10000; X mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; X } X for (i = 0; i < MTRR_N16K; i++, mrd++) { X mrd->mr_base = i * 0x4000 + 0x80000; X mrd->mr_len = 0x4000; X mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; X } X for (i = 0; i < MTRR_N4K; i++, mrd++) { X mrd->mr_base = i * 0x1000 + 0xc0000; X mrd->mr_len = 0x1000; X mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; X } X } X X /* X * Get current settings, anything set now is considered to have X * been set by the firmware. (XXX has something already played here?) X */ X i686_mrfetch(sc); X mrd = sc->mr_desc; X for (i = 0; i < sc->mr_ndesc; i++, mrd++) { X if (mrd->mr_flags & MDF_ACTIVE) X mrd->mr_flags |= MDF_FIRMWARE; X } X} X X/* X * Initialise MTRRs on an AP after the BSP has run the init code. X */ Xstatic void Xi686_mrAPinit(struct mem_range_softc *sc) X{ X i686_mrstoreone((void *)sc); /* set MTRRs to match BSP */ X wrmsr(MSR_MTRRdefType, mtrrdef); /* set MTRR behaviour to match BSP */ X} X X#ifndef __Lynx__ Xstatic X#endif Xvoid Xi686_mem_drvinit(void *unused) X{ X /* Try for i686 MTRRs */ X if ((cpu_feature & CPUID_MTRR) && X ((cpu_id & 0xf00) == 0x600) && X ((strcmp(cpu_vendor, "GenuineIntel") == 0) || X (strcmp(cpu_vendor, "AuthenticAMD") == 0))) { X mem_range_softc.mr_op = &i686_mrops; X } X} X X#ifndef __Lynx__ XSYSINIT(i686memdev,SI_SUB_DRIVERS,SI_ORDER_FIRST,i686_mem_drvinit,NULL) X#endif X END-of-sys/drivers/mtrr/i686_mem.c echo x - sys/drivers/mtrr/k6_mem.c sed 's/^X//' >sys/drivers/mtrr/k6_mem.c << 'END-of-sys/drivers/mtrr/k6_mem.c' X/*- X * Copyright (c) 1999 Brian Fundakowski Feldman X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD: src/sys/i386/i386/k6_mem.c,v 1.4 1999/09/05 15:45:57 green Exp $ X * X */ X X#include X#include X#ifndef __Lynx__ X#include X#include X#include X#else X#include X#include X#include X#include X#include X#include X#endif X#include X X#ifndef __Lynx__ X#include X#include X#else X#include "kprotos.h" X#include "compat.h" X Xextern u_int cpu_feature; Xextern u_int cpu_high; Xextern u_int cpu_id; Xextern char cpu_vendor[]; X#include X#endif X X/* X * A K6-2 MTRR is defined as the highest 15 bits having the address, the next X * 15 having the mask, the 1st bit being "write-combining" and the 0th bit X * being "uncacheable". X * X * Address Mask WC UC X * | XXXXXXXXXXXXXXX | XXXXXXXXXXXXXXX | X | X | X * X * There are two of these in the 64-bit UWCCR. X */ X X/* X * NOTE: I do _not_ comment my code unless it's truly necessary. Don't X * expect anything frivolous here, and do NOT touch my bit-shifts X * unless you want to break this. X */ X X#define UWCCR 0xc0000085 X X#define k6_reg_get(reg, addr, mask, wc, uc) do { \ X addr = (reg) & 0xfffe0000; \ X mask = ((reg) & 0x1fffc) >> 2; \ X wc = ((reg) & 0x2) >> 1; \ X uc = (reg) & 0x1; \ X } while (0) X X#define k6_reg_make(addr, mask, wc, uc) \ X ((addr) | ((mask) << 2) | ((wc) << 1) | uc) X Xstatic void k6_mrinit(struct mem_range_softc *sc); Xstatic int k6_mrset(struct mem_range_softc *, struct mem_range_desc *, int *); Xstatic __inline int k6_mrmake(struct mem_range_desc *, u_int32_t *); X#ifndef __Lynx__ Xstatic X#endif X void k6_mem_drvinit(void *); X Xstatic struct mem_range_ops k6_mrops = { X k6_mrinit, X k6_mrset, X NULL X}; X Xstatic __inline int Xk6_mrmake(struct mem_range_desc *desc, u_int32_t *mtrr) { X u_int32_t len = 0, wc, uc; X register int bit; X X if (desc->mr_base &~ 0xfffe0000) X return EINVAL; X if (desc->mr_len < 131072 || !powerof2(desc->mr_len)) X return EINVAL; X if (desc->mr_flags &~ (MDF_WRITECOMBINE|MDF_UNCACHEABLE)) X return EOPNOTSUPP; X X for (bit = ffs(desc->mr_len >> 17) - 1; bit < 15; bit++) X len |= 1 << (14 - bit); X wc = (desc->mr_flags & MDF_WRITECOMBINE) ? 1 : 0; X uc = (desc->mr_flags & MDF_UNCACHEABLE) ? 1 : 0; X X *mtrr = k6_reg_make(desc->mr_base, len, wc, uc); X return 0; X} X Xstatic void Xk6_mrinit(struct mem_range_softc *sc) { X u_int64_t reg; X u_int32_t addr, mask, wc, uc; X int d; X X sc->mr_cap = 0; X sc->mr_ndesc = 2; /* XXX (BFF) For now, we only have one msr for this */ X#ifndef __Lynx__ X sc->mr_desc = malloc(sc->mr_ndesc * sizeof(struct mem_range_desc), X M_MEMDESC, M_NOWAIT); X#else X sc->mr_desc = (struct mem_range_desc *) sysbrk(sc->mr_ndesc * sizeof(struct mem_range_desc)); X#endif X if (sc->mr_desc == NULL) X panic("k6_mrinit: malloc returns NULL"); X bzero(sc->mr_desc, sc->mr_ndesc * sizeof(struct mem_range_desc)); X X reg = rdmsr(UWCCR); X for (d = 0; d < sc->mr_ndesc; d++) { X u_int32_t one = (reg & (0xffffffff << (32 * d))) >> (32 * d); X X k6_reg_get(one, addr, mask, wc, uc); X sc->mr_desc[d].mr_base = addr; X sc->mr_desc[d].mr_len = ffs(mask) << 17; X if (wc) X sc->mr_desc[d].mr_flags |= MDF_WRITECOMBINE; X if (uc) X sc->mr_desc[d].mr_flags |= MDF_UNCACHEABLE; X } X X if (bootverbose) X printf("K6-family MTRR support enabled (%d registers)\n", sc->mr_ndesc); X} X Xstatic int Xk6_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg) { X u_int64_t reg; X u_int32_t mtrr; X int error, d; X X switch (*arg) { X case MEMRANGE_SET_UPDATE: X error = k6_mrmake(desc, &mtrr); X if (error) X return error; X for (d = 0; d < sc->mr_ndesc; d++) { X if (!sc->mr_desc[d].mr_len) { X sc->mr_desc[d] = *desc; X goto out; X } X if (sc->mr_desc[d].mr_base == desc->mr_base && X sc->mr_desc[d].mr_len == desc->mr_len) X return EEXIST; X } X X return ENOSPC; X case MEMRANGE_SET_REMOVE: X mtrr = 0; X for (d = 0; d < sc->mr_ndesc; d++) X if (sc->mr_desc[d].mr_base == desc->mr_base && X sc->mr_desc[d].mr_len == desc->mr_len) { X bzero(&sc->mr_desc[d], sizeof(sc->mr_desc[d])); X goto out; X } X X return ENOENT; X default: X return EOPNOTSUPP; X } X Xout: X X disable_intr(); X wbinvd(); X reg = rdmsr(UWCCR); X reg &= ~(0xffffffff << (32 * d)); X reg |= mtrr << (32 * d); X wrmsr(UWCCR, reg); X wbinvd(); X enable_intr(); X X return 0; X} X X#ifndef __Lynx__ Xstatic X#endif Xvoid Xk6_mem_drvinit(void *unused) { X if (!strcmp(cpu_vendor, "AuthenticAMD") && X (cpu_id & 0xf00) == 0x500 && X ((cpu_id & 0xf0) > 0x80 || X ((cpu_id & 0xf0) == 0x80 && X (cpu_id & 0xf) > 0x7)) X ) X mem_range_softc.mr_op = &k6_mrops; X} X X#ifndef __Lynx__ XSYSINIT(k6memdev, SI_SUB_DRIVERS, SI_ORDER_FIRST, k6_mem_drvinit, NULL) X#endif END-of-sys/drivers/mtrr/k6_mem.c echo x - sys/drivers/mtrr/kprotos.h sed 's/^X//' >sys/drivers/mtrr/kprotos.h << 'END-of-sys/drivers/mtrr/kprotos.h' X/* X * Copyright 1999 by Thomas Mueller X * X * Permission to use, copy, modify, distribute, and sell this software and its X * documentation for any purpose is hereby granted without fee, provided that X * the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the names of the above listed copyright holder(s) X * not be used in advertising or publicity pertaining to distribution of X * the software without specific, written prior permission. The above listed X * copyright holder(s) make(s) no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X */ X X#ifndef __kprotos_h X#define __kprotos_h X X/* definitions for driver service calls which are currently (3.0.1) X * commented out in the system headers (and probably will be X * present in future versions). X */ X X/* from kernel.h: */ X Xextern void get_timestamp _AP((struct timespec *)); X X/* address fault handling */ X Xextern int recoset _AP((void)); Xextern void noreco _AP((void)); X X/* kernel printf's */ X Xextern void cprintf _AP((char *, ...)); Xextern void kkprintf _AP((char *, ...)); Xextern void ksprintf _AP((char *, ...)); X X/* I/O interrupts */ X Xextern int iointset _AP((int vector, void (*function)(void *), char *argument)); Xextern int iointclr _AP((int)); Xextern void ioint_link _AP((int)); X Xextern void panic _AP((char *)); X X/* timeout */ X Xextern int timeout _AP((void (*)(char *), char *, int)); Xextern void cancel_timeout _AP((int)); X X/* time */ Xextern unsigned long nanotime _AP((unsigned long *secs)); X X/* kernel semaphores */ Xextern int ssignal _AP((int *)); Xextern int ssignaln _AP((int *, int)); Xextern int sreset _AP((int *)); Xextern int swait _AP((int *, int)); Xextern int scount _AP((int *)); X X/* kernel-level errno */ X Xextern int pgeterr _AP((void)); X X/* from mem.h: */ X Xextern int sysfree _AP((char *, int)); X X/* allocate physically-contiguous memory */ Xextern char *alloc_cmem _AP((int size)); Xextern void free_cmem _AP((char *, int size)); Xextern char *permap _AP((long physaddr, long size)); X Xextern int mem_map _AP((struct memblock *mblock, int tjob)); Xextern int mem_unmap _AP((struct memblock *mblock, int tjob)); X X/* from st.h: */ X X/* system threads */ X Xextern int ststart _AP((void (*)(), int, int, char *, int, char *)); Xextern void stsetprio _AP((int stid, int prio)); Xextern int stgetprio _AP((int stid)); Xextern int stgetid _AP((void)); Xextern void stgetowne _AP((int stid)); Xextern void stkill _AP((int stid, int signal)); Xextern void stsignal _AP((int (*handler)(char *arg, int signum), char *arg)); X X/* get priority of current proces */ Xextern int _getpriority _AP((void)); X X/* tracking priorities */ Xextern void priot_remove _AP((struct priotrack *p, int prio)); Xextern int priot_max _AP((struct priotrack *p)); Xextern void priot_removen _AP((struct priotrack *p, int prio, int n)); X X/* user proc signals */ Xextern int _kill _AP((int pid, int signal)); Xextern int _killpg _AP((int pgrp, int signal)); Xextern int getpid _AP((void)); Xextern int suser _AP((void)); X X#endif END-of-sys/drivers/mtrr/kprotos.h echo x - sys/drivers/mtrr/memrange.h sed 's/^X//' >sys/drivers/mtrr/memrange.h << 'END-of-sys/drivers/mtrr/memrange.h' X/* This is /usr/include/sys/memrange.h from FreeBSD 3.3 */ X X/* X * Memory range attribute operations, peformed on /dev/mem X */ X X/* Memory range attributes */ X#define MDF_UNCACHEABLE (1<<0) /* region not cached */ X#define MDF_WRITECOMBINE (1<<1) /* region supports "write combine" action */ X#define MDF_WRITETHROUGH (1<<2) /* write-through cached */ X#define MDF_WRITEBACK (1<<3) /* write-back cached */ X#define MDF_WRITEPROTECT (1<<4) /* read-only region */ X#define MDF_ATTRMASK (0x00ffffff) X X#define MDF_FIXBASE (1<<24) /* fixed base */ X#define MDF_FIXLEN (1<<25) /* fixed length */ X#define MDF_FIRMWARE (1<<26) /* set by firmware (XXX not useful?) */ X#define MDF_ACTIVE (1<<27) /* currently active */ X#define MDF_BOGUS (1<<28) /* we don't like it */ X#define MDF_FIXACTIVE (1<<29) /* can't be turned off */ X#define MDF_BUSY (1<<30) /* range is in use */ X Xstruct mem_range_desc X{ X u_int64_t mr_base; X u_int64_t mr_len; X int mr_flags; X char mr_owner[8]; X}; X Xstruct mem_range_op X{ X struct mem_range_desc *mo_desc; X int mo_arg[2]; X#define MEMRANGE_SET_UPDATE 0 X#define MEMRANGE_SET_REMOVE 1 X /* XXX want a flag that says "set and undo when I exit" */ X}; X X#define MEMRANGE_GET _IOWR('m', 50, struct mem_range_op) X#define MEMRANGE_SET _IOW('m', 51, struct mem_range_op) X X#ifdef KERNEL X X#ifndef __Lynx__ XMALLOC_DECLARE(M_MEMDESC); X#endif X Xstruct mem_range_softc; Xstruct mem_range_ops X{ X void (*init)(struct mem_range_softc *sc); X int (*set)(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg); X void (*initAP)(struct mem_range_softc *sc); X}; X Xstruct mem_range_softc X{ X struct mem_range_ops *mr_op; X int mr_cap; X int mr_ndesc; X struct mem_range_desc *mr_desc; X}; X Xextern struct mem_range_softc mem_range_softc; X Xextern int mem_range_attr_get(struct mem_range_desc *mrd, int *arg); Xextern int mem_range_attr_set(struct mem_range_desc *mrd, int *arg); Xextern void mem_range_AP_init(void); X#endif X END-of-sys/drivers/mtrr/memrange.h echo x - sys/drivers/mtrr/mtrr.4 sed 's/^X//' >sys/drivers/mtrr/mtrr.4 << 'END-of-sys/drivers/mtrr/mtrr.4' X XMTRR(4) device facilities (i386 Architecture) MTRR(4) X XNNAAMMEE X mmttrrrr - MTRR device driver X XDDEESSCCRRIIPPTTIIOONN X The _/_d_e_v_/_m_t_r_r driver provides access to the CPUs memory type range regis- X ters (MTRR) for use by the XFree86 X servers. X XIIOOCCTTLL IINNTTEERRFFAACCEE X Several CPU architectures allow attributes to be associated with ranges X of physical memory. These attributes can be manipulated via iiooccttll() X calls performed on //ddeevv//mmttrrrr. Declarations and data types are to be found X in _<_s_y_s_/_m_e_m_r_a_n_g_e_._h_> X X The specific attributes, and number of programmable ranges may vary be- X tween architectures. The full set of supported attributes is: X X MDF_UNCACHEABLE X The region is not cached. X X MDF_WRITECOMBINE X Writes to the region may be combined or performed out of order. X X MDF_WRITETHROUGH X Writes to the region are committed synchronously. X X MDF_WRITEBACK X Writes to the region are committed asynchronously. X X MDF_WRITEPROTECT X The region cannot be written to. X X Memory ranges are described by _s_t_r_u_c_t _m_e_m___r_a_n_g_e___d_e_s_c: X X u_int64_t mr_base; /* physical base address */ X u_int64_t mr_len; /* physical length of region */ X int mr_flags; /* attributes of region */ X char mr_owner[8]; X X In addition to the region attributes listed above, the following flags X may also be set in the _m_r___f_l_a_g_s field: X X MDF_FIXBASE X The region's base address cannot be changed. X X MDF_FIXLEN X The region's length cannot be changed. X X MDF_FIRMWARE X The region is believed to have been established by the system firmare. X X MDF_ACTIVE X The region is currently active. X X MDF_BOGUS X We believe the region to be invalid or otherwise erroneous. X X MDF_FIXACTIVE X The region cannot be disabled. X X MDF_BUSY X The region is currently owned by another process and may not be al- X tered. X X Operations are performed using _s_t_r_u_c_t _m_e_m___r_a_n_g_e___o_p: X X struct mem_range_desc *mo_desc; X int mo_arg[2]; X X The _M_E_M_R_A_N_G_E___G_E_T ioctl is used to retrieve current memory range at- X tributes. If _m_o___a_r_g_[_0_] is set to 0, it will be updated with the total X number of memory range descriptors. If greater than 0, the array at X _m_o___d_e_s_c will be filled with a corresponding number of descriptor struc- X tures, or the maximum, whichever is less. X X The _M_E_M_R_A_N_G_E___S_E_T ioctl is used to add, alter and remove memory range at- X tributes. A range with the MDF_FIXACTIVE flag may not be removed; a X range with the MDF_BUSY flag may not be removed or updated. X X _m_o___a_r_g_[_0_] should be set to MEMRANGE_SET_UPDATE to update an existing or X establish a new range, or to MEMRANGE_SET_REMOVE to remove a range. X XRREETTUURRNN VVAALLUUEESS X EOPNOTSUPP X Memory range operations are not supported on this architecture. X X ENXIO X No memory range descriptors are available (eg. firmware has not enabled X any). X X EINVAL X The memory range supplied as an argument is invalid or overlaps another X range in a fashion not supported by this architecture. X X EBUSY X An attempt to remove or update a range failed because the range is X busy. X X EBUSY X An attempt to open the device driver more than once. X X ENOSPC X An attempt to create a new range failed due to a shortage of hardware X resources (eg. descriptor slots). X X ENOENT X An attempt to remove a range failed because no range matches the de- X scriptor base/length supplued. X X EPERM X An attempt to remove a range failed because the range is permanently X enabled. X X EPERM X The effective user ID of the calling process is not 0. X XSSEEEE AALLSSOO X XFree86(1), X XHHIISSTTOORRYY X _/_d_e_v_/_m_t_r_r is modeled after the _/_d_e_v_/_m_e_m ioctl interface on FreeBSD 3.3. X XAAUUTTHHOORR X The MTRR driver was written by Thomas Mueller. X X This manual page was derived from the NetBSD and OpenBSD aperture driver X included in the XFree86 distribution which was written for the XFree86 X Project Inc. by Matthieu Herrb. The memory range attributes support was X originally written by Michael Smith for FreeBSD. X XBBUUGGSS X This driver allows access to all addresses above _p_h_y_s_m_e_m. It should be X restricted to the actual address range of the video memory. X X Busy range attributes are not yet managed correctly. X X Memory range attributes configuration should probably be controlled X through _/_d_e_v_/_m_e_m. X X LynxOS November 18, 1999 3 END-of-sys/drivers/mtrr/mtrr.4 echo x - sys/drivers/mtrr/mtrr.c sed 's/^X//' >sys/drivers/mtrr/mtrr.c << 'END-of-sys/drivers/mtrr/mtrr.c' X/* X * Copyright 1999 by Thomas Mueller X * All rights reserved. X * X * Permission to use, copy, modify, distribute, and sell this software and its X * documentation for any purpose is hereby granted without fee, provided that X * the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the names of the above listed copyright holder(s) X * not be used in advertising or publicity pertaining to distribution of X * the software without specific, written prior permission. The above listed X * copyright holder(s) make(s) no representations about the suitability of this X * software for any purpose. It is provided "as is" without express or X * implied warranty. X * X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X */ X X/*---------------------------------------------------------------------- X** X** PentiumPRO/II/III, K6-II/III and Athlon MTRR support character X** device driver. Ported from FreeBSDs /dev/mem memrange ioctl X** interface for use by XFree86 4.0 X Server X** X**---------------------------------------------------------------------- X*/ X Xstatic const char __RCSid[] = "$XFree86: xc/programs/Xserver/hw/xfree86/etc/MTRR-Lynx.shar,v 1.1 1999/12/08 06:10:11 dawes Exp $"; X X/* X** Includes and imports X*/ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include X X#include "kprotos.h" X#include "compat.h" X Xextern void cpuid _AP((void)); Xextern void i686_mem_drvinit _AP((void *unused)); Xextern void k6_mem_drvinit _AP((void *unused)); X Xd_open_t mtrr_open; Xd_close_t mtrr_close; Xd_read_t mtrr_read; Xd_write_t mtrr_write; Xd_ioctl_t mtrr_ioctl; Xd_select_t mtrr_select; X Xstatic int mem_range_attr_get _AP((struct mem_range_desc *mrd, int *arg)); Xstatic int mem_range_attr_set _AP((struct mem_range_desc *mrd, int *arg)); X Xstruct mem_range_softc mem_range_softc; X Xtypedef char *mtrr_ptr_t; /* dummy */ X Xstruct mtrr_statics { X int open; X}; X Xint mtrrinfo = 0; /* dummy device info */ X Xchar * Xmtrr_install(void *info) X{ X struct mtrr_statics *s; X X if ((s = (struct mtrr_statics *) sysbrk(sizeof(struct mtrr_statics))) == NULL) { X pseterr(ENOMEM); X return (char *) SYSERR; X } X s->open = 0; X X bzero(&mem_range_softc, sizeof(mem_range_softc)); X X /* what are we running on? (only CPUID probe!) */ X cpuid(); X X /* add others as they come... */ X i686_mem_drvinit(NULL); X k6_mem_drvinit(NULL); X X /* Initialise memory range handling */ X if (mem_range_softc.mr_op != NULL) { X mem_range_softc.mr_op->init(&mem_range_softc); X return (char *) s; X } X X return (char *) SYSERR; X} X Xvoid Xmtrr_uninstall(void *arg) X{ X sysfree(arg, sizeof(struct mtrr_statics)); X} X X/* X * X */ Xint Xmtrr_open(void *arg, int dev, struct file *f) X{ X struct mtrr_statics *s = arg; X X if (!suser()) { X pseterr(EPERM); X return SYSERR; X } X if (s->open) { X pseterr(EBUSY); X return SYSERR; X } X s->open = 1; X return OK; X} X X X/* X * X */ Xint Xmtrr_close(void *arg, struct file *f) X{ X struct mtrr_statics *s = arg; X X s->open = 0; X return OK; X} X X/* X * X */ Xint Xmtrr_read(void *arg, struct file *f, char *buf, int count) X{ X pseterr(ENXIO); X return SYSERR; X} X X X/* X * X */ Xint Xmtrr_write(void *arg, struct file *f, char *buf, int count) X{ X pseterr(ENXIO); X return SYSERR; X} X Xint Xmtrr_select(void *arg, struct file *f, int what, struct sel *ffs) X{ X pseterr(ENXIO); X return SYSERR; X} X X X/* ====================================================================== */ X X/* memrange interface taken from FreeBSD code in /sys/i386/i386/mem.c X * copyrighted as follows: X */ X X/*- X * Copyright (c) 1988 University of Utah. X * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * the Systems Programming Group of the University of Utah Computer X * Science Department, and code derived from software contributed to X * Berkeley by William Jolitz. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * from: Utah $Hdr: mem.c 1.13 89/10/08$ X * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 X * $FreeBSD: src/sys/i386/i386/mem.c,v 1.53.2.5 1999/08/31 06:45:41 msmith Exp $ X */ X X X/* X * Operations for changing memory attributes. X * X * This is basically just an ioctl shim for mem_range_attr_get X * and mem_range_attr_set. X */ Xint Xmtrr_ioctl(void *arg, struct file *f, int cmd, char *data) X{ X int nd, error = 0; X struct mem_range_op *mo = (struct mem_range_op *)data; X struct mem_range_desc *md; X X /* is this for us? */ X if ((cmd != MEMRANGE_GET) && X (cmd != MEMRANGE_SET)) { X pseterr(EINVAL); X return SYSERR; X } X X /* any chance we can handle this? */ X if (mem_range_softc.mr_op == NULL) { X pseterr(EOPNOTSUPP); X return SYSERR; X } X X /* do we have any descriptors? */ X if (mem_range_softc.mr_ndesc == 0) { X pseterr(ENXIO); X return SYSERR; X } X X switch(cmd) { X case MEMRANGE_GET: X if (wbounds((unsigned long)mo) < sizeof(*mo)) { X pseterr(EFAULT); X return SYSERR; X } X nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc); X if (nd > 0) { X if (wbounds((unsigned long)mo->mo_desc) < nd * sizeof(struct mem_range_desc)) { X pseterr(EFAULT); X return SYSERR; X } X md = (struct mem_range_desc *) X sysbrk(nd * sizeof(struct mem_range_desc)); X error = mem_range_attr_get(md, &nd); X if (!error) { X bcopy(md, mo->mo_desc, X nd * sizeof(struct mem_range_desc)); X } X sysfree((char *)md, nd * sizeof(struct mem_range_desc)); X } else { X nd = mem_range_softc.mr_ndesc; X } X mo->mo_arg[0] = nd; X break; X X case MEMRANGE_SET: X if (rbounds((unsigned long)mo) < sizeof(*mo) || X rbounds((unsigned long)mo->mo_desc) < sizeof(struct mem_range_desc)) { X pseterr(EFAULT); X return SYSERR; X } X md = (struct mem_range_desc *)sysbrk(sizeof(struct mem_range_desc)); X bcopy(mo->mo_desc, md, sizeof(struct mem_range_desc)); X /* clamp description string */ X md->mr_owner[sizeof(md->mr_owner) - 1] = 0; X if (error == 0) X error = mem_range_attr_set(md, &mo->mo_arg[0]); X sysfree((char *)md, sizeof(struct mem_range_desc)); X break; X X default: X error = EOPNOTSUPP; X } X if (error) { X pseterr(error); X return SYSERR; X } X return OK; X} X X/* X * Implementation-neutral, kernel-callable functions for manipulating X * memory range attributes. X */ Xstatic int Xmem_range_attr_get(mrd, arg) X struct mem_range_desc *mrd; X int *arg; X{ X /* can we handle this? */ X if (mem_range_softc.mr_op == NULL) X return(EOPNOTSUPP); X X if (*arg == 0) { X *arg = mem_range_softc.mr_ndesc; X } else { X bcopy(mem_range_softc.mr_desc, mrd, (*arg) * sizeof(struct mem_range_desc)); X } X return(0); X} X Xstatic int Xmem_range_attr_set(mrd, arg) X struct mem_range_desc *mrd; X int *arg; X{ X /* can we handle this? */ X if (mem_range_softc.mr_op == NULL) X return(EOPNOTSUPP); X X return(mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg)); X} END-of-sys/drivers/mtrr/mtrr.c echo x - sys/drivers/mtrr/mtrr.cfg sed 's/^X//' >sys/drivers/mtrr/mtrr.cfg << 'END-of-sys/drivers/mtrr/mtrr.cfg' X#!DYNAMINST!C:mtrr.dldd XC:mtrr: \ X :mtrr_open:mtrr_close:mtrr_read:mtrr_write: \ X :mtrr_select:mtrr_ioctl:mtrr_install:mtrr_uninstall XD:MTRR device:mtrrinfo:: XN:mtrr:0: X END-of-sys/drivers/mtrr/mtrr.cfg echo x - sys/drivers/mtrr/mtrr.man sed 's/^X//' >sys/drivers/mtrr/mtrr.man << 'END-of-sys/drivers/mtrr/mtrr.man' X.\" X.\" Copyright 1999 Thomas Mueller X.\" All rights reserved. X.\" X.\" Redistribution and use in source and binary forms, with or without X.\" modification, are permitted provided that the following conditions X.\" are met: X.\" 1. Redistributions of source code must retain the above copyright X.\" notice, this list of conditions and the following disclaimer. X.\" 2. Redistributions in binary form must reproduce the above copyright X.\" notice, this list of conditions and the following disclaimer in the X.\" documentation and/or other materials provided with the distribution. X.\" 3. The name of the author may not be used to endorse or promote products X.\" derived from this software without specific prior written permission X.\" X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR X.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES X.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. X.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, X.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT X.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, X.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY X.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT X.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF X.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. X.\" X.Dd November 18, 1999 X.Dt MTRR 4 i386 X.Os LynxOS X.Sh NAME X.Nm mtrr X.Nd XMTRR device driver X.Sh DESCRIPTION XThe X.Pa /dev/mtrr Xdriver provides access to the CPUs memory type range registers (MTRR) Xfor use by the XFree86 X servers. X.Sh IOCTL INTERFACE XSeveral CPU architectures allow attributes to be associated with ranges Xof physical memory. These attributes can be manipulated via X.Fn ioctl Xcalls performed on X.Nm /dev/mtrr . XDeclarations and data types are to be found in X.Pa X.Pp XThe specific attributes, and number of programmable ranges may vary between Xarchitectures. The full set of supported attributes is: X.Bl -tag -width 10 X.It MDF_UNCACHEABLE XThe region is not cached. X.It MDF_WRITECOMBINE XWrites to the region may be combined or performed out of order. X.It MDF_WRITETHROUGH XWrites to the region are committed synchronously. X.It MDF_WRITEBACK XWrites to the region are committed asynchronously. X.It MDF_WRITEPROTECT XThe region cannot be written to. X.El X.Pp XMemory ranges are described by X.Fa struct mem_range_desc : X.Bd -literal -offset indent Xu_int64_t mr_base; /\(** physical base address \(**/ Xu_int64_t mr_len; /\(** physical length of region \(**/ Xint mr_flags; /\(** attributes of region \(**/ Xchar mr_owner[8]; X.Ed X.Pp XIn addition to the region attributes listed above, the following flags Xmay also be set in the X.Fa mr_flags Xfield: X.Bl -tag -width 10 X.It MDF_FIXBASE XThe region's base address cannot be changed. X.It MDF_FIXLEN XThe region's length cannot be changed. X.It MDF_FIRMWARE XThe region is believed to have been established by the system firmare. X.It MDF_ACTIVE XThe region is currently active. X.It MDF_BOGUS XWe believe the region to be invalid or otherwise erroneous. X.It MDF_FIXACTIVE XThe region cannot be disabled. X.It MDF_BUSY XThe region is currently owned by another process and may not be Xaltered. X.El X.Pp XOperations are performed using X.Fa struct mem_range_op : X.Bd -literal -offset indent Xstruct mem_range_desc *mo_desc; Xint mo_arg[2]; X.Ed X.Pp XThe X.Fa MEMRANGE_GET Xioctl is used to retrieve current memory range attributes. If X.Fa mo_arg[0] Xis set to 0, it will be updated with the total number of memory range Xdescriptors. If greater than 0, the array at X.Fa mo_desc Xwill be filled with a corresponding number of descriptor structures, Xor the maximum, whichever is less. X.Pp XThe X.Fa MEMRANGE_SET Xioctl is used to add, alter and remove memory range attributes. A range Xwith the MDF_FIXACTIVE flag may not be removed; a range with the MDF_BUSY Xflag may not be removed or updated. X.Pp X.Fa mo_arg[0] Xshould be set to MEMRANGE_SET_UPDATE to update an existing Xor establish a new range, or to MEMRANGE_SET_REMOVE to remove a range. X.Pp X.Sh RETURN VALUES X.Bl -tag -width 10 X.It EOPNOTSUPP XMemory range operations are not supported on this architecture. X.It ENXIO XNo memory range descriptors are available (eg. firmware has not enabled Xany). X.It EINVAL XThe memory range supplied as an argument is invalid or overlaps another Xrange in a fashion not supported by this architecture. X.It EBUSY XAn attempt to remove or update a range failed because the range is busy. X.It EBUSY XAn attempt to open the device driver more than once. X.It ENOSPC XAn attempt to create a new range failed due to a shortage of hardware Xresources (eg. descriptor slots). X.It ENOENT XAn attempt to remove a range failed because no range matches the descriptor Xbase/length supplued. X.It EPERM XAn attempt to remove a range failed because the range is permanently Xenabled. X.It EPERM XThe effective user ID of the calling process is not 0. X.El X.Sh SEE ALSO X.Xr XFree86 1 , X.Sh HISTORY X.Pa /dev/mtrr Xis modeled after the X.Pa /dev/mem Xioctl interface on FreeBSD 3.3. X.Sh AUTHOR XThe MTRR driver was written by Thomas Mueller. X.Pp XThis manual page was derived from the NetBSD and OpenBSD Xaperture driver included in the XFree86 distribution which Xwas written for the XFree86 Project Inc. by XMatthieu Herrb. The memory range Xattributes support was originally written by Michael Smith for FreeBSD. X.Sh BUGS XThis driver allows access to all addresses above X.Va physmem . XIt should be restricted to the actual address range of the video Xmemory. X.Pp XBusy range attributes are not yet managed correctly. X.Pp XMemory range attributes configuration should probably be controlled through X.Pa /dev/mem . END-of-sys/drivers/mtrr/mtrr.man echo x - sys/drivers/mtrr/specialreg.h sed 's/^X//' >sys/drivers/mtrr/specialreg.h << 'END-of-sys/drivers/mtrr/specialreg.h' X/*- X * Copyright (c) 1991 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 X * $FreeBSD: src/sys/i386/include/specialreg.h,v 1.16.2.2 1999/08/31 01:19:23 msmith Exp $ X */ X X#ifndef _MACHINE_SPECIALREG_H_ X#define _MACHINE_SPECIALREG_H_ X X/* X * Bits in 386 special registers: X */ X#define CR0_PE 0x00000001 /* Protected mode Enable */ X#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ X#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ X#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ X#ifdef notused X#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ X#endif X#ifndef CR0_PG X#define CR0_PG 0x80000000 /* PaGing enable */ X#endif X X/* X * Bits in 486 special registers: X */ X#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ X#define CR0_WP 0x00010000 /* Write Protect (honor page protect in X all modes) */ X#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ X#define CR0_NW 0x20000000 /* Not Write-through */ X#define CR0_CD 0x40000000 /* Cache Disable */ X X/* X * Bits in PPro special registers X */ X#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ X#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ X#ifndef CR4_TSD X#define CR4_TSD 0x00000004 /* Time stamp disable */ X#endif X#define CR4_DE 0x00000008 /* Debugging extensions */ X#define CR4_PSE 0x00000010 /* Page size extensions */ X#define CR4_PAE 0x00000020 /* Physical address extension */ X#define CR4_MCE 0x00000040 /* Machine check enable */ X#define CR4_PGE 0x00000080 /* Page global enable */ X#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ X X/* X * CPUID instruction features register X */ X#define CPUID_FPU 0x0001 X#define CPUID_VME 0x0002 X#define CPUID_DE 0x0004 X#define CPUID_PSE 0x0008 X#define CPUID_TSC 0x0010 X#define CPUID_MSR 0x0020 X#define CPUID_PAE 0x0040 X#define CPUID_MCE 0x0080 X#define CPUID_CX8 0x0100 X#define CPUID_APIC 0x0200 X#define CPUID_B10 0x0400 X#define CPUID_B11 0x0800 X#define CPUID_MTRR 0x1000 X#define CPUID_PGE 0x2000 X#define CPUID_MCA 0x4000 X#define CPUID_CMOV 0x8000 X X/* X * Model-specific registers for the i386 family X */ X#define MSR_P5_MC_ADDR 0x000 X#define MSR_P5_MC_TYPE 0x001 X#define MSR_TSC 0x010 X#define MSR_APICBASE 0x01b X#define MSR_EBL_CR_POWERON 0x02a X#define MSR_BIOS_UPDT_TRIG 0x079 X#define MSR_BIOS_SIGN 0x08b X#define MSR_PERFCTR0 0x0c1 X#define MSR_PERFCTR1 0x0c2 X#define MSR_MTRRcap 0x0fe X#define MSR_MCG_CAP 0x179 X#define MSR_MCG_STATUS 0x17a X#define MSR_MCG_CTL 0x17b X#define MSR_EVNTSEL0 0x186 X#define MSR_EVNTSEL1 0x187 X#define MSR_DEBUGCTLMSR 0x1d9 X#define MSR_LASTBRANCHFROMIP 0x1db X#define MSR_LASTBRANCHTOIP 0x1dc X#define MSR_LASTINTFROMIP 0x1dd X#define MSR_LASTINTTOIP 0x1de X#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 X#define MSR_MTRRVarBase 0x200 X#define MSR_MTRR64kBase 0x250 X#define MSR_MTRR16kBase 0x258 X#define MSR_MTRR4kBase 0x268 X#define MSR_MTRRdefType 0x2ff X#define MSR_MC0_CTL 0x400 X#define MSR_MC0_STATUS 0x401 X#define MSR_MC0_ADDR 0x402 X#define MSR_MC0_MISC 0x403 X#define MSR_MC1_CTL 0x404 X#define MSR_MC1_STATUS 0x405 X#define MSR_MC1_ADDR 0x406 X#define MSR_MC1_MISC 0x407 X#define MSR_MC2_CTL 0x408 X#define MSR_MC2_STATUS 0x409 X#define MSR_MC2_ADDR 0x40a X#define MSR_MC2_MISC 0x40b X#define MSR_MC4_CTL 0x40c X#define MSR_MC4_STATUS 0x40d X#define MSR_MC4_ADDR 0x40e X#define MSR_MC4_MISC 0x40f X#define MSR_MC3_CTL 0x410 X#define MSR_MC3_STATUS 0x411 X#define MSR_MC3_ADDR 0x412 X#define MSR_MC3_MISC 0x413 X X/* X * Constants related to MTRRs X */ X#define MTRR_N64K 8 /* numbers of fixed-size entries */ X#define MTRR_N16K 16 X#define MTRR_N4K 64 X X/* X * Cyrix configuration registers, accessible as IO ports. X */ X#define CCR0 0xc0 /* Configuration control register 0 */ X#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is X non-cacheable */ X#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ X#define CCR0_A20M 0x04 /* Enables A20M# input pin */ X#define CCR0_KEN 0x08 /* Enables KEN# input pin */ X#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */ X#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold X state */ X#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set X assoc */ X#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */ X X#define CCR1 0xc1 /* Configuration control register 1 */ X#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */ X#define CCR1_SMI 0x02 /* Enables SMM pins */ X#define CCR1_SMAC 0x04 /* System management memory access */ X#define CCR1_MMAC 0x08 /* Main memory access */ X#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */ X#define CCR1_SM3 0x80 /* SMM address space address region 3 */ X X#define CCR2 0xc2 X#define CCR2_WB 0x02 /* Enables WB cache interface pins */ X#define CCR2_SADS 0x02 /* Slow ADS */ X#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */ X#define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */ X#define CCR2_WT1 0x10 /* WT region 1 */ X#define CCR2_WPR1 0x10 /* Write-protect region 1 */ X#define CCR2_BARB 0x20 /* Flushes write-back cache when entering X hold state. */ X#define CCR2_BWRT 0x40 /* Enables burst write cycles */ X#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ X X#define CCR3 0xc3 X#define CCR3_SMILOCK 0x01 /* SMM register lock */ X#define CCR3_NMI 0x02 /* Enables NMI during SMM */ X#define CCR3_LINBRST 0x04 /* Linear address burst cycles */ X#define CCR3_SMMMODE 0x08 /* SMM Mode */ X#define CCR3_MAPEN0 0x10 /* Enables Map0 */ X#define CCR3_MAPEN1 0x20 /* Enables Map1 */ X#define CCR3_MAPEN2 0x40 /* Enables Map2 */ X#define CCR3_MAPEN3 0x80 /* Enables Map3 */ X X#define CCR4 0xe8 X#define CCR4_IOMASK 0x07 X#define CCR4_MEM 0x08 /* Enables momory bypassing */ X#define CCR4_DTE 0x10 /* Enables directory table entry cache */ X#define CCR4_FASTFPE 0x20 /* Fast FPU exception */ X#define CCR4_CPUID 0x80 /* Enables CPUID instruction */ X X#define CCR5 0xe9 X#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */ X#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */ X#define CCR5_LBR1 0x10 /* Local bus region 1 */ X#define CCR5_ARREN 0x20 /* Enables ARR region */ X X#define CCR6 0xea X X#define CCR7 0xeb X X/* Performance Control Register (5x86 only). */ X#define PCR0 0x20 X#define PCR0_RSTK 0x01 /* Enables return stack */ X#define PCR0_BTB 0x02 /* Enables branch target buffer */ X#define PCR0_LOOP 0x04 /* Enables loop */ X#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to X serialize pipe. */ X#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ X#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ X#define PCR0_LSSER 0x80 /* Disable reorder */ X X/* Device Identification Registers */ X#define DIR0 0xfe X#define DIR1 0xff X X/* X * The following four 3-byte registers control the non-cacheable regions. X * These registers must be written as three separate bytes. X * X * NCRx+0: A31-A24 of starting address X * NCRx+1: A23-A16 of starting address X * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. X * X * The non-cacheable region's starting address must be aligned to the X * size indicated by the NCR_SIZE_xx field. X */ X#define NCR1 0xc4 X#define NCR2 0xc7 X#define NCR3 0xca X#define NCR4 0xcd X X#define NCR_SIZE_0K 0 X#define NCR_SIZE_4K 1 X#define NCR_SIZE_8K 2 X#define NCR_SIZE_16K 3 X#define NCR_SIZE_32K 4 X#define NCR_SIZE_64K 5 X#define NCR_SIZE_128K 6 X#define NCR_SIZE_256K 7 X#define NCR_SIZE_512K 8 X#define NCR_SIZE_1M 9 X#define NCR_SIZE_2M 10 X#define NCR_SIZE_4M 11 X#define NCR_SIZE_8M 12 X#define NCR_SIZE_16M 13 X#define NCR_SIZE_32M 14 X#define NCR_SIZE_4G 15 X X/* X * The address region registers are used to specify the location and X * size for the eight address regions. X * X * ARRx + 0: A31-A24 of start address X * ARRx + 1: A23-A16 of start address X * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx X */ X#define ARR0 0xc4 X#define ARR1 0xc7 X#define ARR2 0xca X#define ARR3 0xcd X#define ARR4 0xd0 X#define ARR5 0xd3 X#define ARR6 0xd6 X#define ARR7 0xd9 X X#define ARR_SIZE_0K 0 X#define ARR_SIZE_4K 1 X#define ARR_SIZE_8K 2 X#define ARR_SIZE_16K 3 X#define ARR_SIZE_32K 4 X#define ARR_SIZE_64K 5 X#define ARR_SIZE_128K 6 X#define ARR_SIZE_256K 7 X#define ARR_SIZE_512K 8 X#define ARR_SIZE_1M 9 X#define ARR_SIZE_2M 10 X#define ARR_SIZE_4M 11 X#define ARR_SIZE_8M 12 X#define ARR_SIZE_16M 13 X#define ARR_SIZE_32M 14 X#define ARR_SIZE_4G 15 X X/* X * The region control registers specify the attributes associated with X * the ARRx addres regions. X */ X#define RCR0 0xdc X#define RCR1 0xdd X#define RCR2 0xde X#define RCR3 0xdf X#define RCR4 0xe0 X#define RCR5 0xe1 X#define RCR6 0xe2 X#define RCR7 0xe3 X X#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ X#define RCR_RCE 0x01 /* Enables caching for ARR7. */ X#define RCR_WWO 0x02 /* Weak write ordering. */ X#define RCR_WL 0x04 /* Weak locking. */ X#define RCR_WG 0x08 /* Write gathering. */ X#define RCR_WT 0x10 /* Write-through. */ X#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ X X/* AMD Write Allocate Top-Of-Memory and Control Register */ X#define AMD_WT_ALLOC_TME 0x40000 /* top-of-memory enable */ X#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */ X#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */ X X X#ifndef LOCORE Xstatic __inline u_char Xread_cyrix_reg(u_char reg) X{ X outb(0x22, reg); X return inb(0x23); X} X Xstatic __inline void Xwrite_cyrix_reg(u_char reg, u_char data) X{ X outb(0x22, reg); X outb(0x23, data); X} X#endif X X#endif /* !_MACHINE_SPECIALREG_H_ */ END-of-sys/drivers/mtrr/specialreg.h echo x - sys/drivers/mtrr/support.S sed 's/^X//' >sys/drivers/mtrr/support.S << 'END-of-sys/drivers/mtrr/support.S' X/* support.S - from the FreeBSD file with the same name X * but stripped down to cpuid and CRx functions X */ X X/*- X * Copyright (c) 1993 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X * X * $FreeBSD: src/sys/i386/i386/support.s,v 1.60.2.1 1999/08/29 16:05:52 peter Exp $ X */ X X X/* X * CNAME and HIDENAME manage the relationship between symbol names in C X * and the equivalent assembly language names. CNAME is given a name as X * it would be used in a C program. It expands to the equivalent assembly X * language name. HIDENAME is given an assembly-language name, and expands X * to a possibly-modified form that will be invisible to C programs. X */ X#define CNAME(csym) csym X#define HIDENAME(asmsym) __CONCAT(.,asmsym) X X#define ALIGN_DATA .p2align 2 /* 4 byte alignment, zero filled */ X#define ALIGN_TEXT .p2align 2,0x90 /* 4-byte alignment, nop filled */ X#define SUPERALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ X X#define ENTRY(name) ALIGN_TEXT; .globl CNAME(name); \ X CNAME(name): X X X#include X X .data X .globl cpu,cpu_vendor,cpu_id, X .globl cpu_high, cpu_feature Xcpu: .long 0 /* are we 386, 386sx, or 486 */ Xcpu_id: .long 0 /* stepping ID */ Xcpu_high: .long 0 /* highest arg to CPUID */ Xcpu_feature: .long 0 /* features */ Xcpu_vendor: .space 20 /* CPU origin code */ X X .text X X/* load_cr0(cr0) */ XENTRY(load_cr0) X movl 4(%esp),%eax X movl %eax,%cr0 X ret X X/* rcr0() */ XENTRY(rcr0) X movl %cr0,%eax X ret X X/* rcr4() */ XENTRY(rcr4) X movl %cr4,%eax X ret X X/* void load_cr4(caddr_t cr4) */ XENTRY(load_cr4) X movl 4(%esp),%eax X movl %eax,%cr4 X ret X X#define R(foo) ((foo)) X XENTRY(cpuid) X push %ebp X mov %esp,%ebp X push %ebx X push %ecx X push %edx X xorl %eax,%eax X .byte 0x0f,0xa2 /* cpuid 0 */ X movl %eax,R(cpu_high) /* highest capability */ X movl %ebx,R(cpu_vendor) /* store vendor string */ X movl %edx,R(cpu_vendor+4) X movl %ecx,R(cpu_vendor+8) X movb $0,R(cpu_vendor+12) X X movl $1,%eax X .byte 0x0f,0xa2 /* cpuid 1 */ X movl %eax,R(cpu_id) /* store cpu_id */ X movl %edx,R(cpu_feature) /* store cpu_feature */ X rorl $8,%eax /* extract family type */ X andl $15,%eax X cmpl $5,%eax X jae .L1 X X /* less than Pentium; must be 486 */ X movl $CPU_486,R(cpu) X jmp .L3 X X.L1: X /* a Pentium? */ X cmpl $5,%eax X jne .L2 X movl $CPU_586,R(cpu) X jmp .L3 X.L2: X /* Greater than Pentium...call it a Pentium Pro */ X movl $CPU_686,R(cpu) X.L3: X pop %edx X pop %ecx X pop %ebx X leave X ret X nop X END-of-sys/drivers/mtrr/support.S exit