From: Borislav Petkov <bp@alien8.de>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: Jiri Olsa <jolsa@redhat.com>, X86 ML <x86@kernel.org>,
LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH 3/5] x86/amd: Check for the C1E bug post ACPI subsystem init
Date: Fri, 9 Dec 2016 19:29:10 +0100 [thread overview]
Message-ID: <20161209182912.2726-4-bp@alien8.de> (raw)
In-Reply-To: <20161209182912.2726-1-bp@alien8.de>
From: Thomas Gleixner <tglx@linutronix.de>
AMD CPUs affected by the E400 erratum suffer from the issue that the
local APIC timer stops when the CPU goes into C1E. Unfortunately there
is no way to detect the affected CPUs on early boot. It's only possible
to determine the range of possibly affected CPUs from the family/model
range.
The actual decision whether to enter C1E and thus cause the bug is done
by the firmware and we need to detect that case late, after ACPI has
been initialized.
The current solution is to check in the idle routine whether the CPU is
affected by reading the MSR_K8_INT_PENDING_MSG MSR and checking for the
K8_INTP_C1E_ACTIVE_MASK bits. If one of the bits is set then the CPU is
affected and the system is switched into forced broadcast mode.
This is ineffective and on non-affected CPUs every entry to idle does
the extra RDMSR.
After doing some research it turns out that the bits are visible on the
boot CPU right after the ACPI subsystem is initialized in the early
boot process. So instead of polling for the bits in the idle loop, add
a detection function after acpi_subsystem_init() and check for the MSR
bits. If set, then the X86_BUG_AMD_APIC_C1E is set on the boot CPU and
the TSC is marked unstable when X86_FEATURE_NONSTOP_TSC is not set as it
will stop in C1E state as well.
The switch to broadcast mode cannot be done at this point because the
boot CPU still uses HPET as a clockevent device and the local APIC timer
is not yet calibrated and installed. The switch to broadcast mode on the
affected CPUs needs to be done when the local APIC timer is actually set
up.
This allows to cleanup the amd_e400_idle() function in the next step.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
---
arch/x86/kernel/process.c | 23 +++++++++++++++++++++++
init/main.c | 3 +++
2 files changed, 26 insertions(+)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index bf1a0bab9187..ee097b7cc117 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -419,6 +419,29 @@ void __init init_amd_e400_c1e_mask(void)
zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL);
}
+void __init arch_post_acpi_subsys_init(void)
+{
+ u32 lo, hi;
+
+ if (!boot_cpu_has_bug(X86_BUG_AMD_E400))
+ return;
+
+ /*
+ * AMD E400 detection needs to happen after ACPI has been enabled. If
+ * the machine is affected K8_INTP_C1E_ACTIVE_MASK bits are set in
+ * MSR_K8_INT_PENDING_MSG.
+ */
+ rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
+ if (!(lo & K8_INTP_C1E_ACTIVE_MASK))
+ return;
+
+ boot_cpu_set_bug(X86_BUG_AMD_APIC_C1E);
+
+ if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ mark_tsc_unstable("TSC halt in AMD C1E");
+ pr_info("System has AMD C1E enabled\n");
+}
+
static int __init idle_setup(char *str)
{
if (!str)
diff --git a/init/main.c b/init/main.c
index 2858be732f6d..1d7038c1ee19 100644
--- a/init/main.c
+++ b/init/main.c
@@ -448,6 +448,8 @@ void __init parse_early_param(void)
done = 1;
}
+void __init __weak arch_post_acpi_subsys_init(void) { }
+
void __init __weak smp_setup_processor_id(void)
{
}
@@ -649,6 +651,7 @@ asmlinkage __visible void __init start_kernel(void)
check_bugs();
acpi_subsystem_init();
+ arch_post_acpi_subsys_init();
sfi_init_late();
if (efi_enabled(EFI_RUNTIME_SERVICES)) {
--
2.11.0
next prev parent reply other threads:[~2016-12-09 18:30 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-09 18:29 [PATCH 0/5] x86/CPU: Improve AMD Erratum 400 workaround Borislav Petkov
2016-12-09 18:29 ` [PATCH 1/5] x86/cpufeature: Provide helper to set bugs bits Borislav Petkov
2016-12-09 20:30 ` [tip:x86/idle] " tip-bot for Borislav Petkov
2016-12-09 18:29 ` [PATCH 2/5] x86/bugs: Separate AMD E400 erratum and C1E bug Borislav Petkov
2016-12-09 20:31 ` [tip:x86/idle] " tip-bot for Thomas Gleixner
2016-12-09 18:29 ` Borislav Petkov [this message]
2016-12-09 20:31 ` [tip:x86/idle] x86/amd: Check for the C1E bug post ACPI subsystem init tip-bot for Thomas Gleixner
2016-12-09 18:29 ` [PATCH 4/5] x86/amd: Simplify AMD E400 aware idle routine Borislav Petkov
2016-12-09 20:32 ` [tip:x86/idle] " tip-bot for Borislav Petkov
2016-12-09 18:29 ` [PATCH 5/5] x86: Remove empty idle.h header Borislav Petkov
2016-12-09 20:32 ` [tip:x86/idle] " tip-bot for Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161209182912.2726-4-bp@alien8.de \
--to=bp@alien8.de \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox