ia64/xen-unstable

view xen/common/sysctl.c @ 16264:3bb94bb35dad

Allow incremental access to hypervisor console log.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Mon Oct 29 12:56:27 2007 +0000 (2007-10-29)
parents 8c67b2038ff2
children d0817f08599a
line source
1 /******************************************************************************
2 * sysctl.c
3 *
4 * System management operations. For use by node control stack.
5 *
6 * Copyright (c) 2002-2006, K 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 <xen/keyhandler.h>
22 #include <asm/current.h>
23 #include <public/sysctl.h>
24 #include <asm/numa.h>
25 #include <xen/nodemask.h>
26 #include <xsm/xsm.h>
28 extern long arch_do_sysctl(
29 struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
31 long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
32 {
33 long ret = 0;
34 struct xen_sysctl curop, *op = &curop;
35 static DEFINE_SPINLOCK(sysctl_lock);
37 if ( !IS_PRIV(current->domain) )
38 return -EPERM;
40 if ( copy_from_guest(op, u_sysctl, 1) )
41 return -EFAULT;
43 if ( op->interface_version != XEN_SYSCTL_INTERFACE_VERSION )
44 return -EACCES;
46 spin_lock(&sysctl_lock);
48 switch ( op->cmd )
49 {
50 case XEN_SYSCTL_readconsole:
51 {
52 ret = xsm_readconsole(op->u.readconsole.clear);
53 if ( ret )
54 break;
56 ret = read_console_ring(&op->u.readconsole);
57 if ( copy_to_guest(u_sysctl, op, 1) )
58 ret = -EFAULT;
59 }
60 break;
62 case XEN_SYSCTL_tbuf_op:
63 {
64 ret = xsm_tbufcontrol();
65 if ( ret )
66 break;
68 ret = tb_control(&op->u.tbuf_op);
69 if ( copy_to_guest(u_sysctl, op, 1) )
70 ret = -EFAULT;
71 }
72 break;
74 case XEN_SYSCTL_sched_id:
75 {
76 ret = xsm_sched_id();
77 if ( ret )
78 break;
80 op->u.sched_id.sched_id = sched_id();
81 if ( copy_to_guest(u_sysctl, op, 1) )
82 ret = -EFAULT;
83 else
84 ret = 0;
85 }
86 break;
88 case XEN_SYSCTL_getdomaininfolist:
89 {
90 struct domain *d;
91 struct xen_domctl_getdomaininfo info;
92 u32 num_domains = 0;
94 rcu_read_lock(&domlist_read_lock);
96 for_each_domain ( d )
97 {
98 if ( d->domain_id < op->u.getdomaininfolist.first_domain )
99 continue;
100 if ( num_domains == op->u.getdomaininfolist.max_domains )
101 break;
103 ret = xsm_getdomaininfo(d);
104 if ( ret )
105 continue;
107 getdomaininfo(d, &info);
109 if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
110 num_domains, &info, 1) )
111 {
112 ret = -EFAULT;
113 break;
114 }
116 num_domains++;
117 }
119 rcu_read_unlock(&domlist_read_lock);
121 if ( ret != 0 )
122 break;
124 op->u.getdomaininfolist.num_domains = num_domains;
126 if ( copy_to_guest(u_sysctl, op, 1) )
127 ret = -EFAULT;
128 }
129 break;
131 #ifdef PERF_COUNTERS
132 case XEN_SYSCTL_perfc_op:
133 {
134 ret = xsm_perfcontrol();
135 if ( ret )
136 break;
138 ret = perfc_control(&op->u.perfc_op);
139 if ( copy_to_guest(u_sysctl, op, 1) )
140 ret = -EFAULT;
141 }
142 break;
143 #endif
145 case XEN_SYSCTL_debug_keys:
146 {
147 char c;
148 uint32_t i;
150 for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
151 {
152 if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
153 return -EFAULT;
154 handle_keypress(c, guest_cpu_user_regs());
155 }
156 }
157 break;
159 case XEN_SYSCTL_getcpuinfo:
160 {
161 uint32_t i, nr_cpus;
162 struct xen_sysctl_cpuinfo cpuinfo;
163 struct vcpu *v;
165 nr_cpus = min_t(uint32_t, op->u.getcpuinfo.max_cpus, NR_CPUS);
167 for ( i = 0; i < nr_cpus; i++ )
168 {
169 /* Assume no holes in idle-vcpu map. */
170 if ( (v = idle_vcpu[i]) == NULL )
171 break;
173 cpuinfo.idletime = v->runstate.time[RUNSTATE_running];
174 if ( v->is_running )
175 cpuinfo.idletime += NOW() - v->runstate.state_entry_time;
177 ret = -EFAULT;
178 if ( copy_to_guest_offset(op->u.getcpuinfo.info, i, &cpuinfo, 1) )
179 goto out;
180 }
182 op->u.getcpuinfo.nr_cpus = i;
183 ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
184 }
185 break;
187 case XEN_SYSCTL_availheap:
188 {
189 op->u.availheap.avail_bytes = avail_domheap_pages_region(
190 op->u.availheap.node,
191 op->u.availheap.min_bitwidth,
192 op->u.availheap.max_bitwidth);
193 op->u.availheap.avail_bytes <<= PAGE_SHIFT;
195 ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
196 }
197 break;
199 default:
200 ret = arch_do_sysctl(op, u_sysctl);
201 break;
202 }
204 out:
205 spin_unlock(&sysctl_lock);
207 return ret;
208 }
210 /*
211 * Local variables:
212 * mode: C
213 * c-set-style: "BSD"
214 * c-basic-offset: 4
215 * tab-width: 4
216 * indent-tabs-mode: nil
217 * End:
218 */