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 <linux/mutex.h>
7 #include <asm/uaccess.h>
12 static DEFINE_MUTEX(mtrr_mutex);
14 void generic_get_mtrr(unsigned int reg, unsigned long *base,
15 unsigned int *size, mtrr_type * type)
19 op.cmd = DOM0_READ_MEMTYPE;
20 op.u.read_memtype.reg = reg;
21 (void)HYPERVISOR_dom0_op(&op);
23 *size = op.u.read_memtype.nr_mfns;
24 *base = op.u.read_memtype.mfn;
25 *type = op.u.read_memtype.type;
28 struct mtrr_ops generic_mtrr_ops = {
30 .get = generic_get_mtrr,
33 struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
34 unsigned int num_var_ranges;
35 unsigned int *usage_table;
37 static void __init set_num_var_ranges(void)
41 for (num_var_ranges = 0; ; num_var_ranges++) {
42 op.cmd = DOM0_READ_MEMTYPE;
43 op.u.read_memtype.reg = num_var_ranges;
44 if (HYPERVISOR_dom0_op(&op) != 0)
49 static void __init init_table(void)
54 if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
56 printk(KERN_ERR "mtrr: could not allocate\n");
59 for (i = 0; i < max; i++)
63 int mtrr_add_page(unsigned long base, unsigned long size,
64 unsigned int type, char increment)
69 mutex_lock(&mtrr_mutex);
71 op.cmd = DOM0_ADD_MEMTYPE;
72 op.u.add_memtype.mfn = base;
73 op.u.add_memtype.nr_mfns = size;
74 op.u.add_memtype.type = type;
75 error = HYPERVISOR_dom0_op(&op);
77 mutex_unlock(&mtrr_mutex);
83 ++usage_table[op.u.add_memtype.reg];
85 mutex_unlock(&mtrr_mutex);
87 return op.u.add_memtype.reg;
90 static int mtrr_check(unsigned long base, unsigned long size)
92 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
94 "mtrr: size and base must be multiples of 4 kiB\n");
96 "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
104 mtrr_add(unsigned long base, unsigned long size, unsigned int type,
107 if (mtrr_check(base, size))
109 return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
113 int mtrr_del_page(int reg, unsigned long base, unsigned long size)
122 mutex_lock(&mtrr_mutex);
125 /* Search for existing MTRR */
126 for (i = 0; i < num_var_ranges; ++i) {
127 mtrr_if->get(i, &lbase, &lsize, <ype);
128 if (lbase == base && lsize == size) {
134 printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
139 if (usage_table[reg] < 1) {
140 printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
143 if (--usage_table[reg] < 1) {
144 op.cmd = DOM0_DEL_MEMTYPE;
145 op.u.del_memtype.handle = 0;
146 op.u.del_memtype.reg = reg;
147 error = HYPERVISOR_dom0_op(&op);
155 mutex_unlock(&mtrr_mutex);
160 mtrr_del(int reg, unsigned long base, unsigned long size)
162 if (mtrr_check(base, size))
164 return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
167 EXPORT_SYMBOL(mtrr_add);
168 EXPORT_SYMBOL(mtrr_del);
170 void __init mtrr_bp_init(void)
174 void mtrr_ap_init(void)
178 static int __init mtrr_init(void)
180 struct cpuinfo_x86 *c = &boot_cpu_data;
182 if (!is_initial_xendomain())
185 if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
186 (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
187 (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
188 (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
191 set_num_var_ranges();
197 subsys_initcall(mtrr_init);