📄 mtrr.c
字号:
/* Generic MTRR (Memory Type Range Register) driver. Copyright (C) 1997-2000 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Richard Gooch may be reached by email at rgooch@atnf.csiro.au The postal address is: Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. Source: "Pentium Pro Family Developer's Manual, Volume 3: Operating System Writer's Guide" (Intel document number 242692), section 11.11.7 ChangeLog Prehistory Martin Tischh鋟ser <martin@ikcbarka.fzk.de> Initial register-setting code (from proform-1.0). 19971216 Richard Gooch <rgooch@atnf.csiro.au> Original version for /proc/mtrr interface, SMP-safe. v1.0 19971217 Richard Gooch <rgooch@atnf.csiro.au> Bug fix for ioctls()'s. Added sample code in Documentation/mtrr.txt v1.1 19971218 Richard Gooch <rgooch@atnf.csiro.au> Disallow overlapping regions. 19971219 Jens Maurer <jmaurer@menuett.rhein-main.de> Register-setting fixups. v1.2 19971222 Richard Gooch <rgooch@atnf.csiro.au> Fixups for kernel 2.1.75. v1.3 19971229 David Wragg <dpw@doc.ic.ac.uk> Register-setting fixups and conformity with Intel conventions. 19971229 Richard Gooch <rgooch@atnf.csiro.au> Cosmetic changes and wrote this ChangeLog ;-) 19980106 Richard Gooch <rgooch@atnf.csiro.au> Fixups for kernel 2.1.78. v1.4 19980119 David Wragg <dpw@doc.ic.ac.uk> Included passive-release enable code (elsewhere in PCI setup). v1.5 19980131 Richard Gooch <rgooch@atnf.csiro.au> Replaced global kernel lock with private spinlock. v1.6 19980201 Richard Gooch <rgooch@atnf.csiro.au> Added wait for other CPUs to complete changes. v1.7 19980202 Richard Gooch <rgooch@atnf.csiro.au> Bug fix in definition of <set_mtrr> for UP. v1.8 19980319 Richard Gooch <rgooch@atnf.csiro.au> Fixups for kernel 2.1.90. 19980323 Richard Gooch <rgooch@atnf.csiro.au> Move SMP BIOS fixup before secondary CPUs call <calibrate_delay> v1.9 19980325 Richard Gooch <rgooch@atnf.csiro.au> Fixed test for overlapping regions: confused by adjacent regions 19980326 Richard Gooch <rgooch@atnf.csiro.au> Added wbinvd in <set_mtrr_prepare>. 19980401 Richard Gooch <rgooch@atnf.csiro.au> Bug fix for non-SMP compilation. 19980418 David Wragg <dpw@doc.ic.ac.uk> Fixed-MTRR synchronisation for SMP and use atomic operations instead of spinlocks. 19980418 Richard Gooch <rgooch@atnf.csiro.au> Differentiate different MTRR register classes for BIOS fixup. v1.10 19980419 David Wragg <dpw@doc.ic.ac.uk> Bug fix in variable MTRR synchronisation. v1.11 19980419 Richard Gooch <rgooch@atnf.csiro.au> Fixups for kernel 2.1.97. v1.12 19980421 Richard Gooch <rgooch@atnf.csiro.au> Safer synchronisation across CPUs when changing MTRRs. v1.13 19980423 Richard Gooch <rgooch@atnf.csiro.au> Bugfix for SMP systems without MTRR support. v1.14 19980427 Richard Gooch <rgooch@atnf.csiro.au> Trap calls to <mtrr_add> and <mtrr_del> on non-MTRR machines. v1.15 19980427 Richard Gooch <rgooch@atnf.csiro.au> Use atomic bitops for setting SMP change mask. v1.16 19980428 Richard Gooch <rgooch@atnf.csiro.au> Removed spurious diagnostic message. v1.17 19980429 Richard Gooch <rgooch@atnf.csiro.au> Moved register-setting macros into this file. Moved setup code from init/main.c to i386-specific areas. v1.18 19980502 Richard Gooch <rgooch@atnf.csiro.au> Moved MTRR detection outside conditionals in <mtrr_init>. v1.19 19980502 Richard Gooch <rgooch@atnf.csiro.au> Documentation improvement: mention Pentium II and AGP. v1.20 19980521 Richard Gooch <rgooch@atnf.csiro.au> Only manipulate interrupt enable flag on local CPU. Allow enclosed uncachable regions. v1.21 19980611 Richard Gooch <rgooch@atnf.csiro.au> Always define <main_lock>. v1.22 19980901 Richard Gooch <rgooch@atnf.csiro.au> Removed module support in order to tidy up code. Added sanity check for <mtrr_add>/<mtrr_del> before <mtrr_init>. Created addition queue for prior to SMP commence. v1.23 19980902 Richard Gooch <rgooch@atnf.csiro.au> Ported patch to kernel 2.1.120-pre3. v1.24 19980910 Richard Gooch <rgooch@atnf.csiro.au> Removed sanity checks and addition queue: Linus prefers an OOPS. v1.25 19981001 Richard Gooch <rgooch@atnf.csiro.au> Fixed harmless compiler warning in include/asm-i386/mtrr.h Fixed version numbering and history for v1.23 -> v1.24. v1.26 19990118 Richard Gooch <rgooch@atnf.csiro.au> Added devfs support. v1.27 19990123 Richard Gooch <rgooch@atnf.csiro.au> Changed locking to spin with reschedule. Made use of new <smp_call_function>. v1.28 19990201 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Extended the driver to be able to use Cyrix style ARRs. 19990204 Richard Gooch <rgooch@atnf.csiro.au> Restructured Cyrix support. v1.29 19990204 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Refined ARR support: enable MAPEN in set_mtrr_prepare() and disable MAPEN in set_mtrr_done(). 19990205 Richard Gooch <rgooch@atnf.csiro.au> Minor cleanups. v1.30 19990208 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Protect plain 6x86s (and other processors without the Page Global Enable feature) against accessing CR4 in set_mtrr_prepare() and set_mtrr_done(). 19990210 Richard Gooch <rgooch@atnf.csiro.au> Turned <set_mtrr_up> and <get_mtrr> into function pointers. v1.31 19990212 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Major rewrite of cyrix_arr_init(): do not touch ARRs, leave them as the BIOS have set them up. Enable usage of all 8 ARRs. Avoid multiplications by 3 everywhere and other code clean ups/speed ups. 19990213 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Set up other Cyrix processors identical to the boot cpu. Since Cyrix don't support Intel APIC, this is l'art pour l'art. Weigh ARRs by size: If size <= 32M is given, set up ARR# we were given. If size > 32M is given, set up ARR7 only if it is free, fail otherwise. 19990214 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Also check for size >= 256K if we are to set up ARR7, mtrr_add() returns the value it gets from set_mtrr() 19990218 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Remove Cyrix "coma bug" workaround from here. Moved to linux/arch/i386/kernel/setup.c and linux/include/asm-i386/bugs.h 19990228 Richard Gooch <rgooch@atnf.csiro.au> Added MTRRIOC_KILL_ENTRY ioctl(2) Trap for counter underflow in <mtrr_file_del>. Trap for 4 MiB aligned regions for PPro, stepping <= 7. 19990301 Richard Gooch <rgooch@atnf.csiro.au> Created <get_free_region> hook. 19990305 Richard Gooch <rgooch@atnf.csiro.au> Temporarily disable AMD support now MTRR capability flag is set. v1.32 19990308 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Adjust my changes (19990212-19990218) to Richard Gooch's latest changes. (19990228-19990305) v1.33 19990309 Richard Gooch <rgooch@atnf.csiro.au> Fixed typo in <printk> message. 19990310 Richard Gooch <rgooch@atnf.csiro.au> Support K6-II/III based on Alan Cox's <alan@redhat.com> patches. v1.34 19990511 Bart Hartgers <bart@etpmod.phys.tue.nl> Support Centaur C6 MCR's. 19990512 Richard Gooch <rgooch@atnf.csiro.au> Minor cleanups. v1.35 19990707 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Check whether ARR3 is protected in cyrix_get_free_region() and mtrr_del(). The code won't attempt to delete or change it from now on if the BIOS protected ARR3. It silently skips ARR3 in cyrix_get_free_region() or returns with an error code from mtrr_del(). 19990711 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Reset some bits in the CCRs in cyrix_arr_init() to disable SMM if ARR3 isn't protected. This is needed because if SMM is active and ARR3 isn't protected then deleting and setting ARR3 again may lock up the processor. With SMM entirely disabled, it does not happen. 19990812 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Rearrange switch() statements so the driver accomodates to the fact that the AMD Athlon handles its MTRRs the same way as Intel does. 19990814 Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> Double check for Intel in mtrr_add()'s big switch() because that revision check is only valid for Intel CPUs. 19990819 Alan Cox <alan@redhat.com> Tested Zoltan's changes on a pre production Athlon - 100% success. 19991008 Manfred Spraul <manfreds@colorfullife.com> replaced spin_lock_reschedule() with a normal semaphore. v1.36 20000221 Richard Gooch <rgooch@atnf.csiro.au> Compile fix if procfs and devfs not enabled. Formatting changes. v1.37 20001109 H. Peter Anvin <hpa@zytor.com> Use the new centralized CPU feature detects.*/#include <linux/types.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/tty.h>#include <linux/timer.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/wait.h>#include <linux/string.h>#include <linux/malloc.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/fs.h>#include <linux/ctype.h>#include <linux/proc_fs.h>#include <linux/devfs_fs_kernel.h>#include <linux/mm.h>#include <linux/module.h>#define MTRR_NEED_STRINGS#include <asm/mtrr.h>#include <linux/init.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/processor.h>#include <asm/system.h>#include <asm/pgtable.h>#include <asm/segment.h>#include <asm/bitops.h>#include <asm/atomic.h>#include <asm/msr.h>#include <asm/hardirq.h>#include <linux/irq.h>#define MTRR_VERSION "1.37 (20001109)"#define TRUE 1#define FALSE 0/* * The code assumes all processors support the same MTRR * interface. This is generally a good assumption, but could * potentially be a problem. */enum mtrr_if_type { MTRR_IF_NONE, /* No MTRRs supported */ MTRR_IF_INTEL, /* Intel (P6) standard MTRRs */ MTRR_IF_AMD_K6, /* AMD pre-Athlon MTRRs */ MTRR_IF_CYRIX_ARR, /* Cyrix ARRs */ MTRR_IF_CENTAUR_MCR, /* Centaur MCRs */} mtrr_if = MTRR_IF_NONE;static __initdata char *mtrr_if_name[] = { "none", "Intel", "AMD K6", "Cyrix ARR", "Centaur MCR"};#define MTRRcap_MSR 0x0fe#define MTRRdefType_MSR 0x2ff#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)#define NUM_FIXED_RANGES 88#define MTRRfix64K_00000_MSR 0x250#define MTRRfix16K_80000_MSR 0x258#define MTRRfix16K_A0000_MSR 0x259#define MTRRfix4K_C0000_MSR 0x268#define MTRRfix4K_C8000_MSR 0x269#define MTRRfix4K_D0000_MSR 0x26a#define MTRRfix4K_D8000_MSR 0x26b#define MTRRfix4K_E0000_MSR 0x26c#define MTRRfix4K_E8000_MSR 0x26d#define MTRRfix4K_F0000_MSR 0x26e#define MTRRfix4K_F8000_MSR 0x26f#ifdef CONFIG_SMP# define MTRR_CHANGE_MASK_FIXED 0x01# define MTRR_CHANGE_MASK_VARIABLE 0x02# define MTRR_CHANGE_MASK_DEFTYPE 0x04#endif/* In the Intel processor's MTRR interface, the MTRR type is always held in an 8 bit field: */typedef u8 mtrr_type;#define LINE_SIZE 80#define JIFFIE_TIMEOUT 100#ifdef CONFIG_SMP# define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)#else# define set_mtrr(reg,base,size,type) (*set_mtrr_up) (reg, base, size, type, \ TRUE)#endif#if defined(CONFIG_PROC_FS) || defined(CONFIG_DEVFS_FS)# define USERSPACE_INTERFACE#endif#ifndef USERSPACE_INTERFACE# define compute_ascii() while (0)#endif#ifdef USERSPACE_INTERFACEstatic char *ascii_buffer;static unsigned int ascii_buf_bytes;#endifstatic unsigned int *usage_table;static DECLARE_MUTEX(main_lock);/* Private functions */#ifdef USERSPACE_INTERFACEstatic void compute_ascii (void);#endifstruct set_mtrr_context{ unsigned long flags; unsigned long deftype_lo; unsigned long deftype_hi; unsigned long cr4val; unsigned long ccr3;};static int arr3_protected;/* Put the processor into a state where MTRRs can be safely set */static void set_mtrr_prepare (struct set_mtrr_context *ctxt){ unsigned long tmp; /* Disable interrupts locally */ __save_flags (ctxt->flags); __cli (); if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) return; /* Save value of CR4 and clear Page Global Enable (bit 7) */ if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) asm volatile ("movl %%cr4, %0\n\t" "movl %0, %1\n\t" "andb $0x7f, %b1\n\t" "movl %1, %%cr4\n\t" : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory"); /* Disable and flush caches. Note that wbinvd flushes the TLBs as a side-effect */ asm volatile ("movl %%cr0, %0\n\t" "orl $0x40000000, %0\n\t" "wbinvd\n\t" "movl %0, %%cr0\n\t" "wbinvd\n\t" : "=r" (tmp) : : "memory"); if ( mtrr_if == MTRR_IF_INTEL ) { /* Disable MTRRs, and set the default type to uncached */ rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi); wrmsr (MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi); } else { /* Cyrix ARRs - everything else were excluded at the top */ tmp = getCx86 (CX86_CCR3); setCx86 (CX86_CCR3, (tmp & 0x0f) | 0x10); ctxt->ccr3 = tmp; }} /* End Function set_mtrr_prepare *//* Restore the processor after a set_mtrr_prepare */static void set_mtrr_done (struct set_mtrr_context *ctxt){ unsigned long tmp; if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) { __restore_flags (ctxt->flags); return; } /* Flush caches and TLBs */ asm volatile ("wbinvd" : : : "memory" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -