aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_pm.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-12-10 13:27:41 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-12-10 13:27:41 +0000
commit7542c4ff00f26a91840afb3336058e8782399365 (patch)
treeb14eaad4185402e0e6f3070a61a023919054dd4c /tools/libxc/xc_pm.c
parent630b6713472007f100b40bf100246ca169b23a14 (diff)
downloadxen-7542c4ff00f26a91840afb3336058e8782399365.tar.gz
xen-7542c4ff00f26a91840afb3336058e8782399365.tar.bz2
xen-7542c4ff00f26a91840afb3336058e8782399365.zip
Add user PM control interface
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Diffstat (limited to 'tools/libxc/xc_pm.c')
-rw-r--r--tools/libxc/xc_pm.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c
index 69f6b6e155..f37cd1d55f 100644
--- a/tools/libxc/xc_pm.c
+++ b/tools/libxc/xc_pm.c
@@ -23,8 +23,15 @@
*
*/
+#include <errno.h>
+#include <curses.h>
+#include <linux/kernel.h>
+
#include "xc_private.h"
+/*
+ * Get PM statistic info
+ */
int xc_pm_get_max_px(int xc_handle, int cpuid, int *max_px)
{
DECLARE_SYSCTL;
@@ -168,3 +175,136 @@ int xc_pm_reset_cxstat(int xc_handle, int cpuid)
return xc_sysctl(xc_handle, &sysctl);
}
+
+
+/*
+ * 1. Get PM parameter
+ * 2. Provide user PM control
+ */
+int xc_get_cpufreq_para(int xc_handle, int cpuid,
+ struct xc_get_cpufreq_para *user_para)
+{
+ DECLARE_SYSCTL;
+ int ret = 0;
+ struct xen_get_cpufreq_para *sys_para = &sysctl.u.pm_op.get_para;
+ bool has_num = user_para->cpu_num &&
+ user_para->freq_num &&
+ user_para->gov_num;
+
+ if ( (xc_handle < 0) || !user_para )
+ return -EINVAL;
+
+ if ( has_num )
+ {
+ if ( (!user_para->affected_cpus) ||
+ (!user_para->scaling_available_frequencies) ||
+ (!user_para->scaling_available_governors) )
+ return -EINVAL;
+
+ if ( (ret = lock_pages(user_para->affected_cpus,
+ user_para->cpu_num * sizeof(uint32_t))) )
+ goto unlock_1;
+ if ( (ret = lock_pages(user_para->scaling_available_frequencies,
+ user_para->freq_num * sizeof(uint32_t))) )
+ goto unlock_2;
+ if ( (ret = lock_pages(user_para->scaling_available_governors,
+ user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
+ goto unlock_3;
+
+ set_xen_guest_handle(sys_para->affected_cpus,
+ user_para->affected_cpus);
+ set_xen_guest_handle(sys_para->scaling_available_frequencies,
+ user_para->scaling_available_frequencies);
+ set_xen_guest_handle(sys_para->scaling_available_governors,
+ user_para->scaling_available_governors);
+ }
+
+ sysctl.cmd = XEN_SYSCTL_pm_op;
+ sysctl.u.pm_op.cmd = GET_CPUFREQ_PARA;
+ sysctl.u.pm_op.cpuid = cpuid;
+ sys_para->cpu_num = user_para->cpu_num;
+ sys_para->freq_num = user_para->freq_num;
+ sys_para->gov_num = user_para->gov_num;
+
+ ret = xc_sysctl(xc_handle, &sysctl);
+ if ( ret )
+ {
+ if ( errno == EAGAIN )
+ {
+ user_para->cpu_num = sys_para->cpu_num;
+ user_para->freq_num = sys_para->freq_num;
+ user_para->gov_num = sys_para->gov_num;
+ ret = -errno;
+ }
+
+ if ( has_num )
+ goto unlock_4;
+ goto unlock_1;
+ }
+ else
+ {
+ user_para->cpuinfo_cur_freq = sys_para->cpuinfo_cur_freq;
+ user_para->cpuinfo_max_freq = sys_para->cpuinfo_max_freq;
+ user_para->cpuinfo_min_freq = sys_para->cpuinfo_min_freq;
+ user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
+ user_para->scaling_max_freq = sys_para->scaling_max_freq;
+ user_para->scaling_min_freq = sys_para->scaling_min_freq;
+
+ memcpy(user_para->scaling_driver,
+ sys_para->scaling_driver, CPUFREQ_NAME_LEN);
+ memcpy(user_para->scaling_governor,
+ sys_para->scaling_governor, CPUFREQ_NAME_LEN);
+
+ /* copy to user_para no matter what cpufreq governor */
+ BUILD_BUG_ON(sizeof(((struct xc_get_cpufreq_para *)0)->u) !=
+ sizeof(((struct xen_get_cpufreq_para *)0)->u));
+
+ memcpy(&user_para->u, &sys_para->u, sizeof(sys_para->u));
+ }
+
+unlock_4:
+ unlock_pages(user_para->scaling_available_governors,
+ user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char));
+unlock_3:
+ unlock_pages(user_para->scaling_available_frequencies,
+ user_para->freq_num * sizeof(uint32_t));
+unlock_2:
+ unlock_pages(user_para->affected_cpus,
+ user_para->cpu_num * sizeof(uint32_t));
+unlock_1:
+ return ret;
+}
+
+int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname)
+{
+ DECLARE_SYSCTL;
+ char *scaling_governor = sysctl.u.pm_op.set_gov.scaling_governor;
+
+ if ( (xc_handle < 0) || (!govname) )
+ return -EINVAL;
+
+ sysctl.cmd = XEN_SYSCTL_pm_op;
+ sysctl.u.pm_op.cmd = SET_CPUFREQ_GOV;
+ sysctl.u.pm_op.cpuid = cpuid;
+ strncpy(scaling_governor, govname, CPUFREQ_NAME_LEN);
+ scaling_governor[CPUFREQ_NAME_LEN] = '\0';
+
+ return xc_sysctl(xc_handle, &sysctl);
+}
+
+int xc_set_cpufreq_para(int xc_handle, int cpuid,
+ int ctrl_type, int ctrl_value)
+{
+ DECLARE_SYSCTL;
+
+ if ( xc_handle < 0 )
+ return -EINVAL;
+
+ sysctl.cmd = XEN_SYSCTL_pm_op;
+ sysctl.u.pm_op.cmd = SET_CPUFREQ_PARA;
+ sysctl.u.pm_op.cpuid = cpuid;
+ sysctl.u.pm_op.set_para.ctrl_type = ctrl_type;
+ sysctl.u.pm_op.set_para.ctrl_value = ctrl_value;
+
+ return xc_sysctl(xc_handle, &sysctl);
+}