diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/apei.c | 62 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 9 |
4 files changed, 69 insertions, 5 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 86216a55eb59..6b71f0417293 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -131,6 +131,8 @@ config X86 | |||
131 | select GENERIC_CPU_AUTOPROBE | 131 | select GENERIC_CPU_AUTOPROBE |
132 | select HAVE_ARCH_AUDITSYSCALL | 132 | select HAVE_ARCH_AUDITSYSCALL |
133 | select ARCH_SUPPORTS_ATOMIC_RMW | 133 | select ARCH_SUPPORTS_ATOMIC_RMW |
134 | select HAVE_ACPI_APEI if ACPI | ||
135 | select HAVE_ACPI_APEI_NMI if ACPI | ||
134 | 136 | ||
135 | config INSTRUCTION_DECODER | 137 | config INSTRUCTION_DECODER |
136 | def_bool y | 138 | def_bool y |
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile index 163b22581472..3242e591fa82 100644 --- a/arch/x86/kernel/acpi/Makefile +++ b/arch/x86/kernel/acpi/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-$(CONFIG_ACPI) += boot.o | 1 | obj-$(CONFIG_ACPI) += boot.o |
2 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o | 2 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o |
3 | obj-$(CONFIG_ACPI_APEI) += apei.o | ||
3 | 4 | ||
4 | ifneq ($(CONFIG_ACPI_PROCESSOR),) | 5 | ifneq ($(CONFIG_ACPI_PROCESSOR),) |
5 | obj-y += cstate.o | 6 | obj-y += cstate.o |
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c new file mode 100644 index 000000000000..c280df6b2aa2 --- /dev/null +++ b/arch/x86/kernel/acpi/apei.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Arch-specific APEI-related functions. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <acpi/apei.h> | ||
16 | |||
17 | #include <asm/mce.h> | ||
18 | #include <asm/tlbflush.h> | ||
19 | |||
20 | int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data) | ||
21 | { | ||
22 | #ifdef CONFIG_X86_MCE | ||
23 | int i; | ||
24 | struct acpi_hest_ia_corrected *cmc; | ||
25 | struct acpi_hest_ia_error_bank *mc_bank; | ||
26 | |||
27 | if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) | ||
28 | return 0; | ||
29 | |||
30 | cmc = (struct acpi_hest_ia_corrected *)hest_hdr; | ||
31 | if (!cmc->enabled) | ||
32 | return 0; | ||
33 | |||
34 | /* | ||
35 | * We expect HEST to provide a list of MC banks that report errors | ||
36 | * in firmware first mode. Otherwise, return non-zero value to | ||
37 | * indicate that we are done parsing HEST. | ||
38 | */ | ||
39 | if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) || | ||
40 | !cmc->num_hardware_banks) | ||
41 | return 1; | ||
42 | |||
43 | pr_info("HEST: Enabling Firmware First mode for corrected errors.\n"); | ||
44 | |||
45 | mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1); | ||
46 | for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++) | ||
47 | mce_disable_bank(mc_bank->bank_number); | ||
48 | #endif | ||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) | ||
53 | { | ||
54 | #ifdef CONFIG_X86_MCE | ||
55 | apei_mce_report_mem_error(sev, mem_err); | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | void arch_apei_flush_tlb_one(unsigned long addr) | ||
60 | { | ||
61 | __flush_tlb_one(addr); | ||
62 | } | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 9a79c8dbd8e8..4fc57975acc1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -2385,6 +2385,10 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
2385 | threshold_cpu_callback(action, cpu); | 2385 | threshold_cpu_callback(action, cpu); |
2386 | mce_device_remove(cpu); | 2386 | mce_device_remove(cpu); |
2387 | mce_intel_hcpu_update(cpu); | 2387 | mce_intel_hcpu_update(cpu); |
2388 | |||
2389 | /* intentionally ignoring frozen here */ | ||
2390 | if (!(action & CPU_TASKS_FROZEN)) | ||
2391 | cmci_rediscover(); | ||
2388 | break; | 2392 | break; |
2389 | case CPU_DOWN_PREPARE: | 2393 | case CPU_DOWN_PREPARE: |
2390 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); | 2394 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); |
@@ -2396,11 +2400,6 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
2396 | break; | 2400 | break; |
2397 | } | 2401 | } |
2398 | 2402 | ||
2399 | if (action == CPU_POST_DEAD) { | ||
2400 | /* intentionally ignoring frozen here */ | ||
2401 | cmci_rediscover(); | ||
2402 | } | ||
2403 | |||
2404 | return NOTIFY_OK; | 2403 | return NOTIFY_OK; |
2405 | } | 2404 | } |
2406 | 2405 | ||