1 #include <linux/init.h>
2 #include <linux/proc_fs.h>
3 #include <linux/ctype.h>
4 #include <linux/module.h>
5 #include <linux/seq_file.h>
6 #include <asm/uaccess.h>
11 void generic_get_mtrr(unsigned int reg, unsigned long *base,
12 unsigned int *size, mtrr_type * type)
16 op.cmd = DOM0_READ_MEMTYPE;
17 op.u.read_memtype.reg = reg;
18 (void)HYPERVISOR_dom0_op(&op);
20 *size = op.u.read_memtype.nr_pfns;
21 *base = op.u.read_memtype.pfn;
22 *type = op.u.read_memtype.type;
25 struct mtrr_ops generic_mtrr_ops = {
27 .get = generic_get_mtrr,
30 struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
31 unsigned int num_var_ranges;
32 unsigned int *usage_table;
34 void __init set_num_var_ranges(void)
38 for (num_var_ranges = 0; ; num_var_ranges++) {
39 op.cmd = DOM0_READ_MEMTYPE;
40 op.u.read_memtype.reg = num_var_ranges;
41 if (HYPERVISOR_dom0_op(&op) != 0)
46 static void __init init_table(void)
51 if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
53 printk(KERN_ERR "mtrr: could not allocate\n");
56 for (i = 0; i < max; i++)
60 int mtrr_add_page(unsigned long base, unsigned long size,
61 unsigned int type, char increment)
66 op.cmd = DOM0_ADD_MEMTYPE;
67 op.u.add_memtype.pfn = base;
68 op.u.add_memtype.nr_pfns = size;
69 op.u.add_memtype.type = type;
70 if ((error = HYPERVISOR_dom0_op(&op)))
74 ++usage_table[op.u.add_memtype.reg];
76 return op.u.add_memtype.reg;
80 mtrr_add(unsigned long base, unsigned long size, unsigned int type,
83 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
84 printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
85 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
88 return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
92 int mtrr_del_page(int reg, unsigned long base, unsigned long size)
101 max = num_var_ranges;
103 /* Search for existing MTRR */
104 for (i = 0; i < max; ++i) {
105 mtrr_if->get(i, &lbase, &lsize, <ype);
106 if (lbase == base && lsize == size) {
112 printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
117 if (usage_table[reg] < 1) {
118 printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
121 if (--usage_table[reg] < 1) {
122 op.cmd = DOM0_DEL_MEMTYPE;
123 op.u.del_memtype.handle = 0;
124 op.u.add_memtype.reg = reg;
125 (void)HYPERVISOR_dom0_op(&op);
133 mtrr_del(int reg, unsigned long base, unsigned long size)
135 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
136 printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
137 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
140 return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
143 EXPORT_SYMBOL(mtrr_add);
144 EXPORT_SYMBOL(mtrr_del);
146 static int __init mtrr_init(void)
148 struct cpuinfo_x86 *c = &boot_cpu_data;
150 if (!(xen_start_info.flags & SIF_PRIVILEGED))
153 if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
154 (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
155 (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
156 (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
159 set_num_var_ranges();
165 subsys_initcall(mtrr_init);