ia64/xen-unstable

view xen/common/sysctl.c @ 19348:dd3219cd019a

Code cleanups after page offline patch.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Mar 12 15:31:36 2009 +0000 (2009-03-12)
parents dd489125a2e7
children 97f78142cd4c
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 int do_get_pm_info(struct xen_sysctl_get_pmstat *op);
29 extern int do_pm_op(struct xen_sysctl_pm_op *op);
31 extern long arch_do_sysctl(
32 struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
34 long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
35 {
36 long ret = 0;
37 struct xen_sysctl curop, *op = &curop;
38 static DEFINE_SPINLOCK(sysctl_lock);
40 if ( !IS_PRIV(current->domain) )
41 return -EPERM;
43 if ( copy_from_guest(op, u_sysctl, 1) )
44 return -EFAULT;
46 if ( op->interface_version != XEN_SYSCTL_INTERFACE_VERSION )
47 return -EACCES;
49 spin_lock(&sysctl_lock);
51 switch ( op->cmd )
52 {
53 case XEN_SYSCTL_readconsole:
54 {
55 ret = xsm_readconsole(op->u.readconsole.clear);
56 if ( ret )
57 break;
59 ret = read_console_ring(&op->u.readconsole);
60 if ( copy_to_guest(u_sysctl, op, 1) )
61 ret = -EFAULT;
62 }
63 break;
65 case XEN_SYSCTL_tbuf_op:
66 {
67 ret = xsm_tbufcontrol();
68 if ( ret )
69 break;
71 ret = tb_control(&op->u.tbuf_op);
72 if ( copy_to_guest(u_sysctl, op, 1) )
73 ret = -EFAULT;
74 }
75 break;
77 case XEN_SYSCTL_sched_id:
78 {
79 ret = xsm_sched_id();
80 if ( ret )
81 break;
83 op->u.sched_id.sched_id = sched_id();
84 if ( copy_to_guest(u_sysctl, op, 1) )
85 ret = -EFAULT;
86 else
87 ret = 0;
88 }
89 break;
91 case XEN_SYSCTL_getdomaininfolist:
92 {
93 struct domain *d;
94 struct xen_domctl_getdomaininfo info;
95 u32 num_domains = 0;
97 rcu_read_lock(&domlist_read_lock);
99 for_each_domain ( d )
100 {
101 if ( d->domain_id < op->u.getdomaininfolist.first_domain )
102 continue;
103 if ( num_domains == op->u.getdomaininfolist.max_domains )
104 break;
106 ret = xsm_getdomaininfo(d);
107 if ( ret )
108 continue;
110 getdomaininfo(d, &info);
112 if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
113 num_domains, &info, 1) )
114 {
115 ret = -EFAULT;
116 break;
117 }
119 num_domains++;
120 }
122 rcu_read_unlock(&domlist_read_lock);
124 if ( ret != 0 )
125 break;
127 op->u.getdomaininfolist.num_domains = num_domains;
129 if ( copy_to_guest(u_sysctl, op, 1) )
130 ret = -EFAULT;
131 }
132 break;
134 #ifdef PERF_COUNTERS
135 case XEN_SYSCTL_perfc_op:
136 {
137 ret = xsm_perfcontrol();
138 if ( ret )
139 break;
141 ret = perfc_control(&op->u.perfc_op);
142 if ( copy_to_guest(u_sysctl, op, 1) )
143 ret = -EFAULT;
144 }
145 break;
146 #endif
148 case XEN_SYSCTL_debug_keys:
149 {
150 char c;
151 uint32_t i;
153 ret = xsm_debug_keys();
154 if ( ret )
155 break;
157 for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
158 {
159 if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
160 return -EFAULT;
161 handle_keypress(c, guest_cpu_user_regs());
162 }
163 }
164 break;
166 case XEN_SYSCTL_getcpuinfo:
167 {
168 uint32_t i, nr_cpus;
169 struct xen_sysctl_cpuinfo cpuinfo;
171 nr_cpus = min_t(uint32_t, op->u.getcpuinfo.max_cpus, NR_CPUS);
173 ret = xsm_getcpuinfo();
174 if ( ret )
175 break;
177 for ( i = 0; i < nr_cpus; i++ )
178 {
179 cpuinfo.idletime = get_cpu_idle_time(i);
181 ret = -EFAULT;
182 if ( copy_to_guest_offset(op->u.getcpuinfo.info, i, &cpuinfo, 1) )
183 goto out;
184 }
186 op->u.getcpuinfo.nr_cpus = i;
187 ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
188 }
189 break;
191 case XEN_SYSCTL_availheap:
192 {
193 ret = xsm_availheap();
194 if ( ret )
195 break;
197 op->u.availheap.avail_bytes = avail_domheap_pages_region(
198 op->u.availheap.node,
199 op->u.availheap.min_bitwidth,
200 op->u.availheap.max_bitwidth);
201 op->u.availheap.avail_bytes <<= PAGE_SHIFT;
203 ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
204 }
205 break;
207 case XEN_SYSCTL_get_pmstat:
208 {
209 ret = do_get_pm_info(&op->u.get_pmstat);
210 if ( ret )
211 break;
213 if ( copy_to_guest(u_sysctl, op, 1) )
214 {
215 ret = -EFAULT;
216 break;
217 }
218 }
219 break;
221 case XEN_SYSCTL_pm_op:
222 {
223 ret = do_pm_op(&op->u.pm_op);
224 if ( ret && (ret != -EAGAIN) )
225 break;
227 if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA )
228 if ( copy_to_guest(u_sysctl, op, 1) )
229 {
230 ret = -EFAULT;
231 break;
232 }
233 }
234 break;
236 case XEN_SYSCTL_page_offline_op:
237 {
238 uint32_t *status, *ptr;
239 unsigned long pfn;
241 ptr = status = xmalloc_bytes( sizeof(uint32_t) *
242 (op->u.page_offline.end -
243 op->u.page_offline.start + 1));
244 if ( !status )
245 {
246 dprintk(XENLOG_WARNING, "Out of memory for page offline op\n");
247 ret = -ENOMEM;
248 break;
249 }
251 memset(status, PG_OFFLINE_INVALID, sizeof(uint32_t) *
252 (op->u.page_offline.end - op->u.page_offline.start + 1));
254 for ( pfn = op->u.page_offline.start;
255 pfn <= op->u.page_offline.end;
256 pfn ++ )
257 {
258 switch ( op->u.page_offline.cmd )
259 {
260 /* Shall revert her if failed, or leave caller do it? */
261 case sysctl_page_offline:
262 ret = offline_page(pfn, 0, ptr++);
263 break;
264 case sysctl_page_online:
265 ret = online_page(pfn, ptr++);
266 break;
267 case sysctl_query_page_offline:
268 ret = query_page_offline(pfn, ptr++);
269 break;
270 default:
271 gdprintk(XENLOG_WARNING, "invalid page offline op %x\n",
272 op->u.page_offline.cmd);
273 ret = -EINVAL;
274 break;
275 }
277 if (ret)
278 break;
279 }
281 if ( copy_to_guest(
282 op->u.page_offline.status, status,
283 op->u.page_offline.end - op->u.page_offline.start + 1) )
284 {
285 ret = -EFAULT;
286 break;
287 }
289 xfree(status);
290 }
291 break;
293 default:
294 ret = arch_do_sysctl(op, u_sysctl);
295 break;
296 }
298 out:
299 spin_unlock(&sysctl_lock);
301 return ret;
302 }
304 /*
305 * Local variables:
306 * mode: C
307 * c-set-style: "BSD"
308 * c-basic-offset: 4
309 * tab-width: 4
310 * indent-tabs-mode: nil
311 * End:
312 */