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 static void generic_get_mtrr(unsigned int reg, unsigned long *base,
15 unsigned long *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 /* This function returns the number of variable MTRRs */
38 static void __init set_num_var_ranges(void)
42 for (num_var_ranges = 0; ; num_var_ranges++) {
43 op.cmd = DOM0_READ_MEMTYPE;
44 op.u.read_memtype.reg = num_var_ranges;
45 if (HYPERVISOR_dom0_op(&op) != 0)
50 static void __init init_table(void)
55 if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
57 printk(KERN_ERR "mtrr: could not allocate\n");
60 for (i = 0; i < max; i++)
64 int mtrr_add_page(unsigned long base, unsigned long size,
65 unsigned int type, char increment)
70 mutex_lock(&mtrr_mutex);
72 op.cmd = DOM0_ADD_MEMTYPE;
73 op.u.add_memtype.mfn = base;
74 op.u.add_memtype.nr_mfns = size;
75 op.u.add_memtype.type = type;
76 error = HYPERVISOR_dom0_op(&op);
78 mutex_unlock(&mtrr_mutex);
84 ++usage_table[op.u.add_memtype.reg];
86 mutex_unlock(&mtrr_mutex);
88 return op.u.add_memtype.reg;
91 static int mtrr_check(unsigned long base, unsigned long size)
93 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
95 "mtrr: size and base must be multiples of 4 kiB\n");
97 "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
105 mtrr_add(unsigned long base, unsigned long size, unsigned int type,
108 if (mtrr_check(base, size))
110 return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
114 int mtrr_del_page(int reg, unsigned long base, unsigned long size)
118 unsigned long lbase, lsize;
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);