[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add user PM control interface
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1228915661 0 # Node ID 605ef79ee46c5d57ee0797ac69521c263b62bce9 # Parent 9ba1541d6dc2d6c6e6c7cf0a57ef8a1f0ea9793d Add user PM control interface Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx> --- tools/libxc/xc_pm.c | 140 +++++++++++++++ tools/libxc/xenctrl.h | 42 ++++ xen/arch/ia64/xen/cpufreq/cpufreq.c | 1 xen/arch/x86/acpi/cpufreq/cpufreq.c | 1 xen/common/sysctl.c | 16 + xen/drivers/acpi/pmstat.c | 306 +++++++++++++++++++++++++++++++++ xen/drivers/cpufreq/cpufreq.c | 6 xen/drivers/cpufreq/cpufreq_ondemand.c | 40 ++++ xen/include/acpi/cpufreq/cpufreq.h | 16 + xen/include/public/sysctl.h | 86 +++++++++ 10 files changed, 647 insertions(+), 7 deletions(-) diff -r 9ba1541d6dc2 -r 605ef79ee46c tools/libxc/xc_pm.c --- a/tools/libxc/xc_pm.c Wed Dec 10 13:27:14 2008 +0000 +++ b/tools/libxc/xc_pm.c Wed Dec 10 13:27:41 2008 +0000 @@ -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, in 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 -r 9ba1541d6dc2 -r 605ef79ee46c tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Wed Dec 10 13:27:14 2008 +0000 +++ b/tools/libxc/xenctrl.h Wed Dec 10 13:27:41 2008 +0000 @@ -1161,4 +1161,46 @@ int xc_pm_reset_cxstat(int xc_handle, in 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 */ diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/arch/ia64/xen/cpufreq/cpufreq.c --- a/xen/arch/ia64/xen/cpufreq/cpufreq.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/arch/ia64/xen/cpufreq/cpufreq.c Wed Dec 10 13:27:41 2008 +0000 @@ -275,6 +275,7 @@ acpi_cpufreq_cpu_exit (struct cpufreq_po } static struct cpufreq_driver acpi_cpufreq_driver = { + .name = "acpi-cpufreq", .verify = acpi_cpufreq_verify, .target = acpi_cpufreq_target, .get = acpi_cpufreq_get, diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/arch/x86/acpi/cpufreq/cpufreq.c --- a/xen/arch/x86/acpi/cpufreq/cpufreq.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c Wed Dec 10 13:27:41 2008 +0000 @@ -549,6 +549,7 @@ static int acpi_cpufreq_cpu_exit(struct } static struct cpufreq_driver acpi_cpufreq_driver = { + .name = "acpi-cpufreq", .verify = acpi_cpufreq_verify, .target = acpi_cpufreq_target, .init = acpi_cpufreq_cpu_init, diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/common/sysctl.c --- a/xen/common/sysctl.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/common/sysctl.c Wed Dec 10 13:27:41 2008 +0000 @@ -26,6 +26,7 @@ #include <xsm/xsm.h> extern int do_get_pm_info(struct xen_sysctl_get_pmstat *op); +extern int do_pm_op(struct xen_sysctl_pm_op *op); extern long arch_do_sysctl( struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl); @@ -221,6 +222,21 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc ret = -EFAULT; break; } + } + break; + + case XEN_SYSCTL_pm_op: + { + ret = do_pm_op(&op->u.pm_op); + if ( ret && (ret != -EAGAIN) ) + break; + + if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA ) + if ( copy_to_guest(u_sysctl, op, 1) ) + { + ret = -EFAULT; + break; + } } break; diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/acpi/pmstat.c --- a/xen/drivers/acpi/pmstat.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/drivers/acpi/pmstat.c Wed Dec 10 13:27:41 2008 +0000 @@ -47,6 +47,11 @@ extern int pmstat_get_cx_stat(uint32_t c extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat); extern int pmstat_reset_cx_stat(uint32_t cpuid); +extern struct list_head cpufreq_governor_list; + +/* + * Get PM statistic info + */ int do_get_pm_info(struct xen_sysctl_get_pmstat *op) { int ret = 0; @@ -156,3 +161,304 @@ int do_get_pm_info(struct xen_sysctl_get return ret; } + +/* + * 1. Get PM parameter + * 2. Provide user PM control + */ +static int read_scaling_available_governors(char *scaling_available_governors, + unsigned int size) +{ + unsigned int i = 0; + struct cpufreq_governor *t; + + if ( !scaling_available_governors ) + return -EINVAL; + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) + { + i += scnprintf(&scaling_available_governors[i], + CPUFREQ_NAME_LEN, "%s ", t->name); + if ( i > size ) + return -EINVAL; + } + scaling_available_governors[i-1] = '\0'; + + return 0; +} + +static int get_cpufreq_para(struct xen_sysctl_pm_op *op) +{ + uint32_t ret = 0; + const struct processor_pminfo *pmpt; + struct cpufreq_policy *policy; + uint32_t gov_num = 0; + uint32_t *affected_cpus; + uint32_t *scaling_available_frequencies; + char *scaling_available_governors; + struct list_head *pos; + uint32_t cpu, i, j = 0; + + if ( !op || !cpu_online(op->cpuid) ) + return -EINVAL; + pmpt = processor_pminfo[op->cpuid]; + policy = cpufreq_cpu_policy[op->cpuid]; + + if ( !pmpt || !pmpt->perf.states || + !policy || !policy->governor ) + return -EINVAL; + + list_for_each(pos, &cpufreq_governor_list) + gov_num++; + + if ( (op->get_para.cpu_num != cpus_weight(policy->cpus)) || + (op->get_para.freq_num != pmpt->perf.state_count) || + (op->get_para.gov_num != gov_num) ) + { + op->get_para.cpu_num = cpus_weight(policy->cpus); + op->get_para.freq_num = pmpt->perf.state_count; + op->get_para.gov_num = gov_num; + return -EAGAIN; + } + + if ( !(affected_cpus = xmalloc_array(uint32_t, op->get_para.cpu_num)) ) + return -ENOMEM; + memset(affected_cpus, 0, op->get_para.cpu_num * sizeof(uint32_t)); + for_each_cpu_mask(cpu, policy->cpus) + affected_cpus[j++] = cpu; + ret = copy_to_guest(op->get_para.affected_cpus, + affected_cpus, op->get_para.cpu_num); + xfree(affected_cpus); + if ( ret ) + return ret; + + if ( !(scaling_available_frequencies = + xmalloc_array(uint32_t, op->get_para.freq_num)) ) + return -ENOMEM; + memset(scaling_available_frequencies, 0, + op->get_para.freq_num * sizeof(uint32_t)); + for ( i = 0; i < op->get_para.freq_num; i++ ) + scaling_available_frequencies[i] = + pmpt->perf.states[i].core_frequency * 1000; + ret = copy_to_guest(op->get_para.scaling_available_frequencies, + scaling_available_frequencies, op->get_para.freq_num); + xfree(scaling_available_frequencies); + if ( ret ) + return ret; + + if ( !(scaling_available_governors = + xmalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) ) + return -ENOMEM; + memset(scaling_available_governors, 0, + gov_num * CPUFREQ_NAME_LEN * sizeof(char)); + if ( (ret = read_scaling_available_governors(scaling_available_governors, + gov_num * CPUFREQ_NAME_LEN * sizeof(char))) ) + { + xfree(scaling_available_governors); + return ret; + } + ret = copy_to_guest(op->get_para.scaling_available_governors, + scaling_available_governors, gov_num * CPUFREQ_NAME_LEN); + xfree(scaling_available_governors); + if ( ret ) + return ret; + + op->get_para.cpuinfo_cur_freq = + cpufreq_driver->get ? cpufreq_driver->get(op->cpuid) : policy->cur; + op->get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq; + op->get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq; + op->get_para.scaling_cur_freq = policy->cur; + op->get_para.scaling_max_freq = policy->max; + op->get_para.scaling_min_freq = policy->min; + + if ( cpufreq_driver->name ) + strlcpy(op->get_para.scaling_driver, + cpufreq_driver->name, CPUFREQ_NAME_LEN); + else + strlcpy(op->get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN); + + if ( policy->governor->name ) + strlcpy(op->get_para.scaling_governor, + policy->governor->name, CPUFREQ_NAME_LEN); + else + strlcpy(op->get_para.scaling_governor, "Unknown", CPUFREQ_NAME_LEN); + + /* governor specific para */ + if ( !strnicmp(op->get_para.scaling_governor, + "userspace", CPUFREQ_NAME_LEN) ) + { + op->get_para.u.userspace.scaling_setspeed = policy->cur; + } + + if ( !strnicmp(op->get_para.scaling_governor, + "ondemand", CPUFREQ_NAME_LEN) ) + { + ret = get_cpufreq_ondemand_para( + &op->get_para.u.ondemand.sampling_rate_max, + &op->get_para.u.ondemand.sampling_rate_min, + &op->get_para.u.ondemand.sampling_rate, + &op->get_para.u.ondemand.up_threshold); + } + + return ret; +} + +static int set_cpufreq_gov(struct xen_sysctl_pm_op *op) +{ + struct cpufreq_policy new_policy, *old_policy; + + if ( !op || !cpu_online(op->cpuid) ) + return -EINVAL; + + old_policy = cpufreq_cpu_policy[op->cpuid]; + if ( !old_policy ) + return -EINVAL; + + memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy)); + + new_policy.governor = __find_governor(op->set_gov.scaling_governor); + if (new_policy.governor == NULL) + return -EINVAL; + + return __cpufreq_set_policy(old_policy, &new_policy); +} + +static int set_cpufreq_para(struct xen_sysctl_pm_op *op) +{ + int ret = 0; + struct cpufreq_policy *policy; + + if ( !op || !cpu_online(op->cpuid) ) + return -EINVAL; + policy = cpufreq_cpu_policy[op->cpuid]; + + if ( !policy || !policy->governor ) + return -EINVAL; + + switch(op->set_para.ctrl_type) + { + case SCALING_MAX_FREQ: + { + struct cpufreq_policy new_policy; + + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + new_policy.max = op->set_para.ctrl_value; + ret = __cpufreq_set_policy(policy, &new_policy); + + break; + } + + case SCALING_MIN_FREQ: + { + struct cpufreq_policy new_policy; + + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + new_policy.min = op->set_para.ctrl_value; + ret = __cpufreq_set_policy(policy, &new_policy); + + break; + } + + case SCALING_SETSPEED: + { + unsigned int freq =op->set_para.ctrl_value; + + if ( !strnicmp(policy->governor->name, + "userspace", CPUFREQ_NAME_LEN) ) + { + if ( freq < policy->min ) + freq = policy->min; + if ( freq > policy->max ) + freq = policy->max; + + ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); + } + else + ret = -EINVAL; + + break; + } + + case SAMPLING_RATE: + { + unsigned int sampling_rate = op->set_para.ctrl_value; + + if ( !strnicmp(policy->governor->name, + "ondemand", CPUFREQ_NAME_LEN) ) + ret = write_ondemand_sampling_rate(sampling_rate); + else + ret = -EINVAL; + + break; + } + + case UP_THRESHOLD: + { + unsigned int up_threshold = op->set_para.ctrl_value; + + if ( !strnicmp(policy->governor->name, + "ondemand", CPUFREQ_NAME_LEN) ) + ret = write_ondemand_up_threshold(up_threshold); + else + ret = -EINVAL; + + break; + } + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +int do_pm_op(struct xen_sysctl_pm_op *op) +{ + int ret = 0; + const struct processor_pminfo *pmpt; + + if ( !op || !cpu_online(op->cpuid) ) + return -EINVAL; + pmpt = processor_pminfo[op->cpuid]; + + switch ( op->cmd & PM_PARA_CATEGORY_MASK ) + { + case CPUFREQ_PARA: + if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) ) + return -ENODEV; + if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) ) + return -EINVAL; + break; + default: + return -ENODEV; + } + + switch ( op->cmd ) + { + case GET_CPUFREQ_PARA: + { + ret = get_cpufreq_para(op); + break; + } + + case SET_CPUFREQ_GOV: + { + ret = set_cpufreq_gov(op); + break; + } + + case SET_CPUFREQ_PARA: + { + ret = set_cpufreq_para(op); + break; + } + + default: + printk("not defined sub-hypercall @ do_pm_op\n"); + ret = -ENOSYS; + break; + } + + return ret; +} diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/cpufreq/cpufreq.c --- a/xen/drivers/cpufreq/cpufreq.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/drivers/cpufreq/cpufreq.c Wed Dec 10 13:27:41 2008 +0000 @@ -53,9 +53,9 @@ struct cpufreq_dom { }; static LIST_HEAD(cpufreq_dom_list_head); -static LIST_HEAD(cpufreq_governor_list); - -static struct cpufreq_governor *__find_governor(const char *governor) +LIST_HEAD(cpufreq_governor_list); + +struct cpufreq_governor *__find_governor(const char *governor) { struct cpufreq_governor *t; diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/cpufreq/cpufreq_ondemand.c --- a/xen/drivers/cpufreq/cpufreq_ondemand.c Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c Wed Dec 10 13:27:41 2008 +0000 @@ -51,11 +51,49 @@ static struct dbs_tuners { unsigned int up_threshold; unsigned int powersave_bias; } dbs_tuners_ins = { + .sampling_rate = 0, .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .powersave_bias = 0, }; static struct timer dbs_timer[NR_CPUS]; + +int write_ondemand_sampling_rate(unsigned int sampling_rate) +{ + if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) || + (sampling_rate < MIN_SAMPLING_RATE / MICROSECS(1)) ) + return -EINVAL; + + dbs_tuners_ins.sampling_rate = sampling_rate * MICROSECS(1); + return 0; +} + +int write_ondemand_up_threshold(unsigned int up_threshold) +{ + if ( (up_threshold > MAX_FREQUENCY_UP_THRESHOLD) || + (up_threshold < MIN_FREQUENCY_UP_THRESHOLD) ) + return -EINVAL; + + dbs_tuners_ins.up_threshold = up_threshold; + return 0; +} + +int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max, + uint32_t *sampling_rate_min, + uint32_t *sampling_rate, + uint32_t *up_threshold) +{ + if (!sampling_rate_max || !sampling_rate_min || + !sampling_rate || !up_threshold) + return -EINVAL; + + *sampling_rate_max = MAX_SAMPLING_RATE/MICROSECS(1); + *sampling_rate_min = MIN_SAMPLING_RATE/MICROSECS(1); + *sampling_rate = dbs_tuners_ins.sampling_rate / MICROSECS(1); + *up_threshold = dbs_tuners_ins.up_threshold; + + return 0; +} uint64_t get_cpu_idle_time(unsigned int cpu) { @@ -214,7 +252,7 @@ int cpufreq_governor_dbs(struct cpufreq_ * Start the timerschedule work, when this governor * is used for first time */ - if (dbs_enable == 1) { + if ((dbs_enable == 1) && !dbs_tuners_ins.sampling_rate) { def_sampling_rate = policy->cpuinfo.transition_latency * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/include/acpi/cpufreq/cpufreq.h --- a/xen/include/acpi/cpufreq/cpufreq.h Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/include/acpi/cpufreq/cpufreq.h Wed Dec 10 13:27:41 2008 +0000 @@ -16,8 +16,6 @@ #include <xen/cpumask.h> #include "processor_perf.h" - -#define CPUFREQ_NAME_LEN 16 struct cpufreq_governor; @@ -88,9 +86,14 @@ struct cpufreq_governor { }; extern struct cpufreq_governor cpufreq_gov_dbs; +extern struct cpufreq_governor cpufreq_gov_userspace; +extern struct cpufreq_governor cpufreq_gov_performance; +extern struct cpufreq_governor cpufreq_gov_powersave; + extern int cpufreq_register_governor(struct cpufreq_governor *governor); extern int cpufreq_unregister_governor(struct cpufreq_governor *governor); -#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs +extern struct cpufreq_governor *__find_governor(const char *governor); +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance /* pass a target to the cpufreq driver */ extern int __cpufreq_driver_target(struct cpufreq_policy *policy, @@ -113,6 +116,7 @@ __cpufreq_governor(struct cpufreq_policy #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ struct cpufreq_driver { + char name[CPUFREQ_NAME_LEN]; int (*init)(struct cpufreq_policy *policy); int (*verify)(struct cpufreq_policy *policy); int (*target)(struct cpufreq_policy *policy, @@ -210,3 +214,9 @@ struct cpu_dbs_info_s { }; int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); +int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max, + uint32_t *sampling_rate_min, + uint32_t *sampling_rate, + uint32_t *up_threshold); +int write_ondemand_sampling_rate(unsigned int sampling_rate); +int write_ondemand_up_threshold(unsigned int up_threshold); diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/include/public/sysctl.h --- a/xen/include/public/sysctl.h Wed Dec 10 13:27:14 2008 +0000 +++ b/xen/include/public/sysctl.h Wed Dec 10 13:27:41 2008 +0000 @@ -273,6 +273,91 @@ typedef struct xen_sysctl_cpu_hotplug xe typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t); +/* + * Get/set xen power management, include + * 1. cpufreq governors and related parameters + */ +#define XEN_SYSCTL_pm_op 12 +struct xen_userspace { + uint32_t scaling_setspeed; +}; +typedef struct xen_userspace xen_userspace_t; + +struct xen_ondemand { + uint32_t sampling_rate_max; + uint32_t sampling_rate_min; + + uint32_t sampling_rate; + uint32_t up_threshold; +}; +typedef struct xen_ondemand xen_ondemand_t; + +/* + * cpufreq para name of this structure named + * same as sysfs file name of native linux + */ +#define CPUFREQ_NAME_LEN 16 +struct xen_get_cpufreq_para { + /* IN/OUT variable */ + uint32_t cpu_num; + uint32_t freq_num; + uint32_t gov_num; + + /* for all governors */ + /* OUT variable */ + XEN_GUEST_HANDLE_64(uint32) affected_cpus; + XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies; + XEN_GUEST_HANDLE_64(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 { + struct xen_userspace userspace; + struct xen_ondemand ondemand; + } u; +}; + +struct xen_set_cpufreq_gov { + char scaling_governor[CPUFREQ_NAME_LEN]; +}; + +struct xen_set_cpufreq_para { + #define SCALING_MAX_FREQ 1 + #define SCALING_MIN_FREQ 2 + #define SCALING_SETSPEED 3 + #define SAMPLING_RATE 4 + #define UP_THRESHOLD 5 + + uint32_t ctrl_type; + uint32_t ctrl_value; +}; + +struct xen_sysctl_pm_op { + #define PM_PARA_CATEGORY_MASK 0xf0 + #define CPUFREQ_PARA 0x10 + + /* cpufreq command type */ + #define GET_CPUFREQ_PARA (CPUFREQ_PARA | 0x01) + #define SET_CPUFREQ_GOV (CPUFREQ_PARA | 0x02) + #define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03) + + uint32_t cmd; + uint32_t cpuid; + union { + struct xen_get_cpufreq_para get_para; + struct xen_set_cpufreq_gov set_gov; + struct xen_set_cpufreq_para set_para; + }; +}; struct xen_sysctl { uint32_t cmd; @@ -289,6 +374,7 @@ struct xen_sysctl { struct xen_sysctl_availheap availheap; struct xen_sysctl_get_pmstat get_pmstat; struct xen_sysctl_cpu_hotplug cpu_hotplug; + struct xen_sysctl_pm_op pm_op; uint8_t pad[128]; } u; }; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |