--- 2.3.30.mtrr.c Wed Dec 8 23:32:09 1999 +++ linux/arch/i386/kernel/mtrr.c Wed Dec 8 23:29:47 1999 @@ -474,11 +474,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) { /* Invalid (i.e. free) range. */ @@ -611,6 +713,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= 0x100000)) { - spin_unlock (&main_lock); + up(&main_lock); printk ("mtrr: no more MTRRs available\n"); return i; } + }; set_mtrr (i, base, size, type); - usage_table[i] = 1; - compute_ascii (); + if(!fixed) + { + usage_table[i] = 1; + }; up(&main_lock); return i; } /* End Function mtrr_add */ @@ -1281,7 +1455,6 @@ return -EINVAL; } if (--usage_table[reg] < 1) set_mtrr (reg, 0, 0, 0); - compute_ascii (); up(&main_lock); return reg; } /* End Function mtrr_del */ @@ -1326,11 +1499,30 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len, loff_t *ppos) -{ - if (*ppos >= ascii_buf_bytes) return 0; +{ int size; + + size=get_num_var_ranges()+NUM_FIXED_RANGES; + if ( ( ascii_buffer = kmalloc (size * LINE_SIZE, GFP_KERNEL) ) == NULL ) + { + printk ("mtrr: could not allocate\n"); + return 0; + } + ascii_buf_bytes = 0; + compute_ascii (); + + if (*ppos >= ascii_buf_bytes) + { + kfree(ascii_buffer); + return 0; + }; if (*ppos + len > ascii_buf_bytes) len = ascii_buf_bytes - *ppos; - if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) return -EFAULT; + if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) + { + kfree(ascii_buffer); + return -EFAULT; + }; *ppos += len; + kfree(ascii_buffer); return len; } /* End Function mtrr_read */ @@ -1436,7 +1628,9 @@ case MTRRIOC_GET_ENTRY: if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) ) return -EFAULT; +/* This check should be done by get_mtrr. 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) ) @@ -1523,6 +1717,19 @@ "reg%02i: base=0x%08lx (%4liMB), size=%4li%cB: %s, count=%d\n", i, base, base>>20, size, factor, attrib_to_str (type), usage_table[i]); + 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); } }