From 1d7f287b7aa12adb24e653908c20efa59f3d574d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Apr 2016 22:48:40 +0100 Subject: [PATCH] [x86] ACPI / processor: Request native thermal interrupt handling via _OSC (Closes: #817016, #819336) --- debian/changelog | 2 + ...equest-native-thermal-interrupt-hand.patch | 166 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 169 insertions(+) create mode 100644 debian/patches/bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch diff --git a/debian/changelog b/debian/changelog index f373ecb88..a40904724 100644 --- a/debian/changelog +++ b/debian/changelog @@ -242,6 +242,8 @@ linux (4.5.1-1) UNRELEASED; urgency=medium * fs: Add MODULE_SOFTDEP declarations for hard-coded crypto drivers (Closes: #819725) * aufs: Update support patches to aufs4.5-20160328 (Closes: #819748) + * [x86] ACPI / processor: Request native thermal interrupt handling via _OSC + (Closes: #817016, #819336) [ Aurelien Jarno ] * [mipsel/mips/config.loongson-2f] Disable VIDEO_CX23885, VIDEO_IVTV, diff --git a/debian/patches/bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch b/debian/patches/bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch new file mode 100644 index 000000000..cc527fabf --- /dev/null +++ b/debian/patches/bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch @@ -0,0 +1,166 @@ +From: Srinivas Pandruvada +Date: Wed, 23 Mar 2016 21:07:39 -0700 +Subject: ACPI / processor: Request native thermal interrupt handling via _OSC +Origin: https://git.kernel.org/linus/a21211672c9a1d730a39aa65d4a5b3414700adfb +Bug-Debian: https://bugs.debian.org/817016 + +There are several reports of freeze on enabling HWP (Hardware PStates) +feature on Skylake-based systems by the Intel P-states driver. The root +cause is identified as the HWP interrupts causing BIOS code to freeze. + +HWP interrupts use the thermal LVT which can be handled by Linux +natively, but on the affected Skylake-based systems SMM will respond +to it by default. This is a problem for several reasons: + - On the affected systems the SMM thermal LVT handler is broken (it + will crash when invoked) and a BIOS update is necessary to fix it. + - With thermal interrupt handled in SMM we lose all of the reporting + features of the arch/x86/kernel/cpu/mcheck/therm_throt driver. + - Some thermal drivers like x86-package-temp depend on the thermal + threshold interrupts signaled via the thermal LVT. + - The HWP interrupts are useful for debugging and tuning + performance (if the kernel can handle them). +The native handling of thermal interrupts needs to be enabled +because of that. + +This requires some way to tell SMM that the OS can handle thermal +interrupts. That can be done by using _OSC/_PDC in processor +scope very early during ACPI initialization. + +The meaning of _OSC/_PDC bit 12 in processor scope is whether or +not the OS supports native handling of interrupts for Collaborative +Processor Performance Control (CPPC) notifications. Since on +HWP-capable systems CPPC is a firmware interface to HWP, setting +this bit effectively tells the firmware that the OS will handle +thermal interrupts natively going forward. + +For details on _OSC/_PDC refer to: +http://www.intel.com/content/www/us/en/standards/processor-vendor-specific-acpi-specification.html + +To implement the _OSC/_PDC handshake as described, introduce a new +function, acpi_early_processor_osc(), that walks the ACPI +namespace looking for ACPI processor objects and invokes _OSC for +them with bit 12 in the capabilities buffer set and terminates the +namespace walk on the first success. + +Also modify intel_thermal_interrupt() to clear HWP status bits in +the HWP_STATUS MSR to acknowledge HWP interrupts (which prevents +them from firing continuously). + +Signed-off-by: Srinivas Pandruvada +[ rjw: Subject & changelog, function rename ] +Signed-off-by: Rafael J. Wysocki +--- + arch/x86/kernel/cpu/mcheck/therm_throt.c | 3 ++ + drivers/acpi/acpi_processor.c | 52 ++++++++++++++++++++++++++++++++ + drivers/acpi/bus.c | 3 ++ + drivers/acpi/internal.h | 6 ++++ + 4 files changed, 64 insertions(+) + +diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c +index 2c5aaf8c2e2f..05538582a809 100644 +--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c ++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c +@@ -385,6 +385,9 @@ static void intel_thermal_interrupt(void) + { + __u64 msr_val; + ++ if (static_cpu_has(X86_FEATURE_HWP)) ++ wrmsrl_safe(MSR_HWP_STATUS, 0); ++ + rdmsrl(MSR_IA32_THERM_STATUS, msr_val); + + /* Check for violation of core thermal thresholds*/ +diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c +index b5e54f2da53d..0d92d0f915e9 100644 +--- a/drivers/acpi/acpi_processor.c ++++ b/drivers/acpi/acpi_processor.c +@@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device) + } + #endif /* CONFIG_ACPI_HOTPLUG_CPU */ + ++#ifdef CONFIG_X86 ++static bool acpi_hwp_native_thermal_lvt_set; ++static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, ++ u32 lvl, ++ void *context, ++ void **rv) ++{ ++ u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; ++ u32 capbuf[2]; ++ struct acpi_osc_context osc_context = { ++ .uuid_str = sb_uuid_str, ++ .rev = 1, ++ .cap.length = 8, ++ .cap.pointer = capbuf, ++ }; ++ ++ if (acpi_hwp_native_thermal_lvt_set) ++ return AE_CTRL_TERMINATE; ++ ++ capbuf[0] = 0x0000; ++ capbuf[1] = 0x1000; /* set bit 12 */ ++ ++ if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { ++ if (osc_context.ret.pointer && osc_context.ret.length > 1) { ++ u32 *capbuf_ret = osc_context.ret.pointer; ++ ++ if (capbuf_ret[1] & 0x1000) { ++ acpi_handle_info(handle, ++ "_OSC native thermal LVT Acked\n"); ++ acpi_hwp_native_thermal_lvt_set = true; ++ } ++ } ++ kfree(osc_context.ret.pointer); ++ } ++ ++ return AE_OK; ++} ++ ++void __init acpi_early_processor_osc(void) ++{ ++ if (boot_cpu_has(X86_FEATURE_HWP)) { ++ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ++ ACPI_UINT32_MAX, ++ acpi_hwp_native_thermal_lvt_osc, ++ NULL, NULL, NULL); ++ acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, ++ acpi_hwp_native_thermal_lvt_osc, ++ NULL, NULL); ++ } ++} ++#endif ++ + /* + * The following ACPI IDs are known to be suitable for representing as + * processor devices. +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index 891c42d1cd65..f9081b791b81 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -1005,6 +1005,9 @@ static int __init acpi_bus_init(void) + goto error1; + } + ++ /* Set capability bits for _OSC under processor scope */ ++ acpi_early_processor_osc(); ++ + /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION +diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h +index 1e6833a5cd44..6f41c73f82bb 100644 +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -138,6 +138,12 @@ void acpi_early_processor_set_pdc(void); + static inline void acpi_early_processor_set_pdc(void) {} + #endif + ++#ifdef CONFIG_X86 ++void acpi_early_processor_osc(void); ++#else ++static inline void acpi_early_processor_osc(void) {} ++#endif ++ + /* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ diff --git a/debian/patches/series b/debian/patches/series index e980d9035..26ee80df6 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -143,3 +143,4 @@ bugfix/all/netfilter-x_tables-make-sure-e-next_offset-covers-re.patch bugfix/all/ipv4-don-t-do-expensive-useless-work-during-inetdev-.patch bugfix/x86/x86-mm-32-enable-full-randomization-on-i386-and-x86_.patch bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch +bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch