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

📄 mtrr.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
    mtrr_type type;    struct mtrr_sentry sentry;    struct mtrr_gentry gentry;    switch (cmd)    {      default:	return -ENOIOCTLCMD;      case MTRRIOC_ADD_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 0);	if (err < 0) return err;	break;      case MTRRIOC_SET_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_add (sentry.base, sentry.size, sentry.type, 0);	if (err < 0) return err;	break;      case MTRRIOC_DEL_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_file_del (sentry.base, sentry.size, file, 0);	if (err < 0) return err;	break;      case MTRRIOC_KILL_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_del (-1, sentry.base, sentry.size);	if (err < 0) return err;	break;      case MTRRIOC_GET_ENTRY:	if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) )	    return -EFAULT;	if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;	(*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);	/* Hide entries that go above 4GB */	if (gentry.base + gentry.size > 0x100000 || gentry.size == 0x100000)	    gentry.base = gentry.size = gentry.type = 0;	else {	    gentry.base <<= PAGE_SHIFT;	    gentry.size <<= PAGE_SHIFT;	    gentry.type = type;	}	if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )	     return -EFAULT;	break;      case MTRRIOC_ADD_PAGE_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 1);	if (err < 0) return err;	break;      case MTRRIOC_SET_PAGE_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);	if (err < 0) return err;	break;      case MTRRIOC_DEL_PAGE_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_file_del (sentry.base, sentry.size, file, 1);	if (err < 0) return err;	break;      case MTRRIOC_KILL_PAGE_ENTRY:	if ( !suser () ) return -EPERM;	if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )	    return -EFAULT;	err = mtrr_del_page (-1, sentry.base, sentry.size);	if (err < 0) return err;	break;      case MTRRIOC_GET_PAGE_ENTRY:	if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) )	    return -EFAULT;	if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;	(*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);	gentry.type = type;	if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )	     return -EFAULT;	break;    }    return 0;}   /*  End Function mtrr_ioctl  */static int mtrr_close (struct inode *ino, struct file *file){    int i, max;    unsigned int *fcount = file->private_data;    if (fcount == NULL) return 0;    lock_kernel();    max = get_num_var_ranges ();    for (i = 0; i < max; ++i)    {	while (fcount[i] > 0)	{	    if (mtrr_del (i, 0, 0) < 0) printk ("mtrr: reg %d not used\n", i);	    --fcount[i];	}    }    unlock_kernel();    kfree (fcount);    file->private_data = NULL;    return 0;}   /*  End Function mtrr_close  */static struct file_operations mtrr_fops ={    owner:	THIS_MODULE,    read:	mtrr_read,    write:	mtrr_write,    ioctl:	mtrr_ioctl,    release:	mtrr_close,};#  ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *proc_root_mtrr;#  endif  /*  CONFIG_PROC_FS  */static devfs_handle_t devfs_handle;static void compute_ascii (void){    char factor;    int i, max;    mtrr_type type;    unsigned long base, size;    ascii_buf_bytes = 0;    max = get_num_var_ranges ();    for (i = 0; i < max; i++)    {	(*get_mtrr) (i, &base, &size, &type);	if (size == 0) usage_table[i] = 0;	else	{	    if (size < (0x100000 >> PAGE_SHIFT))	    {		/* less than 1MB */		factor = 'K';		size <<= PAGE_SHIFT - 10;	    }	    else	    {		factor = 'M';		size >>= 20 - PAGE_SHIFT;	    }	    sprintf		(ascii_buffer + ascii_buf_bytes,		 "reg%02i: base=0x%05lx000 (%4liMB), size=%4li%cB: %s, count=%d\n",		 i, base, base >> (20 - PAGE_SHIFT), size, factor,		 attrib_to_str (type), usage_table[i]);	    ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);	}    }    devfs_set_file_size (devfs_handle, ascii_buf_bytes);#  ifdef CONFIG_PROC_FS    if (proc_root_mtrr)	proc_root_mtrr->size = ascii_buf_bytes;#  endif  /*  CONFIG_PROC_FS  */}   /*  End Function compute_ascii  */#endif  /*  USERSPACE_INTERFACE  */EXPORT_SYMBOL(mtrr_add);EXPORT_SYMBOL(mtrr_del);#ifdef CONFIG_SMPtypedef struct{    unsigned long base;    unsigned long size;    mtrr_type type;} arr_state_t;arr_state_t arr_state[8] __initdata ={    {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},    {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}};unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };static void __init cyrix_arr_init_secondary(void){    struct set_mtrr_context ctxt;    int i;    set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */     /* the CCRs are not contiguous */    for(i=0; i<4; i++) setCx86(CX86_CCR0 + i, ccr_state[i]);    for(   ; i<7; i++) setCx86(CX86_CCR4 + i, ccr_state[i]);    for(i=0; i<8; i++)      cyrix_set_arr_up(i,        arr_state[i].base, arr_state[i].size, arr_state[i].type, FALSE);    set_mtrr_done (&ctxt); /* flush cache and disable MAPEN */}   /*  End Function cyrix_arr_init_secondary  */#endif/* * On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection * with the SMM (System Management Mode) mode. So we need the following: * Check whether SMI_LOCK (CCR3 bit 0) is set *   if it is set, write a warning message: ARR3 cannot be changed! *     (it cannot be changed until the next processor reset) *   if it is reset, then we can change it, set all the needed bits: *   - disable access to SMM memory through ARR3 range (CCR1 bit 7 reset) *   - disable access to SMM memory (CCR1 bit 2 reset) *   - disable SMM mode (CCR1 bit 1 reset) *   - disable write protection of ARR3 (CCR6 bit 1 reset) *   - (maybe) disable ARR3 * Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set) */static void __init cyrix_arr_init(void){    struct set_mtrr_context ctxt;    unsigned char ccr[7];    int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };#ifdef CONFIG_SMP    int i;#endif    set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */    /* Save all CCRs locally */    ccr[0] = getCx86 (CX86_CCR0);    ccr[1] = getCx86 (CX86_CCR1);    ccr[2] = getCx86 (CX86_CCR2);    ccr[3] = ctxt.ccr3;    ccr[4] = getCx86 (CX86_CCR4);    ccr[5] = getCx86 (CX86_CCR5);    ccr[6] = getCx86 (CX86_CCR6);    if (ccr[3] & 1)    {	ccrc[3] = 1;	arr3_protected = 1;    }    else    {	/* Disable SMM mode (bit 1), access to SMM memory (bit 2) and	 * access to SMM memory through ARR3 (bit 7).	 */	if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }	if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }	if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }	arr3_protected = 0;	if (ccr[6] & 0x02) {	    ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3 */	    setCx86 (CX86_CCR6, ccr[6]);	}	/* Disable ARR3. This is safe now that we disabled SMM. */	/* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */    }    /* If we changed CCR1 in memory, change it in the processor, too. */    if (ccrc[1]) setCx86 (CX86_CCR1, ccr[1]);    /* Enable ARR usage by the processor */    if (!(ccr[5] & 0x20))    {	ccr[5] |= 0x20; ccrc[5] = 1;	setCx86 (CX86_CCR5, ccr[5]);    }#ifdef CONFIG_SMP    for(i=0; i<7; i++) ccr_state[i] = ccr[i];    for(i=0; i<8; i++)      cyrix_get_arr(i,        &arr_state[i].base, &arr_state[i].size, &arr_state[i].type);#endif    set_mtrr_done (&ctxt); /* flush cache and disable MAPEN */    if ( ccrc[5] ) printk ("mtrr: ARR usage was not enabled, enabled manually\n");    if ( ccrc[3] ) printk ("mtrr: ARR3 cannot be changed\n");/*    if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n");    if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n");    if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n");*/    if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");}   /*  End Function cyrix_arr_init  *//* *	Initialise the later (saner) Winchip MCR variant. In this version *	the BIOS can pass us the registers it has used (but not their values) *	and the control register is read/write */ static void __init centaur_mcr1_init(void){    unsigned i;    u32 lo, hi;    /* Unfortunately, MCR's are read-only, so there is no way to     * find out what the bios might have done.     */         rdmsr(MSR_IDT_MCR_CTRL, lo, hi);    if(((lo>>17)&7)==1)		/* Type 1 Winchip2 MCR */    {    	lo&= ~0x1C0;		/* clear key */    	lo|= 0x040;		/* set key to 1 */	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);	/* unlock MCR */    }            centaur_mcr_type = 1;        /*     *	Clear any unconfigured MCR's.     */    for (i = 0; i < 8; ++i)    {    	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)    	{    		if(!(lo & (1<<(9+i))))			wrmsr (MSR_IDT_MCR0 + i , 0, 0);		else			/*			 *	If the BIOS set up an MCR we cannot see it			 *	but we don't wish to obliterate it			 */			centaur_mcr_reserved |= (1<<i);	}    }    /*       *	Throw the main write-combining switch...      *	However if OOSTORE is enabled then people have already done far     *  cleverer things and we should behave.      */    lo |= 15;			/* Write combine enables */    wrmsr(MSR_IDT_MCR_CTRL, lo, hi);}   /*  End Function centaur_mcr1_init  *//* *	Initialise the original winchip with read only MCR registers *	no used bitmask for the BIOS to pass on and write only control */ static void __init centaur_mcr0_init(void){    unsigned i;    /* Unfortunately, MCR's are read-only, so there is no way to     * find out what the bios might have done.     */         /* Clear any unconfigured MCR's.     * This way we are sure that the centaur_mcr array contains the actual     * values. The disadvantage is that any BIOS tweaks are thus undone.     *     */    for (i = 0; i < 8; ++i)    {    	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)		wrmsr (MSR_IDT_MCR0 + i , 0, 0);    }    wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);	/* Write only */}   /*  End Function centaur_mcr0_init  *//* *	Initialise Winchip series MCR registers */ static void __init centaur_mcr_init(void){    struct set_mtrr_context ctxt;    set_mtrr_prepare (&ctxt);    if(boot_cpu_data.x86_model==4)    	centaur_mcr0_init();    else if(boot_cpu_data.x86_model==8 || boot_cpu_data.x86_model == 9)    	centaur_mcr1_init();    set_mtrr_done (&ctxt);}   /*  End Function centaur_mcr_init  */static int __init mtrr_setup(void){    if ( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ) {	/* Intel (P6) standard MTRRs */	mtrr_if = MTRR_IF_INTEL;	get_mtrr = intel_get_mtrr;	set_mtrr_up = intel_set_mtrr_up;	switch (boot_cpu_data.x86_vendor) {	case X86_VENDOR_AMD:		/* The original Athlon docs said that		   total addressable memory is 44 bits wide.		   It was not really clear whether its MTRRs		   follow this or not. (Read: 44 or 36 bits).		   However, "x86-64_overview.pdf" explicitly		   states that "previous implementations support		   36 bit MTRRs" and also provides a way to		   query the width (in bits) of the physical		   addressable memor

⌨️ 快捷键说明

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