--- mtrr.c.org Fri Apr 21 15:15:24 2000 +++ mtrr.c Fri Apr 21 15:18:59 2000 @@ -482,11 +482,113 @@ return 0; } /* End Function have_wrcomb */ +static void intel_get_fixed_mtrr (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) +{ + unsigned long lo, hi, calc_base, calc_size; + unsigned long msr_num; + + reg-=get_num_var_ranges(); + + if (reg>=NUM_FIXED_RANGES) { + /* Invalid num. */ + *base = 0; + *size = 0; + *type = 0; + return; + } + + switch(reg>>3){ + case 0: + msr_num=MTRRfix64K_00000_MSR; + calc_base=0; + calc_size=65536; + break; + case 1: + msr_num=MTRRfix16K_80000_MSR; + calc_base=0x80000; + calc_size=16384; + break; + case 2: + msr_num=MTRRfix16K_A0000_MSR; + calc_base=0xA0000; + calc_size=16384; + break; + case 3: + msr_num=MTRRfix4K_C0000_MSR; + calc_base=0xC0000; + calc_size=4096; + break; + case 4: + msr_num=MTRRfix4K_C8000_MSR; + calc_base=0xC8000; + calc_size=4096; + break; + case 5: + msr_num=MTRRfix4K_D0000_MSR; + calc_base=0xD0000; + calc_size=4096; + break; + case 6: + msr_num=MTRRfix4K_D8000_MSR; + calc_base=0xD8000; + calc_size=4096; + break; + case 7: + msr_num=MTRRfix4K_E0000_MSR; + calc_base=0xE0000; + calc_size=4096; + break; + case 8: + msr_num=MTRRfix4K_E8000_MSR; + calc_base=0xE8000; + calc_size=4096; + break; + case 9: + msr_num=MTRRfix4K_F0000_MSR; + calc_base=0xF0000; + calc_size=4096; + break; + case 10: + msr_num=MTRRfix4K_F8000_MSR; + calc_base=0xF8000; + calc_size=4096; + break; + default: + msr_num=0; + calc_base=0; + calc_size=0; + break; + }; + + if (msr_num==0) { + /* Invalid num. */ + *base = 0; + *size = 0; + *type = 0; + return; + } + + rdmsr(msr_num, lo, hi); + + if(reg&4)lo=hi; + lo>>=8*(reg&3); + + *type = (lo & 0xff); + *size=calc_size; + *base=calc_base+(reg&7)*calc_size; +} + static void intel_get_mtrr (unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type *type) { unsigned long dummy, mask_lo, base_lo; + if(reg>=get_num_var_ranges()){ + intel_get_fixed_mtrr(reg,base,size,type); + return; + }; + rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy); if ( (mask_lo & 0x800) == 0 ) { @@ -624,6 +726,71 @@ static void (*get_mtrr) (unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type *type) = NULL; +static int intel_set_fixed_mtrr (unsigned int reg, unsigned long base, + unsigned long size, mtrr_type type) +/* currently, ignore size, only set the fixed mtrr that includes base */ +{ + unsigned long lo, hi, mask, calc_size; + unsigned long msr_num, tmp_base; + int place; + + if((size==0)&&(base==0)&&(type==0)) { + int max=get_num_var_ranges (); + intel_get_fixed_mtrr(reg,&base,&size,&type); + if(reg=max+16)type=0; + }; + + if(size==0) { + size=0x1000; + type=0; + }; + + while(size>0) + { + if (base>=0x100000) return -EFAULT; + tmp_base = base >> 12 ; + + if(tmp_base<128) { + msr_num=MTRRfix64K_00000_MSR; + place=tmp_base>>4; + calc_size=65536; + } else + if(tmp_base<192) { + msr_num=MTRRfix16K_80000_MSR+(tmp_base>=160); + place=(tmp_base>>2)&7l; + calc_size=16384; + } else { + msr_num=MTRRfix4K_C0000_MSR+((tmp_base&0x3f)>>3); + place=tmp_base&7; + calc_size=4096; + }; + + rdmsr(msr_num, lo, hi); + + mask=0xff<<((place&3)<<3); + + if(place&4) { + hi&=~mask; + hi|=type<<((place&3)<<3); + } else { + lo &=~mask; + lo|=type<<(place<<3); + }; + + wrmsr(msr_num, lo, hi); + + if(size= 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) ) @@ -1597,6 +1781,19 @@ ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); } } + if(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + for (i = max; i < max+NUM_FIXED_RANGES; i++) + { + (*get_mtrr) (i, &base, &size, &type); + if(((i=max+16)&&(type!=0))) + { + sprintf + (ascii_buffer + ascii_buf_bytes, + "reg%02i: base=0x%08lx (%4likB), size=%4likB: %s, count=%d\n", + i, base, base>>10, size>>10, attrib_to_str (type), 1); + ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); + } + } devfs_set_file_size (devfs_handle, ascii_buf_bytes); # ifdef CONFIG_PROC_FS proc_root_mtrr->size = ascii_buf_bytes;