ia64/xen-unstable

view xen/arch/x86/dom0_ops.c @ 6518:b1a41c400d5c

VMX domains can have iopl!=0.

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
author adsharma@los-vmm.sc.intel.com
date Tue Aug 09 11:18:23 2005 -0800 (2005-08-09)
parents a83ac0806d6b
children dc61689b4781
line source
1 /******************************************************************************
2 * Arch-specific dom0_ops.c
3 *
4 * Process command requests from domain-0 guest OS.
5 *
6 * Copyright (c) 2002, K A Fraser
7 */
9 #include <xen/config.h>
10 #include <xen/types.h>
11 #include <xen/lib.h>
12 #include <xen/mm.h>
13 #include <public/dom0_ops.h>
14 #include <xen/sched.h>
15 #include <xen/event.h>
16 #include <xen/domain_page.h>
17 #include <asm/msr.h>
18 #include <xen/trace.h>
19 #include <xen/console.h>
20 #include <asm/shadow.h>
21 #include <asm/irq.h>
22 #include <public/sched_ctl.h>
24 #include <asm/mtrr.h>
25 #include "mtrr/mtrr.h"
27 #define TRC_DOM0OP_ENTER_BASE 0x00020000
28 #define TRC_DOM0OP_LEAVE_BASE 0x00030000
30 static int msr_cpu_mask;
31 static unsigned long msr_addr;
32 static unsigned long msr_lo;
33 static unsigned long msr_hi;
35 static void write_msr_for(void *unused)
36 {
37 if (((1 << current->processor) & msr_cpu_mask))
38 (void)wrmsr_user(msr_addr, msr_lo, msr_hi);
39 }
41 static void read_msr_for(void *unused)
42 {
43 if (((1 << current->processor) & msr_cpu_mask))
44 (void)rdmsr_user(msr_addr, msr_lo, msr_hi);
45 }
47 long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
48 {
49 long ret = 0;
51 if ( !IS_PRIV(current->domain) )
52 return -EPERM;
54 switch ( op->cmd )
55 {
57 case DOM0_MSR:
58 {
59 if ( op->u.msr.write )
60 {
61 msr_cpu_mask = op->u.msr.cpu_mask;
62 msr_addr = op->u.msr.msr;
63 msr_lo = op->u.msr.in1;
64 msr_hi = op->u.msr.in2;
65 smp_call_function(write_msr_for, NULL, 1, 1);
66 write_msr_for(NULL);
67 }
68 else
69 {
70 msr_cpu_mask = op->u.msr.cpu_mask;
71 msr_addr = op->u.msr.msr;
72 smp_call_function(read_msr_for, NULL, 1, 1);
73 read_msr_for(NULL);
75 op->u.msr.out1 = msr_lo;
76 op->u.msr.out2 = msr_hi;
77 copy_to_user(u_dom0_op, op, sizeof(*op));
78 }
79 ret = 0;
80 }
81 break;
83 case DOM0_SHADOW_CONTROL:
84 {
85 struct domain *d;
86 ret = -ESRCH;
87 d = find_domain_by_id(op->u.shadow_control.domain);
88 if ( d != NULL )
89 {
90 ret = shadow_mode_control(d, &op->u.shadow_control);
91 put_domain(d);
92 copy_to_user(u_dom0_op, op, sizeof(*op));
93 }
94 }
95 break;
97 case DOM0_ADD_MEMTYPE:
98 {
99 ret = mtrr_add_page(
100 op->u.add_memtype.pfn,
101 op->u.add_memtype.nr_pfns,
102 op->u.add_memtype.type,
103 1);
104 }
105 break;
107 case DOM0_DEL_MEMTYPE:
108 {
109 ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
110 }
111 break;
113 case DOM0_READ_MEMTYPE:
114 {
115 unsigned long pfn;
116 unsigned int nr_pfns;
117 mtrr_type type;
119 ret = -EINVAL;
120 if ( op->u.read_memtype.reg < num_var_ranges )
121 {
122 mtrr_if->get(op->u.read_memtype.reg, &pfn, &nr_pfns, &type);
123 (void)__put_user(pfn, &u_dom0_op->u.read_memtype.pfn);
124 (void)__put_user(nr_pfns, &u_dom0_op->u.read_memtype.nr_pfns);
125 (void)__put_user(type, &u_dom0_op->u.read_memtype.type);
126 ret = 0;
127 }
128 }
129 break;
131 case DOM0_MICROCODE:
132 {
133 extern int microcode_update(void *buf, unsigned long len);
134 ret = microcode_update(op->u.microcode.data, op->u.microcode.length);
135 }
136 break;
138 case DOM0_IOPORT_PERMISSION:
139 {
140 struct domain *d;
141 unsigned int fp = op->u.ioport_permission.first_port;
142 unsigned int np = op->u.ioport_permission.nr_ports;
143 unsigned int p;
145 ret = -EINVAL;
146 if ( (fp + np) >= 65536 )
147 break;
149 ret = -ESRCH;
150 if ( unlikely((d = find_domain_by_id(
151 op->u.ioport_permission.domain)) == NULL) )
152 break;
154 ret = -ENOMEM;
155 if ( d->arch.iobmp_mask != NULL )
156 {
157 if ( (d->arch.iobmp_mask = xmalloc_array(
158 u8, IOBMP_BYTES)) == NULL )
159 {
160 put_domain(d);
161 break;
162 }
163 memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
164 }
166 ret = 0;
167 for ( p = fp; p < (fp + np); p++ )
168 {
169 if ( op->u.ioport_permission.allow_access )
170 clear_bit(p, d->arch.iobmp_mask);
171 else
172 set_bit(p, d->arch.iobmp_mask);
173 }
175 put_domain(d);
176 }
177 break;
179 case DOM0_PHYSINFO:
180 {
181 dom0_physinfo_t *pi = &op->u.physinfo;
183 pi->threads_per_core = smp_num_siblings;
184 pi->cores_per_socket = boot_cpu_data.x86_num_cores;
185 pi->sockets_per_node =
186 num_online_cpus() / (pi->threads_per_core * pi->cores_per_socket);
187 pi->nr_nodes = 1;
188 pi->total_pages = max_page;
189 pi->free_pages = avail_domheap_pages();
190 pi->cpu_khz = cpu_khz;
192 copy_to_user(u_dom0_op, op, sizeof(*op));
193 ret = 0;
194 }
195 break;
197 case DOM0_GETPAGEFRAMEINFO:
198 {
199 struct pfn_info *page;
200 unsigned long pfn = op->u.getpageframeinfo.pfn;
201 domid_t dom = op->u.getpageframeinfo.domain;
202 struct domain *d;
204 ret = -EINVAL;
206 if ( unlikely(pfn >= max_page) ||
207 unlikely((d = find_domain_by_id(dom)) == NULL) )
208 break;
210 page = &frame_table[pfn];
212 if ( likely(get_page(page, d)) )
213 {
214 ret = 0;
216 op->u.getpageframeinfo.type = NOTAB;
218 if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
219 {
220 switch ( page->u.inuse.type_info & PGT_type_mask )
221 {
222 case PGT_l1_page_table:
223 op->u.getpageframeinfo.type = L1TAB;
224 break;
225 case PGT_l2_page_table:
226 op->u.getpageframeinfo.type = L2TAB;
227 break;
228 case PGT_l3_page_table:
229 op->u.getpageframeinfo.type = L3TAB;
230 break;
231 case PGT_l4_page_table:
232 op->u.getpageframeinfo.type = L4TAB;
233 break;
234 }
235 }
237 put_page(page);
238 }
240 put_domain(d);
242 copy_to_user(u_dom0_op, op, sizeof(*op));
243 }
244 break;
246 case DOM0_GETPAGEFRAMEINFO2:
247 {
248 #define GPF2_BATCH 128
249 int n,j;
250 int num = op->u.getpageframeinfo2.num;
251 domid_t dom = op->u.getpageframeinfo2.domain;
252 unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
253 struct domain *d;
254 unsigned long *l_arr;
255 ret = -ESRCH;
257 if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
258 break;
260 if ( unlikely(num > 1024) )
261 {
262 ret = -E2BIG;
263 break;
264 }
266 l_arr = alloc_xenheap_page();
268 ret = 0;
269 for( n = 0; n < num; )
270 {
271 int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
273 if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) )
274 {
275 ret = -EINVAL;
276 break;
277 }
279 for( j = 0; j < k; j++ )
280 {
281 struct pfn_info *page;
282 unsigned long mfn = l_arr[j];
284 if ( unlikely(mfn >= max_page) )
285 goto e2_err;
287 page = &frame_table[mfn];
289 if ( likely(get_page(page, d)) )
290 {
291 unsigned long type = 0;
293 switch( page->u.inuse.type_info & PGT_type_mask )
294 {
295 case PGT_l1_page_table:
296 type = L1TAB;
297 break;
298 case PGT_l2_page_table:
299 type = L2TAB;
300 break;
301 case PGT_l3_page_table:
302 type = L3TAB;
303 break;
304 case PGT_l4_page_table:
305 type = L4TAB;
306 break;
307 }
309 if ( page->u.inuse.type_info & PGT_pinned )
310 type |= LPINTAB;
311 l_arr[j] |= type;
312 put_page(page);
313 }
314 else
315 {
316 e2_err:
317 l_arr[j] |= XTAB;
318 }
320 }
322 if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) )
323 {
324 ret = -EINVAL;
325 break;
326 }
328 n += j;
329 }
331 free_xenheap_page(l_arr);
333 put_domain(d);
334 }
335 break;
337 case DOM0_GETMEMLIST:
338 {
339 int i;
340 struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
341 unsigned long max_pfns = op->u.getmemlist.max_pfns;
342 unsigned long pfn;
343 unsigned long *buffer = op->u.getmemlist.buffer;
344 struct list_head *list_ent;
346 ret = -EINVAL;
347 if ( d != NULL )
348 {
349 ret = 0;
351 spin_lock(&d->page_alloc_lock);
352 list_ent = d->page_list.next;
353 for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ )
354 {
355 pfn = list_entry(list_ent, struct pfn_info, list) -
356 frame_table;
357 if ( put_user(pfn, buffer) )
358 {
359 ret = -EFAULT;
360 break;
361 }
362 buffer++;
363 list_ent = frame_table[pfn].list.next;
364 }
365 spin_unlock(&d->page_alloc_lock);
367 op->u.getmemlist.num_pfns = i;
368 copy_to_user(u_dom0_op, op, sizeof(*op));
370 put_domain(d);
371 }
372 }
373 break;
375 case DOM0_PLATFORM_QUIRK:
376 {
377 extern int opt_noirqbalance;
378 switch ( op->u.platform_quirk.quirk_id )
379 {
380 case QUIRK_NOIRQBALANCING:
381 printk("Platform quirk -- Disabling IRQ balancing/affinity.\n");
382 opt_noirqbalance = 1;
383 setup_ioapic_dest();
384 break;
385 default:
386 ret = -EINVAL;
387 break;
388 }
389 }
390 break;
392 default:
393 ret = -ENOSYS;
395 }
397 return ret;
398 }
400 void arch_getdomaininfo_ctxt(
401 struct vcpu *v, struct vcpu_guest_context *c)
402 {
403 extern void save_vmx_cpu_user_regs(struct cpu_user_regs *);
405 memcpy(c, &v->arch.guest_context, sizeof(*c));
407 /* IOPL privileges are virtualised -- merge back into returned eflags. */
408 BUG_ON(((c->user_regs.eflags & EF_IOPL) != 0) && !(VMX_DOMAIN(v)));
409 c->user_regs.eflags |= v->arch.iopl << 12;
411 if ( VMX_DOMAIN(v) )
412 {
413 save_vmx_cpu_user_regs(&c->user_regs);
414 __vmread(CR0_READ_SHADOW, &c->ctrlreg[0]);
415 __vmread(CR4_READ_SHADOW, &c->ctrlreg[4]);
416 }
418 c->flags = 0;
419 if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) )
420 c->flags |= VGCF_I387_VALID;
421 if ( KERNEL_MODE(v, &v->arch.guest_context.user_regs) )
422 c->flags |= VGCF_IN_KERNEL;
423 if (VMX_DOMAIN(v))
424 c->flags |= VGCF_VMX_GUEST;
426 c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table);
428 c->vm_assist = v->domain->vm_assist;
429 }