Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754339AbYKUIK3 (ORCPT ); Fri, 21 Nov 2008 03:10:29 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752603AbYKUIKO (ORCPT ); Fri, 21 Nov 2008 03:10:14 -0500 Received: from outbound-wa4.frontbridge.com ([216.32.181.16]:37780 "EHLO WA4EHSOBE005.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752381AbYKUIKM (ORCPT ); Fri, 21 Nov 2008 03:10:12 -0500 X-BigFish: VPS-10(zz936eQ4015M4cd6kzzzzz32i6bh61h) X-Spam-TCS-SCL: 0:0 X-FB-SS: 5, X-WSS-ID: 0KAOC0M-01-MRS-01 Date: Fri, 21 Nov 2008 09:08:41 +0100 From: Andreas Herrmann To: Linus Torvalds CC: cpufreq@vger.kernel.org, stable@kernel.org, "Langsdorf, Mark" , linux-kernel@vger.kernel.org, davej@redhat.com Subject: [PATCH] x86: powernow-k8: ignore out-of-range PstateStatus value Message-ID: <20081121080841.GD10940@alberich.amd.com> References: <20081107150811.GI15390@alberich.amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline In-Reply-To: <20081107150811.GI15390@alberich.amd.com> User-Agent: Mutt/1.5.16 (2007-06-09) X-OriginalArrivalTime: 21 Nov 2008 08:09:58.0422 (UTC) FILETIME=[8B8AB360:01C94BB0] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6536 Lines: 170 A workaround for AMD CPU family 11h erratum 311 might cause that the P-state Status Register shows a "current P-state" which is larger than the "current P-state limit" in P-state Current Limit Register. For the wrong P-state value there is no ACPI _PSS object defined and powernow-k8/cpufreq can't determine the proper CPU frequency for that state. As a consequence this can cause a panic during boot (potentially with all recent kernel versions -- at least I have reproduced it with various 2.6.27 kernels and with the current .28 series), as an example: powernow-k8: Found 1 AMD Turion(tm)X2 Ultra DualCore Mobile ZM-82 processors (2 \ ) powernow-k8: 0 : pstate 0 (2200 MHz) powernow-k8: 1 : pstate 1 (1100 MHz) powernow-k8: 2 : pstate 2 (600 MHz) BUG: unable to handle kernel paging request at ffff88086e7528b8 IP: [] cpufreq_stats_update+0x4a/0x5f PGD 202063 PUD 0 Oops: 0002 [#1] SMP last sysfs file: CPU 1 Modules linked in: Pid: 1, comm: swapper Not tainted 2.6.28-rc3-dirty #16 RIP: 0010:[] [] cpufreq_stats_update+0x4a/0\ f Synaptics claims to have extended capabilities, but I'm not able to read them.<6\ 6 RAX: 0000000000000000 RBX: 0000000000000001 RCX: ffff88006e7528c0 RDX: 00000000ffffffff RSI: ffff88006e54af00 RDI: ffffffff808f056c RBP: 00000000fffee697 R08: 0000000000000003 R09: ffff88006e73f080 R10: 0000000000000001 R11: 00000000002191c0 R12: ffff88006fb83c10 R13: 00000000ffffffff R14: 0000000000000001 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88006fb50740(0000) knlGS:0000000000000000 Unable to initialize Synaptics hardware. CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: ffff88086e7528b8 CR3: 0000000000201000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 1, threadinfo ffff88006fb82000, task ffff88006fb816d0) Stack: ffff88006e74da50 0000000000000000 ffff88006e54af00 ffffffff804863c7 ffff88006e74da50 0000000000000000 00000000ffffffff 0000000000000000 ffff88006fb83c10 ffffffff8024b46c ffffffff808f0560 ffff88006fb83c10 Call Trace: [] ? cpufreq_stat_notifier_trans+0x51/0x83 [] ? notifier_call_chain+0x29/0x4c [] ? __srcu_notifier_call_chain+0x46/0x61 [] ? cpufreq_notify_transition+0x93/0xa9 [] ? powernowk8_target+0x1e8/0x5f3 [] ? cpufreq_governor_performance+0x1b/0x20 [] ? __cpufreq_governor+0x71/0xa8 [] ? __cpufreq_set_policy+0x101/0x13e [] ? cpufreq_add_dev+0x3f0/0x4cd [] ? handle_update+0x0/0x8 [] ? sysdev_driver_register+0xb6/0x10d [] ? powernowk8_init+0x0/0x7e [] ? cpufreq_register_driver+0x8f/0x140 [] ? _stext+0x56/0x14f [] ? proc_register+0x122/0x17d [] ? create_proc_entry+0x73/0x8a [] ? register_irq_proc+0x92/0xaa [] ? init_irq_proc+0x57/0x69 [] ? kernel_init+0x116/0x169 [] ? child_rip+0xa/0x11 [] ? kernel_init+0x0/0x169 [] ? child_rip+0x0/0x11 Code: 05 c5 83 36 00 48 c7 c2 48 5d 86 80 48 8b 04 d8 48 8b 40 08 48 8b 34 02 48\ RIP [] cpufreq_stats_update+0x4a/0x5f RSP CR2: ffff88086e7528b8 ---[ end trace 0678bac75e67a2f7 ]--- Kernel panic - not syncing: Attempted to kill init! In short, aftereffect of the wrong P-state is that cpufreq_stats_update() uses "-1" as index for some array in cpufreq_stats_update (unsigned int cpu) { ... if (stat->time_in_state) stat->time_in_state[stat->last_index] = cputime64_add(stat->time_in_state[stat->last_index], cputime_sub(cur_time, stat->last_time)); ... } Fortunately, the wrong P-state value is returned only if the core is in P-state 0. This fix solves the problem by detecting the out-of-range P-state, ignoring it, and using "0" instead. Cc: stable@kernel.org Acked-by: Mark Langsdorf Signed-off-by: Andreas Herrmann --- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 16 +++++++++++++--- arch/x86/kernel/cpu/cpufreq/powernow-k8.h | 4 +++- 2 files changed, 16 insertions(+), 4 deletions(-) Linus, please apply for .28. Thanks, Andreas diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index d3dcd58..8c76905 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -115,9 +115,18 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data) u32 i = 0; if (cpu_family == CPU_HW_PSTATE) { - rdmsr(MSR_PSTATE_STATUS, lo, hi); - i = lo & HW_PSTATE_MASK; - data->currpstate = i; + if (data->currpstate == INVALID_HW_PSTATE) { + /* read (initial) hw pstate if not yet set */ + rdmsr(MSR_PSTATE_STATUS, lo, hi); + i = lo & HW_PSTATE_MASK; + + /* a workaround for family 11h erratum 311 might cause + an "out-of-range Pstate if the core is in Pstate-0 */ + if (i >= data->numps) + data->currpstate = 0; + else + data->currpstate = i; + } return 0; } do { @@ -1121,6 +1130,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) } data->cpu = pol->cpu; + data->currpstate = INVALID_HW_PSTATE; if (powernow_k8_cpu_init_acpi(data)) { /* diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index ab48cfe..4078f5d 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -23,7 +23,9 @@ struct powernow_k8_data { u32 exttype; /* extended interface = 1 */ /* keep track of the current fid / vid or pstate */ - u32 currvid, currfid, currpstate; + u32 currvid, currfid; + u32 currpstate; +#define INVALID_HW_PSTATE 0xff /* the powernow_table includes all frequency and vid/fid pairings: * fid are the lower 8 bits of the index, vid are the upper 8 bits. -- 1.6.0.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/