⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtrr.c

📁 linux下的BOOT程序原码,有需要的可以来下,保证好用
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************                   SciTech OS Portability Manager Library**  ========================================================================**    The contents of this file are subject to the SciTech MGL Public*    License Version 1.0 (the "License"); you may not use this file*    except in compliance with the License. You may obtain a copy of*    the License at http://www.scitechsoft.com/mgl-license.txt**    Software distributed under the License is distributed on an*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*    implied. See the License for the specific language governing*    rights and limitations under the License.**    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.**    The Initial Developer of the Original Code is SciTech Software, Inc.*    All Rights Reserved.**  ========================================================================**               Heavily based on code copyright (C) Richard Gooch** Language:     ANSI C* Environment:  32-bit Ring 0 device driver** Description:  Generic Memory Type Range Register (MTRR) functions to*               manipulate the MTRR registers on supported CPU's. This code*               *must* run at ring 0, so you can't normally include this*               code directly in normal applications (the except is DOS4GW*               apps which run at ring 0 under real DOS). Thus this code*               will normally be compiled into a ring 0 device driver for*               the target operating system.*****************************************************************************/#include "pmapi.h"#include "ztimerc.h"#include "mtrr.h"#ifndef REALMODE/*--------------------------- Global variables ----------------------------*//* Intel pre-defined MTRR registers */#define NUM_FIXED_RANGES        88#define INTEL_cap_MSR           0x0FE#define INTEL_defType_MSR       0x2FF#define INTEL_fix64K_00000_MSR  0x250#define INTEL_fix16K_80000_MSR  0x258#define INTEL_fix16K_A0000_MSR  0x259#define INTEL_fix4K_C0000_MSR   0x268#define INTEL_fix4K_C8000_MSR   0x269#define INTEL_fix4K_D0000_MSR   0x26A#define INTEL_fix4K_D8000_MSR   0x26B#define INTEL_fix4K_E0000_MSR   0x26C#define INTEL_fix4K_E8000_MSR   0x26D#define INTEL_fix4K_F0000_MSR   0x26E#define INTEL_fix4K_F8000_MSR   0x26F/* Macros to find the address of a paricular MSR register */#define INTEL_physBase_MSR(reg) (0x200 + 2 * (reg))#define INTEL_physMask_MSR(reg) (0x200 + 2 * (reg) + 1)/* Cyrix CPU configuration register indexes */#define CX86_CCR0 0xC0#define CX86_CCR1 0xC1#define CX86_CCR2 0xC2#define CX86_CCR3 0xC3#define CX86_CCR4 0xE8#define CX86_CCR5 0xE9#define CX86_CCR6 0xEA#define CX86_DIR0 0xFE#define CX86_DIR1 0xFF#define CX86_ARR_BASE 0xC4#define CX86_RCR_BASE 0xDC/* Structure to maintain machine state while updating MTRR registers */typedef struct {    ulong   flags;    ulong   defTypeLo;    ulong   defTypeHi;    ulong   cr4Val;    ulong   ccr3;    } MTRRContext;static int      numMTRR = -1;static int      cpuFamily,cpuType,cpuStepping;static void     (*getMTRR)(uint reg,ulong *base,ulong *size,int *type) = NULL;static void     (*setMTRR)(uint reg,ulong base,ulong size,int type) = NULL;static int      (*getFreeRegion)(ulong base,ulong size) = NULL;/*----------------------------- Implementation ----------------------------*//****************************************************************************RETURNS:Returns non-zero if we have the write-combining memory type****************************************************************************/static int MTRR_haveWriteCombine(void){    ulong   config,dummy;    switch (cpuFamily) {	case CPU_AMD:	    if (cpuType < CPU_AMDAthlon) {		/* AMD K6-2 stepping 8 and later support the MTRR registers.		 * The earlier K6-2 steppings (300Mhz models) do not		 * support MTRR's.		 */		if ((cpuType < CPU_AMDK6_2) || (cpuType == CPU_AMDK6_2 && cpuStepping < 8))		    return 0;		return 1;		}	    /* Fall through for AMD Athlon which uses P6 style MTRR's */	case CPU_Intel:	    _MTRR_readMSR(INTEL_cap_MSR,&config,&dummy);	    return (config & (1 << 10));	case CPU_Cyrix:	    /* Cyrix 6x86 and later support the MTRR registers */	    if (cpuType < CPU_Cyrix6x86)		return 0;	    return 1;	}    return 0;}/****************************************************************************PARAMETERS:base    - The starting physical base address of the regionsize    - The size in bytes of the regionRETURNS:The index of the region on success, else -1 on error.REMARKS:Generic function to find the location of a free MTRR register to be usedfor creating a new mapping.****************************************************************************/static int GENERIC_getFreeRegion(    ulong base,    ulong size){    int     i,ltype;    ulong   lbase,lsize;    for (i = 0; i < numMTRR; i++) {	getMTRR(i,&lbase,&lsize,&ltype);	if (lsize < 1)	    return i;	}    (void)base;    (void)size;    return -1;}/****************************************************************************PARAMETERS:base    - The starting physical base address of the regionsize    - The size in bytes of the regionRETURNS:The index of the region on success, else -1 on error.REMARKS:Generic function to find the location of a free MTRR register to be usedfor creating a new mapping.****************************************************************************/static int AMDK6_getFreeRegion(    ulong base,    ulong size){    int     i,ltype;    ulong   lbase,lsize;    for (i = 0; i < numMTRR; i++) {	getMTRR(i,&lbase,&lsize,&ltype);	if (lsize < 1)	    return i;	}    (void)base;    (void)size;    return -1;}/****************************************************************************PARAMETERS:base    - The starting physical base address of the regionsize    - The size in bytes of the regionRETURNS:The index of the region on success, else -1 on error.REMARKS:Cyrix specific function to find the location of a free MTRR register to beused for creating a new mapping.****************************************************************************/static int CYRIX_getFreeRegion(    ulong base,    ulong size){    int     i,ltype;    ulong   lbase, lsize;    if (size > 0x2000000UL) {	/* If we are to set up a region >32M then look at ARR7 immediately */	getMTRR(7,&lbase,&lsize,&ltype);	if (lsize < 1)	    return 7;	}    else {	/* Check ARR0-6 registers */	for (i = 0; i < 7; i++) {	    getMTRR(i,&lbase,&lsize,&ltype);	    if (lsize < 1)		return i;	    }	/* Try ARR7 but its size must be at least 256K */	getMTRR(7,&lbase,&lsize,&ltype);	if ((lsize < 1) && (size >= 0x40000))	    return i;	}    (void)base;    return -1;}/****************************************************************************PARAMETERS:c   - Place to store the machine context across the callREMARKS:Puts the processor into a state where MTRRs can be safely updated****************************************************************************/static void MTRR_beginUpdate(    MTRRContext *c){    c->flags = _MTRR_disableInt();    if (cpuFamily != CPU_AMD || (cpuFamily == CPU_AMD && cpuType >= CPU_AMDAthlon)) {	switch (cpuFamily) {	    case CPU_Intel:	    case CPU_AMD:		/* Disable MTRRs, and set the default type to uncached */		c->cr4Val = _MTRR_saveCR4();		_MTRR_readMSR(INTEL_defType_MSR,&c->defTypeLo,&c->defTypeHi);		_MTRR_writeMSR(INTEL_defType_MSR,c->defTypeLo & 0xF300UL,c->defTypeHi);		break;	    case CPU_Cyrix:		c->ccr3 = _MTRR_getCx86(CX86_CCR3);		_MTRR_setCx86(CX86_CCR3, (uchar)((c->ccr3 & 0x0F) | 0x10));		break;	    }	}}/****************************************************************************PARAMETERS:c   - Place to restore the machine context fromREMARKS:Restores the processor after updating any of the registers****************************************************************************/static void MTRR_endUpdate(    MTRRContext *c){    if (cpuFamily != CPU_AMD || (cpuFamily == CPU_AMD && cpuType >= CPU_AMDAthlon)) {	PM_flushTLB();	switch (cpuFamily) {	    case CPU_Intel:	    case CPU_AMD:		_MTRR_writeMSR(INTEL_defType_MSR,c->defTypeLo,c->defTypeHi);		_MTRR_restoreCR4(c->cr4Val);		break;	    case CPU_Cyrix:		_MTRR_setCx86(CX86_CCR3,(uchar)c->ccr3);		break;	    }	}    /* Re-enable interrupts (if enabled previously) */    _MTRR_restoreInt(c->flags);}/****************************************************************************PARAMETERS:reg     - MTRR register to readbase    - Place to store the starting physical base address of the regionsize    - Place to store the size in bytes of the regiontype    - Place to store the type of the MTRR registerREMARKS:Intel specific function to read the value of a specific MTRR register.****************************************************************************/static void INTEL_getMTRR(    uint reg,    ulong *base,    ulong *size,    int *type){    ulong hi,maskLo,baseLo;    _MTRR_readMSR(INTEL_physMask_MSR(reg),&maskLo,&hi);    if ((maskLo & 0x800) == 0) {	/* MTRR is disabled, so it is free */	*base = 0;	*size = 0;	*type = 0;	return;	}    _MTRR_readMSR(INTEL_physBase_MSR(reg),&baseLo,&hi);    maskLo = (maskLo & 0xFFFFF000UL);    *size = ~(maskLo - 1);    *base = (baseLo & 0xFFFFF000UL);    *type = (baseLo & 0xFF);}/****************************************************************************PARAMETERS:reg     - MTRR register to setbase    - The starting physical base address of the regionsize    - The size in bytes of the regiontype    - Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void INTEL_setMTRR(    uint reg,    ulong base,    ulong size,    int type){    MTRRContext c;    MTRR_beginUpdate(&c);    if (size == 0) {	/* The invalid bit is kept in the mask, so we simply clear the	 * relevant mask register to disable a range.	 */	_MTRR_writeMSR(INTEL_physMask_MSR(reg),0,0);	}    else {	_MTRR_writeMSR(INTEL_physBase_MSR(reg),base | type,0);	_MTRR_writeMSR(INTEL_physMask_MSR(reg),~(size - 1) | 0x800,0);	}    MTRR_endUpdate(&c);}/****************************************************************************REMARKS:Disabled banked write combing for Intel processors. We always disable thisbecause it invariably causes problems with older hardware.****************************************************************************/static void INTEL_disableBankedWriteCombine(void){    MTRRContext c;    MTRR_beginUpdate(&c);    _MTRR_writeMSR(INTEL_fix16K_A0000_MSR,0,0);    MTRR_endUpdate(&c);}/****************************************************************************PARAMETERS:reg     - MTRR register to setbase    - The starting physical base address of the regionsize    - The size in bytes of the regiontype    - Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void AMD_getMTRR(    uint reg,    ulong *base,    ulong *size,    int *type){    ulong   low,high;    /*  Upper dword is region 1, lower is region 0  */    _MTRR_readMSR(0xC0000085, &low, &high);    if (reg == 1)	low = high;    /* Find the base and type for the region */    *base = low & 0xFFFE0000;    *type = 0;    if (low & 1)	*type = PM_MTRR_UNCACHABLE;    if (low & 2)	*type = PM_MTRR_WRCOMB;    if ((low & 3) == 0) {	*size = 0;	return;	}    /* This needs a little explaining. The size is stored as an     * inverted mask of bits of 128K granularity 15 bits long offset     * 2 bits     *     * So to get a size we do invert the mask and add 1 to the lowest     * mask bit (4 as its 2 bits in). This gives us a size we then shift     * to turn into 128K blocks     *     *  eg              111 1111 1111 1100      is 512K     *     *  invert          000 0000 0000 0011     *  +1              000 0000 0000 0100     *  *128K   ...     */    low = (~low) & 0x0FFFC;    *size = (low + 4) << 15;}/****************************************************************************PARAMETERS:reg     - MTRR register to setbase    - The starting physical base address of the regionsize    - The size in bytes of the regiontype    - Type to place into the MTRR registerREMARKS:Intel specific function to set the value of a specific MTRR register tothe passed in base, size and type.****************************************************************************/static void AMD_setMTRR(    uint reg,    ulong base,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -