ia64/xen-unstable

view xen/common/sysctl.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 3bb94bb35dad
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 */