debuggers.hg

view tools/libxc/xc_pm.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents a06e9def02bb
children 6c3db6c83a02
line source
1 /******************************************************************************
2 * xc_pm.c - Libxc API for Xen Power Management (Px/Cx/Tx, etc.) statistic
3 *
4 * Copyright (c) 2008, Liu Jinsong <jinsong.liu@intel.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 */
26 #include <errno.h>
27 #include <stdbool.h>
28 #include "xc_private.h"
30 /*
31 * Get PM statistic info
32 */
33 int xc_pm_get_max_px(int xc_handle, int cpuid, int *max_px)
34 {
35 DECLARE_SYSCTL;
36 int ret;
38 sysctl.cmd = XEN_SYSCTL_get_pmstat;
39 sysctl.u.get_pmstat.type = PMSTAT_get_max_px;
40 sysctl.u.get_pmstat.cpuid = cpuid;
41 ret = xc_sysctl(xc_handle, &sysctl);
42 if ( ret )
43 return ret;
45 *max_px = sysctl.u.get_pmstat.u.getpx.total;
46 return ret;
47 }
49 int xc_pm_get_pxstat(int xc_handle, int cpuid, struct xc_px_stat *pxpt)
50 {
51 DECLARE_SYSCTL;
52 int max_px, ret;
54 if ( !pxpt || !(pxpt->trans_pt) || !(pxpt->pt) )
55 return -EINVAL;
57 if ( (ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px)) != 0)
58 return ret;
60 if ( (ret = lock_pages(pxpt->trans_pt,
61 max_px * max_px * sizeof(uint64_t))) != 0 )
62 return ret;
64 if ( (ret = lock_pages(pxpt->pt,
65 max_px * sizeof(struct xc_px_val))) != 0 )
66 {
67 unlock_pages(pxpt->trans_pt, max_px * max_px * sizeof(uint64_t));
68 return ret;
69 }
71 sysctl.cmd = XEN_SYSCTL_get_pmstat;
72 sysctl.u.get_pmstat.type = PMSTAT_get_pxstat;
73 sysctl.u.get_pmstat.cpuid = cpuid;
74 sysctl.u.get_pmstat.u.getpx.total = max_px;
75 set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.trans_pt, pxpt->trans_pt);
76 set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.pt,
77 (pm_px_val_t *)pxpt->pt);
79 ret = xc_sysctl(xc_handle, &sysctl);
80 if ( ret )
81 {
82 unlock_pages(pxpt->trans_pt, max_px * max_px * sizeof(uint64_t));
83 unlock_pages(pxpt->pt, max_px * sizeof(struct xc_px_val));
84 return ret;
85 }
87 pxpt->total = sysctl.u.get_pmstat.u.getpx.total;
88 pxpt->usable = sysctl.u.get_pmstat.u.getpx.usable;
89 pxpt->last = sysctl.u.get_pmstat.u.getpx.last;
90 pxpt->cur = sysctl.u.get_pmstat.u.getpx.cur;
92 unlock_pages(pxpt->trans_pt, max_px * max_px * sizeof(uint64_t));
93 unlock_pages(pxpt->pt, max_px * sizeof(struct xc_px_val));
95 return ret;
96 }
98 int xc_pm_reset_pxstat(int xc_handle, int cpuid)
99 {
100 DECLARE_SYSCTL;
102 sysctl.cmd = XEN_SYSCTL_get_pmstat;
103 sysctl.u.get_pmstat.type = PMSTAT_reset_pxstat;
104 sysctl.u.get_pmstat.cpuid = cpuid;
106 return xc_sysctl(xc_handle, &sysctl);
107 }
109 int xc_pm_get_max_cx(int xc_handle, int cpuid, int *max_cx)
110 {
111 DECLARE_SYSCTL;
112 int ret = 0;
114 sysctl.cmd = XEN_SYSCTL_get_pmstat;
115 sysctl.u.get_pmstat.type = PMSTAT_get_max_cx;
116 sysctl.u.get_pmstat.cpuid = cpuid;
117 if ( (ret = xc_sysctl(xc_handle, &sysctl)) != 0 )
118 return ret;
120 *max_cx = sysctl.u.get_pmstat.u.getcx.nr;
121 return ret;
122 }
124 int xc_pm_get_cxstat(int xc_handle, int cpuid, struct xc_cx_stat *cxpt)
125 {
126 DECLARE_SYSCTL;
127 int max_cx, ret;
129 if( !cxpt || !(cxpt->triggers) || !(cxpt->residencies) )
130 return -EINVAL;
132 if ( (ret = xc_pm_get_max_cx(xc_handle, cpuid, &max_cx)) )
133 goto unlock_0;
135 if ( (ret = lock_pages(cxpt, sizeof(struct xc_cx_stat))) )
136 goto unlock_0;
137 if ( (ret = lock_pages(cxpt->triggers, max_cx * sizeof(uint64_t))) )
138 goto unlock_1;
139 if ( (ret = lock_pages(cxpt->residencies, max_cx * sizeof(uint64_t))) )
140 goto unlock_2;
142 sysctl.cmd = XEN_SYSCTL_get_pmstat;
143 sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
144 sysctl.u.get_pmstat.cpuid = cpuid;
145 set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, cxpt->triggers);
146 set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies,
147 cxpt->residencies);
149 if ( (ret = xc_sysctl(xc_handle, &sysctl)) )
150 goto unlock_3;
152 cxpt->nr = sysctl.u.get_pmstat.u.getcx.nr;
153 cxpt->last = sysctl.u.get_pmstat.u.getcx.last;
154 cxpt->idle_time = sysctl.u.get_pmstat.u.getcx.idle_time;
156 unlock_3:
157 unlock_pages(cxpt->residencies, max_cx * sizeof(uint64_t));
158 unlock_2:
159 unlock_pages(cxpt->triggers, max_cx * sizeof(uint64_t));
160 unlock_1:
161 unlock_pages(cxpt, sizeof(struct xc_cx_stat));
162 unlock_0:
163 return ret;
164 }
166 int xc_pm_reset_cxstat(int xc_handle, int cpuid)
167 {
168 DECLARE_SYSCTL;
170 sysctl.cmd = XEN_SYSCTL_get_pmstat;
171 sysctl.u.get_pmstat.type = PMSTAT_reset_cxstat;
172 sysctl.u.get_pmstat.cpuid = cpuid;
174 return xc_sysctl(xc_handle, &sysctl);
175 }
178 /*
179 * 1. Get PM parameter
180 * 2. Provide user PM control
181 */
182 int xc_get_cpufreq_para(int xc_handle, int cpuid,
183 struct xc_get_cpufreq_para *user_para)
184 {
185 DECLARE_SYSCTL;
186 int ret = 0;
187 struct xen_get_cpufreq_para *sys_para = &sysctl.u.pm_op.u.get_para;
188 bool has_num = user_para->cpu_num &&
189 user_para->freq_num &&
190 user_para->gov_num;
192 if ( (xc_handle < 0) || !user_para )
193 return -EINVAL;
195 if ( has_num )
196 {
197 if ( (!user_para->affected_cpus) ||
198 (!user_para->scaling_available_frequencies) ||
199 (!user_para->scaling_available_governors) )
200 return -EINVAL;
202 if ( (ret = lock_pages(user_para->affected_cpus,
203 user_para->cpu_num * sizeof(uint32_t))) )
204 goto unlock_1;
205 if ( (ret = lock_pages(user_para->scaling_available_frequencies,
206 user_para->freq_num * sizeof(uint32_t))) )
207 goto unlock_2;
208 if ( (ret = lock_pages(user_para->scaling_available_governors,
209 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
210 goto unlock_3;
212 set_xen_guest_handle(sys_para->affected_cpus,
213 user_para->affected_cpus);
214 set_xen_guest_handle(sys_para->scaling_available_frequencies,
215 user_para->scaling_available_frequencies);
216 set_xen_guest_handle(sys_para->scaling_available_governors,
217 user_para->scaling_available_governors);
218 }
220 sysctl.cmd = XEN_SYSCTL_pm_op;
221 sysctl.u.pm_op.cmd = GET_CPUFREQ_PARA;
222 sysctl.u.pm_op.cpuid = cpuid;
223 sys_para->cpu_num = user_para->cpu_num;
224 sys_para->freq_num = user_para->freq_num;
225 sys_para->gov_num = user_para->gov_num;
227 ret = xc_sysctl(xc_handle, &sysctl);
228 if ( ret )
229 {
230 if ( errno == EAGAIN )
231 {
232 user_para->cpu_num = sys_para->cpu_num;
233 user_para->freq_num = sys_para->freq_num;
234 user_para->gov_num = sys_para->gov_num;
235 ret = -errno;
236 }
238 if ( has_num )
239 goto unlock_4;
240 goto unlock_1;
241 }
242 else
243 {
244 user_para->cpuinfo_cur_freq = sys_para->cpuinfo_cur_freq;
245 user_para->cpuinfo_max_freq = sys_para->cpuinfo_max_freq;
246 user_para->cpuinfo_min_freq = sys_para->cpuinfo_min_freq;
247 user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
248 user_para->scaling_max_freq = sys_para->scaling_max_freq;
249 user_para->scaling_min_freq = sys_para->scaling_min_freq;
251 memcpy(user_para->scaling_driver,
252 sys_para->scaling_driver, CPUFREQ_NAME_LEN);
253 memcpy(user_para->scaling_governor,
254 sys_para->scaling_governor, CPUFREQ_NAME_LEN);
256 /* copy to user_para no matter what cpufreq governor */
257 XC_BUILD_BUG_ON(sizeof(((struct xc_get_cpufreq_para *)0)->u) !=
258 sizeof(((struct xen_get_cpufreq_para *)0)->u));
260 memcpy(&user_para->u, &sys_para->u, sizeof(sys_para->u));
261 }
263 unlock_4:
264 unlock_pages(user_para->scaling_available_governors,
265 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char));
266 unlock_3:
267 unlock_pages(user_para->scaling_available_frequencies,
268 user_para->freq_num * sizeof(uint32_t));
269 unlock_2:
270 unlock_pages(user_para->affected_cpus,
271 user_para->cpu_num * sizeof(uint32_t));
272 unlock_1:
273 return ret;
274 }
276 int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname)
277 {
278 DECLARE_SYSCTL;
279 char *scaling_governor = sysctl.u.pm_op.u.set_gov.scaling_governor;
281 if ( (xc_handle < 0) || (!govname) )
282 return -EINVAL;
284 sysctl.cmd = XEN_SYSCTL_pm_op;
285 sysctl.u.pm_op.cmd = SET_CPUFREQ_GOV;
286 sysctl.u.pm_op.cpuid = cpuid;
287 strncpy(scaling_governor, govname, CPUFREQ_NAME_LEN);
288 scaling_governor[CPUFREQ_NAME_LEN - 1] = '\0';
290 return xc_sysctl(xc_handle, &sysctl);
291 }
293 int xc_set_cpufreq_para(int xc_handle, int cpuid,
294 int ctrl_type, int ctrl_value)
295 {
296 DECLARE_SYSCTL;
298 if ( xc_handle < 0 )
299 return -EINVAL;
301 sysctl.cmd = XEN_SYSCTL_pm_op;
302 sysctl.u.pm_op.cmd = SET_CPUFREQ_PARA;
303 sysctl.u.pm_op.cpuid = cpuid;
304 sysctl.u.pm_op.u.set_para.ctrl_type = ctrl_type;
305 sysctl.u.pm_op.u.set_para.ctrl_value = ctrl_value;
307 return xc_sysctl(xc_handle, &sysctl);
308 }
310 int xc_get_cpufreq_avgfreq(int xc_handle, int cpuid, int *avg_freq)
311 {
312 int ret = 0;
313 DECLARE_SYSCTL;
315 if ( (xc_handle < 0) || (!avg_freq) )
316 return -EINVAL;
318 sysctl.cmd = XEN_SYSCTL_pm_op;
319 sysctl.u.pm_op.cmd = GET_CPUFREQ_AVGFREQ;
320 sysctl.u.pm_op.cpuid = cpuid;
321 ret = xc_sysctl(xc_handle, &sysctl);
323 *avg_freq = sysctl.u.pm_op.u.get_avgfreq;
325 return ret;
326 }
328 int xc_get_cputopo(int xc_handle, struct xc_get_cputopo *info)
329 {
330 int rc;
331 DECLARE_SYSCTL;
333 sysctl.cmd = XEN_SYSCTL_pm_op;
334 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_cputopo;
335 sysctl.u.pm_op.cpuid = 0;
336 set_xen_guest_handle( sysctl.u.pm_op.u.get_topo.cpu_to_core,
337 info->cpu_to_core );
338 set_xen_guest_handle( sysctl.u.pm_op.u.get_topo.cpu_to_socket,
339 info->cpu_to_socket );
340 sysctl.u.pm_op.u.get_topo.max_cpus = info->max_cpus;
342 rc = do_sysctl(xc_handle, &sysctl);
343 info->nr_cpus = sysctl.u.pm_op.u.get_topo.nr_cpus;
345 return rc;
346 }
348 /* value: 0 - disable sched_smt_power_savings
349 1 - enable sched_smt_power_savings
350 */
351 int xc_set_sched_opt_smt(int xc_handle, uint32_t value)
352 {
353 int rc;
354 DECLARE_SYSCTL;
356 sysctl.cmd = XEN_SYSCTL_pm_op;
357 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_set_sched_opt_smt;
358 sysctl.u.pm_op.cpuid = 0;
359 sysctl.u.pm_op.u.set_sched_opt_smt = value;
360 rc = do_sysctl(xc_handle, &sysctl);
362 return rc;
363 }
365 int xc_set_vcpu_migration_delay(int xc_handle, uint32_t value)
366 {
367 int rc;
368 DECLARE_SYSCTL;
370 sysctl.cmd = XEN_SYSCTL_pm_op;
371 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_set_vcpu_migration_delay;
372 sysctl.u.pm_op.cpuid = 0;
373 sysctl.u.pm_op.u.set_vcpu_migration_delay = value;
374 rc = do_sysctl(xc_handle, &sysctl);
376 return rc;
377 }
379 int xc_get_vcpu_migration_delay(int xc_handle, uint32_t *value)
380 {
381 int rc;
382 DECLARE_SYSCTL;
384 sysctl.cmd = XEN_SYSCTL_pm_op;
385 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_vcpu_migration_delay;
386 sysctl.u.pm_op.cpuid = 0;
387 rc = do_sysctl(xc_handle, &sysctl);
389 if (!rc && value)
390 *value = sysctl.u.pm_op.u.get_vcpu_migration_delay;
392 return rc;
393 }
395 int xc_get_cpuidle_max_cstate(int xc_handle, uint32_t *value)
396 {
397 int rc;
398 DECLARE_SYSCTL;
400 if ( xc_handle < 0 || !value )
401 return -EINVAL;
403 sysctl.cmd = XEN_SYSCTL_pm_op;
404 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_get_max_cstate;
405 sysctl.u.pm_op.cpuid = 0;
406 sysctl.u.pm_op.u.get_max_cstate = 0;
407 rc = do_sysctl(xc_handle, &sysctl);
408 *value = sysctl.u.pm_op.u.get_max_cstate;
410 return rc;
411 }
413 int xc_set_cpuidle_max_cstate(int xc_handle, uint32_t value)
414 {
415 DECLARE_SYSCTL;
417 if ( xc_handle < 0 )
418 return -EINVAL;
420 sysctl.cmd = XEN_SYSCTL_pm_op;
421 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_set_max_cstate;
422 sysctl.u.pm_op.cpuid = 0;
423 sysctl.u.pm_op.u.set_max_cstate = value;
425 return do_sysctl(xc_handle, &sysctl);
426 }
428 int xc_enable_turbo(int xc_handle, int cpuid)
429 {
430 DECLARE_SYSCTL;
432 if ( xc_handle < 0 )
433 return -EINVAL;
435 sysctl.cmd = XEN_SYSCTL_pm_op;
436 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_enable_turbo;
437 sysctl.u.pm_op.cpuid = cpuid;
438 return do_sysctl(xc_handle, &sysctl);
439 }
441 int xc_disable_turbo(int xc_handle, int cpuid)
442 {
443 DECLARE_SYSCTL;
445 if ( xc_handle < 0 )
446 return -EINVAL;
448 sysctl.cmd = XEN_SYSCTL_pm_op;
449 sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_disable_turbo;
450 sysctl.u.pm_op.cpuid = cpuid;
451 return do_sysctl(xc_handle, &sysctl);
452 }