direct-io.hg

view xen/common/dom0_ops.c @ 11135:88e6bd5e2b54

Whitespace clean-ups.

Signed-off-by: Steven Hand <steven@xensource.com>
author shand@kneesaa.uk.xensource.com
date Wed Aug 16 11:36:13 2006 +0100 (2006-08-16)
parents 462d6e4cb29a
children 0ea9a824c16c
line source
1 /******************************************************************************
2 * 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 <xen/sched.h>
14 #include <xen/domain.h>
15 #include <xen/event.h>
16 #include <xen/domain_page.h>
17 #include <xen/trace.h>
18 #include <xen/console.h>
19 #include <xen/iocap.h>
20 #include <xen/guest_access.h>
21 #include <asm/current.h>
22 #include <public/dom0_ops.h>
23 #include <public/sched_ctl.h>
24 #include <acm/acm_hooks.h>
26 extern long arch_do_dom0_op(
27 struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op);
28 extern void arch_getdomaininfo_ctxt(
29 struct vcpu *, struct vcpu_guest_context *);
31 static inline int is_free_domid(domid_t dom)
32 {
33 struct domain *d;
35 if ( dom >= DOMID_FIRST_RESERVED )
36 return 0;
38 if ( (d = find_domain_by_id(dom)) == NULL )
39 return 1;
41 put_domain(d);
42 return 0;
43 }
45 static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
46 {
47 struct vcpu *v;
48 u64 cpu_time = 0;
49 int flags = DOMFLAGS_BLOCKED;
50 struct vcpu_runstate_info runstate;
52 info->domain = d->domain_id;
53 info->nr_online_vcpus = 0;
55 /*
56 * - domain is marked as blocked only if all its vcpus are blocked
57 * - domain is marked as running if any of its vcpus is running
58 */
59 for_each_vcpu ( d, v ) {
60 vcpu_runstate_get(v, &runstate);
61 cpu_time += runstate.time[RUNSTATE_running];
62 info->max_vcpu_id = v->vcpu_id;
63 if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
64 {
65 if ( !(v->vcpu_flags & VCPUF_blocked) )
66 flags &= ~DOMFLAGS_BLOCKED;
67 if ( v->vcpu_flags & VCPUF_running )
68 flags |= DOMFLAGS_RUNNING;
69 info->nr_online_vcpus++;
70 }
71 }
73 info->cpu_time = cpu_time;
75 info->flags = flags |
76 ((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
77 ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
78 ((d->domain_flags & DOMF_ctrl_pause) ? DOMFLAGS_PAUSED : 0) |
79 d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
81 if (d->ssid != NULL)
82 info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
83 else
84 info->ssidref = ACM_DEFAULT_SSID;
86 info->tot_pages = d->tot_pages;
87 info->max_pages = d->max_pages;
88 info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT;
90 memcpy(info->handle, d->handle, sizeof(xen_domain_handle_t));
91 }
93 static unsigned int default_vcpu0_location(void)
94 {
95 struct domain *d;
96 struct vcpu *v;
97 unsigned int i, cpu, cnt[NR_CPUS] = { 0 };
98 cpumask_t cpu_exclude_map;
100 /* Do an initial CPU placement. Pick the least-populated CPU. */
101 read_lock(&domlist_lock);
102 for_each_domain ( d )
103 for_each_vcpu ( d, v )
104 if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
105 cnt[v->processor]++;
106 read_unlock(&domlist_lock);
108 /*
109 * If we're on a HT system, we only auto-allocate to a non-primary HT. We
110 * favour high numbered CPUs in the event of a tie.
111 */
112 cpu = first_cpu(cpu_sibling_map[0]);
113 if ( cpus_weight(cpu_sibling_map[0]) > 1 )
114 cpu = next_cpu(cpu, cpu_sibling_map[0]);
115 cpu_exclude_map = cpu_sibling_map[0];
116 for_each_online_cpu ( i )
117 {
118 if ( cpu_isset(i, cpu_exclude_map) )
119 continue;
120 if ( (i == first_cpu(cpu_sibling_map[i])) &&
121 (cpus_weight(cpu_sibling_map[i]) > 1) )
122 continue;
123 cpus_or(cpu_exclude_map, cpu_exclude_map, cpu_sibling_map[i]);
124 if ( cnt[i] <= cnt[cpu] )
125 cpu = i;
126 }
128 return cpu;
129 }
131 long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
132 {
133 long ret = 0;
134 struct dom0_op curop, *op = &curop;
135 void *ssid = NULL; /* save security ptr between pre and post/fail hooks */
136 static DEFINE_SPINLOCK(dom0_lock);
138 if ( !IS_PRIV(current->domain) )
139 return -EPERM;
141 if ( copy_from_guest(op, u_dom0_op, 1) )
142 return -EFAULT;
144 if ( op->interface_version != DOM0_INTERFACE_VERSION )
145 return -EACCES;
147 if ( acm_pre_dom0_op(op, &ssid) )
148 return -EPERM;
150 spin_lock(&dom0_lock);
152 switch ( op->cmd )
153 {
155 case DOM0_SETVCPUCONTEXT:
156 {
157 struct domain *d = find_domain_by_id(op->u.setvcpucontext.domain);
158 ret = -ESRCH;
159 if ( d != NULL )
160 {
161 ret = set_info_guest(d, &op->u.setvcpucontext);
162 put_domain(d);
163 }
164 }
165 break;
167 case DOM0_PAUSEDOMAIN:
168 {
169 struct domain *d = find_domain_by_id(op->u.pausedomain.domain);
170 ret = -ESRCH;
171 if ( d != NULL )
172 {
173 ret = -EINVAL;
174 if ( d != current->domain )
175 {
176 domain_pause_by_systemcontroller(d);
177 ret = 0;
178 }
179 put_domain(d);
180 }
181 }
182 break;
184 case DOM0_UNPAUSEDOMAIN:
185 {
186 struct domain *d = find_domain_by_id(op->u.unpausedomain.domain);
187 ret = -ESRCH;
188 if ( d != NULL )
189 {
190 ret = -EINVAL;
191 if ( (d != current->domain) && (d->vcpu[0] != NULL) &&
192 test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) )
193 {
194 domain_unpause_by_systemcontroller(d);
195 ret = 0;
196 }
197 put_domain(d);
198 }
199 }
200 break;
202 case DOM0_CREATEDOMAIN:
203 {
204 struct domain *d;
205 domid_t dom;
206 static domid_t rover = 0;
208 /*
209 * Running the domain 0 kernel in ring 0 is not compatible
210 * with multiple guests.
211 */
212 if ( supervisor_mode_kernel )
213 return -EINVAL;
215 dom = op->u.createdomain.domain;
216 if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) )
217 {
218 ret = -EINVAL;
219 if ( !is_free_domid(dom) )
220 break;
221 }
222 else
223 {
224 for ( dom = rover + 1; dom != rover; dom++ )
225 {
226 if ( dom == DOMID_FIRST_RESERVED )
227 dom = 0;
228 if ( is_free_domid(dom) )
229 break;
230 }
232 ret = -ENOMEM;
233 if ( dom == rover )
234 break;
236 rover = dom;
237 }
239 ret = -ENOMEM;
240 if ( (d = domain_create(dom)) == NULL )
241 break;
243 memcpy(d->handle, op->u.createdomain.handle,
244 sizeof(xen_domain_handle_t));
246 ret = 0;
248 op->u.createdomain.domain = d->domain_id;
249 if ( copy_to_guest(u_dom0_op, op, 1) )
250 ret = -EFAULT;
251 }
252 break;
254 case DOM0_MAX_VCPUS:
255 {
256 struct domain *d;
257 unsigned int i, max = op->u.max_vcpus.max, cpu;
259 ret = -EINVAL;
260 if ( max > MAX_VIRT_CPUS )
261 break;
263 ret = -ESRCH;
264 if ( (d = find_domain_by_id(op->u.max_vcpus.domain)) == NULL )
265 break;
267 /* Needed, for example, to ensure writable p.t. state is synced. */
268 domain_pause(d);
270 /* We cannot reduce maximum VCPUs. */
271 ret = -EINVAL;
272 if ( (max != MAX_VIRT_CPUS) && (d->vcpu[max] != NULL) )
273 goto maxvcpu_out;
275 ret = -ENOMEM;
276 for ( i = 0; i < max; i++ )
277 {
278 if ( d->vcpu[i] != NULL )
279 continue;
281 cpu = (i == 0) ?
282 default_vcpu0_location() :
283 (d->vcpu[i-1]->processor + 1) % num_online_cpus();
285 if ( alloc_vcpu(d, i, cpu) == NULL )
286 goto maxvcpu_out;
287 }
289 ret = 0;
291 maxvcpu_out:
292 domain_unpause(d);
293 put_domain(d);
294 }
295 break;
297 case DOM0_DESTROYDOMAIN:
298 {
299 struct domain *d = find_domain_by_id(op->u.destroydomain.domain);
300 ret = -ESRCH;
301 if ( d != NULL )
302 {
303 ret = -EINVAL;
304 if ( d != current->domain )
305 {
306 domain_kill(d);
307 ret = 0;
308 }
309 put_domain(d);
310 }
311 }
312 break;
314 case DOM0_SETVCPUAFFINITY:
315 {
316 domid_t dom = op->u.setvcpuaffinity.domain;
317 struct domain *d = find_domain_by_id(dom);
318 struct vcpu *v;
319 cpumask_t new_affinity;
321 if ( d == NULL )
322 {
323 ret = -ESRCH;
324 break;
325 }
327 if ( (op->u.setvcpuaffinity.vcpu >= MAX_VIRT_CPUS) ||
328 !d->vcpu[op->u.setvcpuaffinity.vcpu] )
329 {
330 ret = -EINVAL;
331 put_domain(d);
332 break;
333 }
335 v = d->vcpu[op->u.setvcpuaffinity.vcpu];
336 if ( v == NULL )
337 {
338 ret = -ESRCH;
339 put_domain(d);
340 break;
341 }
343 if ( v == current )
344 {
345 ret = -EINVAL;
346 put_domain(d);
347 break;
348 }
350 new_affinity = v->cpu_affinity;
351 memcpy(cpus_addr(new_affinity),
352 &op->u.setvcpuaffinity.cpumap,
353 min((int)(BITS_TO_LONGS(NR_CPUS) * sizeof(long)),
354 (int)sizeof(op->u.setvcpuaffinity.cpumap)));
356 ret = vcpu_set_affinity(v, &new_affinity);
358 put_domain(d);
359 }
360 break;
362 case DOM0_SCHEDCTL:
363 {
364 ret = sched_ctl(&op->u.schedctl);
365 if ( copy_to_guest(u_dom0_op, op, 1) )
366 ret = -EFAULT;
367 }
368 break;
370 case DOM0_ADJUSTDOM:
371 {
372 ret = sched_adjdom(&op->u.adjustdom);
373 if ( copy_to_guest(u_dom0_op, op, 1) )
374 ret = -EFAULT;
375 }
376 break;
378 case DOM0_GETDOMAININFO:
379 {
380 struct domain *d;
381 domid_t dom;
383 dom = op->u.getdomaininfo.domain;
384 if ( dom == DOMID_SELF )
385 dom = current->domain->domain_id;
387 read_lock(&domlist_lock);
389 for_each_domain ( d )
390 {
391 if ( d->domain_id >= dom )
392 break;
393 }
395 if ( (d == NULL) || !get_domain(d) )
396 {
397 read_unlock(&domlist_lock);
398 ret = -ESRCH;
399 break;
400 }
402 read_unlock(&domlist_lock);
404 getdomaininfo(d, &op->u.getdomaininfo);
406 if ( copy_to_guest(u_dom0_op, op, 1) )
407 ret = -EFAULT;
409 put_domain(d);
410 }
411 break;
413 case DOM0_GETDOMAININFOLIST:
414 {
415 struct domain *d;
416 dom0_getdomaininfo_t info;
417 u32 num_domains = 0;
419 read_lock(&domlist_lock);
421 for_each_domain ( d )
422 {
423 if ( d->domain_id < op->u.getdomaininfolist.first_domain )
424 continue;
425 if ( num_domains == op->u.getdomaininfolist.max_domains )
426 break;
427 if ( (d == NULL) || !get_domain(d) )
428 {
429 ret = -ESRCH;
430 break;
431 }
433 getdomaininfo(d, &info);
435 put_domain(d);
437 if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
438 num_domains, &info, 1) )
439 {
440 ret = -EFAULT;
441 break;
442 }
444 num_domains++;
445 }
447 read_unlock(&domlist_lock);
449 if ( ret != 0 )
450 break;
452 op->u.getdomaininfolist.num_domains = num_domains;
454 if ( copy_to_guest(u_dom0_op, op, 1) )
455 ret = -EFAULT;
456 }
457 break;
459 case DOM0_GETVCPUCONTEXT:
460 {
461 struct vcpu_guest_context *c;
462 struct domain *d;
463 struct vcpu *v;
465 ret = -ESRCH;
466 if ( (d = find_domain_by_id(op->u.getvcpucontext.domain)) == NULL )
467 break;
469 ret = -EINVAL;
470 if ( op->u.getvcpucontext.vcpu >= MAX_VIRT_CPUS )
471 goto getvcpucontext_out;
473 ret = -ESRCH;
474 if ( (v = d->vcpu[op->u.getvcpucontext.vcpu]) == NULL )
475 goto getvcpucontext_out;
477 ret = -ENODATA;
478 if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
479 goto getvcpucontext_out;
481 ret = -ENOMEM;
482 if ( (c = xmalloc(struct vcpu_guest_context)) == NULL )
483 goto getvcpucontext_out;
485 if ( v != current )
486 vcpu_pause(v);
488 arch_getdomaininfo_ctxt(v,c);
489 ret = 0;
491 if ( v != current )
492 vcpu_unpause(v);
494 if ( copy_to_guest(op->u.getvcpucontext.ctxt, c, 1) )
495 ret = -EFAULT;
497 xfree(c);
499 if ( copy_to_guest(u_dom0_op, op, 1) )
500 ret = -EFAULT;
502 getvcpucontext_out:
503 put_domain(d);
504 }
505 break;
507 case DOM0_GETVCPUINFO:
508 {
509 struct domain *d;
510 struct vcpu *v;
511 struct vcpu_runstate_info runstate;
513 ret = -ESRCH;
514 if ( (d = find_domain_by_id(op->u.getvcpuinfo.domain)) == NULL )
515 break;
517 ret = -EINVAL;
518 if ( op->u.getvcpuinfo.vcpu >= MAX_VIRT_CPUS )
519 goto getvcpuinfo_out;
521 ret = -ESRCH;
522 if ( (v = d->vcpu[op->u.getvcpuinfo.vcpu]) == NULL )
523 goto getvcpuinfo_out;
525 vcpu_runstate_get(v, &runstate);
527 op->u.getvcpuinfo.online = !test_bit(_VCPUF_down, &v->vcpu_flags);
528 op->u.getvcpuinfo.blocked = test_bit(_VCPUF_blocked, &v->vcpu_flags);
529 op->u.getvcpuinfo.running = test_bit(_VCPUF_running, &v->vcpu_flags);
530 op->u.getvcpuinfo.cpu_time = runstate.time[RUNSTATE_running];
531 op->u.getvcpuinfo.cpu = v->processor;
532 op->u.getvcpuinfo.cpumap = 0;
533 memcpy(&op->u.getvcpuinfo.cpumap,
534 cpus_addr(v->cpu_affinity),
535 min((int)(BITS_TO_LONGS(NR_CPUS) * sizeof(long)),
536 (int)sizeof(op->u.getvcpuinfo.cpumap)));
537 ret = 0;
539 if ( copy_to_guest(u_dom0_op, op, 1) )
540 ret = -EFAULT;
542 getvcpuinfo_out:
543 put_domain(d);
544 }
545 break;
547 case DOM0_SETTIME:
548 {
549 do_settime(op->u.settime.secs,
550 op->u.settime.nsecs,
551 op->u.settime.system_time);
552 ret = 0;
553 }
554 break;
556 case DOM0_TBUFCONTROL:
557 {
558 ret = tb_control(&op->u.tbufcontrol);
559 if ( copy_to_guest(u_dom0_op, op, 1) )
560 ret = -EFAULT;
561 }
562 break;
564 case DOM0_READCONSOLE:
565 {
566 ret = read_console_ring(
567 op->u.readconsole.buffer,
568 &op->u.readconsole.count,
569 op->u.readconsole.clear);
570 if ( copy_to_guest(u_dom0_op, op, 1) )
571 ret = -EFAULT;
572 }
573 break;
575 case DOM0_SCHED_ID:
576 {
577 op->u.sched_id.sched_id = sched_id();
578 if ( copy_to_guest(u_dom0_op, op, 1) )
579 ret = -EFAULT;
580 else
581 ret = 0;
582 }
583 break;
585 case DOM0_SETDOMAINMAXMEM:
586 {
587 struct domain *d;
588 unsigned long new_max;
590 ret = -ESRCH;
591 d = find_domain_by_id(op->u.setdomainmaxmem.domain);
592 if ( d == NULL )
593 break;
595 ret = -EINVAL;
596 new_max = op->u.setdomainmaxmem.max_memkb >> (PAGE_SHIFT-10);
598 spin_lock(&d->page_alloc_lock);
599 if ( new_max >= d->tot_pages )
600 {
601 d->max_pages = new_max;
602 ret = 0;
603 }
604 spin_unlock(&d->page_alloc_lock);
606 put_domain(d);
607 }
608 break;
610 case DOM0_SETDOMAINHANDLE:
611 {
612 struct domain *d;
613 ret = -ESRCH;
614 d = find_domain_by_id(op->u.setdomainhandle.domain);
615 if ( d != NULL )
616 {
617 memcpy(d->handle, op->u.setdomainhandle.handle,
618 sizeof(xen_domain_handle_t));
619 put_domain(d);
620 ret = 0;
621 }
622 }
623 break;
625 case DOM0_SETDEBUGGING:
626 {
627 struct domain *d;
628 ret = -ESRCH;
629 d = find_domain_by_id(op->u.setdebugging.domain);
630 if ( d != NULL )
631 {
632 if ( op->u.setdebugging.enable )
633 set_bit(_DOMF_debugging, &d->domain_flags);
634 else
635 clear_bit(_DOMF_debugging, &d->domain_flags);
636 put_domain(d);
637 ret = 0;
638 }
639 }
640 break;
642 case DOM0_IRQ_PERMISSION:
643 {
644 struct domain *d;
645 unsigned int pirq = op->u.irq_permission.pirq;
647 ret = -EINVAL;
648 if ( pirq >= NR_IRQS )
649 break;
651 ret = -ESRCH;
652 d = find_domain_by_id(op->u.irq_permission.domain);
653 if ( d == NULL )
654 break;
656 if ( op->u.irq_permission.allow_access )
657 ret = irq_permit_access(d, pirq);
658 else
659 ret = irq_deny_access(d, pirq);
661 put_domain(d);
662 }
663 break;
665 case DOM0_IOMEM_PERMISSION:
666 {
667 struct domain *d;
668 unsigned long mfn = op->u.iomem_permission.first_mfn;
669 unsigned long nr_mfns = op->u.iomem_permission.nr_mfns;
671 ret = -EINVAL;
672 if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
673 break;
675 ret = -ESRCH;
676 d = find_domain_by_id(op->u.iomem_permission.domain);
677 if ( d == NULL )
678 break;
680 if ( op->u.iomem_permission.allow_access )
681 ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
682 else
683 ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
685 put_domain(d);
686 }
687 break;
689 #ifdef PERF_COUNTERS
690 case DOM0_PERFCCONTROL:
691 {
692 extern int perfc_control(dom0_perfccontrol_t *);
693 ret = perfc_control(&op->u.perfccontrol);
694 if ( copy_to_guest(u_dom0_op, op, 1) )
695 ret = -EFAULT;
696 }
697 break;
698 #endif
700 case DOM0_SETTIMEOFFSET:
701 {
702 struct domain *d;
704 ret = -ESRCH;
705 d = find_domain_by_id(op->u.settimeoffset.domain);
706 if ( d != NULL )
707 {
708 d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
709 put_domain(d);
710 ret = 0;
711 }
712 }
713 break;
715 default:
716 ret = arch_do_dom0_op(op, u_dom0_op);
717 break;
718 }
720 spin_unlock(&dom0_lock);
722 if (!ret)
723 acm_post_dom0_op(op, &ssid);
724 else
725 acm_fail_dom0_op(op, &ssid);
727 return ret;
728 }
730 /*
731 * Local variables:
732 * mode: C
733 * c-set-style: "BSD"
734 * c-basic-offset: 4
735 * tab-width: 4
736 * indent-tabs-mode: nil
737 * End:
738 */