direct-io.hg

view linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c @ 8496:ecc20905cde3

Fixes to mtrr interface code in linux guest.

Signed-off-by: Jan Beulich <JBeulich@novell.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jan 04 18:47:11 2006 +0100 (2006-01-04)
parents 06d84bf87159
children
line source
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>
8 #include <asm/mtrr.h>
9 #include "mtrr.h"
11 void generic_get_mtrr(unsigned int reg, unsigned long *base,
12 unsigned int *size, mtrr_type * type)
13 {
14 dom0_op_t op;
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;
23 }
25 struct mtrr_ops generic_mtrr_ops = {
26 .use_intel_if = 1,
27 .get = generic_get_mtrr,
28 };
30 struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
31 unsigned int num_var_ranges;
32 unsigned int *usage_table;
34 static void __init set_num_var_ranges(void)
35 {
36 dom0_op_t op;
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)
42 break;
43 }
44 }
46 static void __init init_table(void)
47 {
48 int i, max;
50 max = num_var_ranges;
51 if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
52 == NULL) {
53 printk(KERN_ERR "mtrr: could not allocate\n");
54 return;
55 }
56 for (i = 0; i < max; i++)
57 usage_table[i] = 0;
58 }
60 int mtrr_add_page(unsigned long base, unsigned long size,
61 unsigned int type, char increment)
62 {
63 int error;
64 dom0_op_t op;
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 error = HYPERVISOR_dom0_op(&op);
71 if (error) {
72 BUG_ON(error > 0);
73 return error;
74 }
76 if (increment)
77 ++usage_table[op.u.add_memtype.reg];
79 return op.u.add_memtype.reg;
80 }
82 int
83 mtrr_add(unsigned long base, unsigned long size, unsigned int type,
84 char increment)
85 {
86 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
87 printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
88 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
89 return -EINVAL;
90 }
91 return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
92 increment);
93 }
95 int mtrr_del_page(int reg, unsigned long base, unsigned long size)
96 {
97 int i, max;
98 mtrr_type ltype;
99 unsigned long lbase;
100 unsigned int lsize;
101 int error = -EINVAL;
102 dom0_op_t op;
104 max = num_var_ranges;
105 if (reg < 0) {
106 /* Search for existing MTRR */
107 for (i = 0; i < max; ++i) {
108 mtrr_if->get(i, &lbase, &lsize, &ltype);
109 if (lbase == base && lsize == size) {
110 reg = i;
111 break;
112 }
113 }
114 if (reg < 0) {
115 printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
116 size);
117 goto out;
118 }
119 }
120 if (usage_table[reg] < 1) {
121 printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
122 goto out;
123 }
124 if (--usage_table[reg] < 1) {
125 op.cmd = DOM0_DEL_MEMTYPE;
126 op.u.del_memtype.handle = 0;
127 op.u.del_memtype.reg = reg;
128 error = HYPERVISOR_dom0_op(&op);
129 if (error) {
130 BUG_ON(error > 0);
131 goto out;
132 }
133 }
134 error = reg;
135 out:
136 return error;
137 }
139 int
140 mtrr_del(int reg, unsigned long base, unsigned long size)
141 {
142 if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
143 printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
144 printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
145 return -EINVAL;
146 }
147 return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
148 }
150 EXPORT_SYMBOL(mtrr_add);
151 EXPORT_SYMBOL(mtrr_del);
153 static int __init mtrr_init(void)
154 {
155 struct cpuinfo_x86 *c = &boot_cpu_data;
157 if (!(xen_start_info->flags & SIF_PRIVILEGED))
158 return -ENODEV;
160 if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
161 (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
162 (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
163 (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
164 return -ENODEV;
166 set_num_var_ranges();
167 init_table();
169 return 0;
170 }
172 subsys_initcall(mtrr_init);