x86/RAS changes for v3.12
Subsystems (13)
Linus,
Please pull the latest x86-ras-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-ras-for-linus
HEAD: ead6fa95b7e9d38b4526503403ba1c029b03dd72 Merge tag 'edac_fixes_for_3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp into x86/ras
[ The reason for drivers/ updates is that Boris asked for the
drivers/edac/ changes to go via x86/ras in this cycle. ]
Main changes:
- AMD CPUs:
. Add ECC event decoding support for new F15h models
. Various erratum fixes
. Fix single-channel on dual-channel-controllers bug.
- Intel CPUs:
. UC uncorrectable memory error parsing fix
. Add support for CMC (Corrected Machine Check) 'FF' (Firmware First)
flag in the APEI HEST
- Various cleanups and fixes.
out-of-topic modifications in x86-ras-for-linus:
------------------------------------------------
drivers/acpi/apei/erst.c # cb82a2e: APEI/ERST: Fix error message form drivers/acpi/apei/ghes.c # cf870c7: mce: acpi/apei: Soft-offline a pa drivers/acpi/apei/hest.c # 7781544: x86/mce, acpi/apei: Only disable
# 9ad9587: mce: acpi/apei: Add a boot option # c3d1fb5: mce: acpi/apei: Honour Firmware Fdrivers/edac/amd64_edac.c # 4fc06b3: amd64_edac: Fix incorrect wraparo
# 3f0aba4: amd64_edac: Correct erratum 505 r # a4b4bed: amd64_edac: Get rid of boot_cpu_d # 18b94f6: amd64_edac: Add ECC decoding supp # f0a56c4: amd64_edac: Fix single-channel sedrivers/edac/amd64_edac.h # a4b4bed: amd64_edac: Get rid of boot_cpu_d
# 18b94f6: amd64_edac: Add ECC decoding supp
drivers/edac/cpc925_edac.c # 75a9551: cpc925_edac: Use proper array ter drivers/edac/edac_mc_sysfs.c # c542b53: EDAC: Replace strict_strtol() wit drivers/edac/i3200_edac.c # 166e933: i3200_edac: Make a local function drivers/edac/x38_edac.c # e0d391a: x38_edac: Make a local function s include/linux/mm.h # cf870c7: mce: acpi/apei: Soft-offline a pa include/linux/pci_ids.h # 6bdaa63: pci_ids: Add PCI device ID functi mm/memory-failure.c # cf870c7: mce: acpi/apei: Soft-offline a pa
Thanks,
Ingo
------------------>
Aravind Gopalakrishnan (4):
pci_ids: Add PCI device ID functions 3 and 4 for newer F15h models. x86, amd_nb: Clarify F15h, model 30h GART and L3 support
amd64_edac: Add ECC decoding support for newer F15h models
amd64_edac: Fix incorrect wraparounds
Borislav Petkov (4):
amd64_edac: Fix single-channel setups APEI/ERST: Fix error message formatting
amd64_edac: Get rid of boot_cpu_data accesses
amd64_edac: Correct erratum 505 range
Jingoo Han (4):
EDAC: Replace strict_strtol() with kstrtol()
i3200_edac: Make a local function static
x38_edac: Make a local function static
cpc925_edac: Use proper array termination
Naveen N. Rao (4):
mce: acpi/apei: Honour Firmware First for MCA banks listed in APEI HEST CMC
mce: acpi/apei: Add a boot option to disable ff mode for corrected errors
mce: acpi/apei: Soft-offline a page on firmware GHES notification x86/mce, acpi/apei: Only disable banks listed in HEST if mce is configured
Tony Luck (1):
x86/mce: Pay no attention to 'F' bit in MCACOD when parsing 'UC' errors
Documentation/x86/x86_64/boot-options.txt | 5 + arch/x86/include/asm/acpi.h | 2 + arch/x86/include/asm/mce.h | 16 +- arch/x86/kernel/acpi/boot.c | 5 + arch/x86/kernel/amd_nb.c | 13 +- arch/x86/kernel/cpu/mcheck/mce-internal.h | 3 + arch/x86/kernel/cpu/mcheck/mce.c | 28 +++ arch/x86/kernel/cpu/mcheck/mce_intel.c | 42 +++- drivers/acpi/apei/erst.c | 51 ++--- drivers/acpi/apei/ghes.c | 38 +++- drivers/acpi/apei/hest.c | 39 ++++ drivers/edac/amd64_edac.c | 334 +++++++++++++++++++++++------- drivers/edac/amd64_edac.h | 60 +++++- drivers/edac/cpc925_edac.c | 2 +- drivers/edac/edac_mc_sysfs.c | 6 +- drivers/edac/i3200_edac.c | 3 +- drivers/edac/x38_edac.c | 3 +- include/linux/mm.h | 1 + include/linux/pci_ids.h | 2 + mm/memory-failure.c | 5 +- 20 files changed, 523 insertions(+), 135 deletions(-)
Documentation/x86/x86_64/boot-options.txt +5 -0
@@ -176,6 +176,11 @@ ACPI acpi=noirq Don't route interrupts + acpi=nocmcff Disable firmware first mode for corrected errors. This + disables parsing the HEST CMC error source to check if + firmware has set the FF flag. This may result in + duplicate corrected error reports. + PCI pci=off Don't use PCI
arch/x86/include/asm/acpi.h +2 -0
@@ -86,6 +86,7 @@ extern int acpi_pci_disabled;extern int acpi_skip_timer_override;extern int acpi_use_timer_override;extern int acpi_fix_pin2_polarity; +extern int acpi_disable_cmcff;extern u8 acpi_sci_flags;extern int acpi_sci_override_gsi;
@@ -168,6 +169,7 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)#define acpi_lapic 0#define acpi_ioapic 0 +#define acpi_disable_cmcff 0static inline void acpi_noirq_set (void ) { }static inline void acpi_disable_pci (void ) { }static inline void disable_acpi (void ) { }
arch/x86/include/asm/mce.h +14 -2
@@ -32,11 +32,20 @@#define MCI_STATUS_PCC (1ULL<<57)/* processor context corrupt */ #define MCI_STATUS_S (1ULL<<56)/* Signaled machine check */ #define MCI_STATUS_AR (1ULL<<55)/* Action required */ -#define MCACOD 0xffff/* MCA Error Code */ + +/* +* Note that the full MCACOD field of IA32_MCi_STATUS MSR is +* bits 15:0. But bit 12 is the 'F' bit, defined for corrected +* errors to indicate that errors are being filtered by hardware. +* We should mask out bit 12 when looking for specific signatures +* of uncorrected errors - so the F bit is deliberately skipped +* in this #define. +*/ +#define MCACOD 0xefff/* MCA Error Code */ /* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ #define MCACOD_SCRUB 0x00C0/* 0xC0-0xCF Memory Scrubbing */ -#define MCACOD_SCRUBMSK 0xfff0 +#define MCACOD_SCRUBMSK 0xeff0/* Skip bit 12 ('F' bit) */ #define MCACOD_L3WB 0x017A/* L3 Explicit Writeback */ #define MCACOD_DATA 0x0134/* Data Load */ #define MCACOD_INSTR 0x0150/* Instruction Fetch */
@@ -188,6 +197,9 @@ extern void register_mce_write_callback(ssize_t (*)(struct file *filp,const char __user *ubuf, size_t usize, loff_t *off)); +/* Disable CMCI/polling for MCA bank claimed by firmware */ +extern void mce_disable_bank (int bank); +/* * Exception handler */
arch/x86/kernel/acpi/boot.c +5 -0
@@ -67,6 +67,7 @@ EXPORT_SYMBOL(acpi_pci_disabled);int acpi_lapic;int acpi_ioapic;int acpi_strict; +int acpi_disable_cmcff;u8 acpi_sci_flags__initdata ;int acpi_sci_override_gsi__initdata ;
@@ -1626,6 +1627,10 @@ static int __init parse_acpi(char *arg)/* "acpi=copy_dsdt" copys DSDT */ else if (strcmp(arg, "copy_dsdt") == 0) { acpi_gbl_copy_dsdt_locally = 1; + } +/* "acpi=nocmcff" disables FF mode for corrected errors */ + else if (strcmp(arg, "nocmcff") == 0) { + acpi_disable_cmcff = 1; } else { /* Core will printk when we return error. */ return -EINVAL;
arch/x86/kernel/amd_nb.c +11 -2
@@ -20,6 +20,7 @@ const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, {} };
@@ -27,6 +28,7 @@ EXPORT_SYMBOL(amd_nb_misc_ids);static const struct pci_device_id amd_nb_link_ids[] = { {PCI_DEVICE (PCI_VENDOR_ID_AMD ,PCI_DEVICE_ID_AMD_15H_NB_F4 ) }, + {PCI_DEVICE (PCI_VENDOR_ID_AMD ,PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 ) }, {PCI_DEVICE (PCI_VENDOR_ID_AMD ,PCI_DEVICE_ID_AMD_16H_NB_F4 ) }, {} };
@@ -81,13 +83,20 @@ int amd_cache_northbridges(void)next_northbridge (misc, amd_nb_misc_ids);node_to_amd_nb (i)->link = link =next_northbridge (link, amd_nb_link_ids); - } + } +/* GART present only on Fam15h upto model 0fh */ if (boot_cpu_data.x86 ==0xf || boot_cpu_data.x86 ==0x10 || - boot_cpu_data.x86 ==0x15 ) + (boot_cpu_data.x86 ==0x15 && boot_cpu_data.x86_model <0x10 )) amd_northbridges.flags |=AMD_NB_GART ;/* +* Check for L3 cache presence. +*/ +if (!cpuid_edx (0x80000006 )) +return 0 ; + +/* * Some CPU families support L3 Cache Index Disable. There are some * limitations because of E382 and E388 on family 0x10. */
arch/x86/kernel/cpu/mcheck/mce-internal.h +3 -0
@@ -25,15 +25,18 @@ int mce_severity(struct mce *a, int tolerant, char **msg);struct dentry *mce_get_debugfs_dir (void );extern struct mce_bank *mce_banks; +extern mce_banks_t mce_banks_ce_disabled;#ifdef CONFIG_X86_MCE_INTEL unsigned long mce_intel_adjust_timer (unsigned long interval);void mce_intel_cmci_poll (void );void mce_intel_hcpu_update (unsigned long cpu); +void cmci_disable_bank (int bank);#else # define mce_intel_adjust_timer mce_adjust_timer_defaultstatic inline void mce_intel_cmci_poll (void ) { }static inline void mce_intel_hcpu_update (unsigned long cpu) { } +static inline void cmci_disable_bank (int bank) { }#endif void mce_timer_kick (unsigned long interval);
arch/x86/kernel/cpu/mcheck/mce.c +28 -0
@@ -97,6 +97,15 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL }; +/* +* MCA banks controlled through firmware first for corrected errors. +* This is a global list of banks for which we won't enable CMCI and we +* won't poll. Firmware controls these banks and is responsible for +* reporting corrected errors through GHES. Uncorrected/recoverable +* errors are still notified through a machine check. +*/ +mce_banks_t mce_banks_ce_disabled; + static DEFINE_PER_CPU(struct work_struct, mce_work);static void (*quirk_no_way_out)(int bank,struct mce *m,struct pt_regs *regs);
@@ -1935,6 +1944,25 @@ static struct miscdevice mce_chrdev_device = { &mce_chrdev_ops, }; +static void __mce_disable_bank (void *arg) +{ +int bank = *((int *)arg); +__clear_bit (bank,__get_cpu_var (mce_poll_banks)); +cmci_disable_bank (bank); +} + +void mce_disable_bank (int bank) +{ +if (bank >= mca_cfg.banks) { +pr_warn (FW_BUG +"Ignoring request to disable invalid MCA bank %d.\n" , + bank); +return ; + } +set_bit (bank, mce_banks_ce_disabled); +on_each_cpu (__mce_disable_bank, &bank,1 ); +} +/* * mce=off Disables machine check * mce=no_cmci Disables CMCI
arch/x86/kernel/cpu/mcheck/mce_intel.c +32 -10
70 lines not on this page · raw message
drivers/acpi/apei/erst.c +23 -28
142 lines not on this page · raw message
drivers/acpi/apei/ghes.c +29 -9
@@ -409,6 +409,34 @@ static void ghes_clear_estatus(struct ghes *ghes) ghes->flags &= ~GHES_TO_CLEAR ; } +static void ghes_handle_memory_failure (struct acpi_hest_generic_data *gdata,int sev) +{ +#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE +unsigned long pfn; +int sec_sev =ghes_severity (gdata->error_severity); +struct cper_sec_mem_err *mem_err; + mem_err = (struct cper_sec_mem_err *)(gdata +1 ); + +if (sec_sev ==GHES_SEV_CORRECTED && + (gdata->flags &CPER_SEC_ERROR_THRESHOLD_EXCEEDED ) && + (mem_err->validation_bits &CPER_MEM_VALID_PHYSICAL_ADDRESS )) { + pfn = mem_err->physical_addr >>PAGE_SHIFT ; +if (pfn_valid (pfn)) +memory_failure_queue (pfn,0 ,MF_SOFT_OFFLINE ); +else if (printk_ratelimit ()) + pr_warn(FW_WARN GHES_PFX +"Invalid address in generic error data: %#llx\n" , + mem_err->physical_addr); + } +if (sev ==GHES_SEV_RECOVERABLE && + sec_sev ==GHES_SEV_RECOVERABLE && + mem_err->validation_bits &CPER_MEM_VALID_PHYSICAL_ADDRESS ) { + pfn = mem_err->physical_addr >>PAGE_SHIFT ; +memory_failure_queue (pfn,0 ,0 ); + } +#endif +} +static void ghes_do_proc (struct ghes *ghes,const struct acpi_hest_generic_status *estatus) {
@@ -428,15 +456,7 @@ static void ghes_do_proc(struct ghes *ghes,apei_mce_report_mem_error (sev ==GHES_SEV_CORRECTED , mem_err);#endif -#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE -if (sev ==GHES_SEV_RECOVERABLE && - sec_sev ==GHES_SEV_RECOVERABLE && - mem_err->validation_bits &CPER_MEM_VALID_PHYSICAL_ADDRESS ) { -unsigned long pfn; - pfn = mem_err->physical_addr >>PAGE_SHIFT ; -memory_failure_queue (pfn,0 ,0 ); - } -#endif +ghes_handle_memory_failure (gdata, sev); }#ifdef CONFIG_ACPI_APEI_PCIEAER else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
drivers/acpi/apei/hest.c +39 -0
@@ -36,6 +36,7 @@#include <linux/io.h> #include <linux/platform_device.h> #include <acpi/apei.h> +#include <asm/mce.h> #include "apei-internal.h"
@@ -121,6 +122,41 @@ int apei_hest_parse(apei_hest_func_t func, void *data) }EXPORT_SYMBOL_GPL (apei_hest_parse); +/* +* Check if firmware advertises firmware first mode. We need FF bit to be set +* along with a set of MC banks which work in FF mode. +*/ +static int __init hest_parse_cmc (struct acpi_hest_header *hest_hdr,void *data) +{ +#ifdef CONFIG_X86_MCE +int i; +struct acpi_hest_ia_corrected *cmc; +struct acpi_hest_ia_error_bank *mc_bank; + +if (hest_hdr->type !=ACPI_HEST_TYPE_IA32_CORRECTED_CHECK ) +return 0 ; + + cmc = (struct acpi_hest_ia_corrected *)hest_hdr; +if (!cmc->enabled) +return 0 ; + +/* +* We expect HEST to provide a list of MC banks that report errors +* in firmware first mode. Otherwise, return non-zero value to +* indicate that we are done parsing HEST. +*/ +if (!(cmc->flags &ACPI_HEST_FIRMWARE_FIRST ) || !cmc->num_hardware_banks) +return 1 ; + +pr_info (HEST_PFX "Enabling Firmware First mode for corrected errors.\n" ); + + mc_bank = (struct acpi_hest_ia_error_bank *)(cmc +1 ); +for (i =0 ; i < cmc->num_hardware_banks; i++, mc_bank++) +mce_disable_bank (mc_bank->bank_number); +#endif +return 1 ; +} +struct ghes_arr {struct platform_device **ghes_devs;unsigned int count;
@@ -227,6 +263,9 @@ void __init acpi_hest_init(void) goto err; } +if (!acpi_disable_cmcff) +apei_hest_parse (hest_parse_cmc,NULL ); +if (!ghes_disable) { rc =apei_hest_parse (hest_parse_ghes_count, &ghes_count);if (rc)
drivers/edac/amd64_edac.c +262 -72
667 lines not on this page · raw message
drivers/edac/amd64_edac.h +56 -4
104 lines not on this page · raw message
drivers/edac/cpc925_edac.c +1 -1
@@ -789,7 +789,7 @@ static struct cpc925_dev_info cpc925_devs[] = { .exit = cpc925_htlink_exit, .check = cpc925_htlink_check, }, - {0}, /* Terminated by NULL */ + { } };/*
drivers/edac/edac_mc_sysfs.c +4 -2
@@ -58,8 +58,10 @@ static int edac_set_poll_msec(const char *val, struct kernel_param *kp)if (!val)return -EINVAL ; - ret =strict_strtol (val,0 , &l); -if (ret == -EINVAL || ((int )l != l)) + ret =kstrtol (val,0 , &l); +if (ret) +return ret; +if ((int )l != l)return -EINVAL ; *((int *)kp->arg) = l;
drivers/edac/i3200_edac.c +1 -2
@@ -260,8 +260,7 @@ static void i3200_check(struct mem_ctl_info *mci)i3200_process_error_info (mci, &info); } - -void __iomem *i3200_map_mchbar (struct pci_dev *pdev) +static void __iomem *i3200_map_mchbar (struct pci_dev *pdev) {union {u64 mchbar;
drivers/edac/x38_edac.c +1 -2
@@ -248,8 +248,7 @@ static void x38_check(struct mem_ctl_info *mci)x38_process_error_info (mci, &info); } - -void __iomem *x38_map_mchbar (struct pci_dev *pdev) +static void __iomem *x38_map_mchbar (struct pci_dev *pdev) {union {u64 mchbar;
include/linux/mm.h +1 -0
@@ -1798,6 +1798,7 @@ enum mf_flags {MF_COUNT_INCREASED =1 <<0 ,MF_ACTION_REQUIRED =1 <<1 ,MF_MUST_KILL =1 <<2 , + MF_SOFT_OFFLINE = 1 << 3, };extern int memory_failure (unsigned long pfn,int trapno,int flags);extern void memory_failure_queue (unsigned long pfn,int trapno,int flags);
include/linux/pci_ids.h +2 -0
@@ -518,6 +518,8 @@#define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303#define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304#define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602
mm/memory-failure.c +4 -1
@@ -1286,7 +1286,10 @@ static void memory_failure_work_func(struct work_struct *work)spin_unlock_irqrestore (&mf_cpu->lock, proc_flags);if (!gotten)break ; -memory_failure (entry.pfn, entry.trapno, entry.flags); +if (entry.flags &MF_SOFT_OFFLINE ) +soft_offline_page (pfn_to_page (entry.pfn), entry.flags); +else +memory_failure (entry.pfn, entry.trapno, entry.flags); } }