Xen support for the ondemand governor [2/2] (linux)
Subsystems (2)
PATCH 1/1 Xen support for the ondemand governor [2/2] (linux)
Modify the cpufreq ondemand governor so that it can get idle and total ticks from the Xen hypervisor. Linux and Xen have different ideas of what an idle tick is, so the Xen values for both have to be returned in the same platform hypercall. Otherwise, use basically the same scheme as native Linux.
iff -r 9bf1ddd0f6bf drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_ondemand.c +68 -11
@@ -221,18 +222,14 @@ static struct attribute_group dbs_attr_g };/************************** sysfs end ************************/ - -static void dbs_check_cpu (struct cpu_dbs_info_s *this_dbs_info) -{ -unsigned int idle_ticks, total_ticks; -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; - -struct cpufreq_policy *policy; +cputime64_t total_ticks, idle_ticks;unsigned int j; - -if (!this_dbs_info->enable) -return ; +int load; policy = this_dbs_info->cur_policy; cur_jiffies =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 = cur_jiffies;if (!total_ticks) -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,67 @@ static void dbs_check_cpu(struct cpu_dbs idle_ticks = tmp_idle_ticks; } load = (100 * (total_ticks - idle_ticks)) / total_ticks; +return load; +} +#else + +#include <xen/interface/platform.h> +static int dbs_calc_load (struct cpu_dbs_info_s *this_dbs_info) +{ +int load =0 ; +struct xen_platform_op op; +uint64_t idletime[NR_CPUS ]; +uint64_t totaltime[NR_CPUS ]; +struct cpufreq_policy *policy; +unsigned int j; + + op.cmd = XENPF_getidletime; + op.u.getidletime.max_cpus =num_online_cpus (); +set_xen_guest_handle (op.u.getidletime.idletime, idletime); +set_xen_guest_handle (op.u.getidletime.totaltime, totaltime); +HYPERVISOR_platform_op (&op); + + policy = this_dbs_info->cur_policy; +for_each_cpu_mask (j, policy->cpus) { +cputime64_t total_idle_ticks, total_wall_ticks; +cputime64_t tmp_idle_ticks, tmp_wall_ticks; +struct cpu_dbs_info_s *j_dbs_info; +unsigned long tmp_load; + + j_dbs_info = &per_cpu (cpu_dbs_info, j); + total_idle_ticks = idletime[j]; + tmp_idle_ticks =cputime64_sub (total_idle_ticks, + j_dbs_info->prev_cpu_idle); + total_wall_ticks = totaltime[j]; + tmp_wall_ticks =cputime64_sub (total_wall_ticks, + j_dbs_info->prev_cpu_wall); +if (tmp_wall_ticks ==0 ) +return 200 ; + + j_dbs_info->prev_cpu_wall = total_wall_ticks; + j_dbs_info->prev_cpu_idle = total_idle_ticks; + + tmp_load = (100 * (tmp_wall_ticks - tmp_idle_ticks)) / + tmp_wall_ticks; + load =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 = this_dbs_info->cur_policy; + load =dbs_calc_load (this_dbs_info); +if (load >100 ) +return ;/* Check for frequency increase */ if (load > dbs_tuners_ins.up_threshold) {
include/xen/interface/platform.h +1 -0
@@ -179,6 +179,7 @@ struct xenpf_getidletime {/* IN variables. */ uint32_t max_cpus;XEN_GUEST_HANDLE (uint64_t ) idletime; +XEN_GUEST_HANDLE (uint64_t ) totaltime;/* OUT variables. */ uint32_t nr_cpus; };
Quoted 11 lines
From: Mark Langsdorf
Sent: 2007年10月24日 6:00Modify the cpufreq ondemand governor so that it can get idle and total ticks from the Xen hypervisor. Linux and Xen have different ideas of what an idle tick is, so the Xen values for both have to be returned in the same platform hypercall. Otherwise, use basically the same scheme as native Linux.
Signed-off-by Mark Langsdorf <[email protected]>
[...]
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 282
Quoted 11 lines
drivers/cpufreq/cpufreq_ondemand.c +11
-0+#else + +#include <xen/interface/platform.h> +static int dbs_calc_load (struct cpu_dbs_info_s *this_dbs_info) +{ +int load =0 ; +struct xen_platform_op op; +uint64_t idletime[NR_CPUS ]; +uint64_t totaltime[NR_CPUS ]; +struct cpufreq_policy *policy; +unsigned int j;
Note indent.
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 285
Quoted 3 lines
drivers/cpufreq/cpufreq_ondemand.c +3
-0+ + op.cmd = XENPF_getidletime; + op.u.getidletime.max_cpus =num_online_cpus ();
For current getidletime syntax, max_cpus is the max cpu index instead of max active cpu numbers. How do you handle cpu-hotplug case?
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 288
Quoted 3 lines
drivers/cpufreq/cpufreq_ondemand.c +3
-0+set_xen_guest_handle (op.u.getidletime.idletime, idletime); +set_xen_guest_handle (op.u.getidletime.totaltime, totaltime); +HYPERVISOR_platform_op (&op);
Check return value.
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 293
Quoted 5 lines
drivers/cpufreq/cpufreq_ondemand.c +5
-0+ + policy = this_dbs_info->cur_policy; +for_each_cpu_mask (j, policy->cpus) { +cputime64_t total_idle_ticks, total_wall_ticks; +cputime64_t tmp_idle_ticks, tmp_wall_ticks;
Rename "*_ticks" since Xen returns ns-based values?
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 305
Quoted 12 lines
drivers/cpufreq/cpufreq_ondemand.c +12
-0+struct cpu_dbs_info_s *j_dbs_info; +unsigned long tmp_load; + + j_dbs_info = &per_cpu (cpu_dbs_info, j); + total_idle_ticks = idletime[j]; + tmp_idle_ticks =cputime64_sub (total_idle_ticks, + j_dbs_info->prev_cpu_idle); + total_wall_ticks = totaltime[j]; + tmp_wall_ticks =cputime64_sub (total_wall_ticks, + j_dbs_info->prev_cpu_wall); +if (tmp_wall_ticks ==0 ) +return 200 ;
As I commented in another mail, you don't need count on elapsed time on other cpus. The agent cpu runs governor and thus the sample period is decided by that cpu. Just like the native Linux case, only pick the smallest idle delta in this loop.
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 312
Quoted 7 lines
drivers/cpufreq/cpufreq_ondemand.c +7
-0+ + j_dbs_info->prev_cpu_wall = total_wall_ticks; + j_dbs_info->prev_cpu_idle = total_idle_ticks; + + tmp_load = (100 * (tmp_wall_ticks - tmp_idle_ticks)) / + tmp_wall_ticks; + load =max (load,min (100 , (int ) tmp_load));
I suppose 'min' here instead of 'max'. and then init value of load is set to ~0...
drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 316
Quoted 4 lines
drivers/cpufreq/cpufreq_ondemand.c +4
-0+ } +return load; +} +#endif
[...]
Thanks,
Kevin
RE: [PATCH][cpufreq] Xen support for the ondemandgovernor [2/2] (linux)
Quoted 7 lines
From: Tian, Kevin
Sent: 2007年10月24日 11:19drivers/cpufreq/cpufreq_ondemand.c static void dbs_check_cpu(struct cpu_dbs · line 312
Quoted 1 line
drivers/cpufreq/cpufreq_ondemand.c +1
-0+ load =max (load,min (100 , (int ) tmp_load));I suppose 'min' here instead of 'max'. and then init value of load is set to ~0...
Oh, forgive my mindless comment, and yours are correct indeed. :-)
Thanks,
Kevin