aboutsummaryrefslogtreecommitdiffstats
path: root/tools
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
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')
-rw-r--r--tools/libxc/xc_pm.c140
-rw-r--r--tools/libxc/xenctrl.h42
2 files changed, 182 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);
+}
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 100749a9ab..18d2f5f4d1 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1161,4 +1161,46 @@ int xc_pm_reset_cxstat(int xc_handle, int cpuid);
int xc_cpu_online(int xc_handle, int cpu);
int xc_cpu_offline(int xc_handle, int cpu);
+
+/*
+ * cpufreq para name of this structure named
+ * same as sysfs file name of native linux
+ */
+typedef xen_userspace_t xc_userspace_t;
+typedef xen_ondemand_t xc_ondemand_t;
+
+struct xc_get_cpufreq_para {
+ /* IN/OUT variable */
+ uint32_t cpu_num;
+ uint32_t freq_num;
+ uint32_t gov_num;
+
+ /* for all governors */
+ /* OUT variable */
+ uint32_t *affected_cpus;
+ uint32_t *scaling_available_frequencies;
+ char *scaling_available_governors;
+ char scaling_driver[CPUFREQ_NAME_LEN];
+
+ uint32_t cpuinfo_cur_freq;
+ uint32_t cpuinfo_max_freq;
+ uint32_t cpuinfo_min_freq;
+ uint32_t scaling_cur_freq;
+
+ char scaling_governor[CPUFREQ_NAME_LEN];
+ uint32_t scaling_max_freq;
+ uint32_t scaling_min_freq;
+
+ /* for specific governor */
+ union {
+ xc_userspace_t userspace;
+ xc_ondemand_t ondemand;
+ } u;
+};
+
+int xc_get_cpufreq_para(int xc_handle, int cpuid,
+ struct xc_get_cpufreq_para *user_para);
+int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
+int xc_set_cpufreq_para(int xc_handle, int cpuid,
+ int ctrl_type, int ctrl_value);
#endif /* XENCTRL_H */