CPU Frequency scaling
Hello,
I'm playing around with 2.5.53 on my machine, and activating :
CPU Frequency scaling
Intel Pentium 4 clock modulation
results in a oops at boot time.
Details :
- Motherboard is P4S8X, 512 MB Ram, P4 2.4 Ghz (if you need more details, please ask)
- Kernel : plain 2.5.53, no patch.
Do you need a copy of the .config ?
Oops, from a serial console on the machine :
cpufreq: P4/Xeon(TM) CPU On-Demand Clock Modulation available
divide error: 0000
CPU: 0
EIP: 0060:[<c0114879>] Not tainted
EFLAGS: 00010246
eax: 0024f9b6 ebx: 0024f9b6 ecx: 00005ea8 edx: 00000000
esi: 51eb851f edi: 00000000 ebp: dff8ff2c esp: dff8fec4
ds: 0068 es: 0068 ss: 0068
Process swapper (pid: 1, threadinfo=dff8e000 task=dff8c080)
Stack: 00000000 00000001 c04b9774 dff8ff2c 00000000 0000019a c01252b3
c04b9774
00000000 dff8ff2c 00000000 dff8ff2c 00000000 c012cbdb c0559474
00000000
dff8ff2c 00000000 00000008 00000000 0000019a c0114331 dff8ff2c
00000000
Call Trace: [<c01252b3>] [<c012cbdb>] [<c0114331>] [<c01144a5>]
[<c012cabc>]
[<c012cd26>] [<c0105058>] [<c010502e>] [<c0108b9d>]
Code: f7 f7 0f af d1 89 c3 89 54 24 04 89 d0 0f af d9 31 d2 8b 0d
<0>Kernel panic: Attempted to kill init!ksymoops decoding, after reboot in a 2.4.20 :
4 [12:07] rol@donald:~> more oops-cpufreq.decode ksymoops 2.4.8 on i686 2.4.20. Options used
-v /kernels/linux-2.5.53/vmlinux (specified)
-K (specified)
-l /proc/modules (default)
-o /lib/modules/2.4.20/ (default)
-m /boot/System.map-2.5.53 (specified)No modules in ksyms, skipping objects
No ksyms, skipping lsmod
CPU: 0 EIP: 0060:[<c0114879>] Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010246
eax: 0024f9b6 ebx: 0024f9b6 ecx: 00005ea8 edx: 00000000
esi: 51eb851f edi: 00000000 ebp: dff8ff2c esp: dff8fec4
ds: 0068 es: 0068 ss: 0068
Stack: 00000000 00000001 c04b9774 dff8ff2c 00000000 0000019a c01252b3
c04b9774
00000000 dff8ff2c 00000000 dff8ff2c 00000000 c012cbdb c0559474
00000000
dff8ff2c 00000000 00000008 00000000 0000019a c0114331 dff8ff2c
00000000
Call Trace: [<c01252b3>] [<c012cbdb>] [<c0114331>] [<c01144a5>]
[<c012cabc>]
[<c012cd26>] [<c0105058>] [<c010502e>] [<c0108b9d>]
Code: f7 f7 0f af d1 89 c3 89 54 24 04 89 d0 0f af d9 31 d2 8b 0d Quoted 1 line
Quoted 1 line
EIP;
c0114879<time_cpufreq_notifier+14f/208> <=====
Trace; c01252b3 <notifier_call_chain+27/3e> Trace; c012cbdb <cpufreq_notify_transition+d9/12e> Trace; c0114331 <cpufreq_p4_setdc+a1/1a0> Trace; c01144a5 <cpufreq_p4_setpolicy+75/c6> Trace; c012cabc <cpufreq_set_policy+178/1be> Trace; c012cd26 <cpufreq_register+f6/14a> Trace; c0105058 <init+2a/142>
Trace; c010502e <init+0/142>
Trace; c0108b9d <kernel_thread_helper+5/c>
Code; c0114879 <time_cpufreq_notifier+14f/208> 00000000 <_EIP>:
Code; c0114879 <time_cpufreq_notifier+14f/208> <=====
0: f7 f7 div %edi <=====
Code; c011487b <time_cpufreq_notifier+151/208>
2: 0f af d1 imul %ecx,%edx
Code; c011487e <time_cpufreq_notifier+154/208>
5: 89 c3 mov %eax,%ebx
Code; c0114880 <time_cpufreq_notifier+156/208>
7: 89 54 24 04 mov %edx,0x4(%esp,1)
Code; c0114884 <time_cpufreq_notifier+15a/208>
b: 89 d0 mov %edx,%eax
Code; c0114886 <time_cpufreq_notifier+15c/208>
d: 0f af d9 imul %ecx,%ebx
Code; c0114889 <time_cpufreq_notifier+15f/208>
10: 31 d2 xor %edx,%edx
Code; c011488b <time_cpufreq_notifier+161/208>
12: 8b 0d 00 00 00 00 mov 0x0,%ecx
<0>Kernel panic: Attempted to kill init!
If you need more info, if there is a standard bug report form, please tell !
Paul Rolland, [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Hi,
Thanks for testing cpufreq - and sorry for that oops. The attached patches should resolve this problem. For further cpufreq updates, check
http://www.brodo.de/cpufreq/advanced.html
Dominik
[PATCH 2.5][RESEND] cpufreq: p4-clockmod bugfixes
The "get current state" algorithm wasn't aware of the disable/enable bit, and the policy verification function wasn't aware of the N44 / O17 bug. Also, some unused code is removed.
Dominik
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +37 -36
@@ -82,12 +82,17 @@/* get current state */ rdmsr (MSR_IA32_THERM_CONTROL , l, h); - l = l >>1 ; - l &=0x7 ; - +if (l &0x10 ) { + l = l >>1 ; + l &=0x7 ; + }else + l =DC_DISABLE ; +if (l == newstate) {set_cpus_allowed (current, cpus_allowed);return 0 ; + }else if (l ==DC_RESV ) { + printk(KERN_ERR PFX "BIG FAT WARNING: currently in invalid setting\n"); }/* notifiers */
@@ -141,13 +146,18 @@unsigned int i;unsigned int newstate =0 ;unsigned int number_states =0 ; +unsigned int minstate =1 ; -if (!cpufreq_p4_driver || !stock_freq || !policy) +if (!cpufreq_p4_driver || !stock_freq || + !policy || !cpu_online (policy->cpu))return -EINVAL ; +if (has_N44_O17_errata) + minstate =3 ; +if (policy->policy ==CPUFREQ_POLICY_POWERSAVE ) { -for (i=8 ; i>0 ; i--) +for (i=8 ; i>=minstate; i--)if ((policy->min <= ((stock_freq /8 ) * i)) && (policy->max >= ((stock_freq /8 ) * i))) {
@@ -155,7 +165,7 @@ number_states++; } }else { -for (i=1 ; i<=8 ; i++) +for (i=minstate; i<=8 ; i++)if ((policy->min <= ((stock_freq /8 ) * i)) && (policy->max >= ((stock_freq /8 ) * i))) {
@@ -164,25 +174,8 @@ } } -/* if (number_states == 1) */ - { -if (policy->cpu ==CPUFREQ_ALL_CPUS ) { -for (i=0 ; i<NR_CPUS ; i++) -if (cpu_online (i)) -cpufreq_p4_setdc (i, newstate); - }else { -cpufreq_p4_setdc (policy->cpu, newstate); - } - } -/* else { -if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { -min_state = newstate; -max_state = newstate + (number_states - 1); -} else { -max_state = newstate; -min_state = newstate - (number_states - 1); -} -} */ +cpufreq_p4_setdc (policy->cpu, newstate); +return 0 ; }
@@ -190,17 +183,21 @@static int cpufreq_p4_verify (struct cpufreq_policy *policy) {unsigned int number_states =0 ; -unsigned int i; +unsigned int i =1 ; -if (!cpufreq_p4_driver || !stock_freq || !policy) +if (!cpufreq_p4_driver || !stock_freq || + !policy || !cpu_online (policy->cpu))return -EINVAL ; -if (!cpu_online (policy->cpu)) - policy->cpu =CPUFREQ_ALL_CPUS ; -cpufreq_verify_within_limits (policy, (stock_freq /8 ), stock_freq); +cpufreq_verify_within_limits (policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + +if (has_N44_O17_errata) + i =3 ; -/* is there at least one state within limit? */ -for (i=1 ; i<=8 ; i++) +/* is there at least one state within the limit? */ +for (; i<=8 ; i++)if ((policy->min <= ((stock_freq /8 ) * i)) && (policy->max >= ((stock_freq /8 ) * i))) number_states++;
@@ -209,6 +206,9 @@return 0 ; policy->max = (stock_freq /8 ) * (((unsigned int ) ((policy->max *8 ) / stock_freq)) +1 ); +cpufreq_verify_within_limits (policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq);return 0 ; }
@@ -292,13 +292,14 @@ void __exit cpufreq_p4_exit(void) { -u32 l, h; +unsigned int i;if (cpufreq_p4_driver) { +for (i=0 ; i<NR_CPUS ; i++) { +if (cpu_online (i)) +cpufreq_p4_setdc (i,DC_DISABLE ); + }cpufreq_unregister (); -/* return back to a non modulated state */ -rdmsr (MSR_IA32_THERM_CONTROL , l, h); -wrmsr (MSR_IA32_THERM_CONTROL , l & ~(1 <<4 ), h);kfree (cpufreq_p4_driver); } }
[PATCH] cpufreq: update timer notifiers
- The global loops_per_jiffy can only be safely adjusted on UP.
- x86 per-CPU loops_per_jiffy is not dependend of TSC, so move it to non-TSC code.
- Save reference values so that rounding errors do not accumulate
arch/i386/kernel/cpu/common.c | 47 ++++++++++++++++++++++++++++++++++++ arch/i386/kernel/timers/timer_tsc.c | 44 ++++++++++++++++----------------- kernel/cpufreq.c | 20 +++++++++++---- 3 files changed, 84 insertions(+), 27 deletions(-)
arch/i386/kernel/cpu/common.c +47 -0
64 lines not on this page · raw message
arch/i386/kernel/timers/timer_tsc.c +22 -22
75 lines not on this page · raw message
kernel/cpufreq.c +15 -5
@@ -936,17 +936,27 @@* adjust_jiffies - adjust the system "loops_per_jiffy" * * This function alters the system "loops_per_jiffy" for the clock -* speed change. Note that loops_per_jiffy is only updated if all -* CPUs are affected - else there is a need for per-CPU loops_per_jiffy -* values which are provided by various architectures. +* speed change. Note that loops_per_jiffy cannot be updated on SMP +* systems as each CPU might be scaled differently. So, use the arch +* per-CPU loops_per_jiffy value wherever possible. */ +#ifndef CONFIG_SMP +static unsigned long l_p_j_ref =0 ; +static unsigned int l_p_j_ref_freq =0 ; +static inline void adjust_jiffies (unsigned long val,struct cpufreq_freqs *ci) { +if (!l_p_j_ref_freq) { + l_p_j_ref = loops_per_jiffy; + l_p_j_ref_freq = ci->old; + }if ((val ==CPUFREQ_PRECHANGE && ci->old < ci->new) || (val ==CPUFREQ_POSTCHANGE && ci->old > ci->new)) -if (ci->cpu ==CPUFREQ_ALL_CPUS ) - loops_per_jiffy =cpufreq_scale (loops_per_jiffy, ci->old, ci->new); + loops_per_jiffy =cpufreq_scale (l_p_j_ref, l_p_j_ref_freq, ci->new); } +#else +#define adjust_jiffies (...) +#endif /**