From: "Mark Langsdorf" Subject: [PATCH][retry 2][cpufreq] Xen support for the ondemand governor in Linux dom0 Date: Mon, 29 Oct 2007 12:38:07 -0500 Message-ID: <200710291238.07917.mark.langsdorf@amd.com> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable Return-path: Content-Disposition: inline List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org Modify the cpufreq ondemand governor so that it can get idle and total nsecs from the Xen hypervisor. =A0Xen uses nsecs to measure idle time, while Linux uses ticks. Other than accounting for=20 that difference, use the same algorithm to calculate idle time as Linux does. Signed-off-by: Mark Langsdorf diff -r 26962454b508 drivers/cpufreq/cpufreq_ondemand.c =2D-- a/drivers/cpufreq/cpufreq_ondemand.c Wed Oct 24 17:17:09 2007 +0100 +++ b/drivers/cpufreq/cpufreq_ondemand.c Mon Oct 29 12:39:23 2007 -0500 @@ -96,6 +96,7 @@ static inline cputime64_t get_cpu_idle_t return retval; } =20 + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char = *buf) { @@ -221,18 +222,14 @@ static struct attribute_group dbs_attr_g }; =20 /************************** sysfs end ************************/ =2D =2Dstatic void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) =2D{ =2D unsigned int idle_ticks, total_ticks; =2D unsigned int load; +#ifndef CONFIG_XEN +static int dbs_calc_load(struct cpu_dbs_info_s *this_dbs_info) +{ + struct cpufreq_policy *policy; cputime64_t cur_jiffies; =2D =2D struct cpufreq_policy *policy; + cputime64_t total_ticks, idle_ticks; unsigned int j; =2D =2D if (!this_dbs_info->enable) =2D return; + int load; =20 policy =3D this_dbs_info->cur_policy; cur_jiffies =3D jiffies64_to_cputime64(get_jiffies_64()); @@ -240,7 +237,7 @@ static void dbs_check_cpu(struct cpu_dbs this_dbs_info->prev_cpu_wall); this_dbs_info->prev_cpu_wall =3D cur_jiffies; if (!total_ticks) =2D return; + return 200; /* * Every sampling_rate, we check, if current idle time is less * than 20% (default), then we try to increase frequency @@ -270,6 +267,70 @@ static void dbs_check_cpu(struct cpu_dbs idle_ticks =3D tmp_idle_ticks; } load =3D (100 * (total_ticks - idle_ticks)) / total_ticks; + return load; +} +#else + +#include +static int dbs_calc_load(struct cpu_dbs_info_s *this_dbs_info) +{ + int load =3D 0; + struct xen_platform_op op; + uint64_t idletime[NR_CPUS]; + struct cpufreq_policy *policy; + unsigned int j; + cpumask_t cpumap; + + op.cmd =3D XENPF_getidletime; + set_xen_guest_handle(op.u.getidletime.cpumap_bitmap, (uint8_t *) cpus_add= r(cpumap)); + op.u.getidletime.cpumap_nr_cpus =3D NR_CPUS;// num_online_cpus(); + set_xen_guest_handle(op.u.getidletime.idletime, idletime); + if (HYPERVISOR_platform_op(&op)) + return 200; + + policy =3D this_dbs_info->cur_policy; + cpumap =3D policy->cpus; + for_each_cpu_mask(j, cpumap) { + cputime64_t total_idle_nsecs, tmp_idle_nsecs; + cputime64_t total_wall_nsecs, tmp_wall_nsecs; + struct cpu_dbs_info_s *j_dbs_info; + unsigned long tmp_load; + + j_dbs_info =3D &per_cpu(cpu_dbs_info, j); + total_idle_nsecs =3D idletime[j]; + tmp_idle_nsecs =3D cputime64_sub(total_idle_nsecs, + j_dbs_info->prev_cpu_idle); + total_wall_nsecs =3D op.u.getidletime.now; + tmp_wall_nsecs =3D cputime64_sub(total_wall_nsecs, + j_dbs_info->prev_cpu_wall); + + if (tmp_wall_nsecs =3D=3D 0) + return 200; + + j_dbs_info->prev_cpu_wall =3D total_wall_nsecs; + j_dbs_info->prev_cpu_idle =3D total_idle_nsecs; + + tmp_load =3D (100 * (tmp_wall_nsecs - tmp_idle_nsecs)) / + tmp_wall_nsecs; + load =3D max(load, min(100, (int) tmp_load)); + } + return load; +} +#endif + +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) +{ + int load; + + struct cpufreq_policy *policy; + + if (!this_dbs_info->enable) + return; + + policy =3D this_dbs_info->cur_policy; + load =3D dbs_calc_load(this_dbs_info); + if (load > 100)=20 + return; =20 /* Check for frequency increase */ if (load > dbs_tuners_ins.up_threshold) {