ia64/xen-unstable

view xen/arch/x86/platform_hypercall.c @ 16203:4393255607be

x86, dom0: Allow get idle time stats by mask.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir@xensource.com>
date Wed Oct 24 10:49:03 2007 +0100 (2007-10-24)
parents 0d7d6804af22
children eb786950169c
line source
1 /******************************************************************************
2 * platform_hypercall.c
3 *
4 * Hardware platform operations. Intended for use by domain-0 kernel.
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/acpi.h>
22 #include <asm/current.h>
23 #include <public/platform.h>
24 #include <asm/edd.h>
25 #include <asm/mtrr.h>
26 #include "cpu/mtrr/mtrr.h"
27 #include <xsm/xsm.h>
29 extern uint16_t boot_edid_caps;
30 extern uint8_t boot_edid_info[];
32 #ifndef COMPAT
33 typedef long ret_t;
34 DEFINE_SPINLOCK(xenpf_lock);
35 # undef copy_from_compat
36 # define copy_from_compat copy_from_guest
37 # undef copy_to_compat
38 # define copy_to_compat copy_to_guest
39 # undef guest_from_compat_handle
40 # define guest_from_compat_handle(x,y) ((x)=(y))
41 #else
42 extern spinlock_t xenpf_lock;
43 #endif
45 static long cpu_frequency_change_helper(void *data)
46 {
47 return cpu_frequency_change(*(uint64_t *)data);
48 }
50 ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
51 {
52 ret_t ret = 0;
53 struct xen_platform_op curop, *op = &curop;
55 if ( !IS_PRIV(current->domain) )
56 return -EPERM;
58 if ( copy_from_guest(op, u_xenpf_op, 1) )
59 return -EFAULT;
61 if ( op->interface_version != XENPF_INTERFACE_VERSION )
62 return -EACCES;
64 spin_lock(&xenpf_lock);
66 switch ( op->cmd )
67 {
68 case XENPF_settime:
69 {
70 ret = xsm_xen_settime();
71 if ( ret )
72 break;
74 do_settime(op->u.settime.secs,
75 op->u.settime.nsecs,
76 op->u.settime.system_time);
77 ret = 0;
78 }
79 break;
81 case XENPF_add_memtype:
82 {
83 ret = xsm_memtype(op->cmd);
84 if ( ret )
85 break;
87 ret = mtrr_add_page(
88 op->u.add_memtype.mfn,
89 op->u.add_memtype.nr_mfns,
90 op->u.add_memtype.type,
91 1);
92 if ( ret >= 0 )
93 {
94 op->u.add_memtype.handle = 0;
95 op->u.add_memtype.reg = ret;
96 ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
97 if ( ret != 0 )
98 mtrr_del_page(ret, 0, 0);
99 }
100 }
101 break;
103 case XENPF_del_memtype:
104 {
105 ret = xsm_memtype(op->cmd);
106 if ( ret )
107 break;
109 if (op->u.del_memtype.handle == 0
110 /* mtrr/main.c otherwise does a lookup */
111 && (int)op->u.del_memtype.reg >= 0)
112 {
113 ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
114 if ( ret > 0 )
115 ret = 0;
116 }
117 else
118 ret = -EINVAL;
119 }
120 break;
122 case XENPF_read_memtype:
123 {
124 unsigned long mfn, nr_mfns;
125 mtrr_type type;
127 ret = xsm_memtype(op->cmd);
128 if ( ret )
129 break;
131 ret = -EINVAL;
132 if ( op->u.read_memtype.reg < num_var_ranges )
133 {
134 mtrr_if->get(op->u.read_memtype.reg, &mfn, &nr_mfns, &type);
135 op->u.read_memtype.mfn = mfn;
136 op->u.read_memtype.nr_mfns = nr_mfns;
137 op->u.read_memtype.type = type;
138 ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
139 }
140 }
141 break;
143 case XENPF_microcode_update:
144 {
145 extern int microcode_update(XEN_GUEST_HANDLE(void), unsigned long len);
146 XEN_GUEST_HANDLE(void) data;
148 ret = xsm_microcode();
149 if ( ret )
150 break;
152 guest_from_compat_handle(data, op->u.microcode.data);
153 ret = microcode_update(data, op->u.microcode.length);
154 }
155 break;
157 case XENPF_platform_quirk:
158 {
159 extern int opt_noirqbalance;
160 int quirk_id = op->u.platform_quirk.quirk_id;
162 ret = xsm_platform_quirk(quirk_id);
163 if ( ret )
164 break;
166 switch ( quirk_id )
167 {
168 case QUIRK_NOIRQBALANCING:
169 printk("Platform quirk -- Disabling IRQ balancing/affinity.\n");
170 opt_noirqbalance = 1;
171 setup_ioapic_dest();
172 break;
173 case QUIRK_IOAPIC_BAD_REGSEL:
174 case QUIRK_IOAPIC_GOOD_REGSEL:
175 #ifndef sis_apic_bug
176 sis_apic_bug = (quirk_id == QUIRK_IOAPIC_BAD_REGSEL);
177 dprintk(XENLOG_INFO, "Domain 0 says that IO-APIC REGSEL is %s\n",
178 sis_apic_bug ? "bad" : "good");
179 #else
180 BUG_ON(sis_apic_bug != (quirk_id == QUIRK_IOAPIC_BAD_REGSEL));
181 #endif
182 break;
183 default:
184 ret = -EINVAL;
185 break;
186 }
187 }
188 break;
190 case XENPF_firmware_info:
191 switch ( op->u.firmware_info.type )
192 {
193 case XEN_FW_DISK_INFO: {
194 const struct edd_info *info;
195 u16 length;
197 ret = -ESRCH;
198 if ( op->u.firmware_info.index >= bootsym(boot_edd_info_nr) )
199 break;
201 info = bootsym(boot_edd_info) + op->u.firmware_info.index;
203 /* Transfer the EDD info block. */
204 ret = -EFAULT;
205 if ( copy_from_compat(&length, op->u.firmware_info.u.
206 disk_info.edd_params, 1) )
207 break;
208 if ( length > info->edd_device_params.length )
209 length = info->edd_device_params.length;
210 if ( copy_to_compat(op->u.firmware_info.u.disk_info.edd_params,
211 (u8 *)&info->edd_device_params,
212 length) )
213 break;
214 if ( copy_to_compat(op->u.firmware_info.u.disk_info.edd_params,
215 &length, 1) )
216 break;
218 /* Transfer miscellaneous other information values. */
219 #define C(x) op->u.firmware_info.u.disk_info.x = info->x
220 C(device);
221 C(version);
222 C(interface_support);
223 C(legacy_max_cylinder);
224 C(legacy_max_head);
225 C(legacy_sectors_per_track);
226 #undef C
228 ret = (copy_field_to_guest(u_xenpf_op, op,
229 u.firmware_info.u.disk_info)
230 ? -EFAULT : 0);
231 break;
232 }
233 case XEN_FW_DISK_MBR_SIGNATURE: {
234 const struct mbr_signature *sig;
236 ret = -ESRCH;
237 if ( op->u.firmware_info.index >= bootsym(boot_mbr_signature_nr) )
238 break;
240 sig = bootsym(boot_mbr_signature) + op->u.firmware_info.index;
242 op->u.firmware_info.u.disk_mbr_signature.device = sig->device;
243 op->u.firmware_info.u.disk_mbr_signature.mbr_signature =
244 sig->signature;
246 ret = (copy_field_to_guest(u_xenpf_op, op,
247 u.firmware_info.u.disk_mbr_signature)
248 ? -EFAULT : 0);
249 break;
250 }
251 case XEN_FW_VBEDDC_INFO:
252 ret = -ESRCH;
253 if ( op->u.firmware_info.index != 0 )
254 break;
255 if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
256 break;
258 op->u.firmware_info.u.vbeddc_info.capabilities =
259 bootsym(boot_edid_caps);
260 op->u.firmware_info.u.vbeddc_info.edid_transfer_time =
261 bootsym(boot_edid_caps) >> 8;
263 ret = 0;
264 if ( copy_field_to_guest(u_xenpf_op, op, u.firmware_info.
265 u.vbeddc_info.capabilities) ||
266 copy_field_to_guest(u_xenpf_op, op, u.firmware_info.
267 u.vbeddc_info.edid_transfer_time) ||
268 copy_to_compat(op->u.firmware_info.u.vbeddc_info.edid,
269 bootsym(boot_edid_info), 128) )
270 ret = -EFAULT;
271 break;
272 default:
273 ret = -EINVAL;
274 break;
275 }
276 break;
278 case XENPF_enter_acpi_sleep:
279 ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
280 break;
282 case XENPF_change_freq:
283 ret = -ENOSYS;
284 if ( cpufreq_controller != FREQCTL_dom0_kernel )
285 break;
286 ret = -EINVAL;
287 if ( op->u.change_freq.flags != 0 )
288 break;
289 ret = continue_hypercall_on_cpu(op->u.change_freq.cpu,
290 cpu_frequency_change_helper,
291 &op->u.change_freq.freq);
292 break;
294 case XENPF_getidletime:
295 {
296 uint32_t cpu;
297 uint64_t idletime, now = NOW();
298 struct vcpu *v;
299 struct xenctl_cpumap ctlmap;
300 cpumask_t cpumap;
301 XEN_GUEST_HANDLE(uint64_t) idletimes;
303 ret = -ENOSYS;
304 if ( cpufreq_controller != FREQCTL_dom0_kernel )
305 break;
307 memset(&ctlmap, 0, sizeof(ctlmap));
308 ctlmap.nr_cpus = op->u.getidletime.cpumap_nr_cpus;
309 ctlmap.bitmap.p = op->u.getidletime.cpumap_bitmap.p;
310 xenctl_cpumap_to_cpumask(&cpumap, &ctlmap);
311 guest_from_compat_handle(idletimes, op->u.getidletime.idletime);
313 for_each_cpu_mask ( cpu, cpumap )
314 {
315 if ( (v = idle_vcpu[cpu]) != NULL )
316 {
317 idletime = v->runstate.time[RUNSTATE_running];
318 if ( v->is_running )
319 idletime += now - v->runstate.state_entry_time;
320 }
321 else
322 {
323 idletime = 0;
324 cpu_clear(cpu, cpumap);
325 }
327 ret = -EFAULT;
328 if ( copy_to_guest_offset(idletimes, cpu, &idletime, 1) )
329 goto out;
330 }
332 op->u.getidletime.now = now;
333 cpumask_to_xenctl_cpumap(&ctlmap, &cpumap);
334 ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
335 }
336 break;
338 default:
339 ret = -ENOSYS;
340 break;
341 }
343 out:
344 spin_unlock(&xenpf_lock);
346 return ret;
347 }
349 /*
350 * Local variables:
351 * mode: C
352 * c-set-style: "BSD"
353 * c-basic-offset: 4
354 * tab-width: 4
355 * indent-tabs-mode: nil
356 * End:
357 */