debuggers.hg

view xen/drivers/cpufreq/cpufreq_ondemand.c @ 20960:6dd69b92d131

xenpm: Fix ia64 build

cpuid_eax() is x86-specific.

Signed-off-by: KUWAMURA Shin'ya <kuwa@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 10 09:06:59 2010 +0000 (2010-02-10)
parents a06e9def02bb
children efa827c5bf73
line source
1 /*
2 * xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
3 *
4 * Copyright (C) 2001 Russell King
5 * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
6 * Jun Nakajima <jun.nakajima@intel.com>
7 * Feb 2008 Liu Jinsong <jinsong.liu@intel.com>
8 * Porting cpufreq_ondemand.c from Liunx 2.6.23 to Xen hypervisor
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
15 #include <xen/types.h>
16 #include <xen/percpu.h>
17 #include <xen/cpumask.h>
18 #include <xen/types.h>
19 #include <xen/sched.h>
20 #include <xen/timer.h>
21 #include <asm/config.h>
22 #include <acpi/cpufreq/cpufreq.h>
24 #define DEF_FREQUENCY_UP_THRESHOLD (80)
25 #define MIN_FREQUENCY_UP_THRESHOLD (11)
26 #define MAX_FREQUENCY_UP_THRESHOLD (100)
28 #define MIN_DBS_INTERVAL (MICROSECS(100))
29 #define MIN_SAMPLING_RATE_RATIO (2)
30 #define MIN_SAMPLING_MILLISECS (MIN_SAMPLING_RATE_RATIO * 10)
31 #define MIN_STAT_SAMPLING_RATE \
32 (MIN_SAMPLING_MILLISECS * MILLISECS(1))
33 #define MIN_SAMPLING_RATE \
34 (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
35 #define MAX_SAMPLING_RATE (500 * def_sampling_rate)
36 #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
37 #define TRANSITION_LATENCY_LIMIT (10 * 1000 )
39 static uint64_t def_sampling_rate;
40 static uint64_t usr_sampling_rate;
42 /* Sampling types */
43 enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
45 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
47 static unsigned int dbs_enable; /* number of CPUs using this policy */
49 static struct dbs_tuners {
50 uint64_t sampling_rate;
51 unsigned int up_threshold;
52 unsigned int powersave_bias;
53 } dbs_tuners_ins = {
54 .sampling_rate = 0,
55 .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
56 .powersave_bias = 0,
57 };
59 static struct timer dbs_timer[NR_CPUS];
61 /* Turbo Mode */
62 static int turbo_detected = 0;
64 int write_ondemand_sampling_rate(unsigned int sampling_rate)
65 {
66 if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) ||
67 (sampling_rate < MIN_SAMPLING_RATE / MICROSECS(1)) )
68 return -EINVAL;
70 dbs_tuners_ins.sampling_rate = sampling_rate * MICROSECS(1);
71 return 0;
72 }
74 int write_ondemand_up_threshold(unsigned int up_threshold)
75 {
76 if ( (up_threshold > MAX_FREQUENCY_UP_THRESHOLD) ||
77 (up_threshold < MIN_FREQUENCY_UP_THRESHOLD) )
78 return -EINVAL;
80 dbs_tuners_ins.up_threshold = up_threshold;
81 return 0;
82 }
84 int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
85 uint32_t *sampling_rate_min,
86 uint32_t *sampling_rate,
87 uint32_t *up_threshold)
88 {
89 if (!sampling_rate_max || !sampling_rate_min ||
90 !sampling_rate || !up_threshold)
91 return -EINVAL;
93 *sampling_rate_max = MAX_SAMPLING_RATE/MICROSECS(1);
94 *sampling_rate_min = MIN_SAMPLING_RATE/MICROSECS(1);
95 *sampling_rate = dbs_tuners_ins.sampling_rate / MICROSECS(1);
96 *up_threshold = dbs_tuners_ins.up_threshold;
98 return 0;
99 }
101 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
102 {
103 uint64_t cur_ns, total_ns;
104 uint64_t max_load_freq = 0;
105 struct cpufreq_policy *policy;
106 unsigned int max;
107 unsigned int j;
109 if (!this_dbs_info->enable)
110 return;
112 policy = this_dbs_info->cur_policy;
113 max = policy->max;
114 if (turbo_detected && !this_dbs_info->turbo_enabled) {
115 if (max > policy->cpuinfo.second_max_freq)
116 max = policy->cpuinfo.second_max_freq;
117 }
119 if (unlikely(policy->resume)) {
120 __cpufreq_driver_target(policy, max,CPUFREQ_RELATION_H);
121 return;
122 }
124 cur_ns = NOW();
125 total_ns = cur_ns - this_dbs_info->prev_cpu_wall;
126 this_dbs_info->prev_cpu_wall = NOW();
128 if (total_ns < MIN_DBS_INTERVAL)
129 return;
131 /* Get Idle Time */
132 for_each_cpu_mask(j, policy->cpus) {
133 uint64_t idle_ns, total_idle_ns;
134 uint64_t load, load_freq, freq_avg;
135 struct cpu_dbs_info_s *j_dbs_info;
137 j_dbs_info = &per_cpu(cpu_dbs_info, j);
138 total_idle_ns = get_cpu_idle_time(j);
139 idle_ns = total_idle_ns - j_dbs_info->prev_cpu_idle;
140 j_dbs_info->prev_cpu_idle = total_idle_ns;
142 if (unlikely(total_ns < idle_ns))
143 continue;
145 load = 100 * (total_ns - idle_ns) / total_ns;
147 freq_avg = cpufreq_driver_getavg(j, GOV_GETAVG);
149 load_freq = load * freq_avg;
150 if (load_freq > max_load_freq)
151 max_load_freq = load_freq;
152 }
154 /* Check for frequency increase */
155 if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
156 /* if we are already at full speed then break out early */
157 if (policy->cur == max)
158 return;
159 __cpufreq_driver_target(policy, max, CPUFREQ_RELATION_H);
160 return;
161 }
163 /* Check for frequency decrease */
164 /* if we cannot reduce the frequency anymore, break out early */
165 if (policy->cur == policy->min)
166 return;
168 /*
169 * The optimal frequency is the frequency that is the lowest that
170 * can support the current CPU usage without triggering the up
171 * policy. To be safe, we focus 10 points under the threshold.
172 */
173 if (max_load_freq < (dbs_tuners_ins.up_threshold - 10) * policy->cur) {
174 uint64_t freq_next;
176 freq_next = max_load_freq / (dbs_tuners_ins.up_threshold - 10);
178 __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
179 }
180 }
182 static void do_dbs_timer(void *dbs)
183 {
184 struct cpu_dbs_info_s *dbs_info = (struct cpu_dbs_info_s *)dbs;
186 if (!dbs_info->enable)
187 return;
189 dbs_check_cpu(dbs_info);
191 set_timer(&dbs_timer[dbs_info->cpu],
192 align_timer(NOW() , dbs_tuners_ins.sampling_rate));
193 }
195 static void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
196 {
197 dbs_info->enable = 1;
199 init_timer(&dbs_timer[dbs_info->cpu], do_dbs_timer,
200 (void *)dbs_info, dbs_info->cpu);
202 set_timer(&dbs_timer[dbs_info->cpu], NOW()+dbs_tuners_ins.sampling_rate);
204 if ( processor_pminfo[dbs_info->cpu]->perf.shared_type
205 == CPUFREQ_SHARED_TYPE_HW )
206 {
207 dbs_info->stoppable = 1;
208 }
209 }
211 static void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
212 {
213 dbs_info->enable = 0;
214 stop_timer(&dbs_timer[dbs_info->cpu]);
215 }
217 int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
218 {
219 unsigned int cpu = policy->cpu;
220 struct cpu_dbs_info_s *this_dbs_info;
221 unsigned int j;
223 this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
225 switch (event) {
226 case CPUFREQ_GOV_START:
227 if ((!cpu_online(cpu)) || (!policy->cur))
228 return -EINVAL;
230 if (policy->cpuinfo.transition_latency >
231 (TRANSITION_LATENCY_LIMIT * 1000)) {
232 printk(KERN_WARNING "ondemand governor failed to load "
233 "due to too long transition latency\n");
234 return -EINVAL;
235 }
236 if (this_dbs_info->enable)
237 /* Already enabled */
238 break;
240 dbs_enable++;
242 for_each_cpu_mask(j, policy->cpus) {
243 struct cpu_dbs_info_s *j_dbs_info;
244 j_dbs_info = &per_cpu(cpu_dbs_info, j);
245 j_dbs_info->cur_policy = policy;
247 j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
248 j_dbs_info->prev_cpu_wall = NOW();
249 }
250 this_dbs_info->cpu = cpu;
251 /*
252 * Start the timerschedule work, when this governor
253 * is used for first time
254 */
255 if ((dbs_enable == 1) && !dbs_tuners_ins.sampling_rate) {
256 def_sampling_rate = policy->cpuinfo.transition_latency *
257 DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
259 if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
260 def_sampling_rate = MIN_STAT_SAMPLING_RATE;
262 if (!usr_sampling_rate)
263 dbs_tuners_ins.sampling_rate = def_sampling_rate;
264 else if (usr_sampling_rate < MIN_SAMPLING_RATE) {
265 printk(KERN_WARNING "cpufreq/ondemand: "
266 "specified sampling rate too low, using %"PRIu64"\n",
267 MIN_SAMPLING_RATE);
268 dbs_tuners_ins.sampling_rate = MIN_SAMPLING_RATE;
269 } else if (usr_sampling_rate > MAX_SAMPLING_RATE) {
270 printk(KERN_WARNING "cpufreq/ondemand: "
271 "specified sampling rate too high, using %"PRIu64"\n",
272 MAX_SAMPLING_RATE);
273 dbs_tuners_ins.sampling_rate = MAX_SAMPLING_RATE;
274 } else
275 dbs_tuners_ins.sampling_rate = usr_sampling_rate;
276 }
277 this_dbs_info->turbo_enabled = 1;
278 dbs_timer_init(this_dbs_info);
280 break;
282 case CPUFREQ_GOV_STOP:
283 dbs_timer_exit(this_dbs_info);
284 dbs_enable--;
286 break;
288 case CPUFREQ_GOV_LIMITS:
289 if (policy->max < this_dbs_info->cur_policy->cur)
290 __cpufreq_driver_target(this_dbs_info->cur_policy,
291 policy->max, CPUFREQ_RELATION_H);
292 else if (policy->min > this_dbs_info->cur_policy->cur)
293 __cpufreq_driver_target(this_dbs_info->cur_policy,
294 policy->min, CPUFREQ_RELATION_L);
295 break;
296 }
297 return 0;
298 }
300 static void __init cpufreq_dbs_handle_option(const char *name, const char *val)
301 {
302 if ( !strcmp(name, "rate") && val )
303 {
304 usr_sampling_rate = simple_strtoull(val, NULL, 0) * MICROSECS(1);
305 }
306 else if ( !strcmp(name, "up_threshold") && val )
307 {
308 unsigned long tmp = simple_strtoul(val, NULL, 0);
310 if ( tmp < MIN_FREQUENCY_UP_THRESHOLD )
311 {
312 printk(XENLOG_WARNING "cpufreq/ondemand: "
313 "specified threshold too low, using %d\n",
314 MIN_FREQUENCY_UP_THRESHOLD);
315 tmp = MIN_FREQUENCY_UP_THRESHOLD;
316 }
317 else if ( tmp > MAX_FREQUENCY_UP_THRESHOLD )
318 {
319 printk(XENLOG_WARNING "cpufreq/ondemand: "
320 "specified threshold too high, using %d\n",
321 MAX_FREQUENCY_UP_THRESHOLD);
322 tmp = MAX_FREQUENCY_UP_THRESHOLD;
323 }
324 dbs_tuners_ins.up_threshold = tmp;
325 }
326 else if ( !strcmp(name, "bias") && val )
327 {
328 unsigned long tmp = simple_strtoul(val, NULL, 0);
330 if ( tmp > 1000 )
331 {
332 printk(XENLOG_WARNING "cpufreq/ondemand: "
333 "specified bias too high, using 1000\n");
334 tmp = 1000;
335 }
336 dbs_tuners_ins.powersave_bias = tmp;
337 }
338 }
340 struct cpufreq_governor cpufreq_gov_dbs = {
341 .name = "ondemand",
342 .governor = cpufreq_governor_dbs,
343 .handle_option = cpufreq_dbs_handle_option
344 };
346 static int __init cpufreq_gov_dbs_init(void)
347 {
348 #ifdef CONFIG_X86
349 unsigned int eax = cpuid_eax(6);
350 if ( eax & 0x2 ) {
351 turbo_detected = 1;
352 printk(XENLOG_INFO "Turbo Mode detected!\n");
353 }
354 #endif
355 return cpufreq_register_governor(&cpufreq_gov_dbs);
356 }
357 __initcall(cpufreq_gov_dbs_init);
359 static void __exit cpufreq_gov_dbs_exit(void)
360 {
361 cpufreq_unregister_governor(&cpufreq_gov_dbs);
362 }
363 __exitcall(cpufreq_gov_dbs_exit);
365 void cpufreq_dbs_timer_suspend(void)
366 {
367 int cpu;
369 cpu = smp_processor_id();
371 if ( per_cpu(cpu_dbs_info,cpu).stoppable )
372 {
373 stop_timer( &dbs_timer[cpu] );
374 }
375 }
377 void cpufreq_dbs_timer_resume(void)
378 {
379 int cpu;
380 struct timer* t;
381 s_time_t now;
383 cpu = smp_processor_id();
385 if ( per_cpu(cpu_dbs_info,cpu).stoppable )
386 {
387 now = NOW();
388 t = &dbs_timer[cpu];
389 if (t->expires <= now)
390 {
391 t->function(t->data);
392 }
393 else
394 {
395 set_timer(t, align_timer(now , dbs_tuners_ins.sampling_rate));
396 }
397 }
398 }
400 void cpufreq_dbs_enable_turbo(int cpuid)
401 {
402 per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 1;
403 }
405 void cpufreq_dbs_disable_turbo(int cpuid)
406 {
407 per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 0;
408 }
410 unsigned int cpufreq_dbs_get_turbo_status(int cpuid)
411 {
412 return turbo_detected && per_cpu(cpu_dbs_info, cpuid).turbo_enabled;
413 }