| 1 | // SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 2 | /* | 
|---|
| 3 | *  (c) 2005-2016 Advanced Micro Devices, Inc. | 
|---|
| 4 | * | 
|---|
| 5 | *  Written by Jacob Shin - AMD, Inc. | 
|---|
| 6 | *  Maintained by: Borislav Petkov <bp@alien8.de> | 
|---|
| 7 | */ | 
|---|
| 8 | #include <linux/interrupt.h> | 
|---|
| 9 | #include <linux/notifier.h> | 
|---|
| 10 | #include <linux/kobject.h> | 
|---|
| 11 | #include <linux/percpu.h> | 
|---|
| 12 | #include <linux/errno.h> | 
|---|
| 13 | #include <linux/sched.h> | 
|---|
| 14 | #include <linux/sysfs.h> | 
|---|
| 15 | #include <linux/slab.h> | 
|---|
| 16 | #include <linux/init.h> | 
|---|
| 17 | #include <linux/cpu.h> | 
|---|
| 18 | #include <linux/smp.h> | 
|---|
| 19 | #include <linux/string.h> | 
|---|
| 20 |  | 
|---|
| 21 | #include <asm/traps.h> | 
|---|
| 22 | #include <asm/apic.h> | 
|---|
| 23 | #include <asm/mce.h> | 
|---|
| 24 | #include <asm/msr.h> | 
|---|
| 25 | #include <asm/trace/irq_vectors.h> | 
|---|
| 26 |  | 
|---|
| 27 | #include "internal.h" | 
|---|
| 28 |  | 
|---|
| 29 | #define NR_BLOCKS         5 | 
|---|
| 30 | #define THRESHOLD_MAX     0xFFF | 
|---|
| 31 | #define INT_TYPE_APIC     0x00020000 | 
|---|
| 32 | #define MASK_VALID_HI     0x80000000 | 
|---|
| 33 | #define MASK_CNTP_HI      0x40000000 | 
|---|
| 34 | #define MASK_LOCKED_HI    0x20000000 | 
|---|
| 35 | #define MASK_LVTOFF_HI    0x00F00000 | 
|---|
| 36 | #define MASK_COUNT_EN_HI  0x00080000 | 
|---|
| 37 | #define MASK_INT_TYPE_HI  0x00060000 | 
|---|
| 38 | #define MASK_OVERFLOW_HI  0x00010000 | 
|---|
| 39 | #define MASK_ERR_COUNT_HI 0x00000FFF | 
|---|
| 40 | #define MASK_BLKPTR_LO    0xFF000000 | 
|---|
| 41 | #define MCG_XBLK_ADDR     0xC0000400 | 
|---|
| 42 |  | 
|---|
| 43 | /* Deferred error settings */ | 
|---|
| 44 | #define MSR_CU_DEF_ERR		0xC0000410 | 
|---|
| 45 | #define MASK_DEF_LVTOFF		0x000000F0 | 
|---|
| 46 | #define MASK_DEF_INT_TYPE	0x00000006 | 
|---|
| 47 | #define DEF_LVT_OFF		0x2 | 
|---|
| 48 | #define DEF_INT_TYPE_APIC	0x2 | 
|---|
| 49 |  | 
|---|
| 50 | /* Scalable MCA: */ | 
|---|
| 51 |  | 
|---|
| 52 | /* Threshold LVT offset is at MSR0xC0000410[15:12] */ | 
|---|
| 53 | #define SMCA_THR_LVT_OFF	0xF000 | 
|---|
| 54 |  | 
|---|
| 55 | static bool thresholding_irq_en; | 
|---|
| 56 |  | 
|---|
| 57 | static const char * const th_names[] = { | 
|---|
| 58 | "load_store", | 
|---|
| 59 | "insn_fetch", | 
|---|
| 60 | "combined_unit", | 
|---|
| 61 | "decode_unit", | 
|---|
| 62 | "northbridge", | 
|---|
| 63 | "execution_unit", | 
|---|
| 64 | }; | 
|---|
| 65 |  | 
|---|
| 66 | static const char * const smca_umc_block_names[] = { | 
|---|
| 67 | "dram_ecc", | 
|---|
| 68 | "misc_umc" | 
|---|
| 69 | }; | 
|---|
| 70 |  | 
|---|
| 71 | #define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype)) | 
|---|
| 72 |  | 
|---|
| 73 | struct smca_hwid { | 
|---|
| 74 | unsigned int bank_type;	/* Use with smca_bank_types for easy indexing. */ | 
|---|
| 75 | u32 hwid_mcatype;	/* (hwid,mcatype) tuple */ | 
|---|
| 76 | }; | 
|---|
| 77 |  | 
|---|
| 78 | struct smca_bank { | 
|---|
| 79 | const struct smca_hwid *hwid; | 
|---|
| 80 | u32 id;			/* Value of MCA_IPID[InstanceId]. */ | 
|---|
| 81 | u8 sysfs_id;		/* Value used for sysfs name. */ | 
|---|
| 82 | }; | 
|---|
| 83 |  | 
|---|
| 84 | static DEFINE_PER_CPU_READ_MOSTLY(struct smca_bank[MAX_NR_BANKS], smca_banks); | 
|---|
| 85 | static DEFINE_PER_CPU_READ_MOSTLY(u8[N_SMCA_BANK_TYPES], smca_bank_counts); | 
|---|
| 86 |  | 
|---|
| 87 | static const char * const smca_names[] = { | 
|---|
| 88 | [SMCA_LS ... SMCA_LS_V2]	= "load_store", | 
|---|
| 89 | [SMCA_IF]			= "insn_fetch", | 
|---|
| 90 | [SMCA_L2_CACHE]			= "l2_cache", | 
|---|
| 91 | [SMCA_DE]			= "decode_unit", | 
|---|
| 92 | [SMCA_RESERVED]			= "reserved", | 
|---|
| 93 | [SMCA_EX]			= "execution_unit", | 
|---|
| 94 | [SMCA_FP]			= "floating_point", | 
|---|
| 95 | [SMCA_L3_CACHE]			= "l3_cache", | 
|---|
| 96 | [SMCA_CS ... SMCA_CS_V2]	= "coherent_slave", | 
|---|
| 97 | [SMCA_PIE]			= "pie", | 
|---|
| 98 |  | 
|---|
| 99 | /* UMC v2 is separate because both of them can exist in a single system. */ | 
|---|
| 100 | [SMCA_UMC]			= "umc", | 
|---|
| 101 | [SMCA_UMC_V2]			= "umc_v2", | 
|---|
| 102 | [SMCA_MA_LLC]			= "ma_llc", | 
|---|
| 103 | [SMCA_PB]			= "param_block", | 
|---|
| 104 | [SMCA_PSP ... SMCA_PSP_V2]	= "psp", | 
|---|
| 105 | [SMCA_SMU ... SMCA_SMU_V2]	= "smu", | 
|---|
| 106 | [SMCA_MP5]			= "mp5", | 
|---|
| 107 | [SMCA_MPDMA]			= "mpdma", | 
|---|
| 108 | [SMCA_NBIO]			= "nbio", | 
|---|
| 109 | [SMCA_PCIE ... SMCA_PCIE_V2]	= "pcie", | 
|---|
| 110 | [SMCA_XGMI_PCS]			= "xgmi_pcs", | 
|---|
| 111 | [SMCA_NBIF]			= "nbif", | 
|---|
| 112 | [SMCA_SHUB]			= "shub", | 
|---|
| 113 | [SMCA_SATA]			= "sata", | 
|---|
| 114 | [SMCA_USB]			= "usb", | 
|---|
| 115 | [SMCA_USR_DP]			= "usr_dp", | 
|---|
| 116 | [SMCA_USR_CP]			= "usr_cp", | 
|---|
| 117 | [SMCA_GMI_PCS]			= "gmi_pcs", | 
|---|
| 118 | [SMCA_XGMI_PHY]			= "xgmi_phy", | 
|---|
| 119 | [SMCA_WAFL_PHY]			= "wafl_phy", | 
|---|
| 120 | [SMCA_GMI_PHY]			= "gmi_phy", | 
|---|
| 121 | }; | 
|---|
| 122 |  | 
|---|
| 123 | static const char *smca_get_name(enum smca_bank_types t) | 
|---|
| 124 | { | 
|---|
| 125 | if (t >= N_SMCA_BANK_TYPES) | 
|---|
| 126 | return NULL; | 
|---|
| 127 |  | 
|---|
| 128 | return smca_names[t]; | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | enum smca_bank_types smca_get_bank_type(unsigned int cpu, unsigned int bank) | 
|---|
| 132 | { | 
|---|
| 133 | struct smca_bank *b; | 
|---|
| 134 |  | 
|---|
| 135 | if (bank >= MAX_NR_BANKS) | 
|---|
| 136 | return N_SMCA_BANK_TYPES; | 
|---|
| 137 |  | 
|---|
| 138 | b = &per_cpu(smca_banks, cpu)[bank]; | 
|---|
| 139 | if (!b->hwid) | 
|---|
| 140 | return N_SMCA_BANK_TYPES; | 
|---|
| 141 |  | 
|---|
| 142 | return b->hwid->bank_type; | 
|---|
| 143 | } | 
|---|
| 144 | EXPORT_SYMBOL_GPL(smca_get_bank_type); | 
|---|
| 145 |  | 
|---|
| 146 | static const struct smca_hwid smca_hwid_mcatypes[] = { | 
|---|
| 147 | /* { bank_type, hwid_mcatype } */ | 
|---|
| 148 |  | 
|---|
| 149 | /* Reserved type */ | 
|---|
| 150 | { SMCA_RESERVED, HWID_MCATYPE(0x00, 0x0)	}, | 
|---|
| 151 |  | 
|---|
| 152 | /* ZN Core (HWID=0xB0) MCA types */ | 
|---|
| 153 | { SMCA_LS,	 HWID_MCATYPE(0xB0, 0x0)	}, | 
|---|
| 154 | { SMCA_LS_V2,	 HWID_MCATYPE(0xB0, 0x10)	}, | 
|---|
| 155 | { SMCA_IF,	 HWID_MCATYPE(0xB0, 0x1)	}, | 
|---|
| 156 | { SMCA_L2_CACHE, HWID_MCATYPE(0xB0, 0x2)	}, | 
|---|
| 157 | { SMCA_DE,	 HWID_MCATYPE(0xB0, 0x3)	}, | 
|---|
| 158 | /* HWID 0xB0 MCATYPE 0x4 is Reserved */ | 
|---|
| 159 | { SMCA_EX,	 HWID_MCATYPE(0xB0, 0x5)	}, | 
|---|
| 160 | { SMCA_FP,	 HWID_MCATYPE(0xB0, 0x6)	}, | 
|---|
| 161 | { SMCA_L3_CACHE, HWID_MCATYPE(0xB0, 0x7)	}, | 
|---|
| 162 |  | 
|---|
| 163 | /* Data Fabric MCA types */ | 
|---|
| 164 | { SMCA_CS,	 HWID_MCATYPE(0x2E, 0x0)	}, | 
|---|
| 165 | { SMCA_PIE,	 HWID_MCATYPE(0x2E, 0x1)	}, | 
|---|
| 166 | { SMCA_CS_V2,	 HWID_MCATYPE(0x2E, 0x2)	}, | 
|---|
| 167 | { SMCA_MA_LLC,	 HWID_MCATYPE(0x2E, 0x4)	}, | 
|---|
| 168 |  | 
|---|
| 169 | /* Unified Memory Controller MCA type */ | 
|---|
| 170 | { SMCA_UMC,	 HWID_MCATYPE(0x96, 0x0)	}, | 
|---|
| 171 | { SMCA_UMC_V2,	 HWID_MCATYPE(0x96, 0x1)	}, | 
|---|
| 172 |  | 
|---|
| 173 | /* Parameter Block MCA type */ | 
|---|
| 174 | { SMCA_PB,	 HWID_MCATYPE(0x05, 0x0)	}, | 
|---|
| 175 |  | 
|---|
| 176 | /* Platform Security Processor MCA type */ | 
|---|
| 177 | { SMCA_PSP,	 HWID_MCATYPE(0xFF, 0x0)	}, | 
|---|
| 178 | { SMCA_PSP_V2,	 HWID_MCATYPE(0xFF, 0x1)	}, | 
|---|
| 179 |  | 
|---|
| 180 | /* System Management Unit MCA type */ | 
|---|
| 181 | { SMCA_SMU,	 HWID_MCATYPE(0x01, 0x0)	}, | 
|---|
| 182 | { SMCA_SMU_V2,	 HWID_MCATYPE(0x01, 0x1)	}, | 
|---|
| 183 |  | 
|---|
| 184 | /* Microprocessor 5 Unit MCA type */ | 
|---|
| 185 | { SMCA_MP5,	 HWID_MCATYPE(0x01, 0x2)	}, | 
|---|
| 186 |  | 
|---|
| 187 | /* MPDMA MCA type */ | 
|---|
| 188 | { SMCA_MPDMA,	 HWID_MCATYPE(0x01, 0x3)	}, | 
|---|
| 189 |  | 
|---|
| 190 | /* Northbridge IO Unit MCA type */ | 
|---|
| 191 | { SMCA_NBIO,	 HWID_MCATYPE(0x18, 0x0)	}, | 
|---|
| 192 |  | 
|---|
| 193 | /* PCI Express Unit MCA type */ | 
|---|
| 194 | { SMCA_PCIE,	 HWID_MCATYPE(0x46, 0x0)	}, | 
|---|
| 195 | { SMCA_PCIE_V2,	 HWID_MCATYPE(0x46, 0x1)	}, | 
|---|
| 196 |  | 
|---|
| 197 | { SMCA_XGMI_PCS, HWID_MCATYPE(0x50, 0x0)	}, | 
|---|
| 198 | { SMCA_NBIF,	 HWID_MCATYPE(0x6C, 0x0)	}, | 
|---|
| 199 | { SMCA_SHUB,	 HWID_MCATYPE(0x80, 0x0)	}, | 
|---|
| 200 | { SMCA_SATA,	 HWID_MCATYPE(0xA8, 0x0)	}, | 
|---|
| 201 | { SMCA_USB,	 HWID_MCATYPE(0xAA, 0x0)	}, | 
|---|
| 202 | { SMCA_USR_DP,	 HWID_MCATYPE(0x170, 0x0)	}, | 
|---|
| 203 | { SMCA_USR_CP,	 HWID_MCATYPE(0x180, 0x0)	}, | 
|---|
| 204 | { SMCA_GMI_PCS,  HWID_MCATYPE(0x241, 0x0)	}, | 
|---|
| 205 | { SMCA_XGMI_PHY, HWID_MCATYPE(0x259, 0x0)	}, | 
|---|
| 206 | { SMCA_WAFL_PHY, HWID_MCATYPE(0x267, 0x0)	}, | 
|---|
| 207 | { SMCA_GMI_PHY,	 HWID_MCATYPE(0x269, 0x0)	}, | 
|---|
| 208 | }; | 
|---|
| 209 |  | 
|---|
| 210 | /* | 
|---|
| 211 | * In SMCA enabled processors, we can have multiple banks for a given IP type. | 
|---|
| 212 | * So to define a unique name for each bank, we use a temp c-string to append | 
|---|
| 213 | * the MCA_IPID[InstanceId] to type's name in get_name(). | 
|---|
| 214 | * | 
|---|
| 215 | * InstanceId is 32 bits which is 8 characters. Make sure MAX_MCATYPE_NAME_LEN | 
|---|
| 216 | * is greater than 8 plus 1 (for underscore) plus length of longest type name. | 
|---|
| 217 | */ | 
|---|
| 218 | #define MAX_MCATYPE_NAME_LEN	30 | 
|---|
| 219 | static char buf_mcatype[MAX_MCATYPE_NAME_LEN]; | 
|---|
| 220 |  | 
|---|
| 221 | struct threshold_block { | 
|---|
| 222 | /* This block's number within its bank. */ | 
|---|
| 223 | unsigned int		block; | 
|---|
| 224 | /* MCA bank number that contains this block. */ | 
|---|
| 225 | unsigned int		bank; | 
|---|
| 226 | /* CPU which controls this block's MCA bank. */ | 
|---|
| 227 | unsigned int		cpu; | 
|---|
| 228 | /* MCA_MISC MSR address for this block. */ | 
|---|
| 229 | u32			address; | 
|---|
| 230 | /* Enable/Disable APIC interrupt. */ | 
|---|
| 231 | bool			interrupt_enable; | 
|---|
| 232 | /* Bank can generate an interrupt. */ | 
|---|
| 233 | bool			interrupt_capable; | 
|---|
| 234 | /* Value upon which threshold interrupt is generated. */ | 
|---|
| 235 | u16			threshold_limit; | 
|---|
| 236 | /* sysfs object */ | 
|---|
| 237 | struct kobject		kobj; | 
|---|
| 238 | /* List of threshold blocks within this block's MCA bank. */ | 
|---|
| 239 | struct list_head	miscj; | 
|---|
| 240 | }; | 
|---|
| 241 |  | 
|---|
| 242 | struct threshold_bank { | 
|---|
| 243 | struct kobject		*kobj; | 
|---|
| 244 | /* List of threshold blocks within this MCA bank. */ | 
|---|
| 245 | struct list_head	miscj; | 
|---|
| 246 | }; | 
|---|
| 247 |  | 
|---|
| 248 | static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks); | 
|---|
| 249 |  | 
|---|
| 250 | /* | 
|---|
| 251 | * A list of the banks enabled on each logical CPU. Controls which respective | 
|---|
| 252 | * descriptors to initialize later in mce_threshold_create_device(). | 
|---|
| 253 | */ | 
|---|
| 254 | static DEFINE_PER_CPU(u64, bank_map); | 
|---|
| 255 |  | 
|---|
| 256 | static void amd_threshold_interrupt(void); | 
|---|
| 257 | static void amd_deferred_error_interrupt(void); | 
|---|
| 258 |  | 
|---|
| 259 | static void default_deferred_error_interrupt(void) | 
|---|
| 260 | { | 
|---|
| 261 | pr_err( "Unexpected deferred interrupt at vector %x\n", DEFERRED_ERROR_VECTOR); | 
|---|
| 262 | } | 
|---|
| 263 | void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt; | 
|---|
| 264 |  | 
|---|
| 265 | static void smca_configure(unsigned int bank, unsigned int cpu) | 
|---|
| 266 | { | 
|---|
| 267 | u8 *bank_counts = this_cpu_ptr(smca_bank_counts); | 
|---|
| 268 | const struct smca_hwid *s_hwid; | 
|---|
| 269 | unsigned int i, hwid_mcatype; | 
|---|
| 270 | u32 high, low; | 
|---|
| 271 | u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank); | 
|---|
| 272 |  | 
|---|
| 273 | /* Set appropriate bits in MCA_CONFIG */ | 
|---|
| 274 | if (!rdmsr_safe(smca_config, &low, &high)) { | 
|---|
| 275 | /* | 
|---|
| 276 | * OS is required to set the MCAX bit to acknowledge that it is | 
|---|
| 277 | * now using the new MSR ranges and new registers under each | 
|---|
| 278 | * bank. It also means that the OS will configure deferred | 
|---|
| 279 | * errors in the new MCx_CONFIG register. If the bit is not set, | 
|---|
| 280 | * uncorrectable errors will cause a system panic. | 
|---|
| 281 | * | 
|---|
| 282 | * MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.) | 
|---|
| 283 | */ | 
|---|
| 284 | high |= BIT(0); | 
|---|
| 285 |  | 
|---|
| 286 | /* | 
|---|
| 287 | * SMCA sets the Deferred Error Interrupt type per bank. | 
|---|
| 288 | * | 
|---|
| 289 | * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us | 
|---|
| 290 | * if the DeferredIntType bit field is available. | 
|---|
| 291 | * | 
|---|
| 292 | * MCA_CONFIG[DeferredIntType] is bits [38:37] ([6:5] in the | 
|---|
| 293 | * high portion of the MSR). OS should set this to 0x1 to enable | 
|---|
| 294 | * APIC based interrupt. First, check that no interrupt has been | 
|---|
| 295 | * set. | 
|---|
| 296 | */ | 
|---|
| 297 | if ((low & BIT(5)) && !((high >> 5) & 0x3)) | 
|---|
| 298 | high |= BIT(5); | 
|---|
| 299 |  | 
|---|
| 300 | this_cpu_ptr(mce_banks_array)[bank].lsb_in_status = !!(low & BIT(8)); | 
|---|
| 301 |  | 
|---|
| 302 | wrmsr(msr: smca_config, low, high); | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) { | 
|---|
| 306 | pr_warn( "Failed to read MCA_IPID for bank %d\n", bank); | 
|---|
| 307 | return; | 
|---|
| 308 | } | 
|---|
| 309 |  | 
|---|
| 310 | hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID, | 
|---|
| 311 | (high & MCI_IPID_MCATYPE) >> 16); | 
|---|
| 312 |  | 
|---|
| 313 | for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) { | 
|---|
| 314 | s_hwid = &smca_hwid_mcatypes[i]; | 
|---|
| 315 |  | 
|---|
| 316 | if (hwid_mcatype == s_hwid->hwid_mcatype) { | 
|---|
| 317 | this_cpu_ptr(smca_banks)[bank].hwid = s_hwid; | 
|---|
| 318 | this_cpu_ptr(smca_banks)[bank].id = low; | 
|---|
| 319 | this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++; | 
|---|
| 320 | break; | 
|---|
| 321 | } | 
|---|
| 322 | } | 
|---|
| 323 | } | 
|---|
| 324 |  | 
|---|
| 325 | struct thresh_restart { | 
|---|
| 326 | struct threshold_block	*b; | 
|---|
| 327 | int			set_lvt_off; | 
|---|
| 328 | int			lvt_off; | 
|---|
| 329 | u16			old_limit; | 
|---|
| 330 | }; | 
|---|
| 331 |  | 
|---|
| 332 | static const char *bank4_names(const struct threshold_block *b) | 
|---|
| 333 | { | 
|---|
| 334 | switch (b->address) { | 
|---|
| 335 | /* MSR4_MISC0 */ | 
|---|
| 336 | case 0x00000413: | 
|---|
| 337 | return "dram"; | 
|---|
| 338 |  | 
|---|
| 339 | case 0xc0000408: | 
|---|
| 340 | return "ht_links"; | 
|---|
| 341 |  | 
|---|
| 342 | case 0xc0000409: | 
|---|
| 343 | return "l3_cache"; | 
|---|
| 344 |  | 
|---|
| 345 | default: | 
|---|
| 346 | WARN(1, "Funny MSR: 0x%08x\n", b->address); | 
|---|
| 347 | return ""; | 
|---|
| 348 | } | 
|---|
| 349 | }; | 
|---|
| 350 |  | 
|---|
| 351 |  | 
|---|
| 352 | static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits) | 
|---|
| 353 | { | 
|---|
| 354 | /* | 
|---|
| 355 | * bank 4 supports APIC LVT interrupts implicitly since forever. | 
|---|
| 356 | */ | 
|---|
| 357 | if (bank == 4) | 
|---|
| 358 | return true; | 
|---|
| 359 |  | 
|---|
| 360 | /* | 
|---|
| 361 | * IntP: interrupt present; if this bit is set, the thresholding | 
|---|
| 362 | * bank can generate APIC LVT interrupts | 
|---|
| 363 | */ | 
|---|
| 364 | return msr_high_bits & BIT(28); | 
|---|
| 365 | } | 
|---|
| 366 |  | 
|---|
| 367 | static bool lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) | 
|---|
| 368 | { | 
|---|
| 369 | int msr = (hi & MASK_LVTOFF_HI) >> 20; | 
|---|
| 370 |  | 
|---|
| 371 | if (apic < 0) { | 
|---|
| 372 | pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt " | 
|---|
| 373 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, | 
|---|
| 374 | b->bank, b->block, b->address, hi, lo); | 
|---|
| 375 | return false; | 
|---|
| 376 | } | 
|---|
| 377 |  | 
|---|
| 378 | if (apic != msr) { | 
|---|
| 379 | /* | 
|---|
| 380 | * On SMCA CPUs, LVT offset is programmed at a different MSR, and | 
|---|
| 381 | * the BIOS provides the value. The original field where LVT offset | 
|---|
| 382 | * was set is reserved. Return early here: | 
|---|
| 383 | */ | 
|---|
| 384 | if (mce_flags.smca) | 
|---|
| 385 | return false; | 
|---|
| 386 |  | 
|---|
| 387 | pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " | 
|---|
| 388 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", | 
|---|
| 389 | b->cpu, apic, b->bank, b->block, b->address, hi, lo); | 
|---|
| 390 | return false; | 
|---|
| 391 | } | 
|---|
| 392 |  | 
|---|
| 393 | return true; | 
|---|
| 394 | }; | 
|---|
| 395 |  | 
|---|
| 396 | /* Reprogram MCx_MISC MSR behind this threshold block. */ | 
|---|
| 397 | static void threshold_restart_block(void *_tr) | 
|---|
| 398 | { | 
|---|
| 399 | struct thresh_restart *tr = _tr; | 
|---|
| 400 | u32 hi, lo; | 
|---|
| 401 |  | 
|---|
| 402 | /* sysfs write might race against an offline operation */ | 
|---|
| 403 | if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off) | 
|---|
| 404 | return; | 
|---|
| 405 |  | 
|---|
| 406 | rdmsr(tr->b->address, lo, hi); | 
|---|
| 407 |  | 
|---|
| 408 | /* | 
|---|
| 409 | * Reset error count and overflow bit. | 
|---|
| 410 | * This is done during init or after handling an interrupt. | 
|---|
| 411 | */ | 
|---|
| 412 | if (hi & MASK_OVERFLOW_HI || tr->set_lvt_off) { | 
|---|
| 413 | hi &= ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI); | 
|---|
| 414 | hi |= THRESHOLD_MAX - tr->b->threshold_limit; | 
|---|
| 415 | } else if (tr->old_limit) {	/* change limit w/o reset */ | 
|---|
| 416 | int new_count = (hi & THRESHOLD_MAX) + | 
|---|
| 417 | (tr->old_limit - tr->b->threshold_limit); | 
|---|
| 418 |  | 
|---|
| 419 | hi = (hi & ~MASK_ERR_COUNT_HI) | | 
|---|
| 420 | (new_count & THRESHOLD_MAX); | 
|---|
| 421 | } | 
|---|
| 422 |  | 
|---|
| 423 | /* clear IntType */ | 
|---|
| 424 | hi &= ~MASK_INT_TYPE_HI; | 
|---|
| 425 |  | 
|---|
| 426 | if (!tr->b->interrupt_capable) | 
|---|
| 427 | goto done; | 
|---|
| 428 |  | 
|---|
| 429 | if (tr->set_lvt_off) { | 
|---|
| 430 | if (lvt_off_valid(b: tr->b, apic: tr->lvt_off, lo, hi)) { | 
|---|
| 431 | /* set new lvt offset */ | 
|---|
| 432 | hi &= ~MASK_LVTOFF_HI; | 
|---|
| 433 | hi |= tr->lvt_off << 20; | 
|---|
| 434 | } | 
|---|
| 435 | } | 
|---|
| 436 |  | 
|---|
| 437 | if (tr->b->interrupt_enable) | 
|---|
| 438 | hi |= INT_TYPE_APIC; | 
|---|
| 439 |  | 
|---|
| 440 | done: | 
|---|
| 441 |  | 
|---|
| 442 | hi |= MASK_COUNT_EN_HI; | 
|---|
| 443 | wrmsr(msr: tr->b->address, low: lo, high: hi); | 
|---|
| 444 | } | 
|---|
| 445 |  | 
|---|
| 446 | static void mce_threshold_block_init(struct threshold_block *b, int offset) | 
|---|
| 447 | { | 
|---|
| 448 | struct thresh_restart tr = { | 
|---|
| 449 | .b			= b, | 
|---|
| 450 | .set_lvt_off		= 1, | 
|---|
| 451 | .lvt_off		= offset, | 
|---|
| 452 | }; | 
|---|
| 453 |  | 
|---|
| 454 | b->threshold_limit		= THRESHOLD_MAX; | 
|---|
| 455 | threshold_restart_block(tr: &tr); | 
|---|
| 456 | }; | 
|---|
| 457 |  | 
|---|
| 458 | static int setup_APIC_mce_threshold(int reserved, int new) | 
|---|
| 459 | { | 
|---|
| 460 | if (reserved < 0 && !setup_APIC_eilvt(lvt_off: new, THRESHOLD_APIC_VECTOR, | 
|---|
| 461 | APIC_EILVT_MSG_FIX, mask: 0)) | 
|---|
| 462 | return new; | 
|---|
| 463 |  | 
|---|
| 464 | return reserved; | 
|---|
| 465 | } | 
|---|
| 466 |  | 
|---|
| 467 | static int setup_APIC_deferred_error(int reserved, int new) | 
|---|
| 468 | { | 
|---|
| 469 | if (reserved < 0 && !setup_APIC_eilvt(lvt_off: new, DEFERRED_ERROR_VECTOR, | 
|---|
| 470 | APIC_EILVT_MSG_FIX, mask: 0)) | 
|---|
| 471 | return new; | 
|---|
| 472 |  | 
|---|
| 473 | return reserved; | 
|---|
| 474 | } | 
|---|
| 475 |  | 
|---|
| 476 | static void deferred_error_interrupt_enable(struct cpuinfo_x86 *c) | 
|---|
| 477 | { | 
|---|
| 478 | u32 low = 0, high = 0; | 
|---|
| 479 | int def_offset = -1, def_new; | 
|---|
| 480 |  | 
|---|
| 481 | if (rdmsr_safe(MSR_CU_DEF_ERR, &low, &high)) | 
|---|
| 482 | return; | 
|---|
| 483 |  | 
|---|
| 484 | def_new = (low & MASK_DEF_LVTOFF) >> 4; | 
|---|
| 485 | if (!(low & MASK_DEF_LVTOFF)) { | 
|---|
| 486 | pr_err(FW_BUG "Your BIOS is not setting up LVT offset 0x2 for deferred error IRQs correctly.\n"); | 
|---|
| 487 | def_new = DEF_LVT_OFF; | 
|---|
| 488 | low = (low & ~MASK_DEF_LVTOFF) | (DEF_LVT_OFF << 4); | 
|---|
| 489 | } | 
|---|
| 490 |  | 
|---|
| 491 | def_offset = setup_APIC_deferred_error(reserved: def_offset, new: def_new); | 
|---|
| 492 | if ((def_offset == def_new) && | 
|---|
| 493 | (deferred_error_int_vector != amd_deferred_error_interrupt)) | 
|---|
| 494 | deferred_error_int_vector = amd_deferred_error_interrupt; | 
|---|
| 495 |  | 
|---|
| 496 | if (!mce_flags.smca) | 
|---|
| 497 | low = (low & ~MASK_DEF_INT_TYPE) | DEF_INT_TYPE_APIC; | 
|---|
| 498 |  | 
|---|
| 499 | wrmsr(MSR_CU_DEF_ERR, low, high); | 
|---|
| 500 | } | 
|---|
| 501 |  | 
|---|
| 502 | static u32 get_block_address(u32 current_addr, u32 low, u32 high, | 
|---|
| 503 | unsigned int bank, unsigned int block, | 
|---|
| 504 | unsigned int cpu) | 
|---|
| 505 | { | 
|---|
| 506 | u32 addr = 0, offset = 0; | 
|---|
| 507 |  | 
|---|
| 508 | if ((bank >= per_cpu(mce_num_banks, cpu)) || (block >= NR_BLOCKS)) | 
|---|
| 509 | return addr; | 
|---|
| 510 |  | 
|---|
| 511 | if (mce_flags.smca) { | 
|---|
| 512 | if (!block) | 
|---|
| 513 | return MSR_AMD64_SMCA_MCx_MISC(bank); | 
|---|
| 514 |  | 
|---|
| 515 | if (!(low & MASK_BLKPTR_LO)) | 
|---|
| 516 | return 0; | 
|---|
| 517 |  | 
|---|
| 518 | return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1); | 
|---|
| 519 | } | 
|---|
| 520 |  | 
|---|
| 521 | /* Fall back to method we used for older processors: */ | 
|---|
| 522 | switch (block) { | 
|---|
| 523 | case 0: | 
|---|
| 524 | addr = mca_msr_reg(bank, reg: MCA_MISC); | 
|---|
| 525 | break; | 
|---|
| 526 | case 1: | 
|---|
| 527 | offset = ((low & MASK_BLKPTR_LO) >> 21); | 
|---|
| 528 | if (offset) | 
|---|
| 529 | addr = MCG_XBLK_ADDR + offset; | 
|---|
| 530 | break; | 
|---|
| 531 | default: | 
|---|
| 532 | addr = ++current_addr; | 
|---|
| 533 | } | 
|---|
| 534 | return addr; | 
|---|
| 535 | } | 
|---|
| 536 |  | 
|---|
| 537 | static int | 
|---|
| 538 | prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, | 
|---|
| 539 | int offset, u32 misc_high) | 
|---|
| 540 | { | 
|---|
| 541 | unsigned int cpu = smp_processor_id(); | 
|---|
| 542 | u32 smca_low, smca_high; | 
|---|
| 543 | struct threshold_block b; | 
|---|
| 544 | int new; | 
|---|
| 545 |  | 
|---|
| 546 | if (!block) | 
|---|
| 547 | per_cpu(bank_map, cpu) |= BIT_ULL(bank); | 
|---|
| 548 |  | 
|---|
| 549 | memset(s: &b, c: 0, n: sizeof(b)); | 
|---|
| 550 | b.cpu			= cpu; | 
|---|
| 551 | b.bank			= bank; | 
|---|
| 552 | b.block			= block; | 
|---|
| 553 | b.address		= addr; | 
|---|
| 554 | b.interrupt_capable	= lvt_interrupt_supported(bank, msr_high_bits: misc_high); | 
|---|
| 555 |  | 
|---|
| 556 | if (!b.interrupt_capable) | 
|---|
| 557 | goto done; | 
|---|
| 558 |  | 
|---|
| 559 | b.interrupt_enable = 1; | 
|---|
| 560 |  | 
|---|
| 561 | if (!mce_flags.smca) { | 
|---|
| 562 | new = (misc_high & MASK_LVTOFF_HI) >> 20; | 
|---|
| 563 | goto set_offset; | 
|---|
| 564 | } | 
|---|
| 565 |  | 
|---|
| 566 | /* Gather LVT offset for thresholding: */ | 
|---|
| 567 | if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high)) | 
|---|
| 568 | goto out; | 
|---|
| 569 |  | 
|---|
| 570 | new = (smca_low & SMCA_THR_LVT_OFF) >> 12; | 
|---|
| 571 |  | 
|---|
| 572 | set_offset: | 
|---|
| 573 | offset = setup_APIC_mce_threshold(reserved: offset, new); | 
|---|
| 574 | if (offset == new) | 
|---|
| 575 | thresholding_irq_en = true; | 
|---|
| 576 |  | 
|---|
| 577 | done: | 
|---|
| 578 | mce_threshold_block_init(b: &b, offset); | 
|---|
| 579 |  | 
|---|
| 580 | out: | 
|---|
| 581 | return offset; | 
|---|
| 582 | } | 
|---|
| 583 |  | 
|---|
| 584 | bool amd_filter_mce(struct mce *m) | 
|---|
| 585 | { | 
|---|
| 586 | enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank); | 
|---|
| 587 | struct cpuinfo_x86 *c = &boot_cpu_data; | 
|---|
| 588 |  | 
|---|
| 589 | /* See Family 17h Models 10h-2Fh Erratum #1114. */ | 
|---|
| 590 | if (c->x86 == 0x17 && | 
|---|
| 591 | c->x86_model >= 0x10 && c->x86_model <= 0x2F && | 
|---|
| 592 | bank_type == SMCA_IF && XEC(m->status, 0x3f) == 10) | 
|---|
| 593 | return true; | 
|---|
| 594 |  | 
|---|
| 595 | /* NB GART TLB error reporting is disabled by default. */ | 
|---|
| 596 | if (c->x86 < 0x17) { | 
|---|
| 597 | if (m->bank == 4 && XEC(m->status, 0x1f) == 0x5) | 
|---|
| 598 | return true; | 
|---|
| 599 | } | 
|---|
| 600 |  | 
|---|
| 601 | return false; | 
|---|
| 602 | } | 
|---|
| 603 |  | 
|---|
| 604 | /* | 
|---|
| 605 | * Turn off thresholding banks for the following conditions: | 
|---|
| 606 | * - MC4_MISC thresholding is not supported on Family 0x15. | 
|---|
| 607 | * - Prevent possible spurious interrupts from the IF bank on Family 0x17 | 
|---|
| 608 | *   Models 0x10-0x2F due to Erratum #1114. | 
|---|
| 609 | */ | 
|---|
| 610 | static void disable_err_thresholding(struct cpuinfo_x86 *c, unsigned int bank) | 
|---|
| 611 | { | 
|---|
| 612 | int i, num_msrs; | 
|---|
| 613 | u64 hwcr; | 
|---|
| 614 | bool need_toggle; | 
|---|
| 615 | u32 msrs[NR_BLOCKS]; | 
|---|
| 616 |  | 
|---|
| 617 | if (c->x86 == 0x15 && bank == 4) { | 
|---|
| 618 | msrs[0] = 0x00000413; /* MC4_MISC0 */ | 
|---|
| 619 | msrs[1] = 0xc0000408; /* MC4_MISC1 */ | 
|---|
| 620 | num_msrs = 2; | 
|---|
| 621 | } else if (c->x86 == 0x17 && | 
|---|
| 622 | (c->x86_model >= 0x10 && c->x86_model <= 0x2F)) { | 
|---|
| 623 |  | 
|---|
| 624 | if (smca_get_bank_type(smp_processor_id(), bank) != SMCA_IF) | 
|---|
| 625 | return; | 
|---|
| 626 |  | 
|---|
| 627 | msrs[0] = MSR_AMD64_SMCA_MCx_MISC(bank); | 
|---|
| 628 | num_msrs = 1; | 
|---|
| 629 | } else { | 
|---|
| 630 | return; | 
|---|
| 631 | } | 
|---|
| 632 |  | 
|---|
| 633 | rdmsrq(MSR_K7_HWCR, hwcr); | 
|---|
| 634 |  | 
|---|
| 635 | /* McStatusWrEn has to be set */ | 
|---|
| 636 | need_toggle = !(hwcr & BIT(18)); | 
|---|
| 637 | if (need_toggle) | 
|---|
| 638 | wrmsrq(MSR_K7_HWCR, val: hwcr | BIT(18)); | 
|---|
| 639 |  | 
|---|
| 640 | /* Clear CntP bit safely */ | 
|---|
| 641 | for (i = 0; i < num_msrs; i++) | 
|---|
| 642 | msr_clear_bit(msr: msrs[i], bit: 62); | 
|---|
| 643 |  | 
|---|
| 644 | /* restore old settings */ | 
|---|
| 645 | if (need_toggle) | 
|---|
| 646 | wrmsrq(MSR_K7_HWCR, val: hwcr); | 
|---|
| 647 | } | 
|---|
| 648 |  | 
|---|
| 649 | static void amd_apply_cpu_quirks(struct cpuinfo_x86 *c) | 
|---|
| 650 | { | 
|---|
| 651 | struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array); | 
|---|
| 652 |  | 
|---|
| 653 | /* This should be disabled by the BIOS, but isn't always */ | 
|---|
| 654 | if (c->x86 == 15 && this_cpu_read(mce_num_banks) > 4) { | 
|---|
| 655 | /* | 
|---|
| 656 | * disable GART TBL walk error reporting, which | 
|---|
| 657 | * trips off incorrectly with the IOMMU & 3ware | 
|---|
| 658 | * & Cerberus: | 
|---|
| 659 | */ | 
|---|
| 660 | clear_bit(nr: 10, addr: (unsigned long *)&mce_banks[4].ctl); | 
|---|
| 661 | } | 
|---|
| 662 |  | 
|---|
| 663 | /* | 
|---|
| 664 | * Various K7s with broken bank 0 around. Always disable | 
|---|
| 665 | * by default. | 
|---|
| 666 | */ | 
|---|
| 667 | if (c->x86 == 6 && this_cpu_read(mce_num_banks)) | 
|---|
| 668 | mce_banks[0].ctl = 0; | 
|---|
| 669 | } | 
|---|
| 670 |  | 
|---|
| 671 | /* cpu init entry point, called from mce.c with preempt off */ | 
|---|
| 672 | void mce_amd_feature_init(struct cpuinfo_x86 *c) | 
|---|
| 673 | { | 
|---|
| 674 | unsigned int bank, block, cpu = smp_processor_id(); | 
|---|
| 675 | u32 low = 0, high = 0, address = 0; | 
|---|
| 676 | int offset = -1; | 
|---|
| 677 |  | 
|---|
| 678 | amd_apply_cpu_quirks(c); | 
|---|
| 679 |  | 
|---|
| 680 | mce_flags.amd_threshold	 = 1; | 
|---|
| 681 |  | 
|---|
| 682 | for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) { | 
|---|
| 683 | if (mce_flags.smca) | 
|---|
| 684 | smca_configure(bank, cpu); | 
|---|
| 685 |  | 
|---|
| 686 | disable_err_thresholding(c, bank); | 
|---|
| 687 |  | 
|---|
| 688 | for (block = 0; block < NR_BLOCKS; ++block) { | 
|---|
| 689 | address = get_block_address(current_addr: address, low, high, bank, block, cpu); | 
|---|
| 690 | if (!address) | 
|---|
| 691 | break; | 
|---|
| 692 |  | 
|---|
| 693 | if (rdmsr_safe(address, &low, &high)) | 
|---|
| 694 | break; | 
|---|
| 695 |  | 
|---|
| 696 | if (!(high & MASK_VALID_HI)) | 
|---|
| 697 | continue; | 
|---|
| 698 |  | 
|---|
| 699 | if (!(high & MASK_CNTP_HI)  || | 
|---|
| 700 | (high & MASK_LOCKED_HI)) | 
|---|
| 701 | continue; | 
|---|
| 702 |  | 
|---|
| 703 | offset = prepare_threshold_block(bank, block, addr: address, offset, misc_high: high); | 
|---|
| 704 | } | 
|---|
| 705 | } | 
|---|
| 706 |  | 
|---|
| 707 | if (mce_flags.succor) | 
|---|
| 708 | deferred_error_interrupt_enable(c); | 
|---|
| 709 | } | 
|---|
| 710 |  | 
|---|
| 711 | void smca_bsp_init(void) | 
|---|
| 712 | { | 
|---|
| 713 | mce_threshold_vector	  = amd_threshold_interrupt; | 
|---|
| 714 | deferred_error_int_vector = amd_deferred_error_interrupt; | 
|---|
| 715 | } | 
|---|
| 716 |  | 
|---|
| 717 | /* | 
|---|
| 718 | * DRAM ECC errors are reported in the Northbridge (bank 4) with | 
|---|
| 719 | * Extended Error Code 8. | 
|---|
| 720 | */ | 
|---|
| 721 | static bool legacy_mce_is_memory_error(struct mce *m) | 
|---|
| 722 | { | 
|---|
| 723 | return m->bank == 4 && XEC(m->status, 0x1f) == 8; | 
|---|
| 724 | } | 
|---|
| 725 |  | 
|---|
| 726 | /* | 
|---|
| 727 | * DRAM ECC errors are reported in Unified Memory Controllers with | 
|---|
| 728 | * Extended Error Code 0. | 
|---|
| 729 | */ | 
|---|
| 730 | static bool smca_mce_is_memory_error(struct mce *m) | 
|---|
| 731 | { | 
|---|
| 732 | enum smca_bank_types bank_type; | 
|---|
| 733 |  | 
|---|
| 734 | if (XEC(m->status, 0x3f)) | 
|---|
| 735 | return false; | 
|---|
| 736 |  | 
|---|
| 737 | bank_type = smca_get_bank_type(m->extcpu, m->bank); | 
|---|
| 738 |  | 
|---|
| 739 | return bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2; | 
|---|
| 740 | } | 
|---|
| 741 |  | 
|---|
| 742 | bool amd_mce_is_memory_error(struct mce *m) | 
|---|
| 743 | { | 
|---|
| 744 | if (mce_flags.smca) | 
|---|
| 745 | return smca_mce_is_memory_error(m); | 
|---|
| 746 | else | 
|---|
| 747 | return legacy_mce_is_memory_error(m); | 
|---|
| 748 | } | 
|---|
| 749 |  | 
|---|
| 750 | /* | 
|---|
| 751 | * AMD systems do not have an explicit indicator that the value in MCA_ADDR is | 
|---|
| 752 | * a system physical address. Therefore, individual cases need to be detected. | 
|---|
| 753 | * Future cases and checks will be added as needed. | 
|---|
| 754 | * | 
|---|
| 755 | * 1) General case | 
|---|
| 756 | *	a) Assume address is not usable. | 
|---|
| 757 | * 2) Poison errors | 
|---|
| 758 | *	a) Indicated by MCA_STATUS[43]: poison. Defined for all banks except legacy | 
|---|
| 759 | *	   northbridge (bank 4). | 
|---|
| 760 | *	b) Refers to poison consumption in the core. Does not include "no action", | 
|---|
| 761 | *	   "action optional", or "deferred" error severities. | 
|---|
| 762 | *	c) Will include a usable address so that immediate action can be taken. | 
|---|
| 763 | * 3) Northbridge DRAM ECC errors | 
|---|
| 764 | *	a) Reported in legacy bank 4 with extended error code (XEC) 8. | 
|---|
| 765 | *	b) MCA_STATUS[43] is *not* defined as poison in legacy bank 4. Therefore, | 
|---|
| 766 | *	   this bit should not be checked. | 
|---|
| 767 | * | 
|---|
| 768 | * NOTE: SMCA UMC memory errors fall into case #1. | 
|---|
| 769 | */ | 
|---|
| 770 | bool amd_mce_usable_address(struct mce *m) | 
|---|
| 771 | { | 
|---|
| 772 | /* Check special northbridge case 3) first. */ | 
|---|
| 773 | if (!mce_flags.smca) { | 
|---|
| 774 | if (legacy_mce_is_memory_error(m)) | 
|---|
| 775 | return true; | 
|---|
| 776 | else if (m->bank == 4) | 
|---|
| 777 | return false; | 
|---|
| 778 | } | 
|---|
| 779 |  | 
|---|
| 780 | /* Check poison bit for all other bank types. */ | 
|---|
| 781 | if (m->status & MCI_STATUS_POISON) | 
|---|
| 782 | return true; | 
|---|
| 783 |  | 
|---|
| 784 | /* Assume address is not usable for all others. */ | 
|---|
| 785 | return false; | 
|---|
| 786 | } | 
|---|
| 787 |  | 
|---|
| 788 | static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc) | 
|---|
| 789 | { | 
|---|
| 790 | struct mce_hw_err err; | 
|---|
| 791 | struct mce *m = &err.m; | 
|---|
| 792 |  | 
|---|
| 793 | mce_prep_record(err: &err); | 
|---|
| 794 |  | 
|---|
| 795 | m->status = status; | 
|---|
| 796 | m->misc   = misc; | 
|---|
| 797 | m->bank   = bank; | 
|---|
| 798 | m->tsc	 = rdtsc(); | 
|---|
| 799 |  | 
|---|
| 800 | if (m->status & MCI_STATUS_ADDRV) { | 
|---|
| 801 | m->addr = addr; | 
|---|
| 802 |  | 
|---|
| 803 | smca_extract_err_addr(m); | 
|---|
| 804 | } | 
|---|
| 805 |  | 
|---|
| 806 | if (mce_flags.smca) { | 
|---|
| 807 | rdmsrq(MSR_AMD64_SMCA_MCx_IPID(bank), m->ipid); | 
|---|
| 808 |  | 
|---|
| 809 | if (m->status & MCI_STATUS_SYNDV) { | 
|---|
| 810 | rdmsrq(MSR_AMD64_SMCA_MCx_SYND(bank), m->synd); | 
|---|
| 811 | rdmsrq(MSR_AMD64_SMCA_MCx_SYND1(bank), err.vendor.amd.synd1); | 
|---|
| 812 | rdmsrq(MSR_AMD64_SMCA_MCx_SYND2(bank), err.vendor.amd.synd2); | 
|---|
| 813 | } | 
|---|
| 814 | } | 
|---|
| 815 |  | 
|---|
| 816 | mce_log(err: &err); | 
|---|
| 817 | } | 
|---|
| 818 |  | 
|---|
| 819 | DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error) | 
|---|
| 820 | { | 
|---|
| 821 | trace_deferred_error_apic_entry(DEFERRED_ERROR_VECTOR); | 
|---|
| 822 | inc_irq_stat(irq_deferred_error_count); | 
|---|
| 823 | deferred_error_int_vector(); | 
|---|
| 824 | trace_deferred_error_apic_exit(DEFERRED_ERROR_VECTOR); | 
|---|
| 825 | apic_eoi(); | 
|---|
| 826 | } | 
|---|
| 827 |  | 
|---|
| 828 | /* | 
|---|
| 829 | * Returns true if the logged error is deferred. False, otherwise. | 
|---|
| 830 | */ | 
|---|
| 831 | static inline bool | 
|---|
| 832 | _log_error_bank(unsigned int bank, u32 msr_stat, u32 msr_addr, u64 misc) | 
|---|
| 833 | { | 
|---|
| 834 | u64 status, addr = 0; | 
|---|
| 835 |  | 
|---|
| 836 | rdmsrq(msr_stat, status); | 
|---|
| 837 | if (!(status & MCI_STATUS_VAL)) | 
|---|
| 838 | return false; | 
|---|
| 839 |  | 
|---|
| 840 | if (status & MCI_STATUS_ADDRV) | 
|---|
| 841 | rdmsrq(msr_addr, addr); | 
|---|
| 842 |  | 
|---|
| 843 | __log_error(bank, status, addr, misc); | 
|---|
| 844 |  | 
|---|
| 845 | wrmsrq(msr: msr_stat, val: 0); | 
|---|
| 846 |  | 
|---|
| 847 | return status & MCI_STATUS_DEFERRED; | 
|---|
| 848 | } | 
|---|
| 849 |  | 
|---|
| 850 | static bool _log_error_deferred(unsigned int bank, u32 misc) | 
|---|
| 851 | { | 
|---|
| 852 | if (!_log_error_bank(bank, msr_stat: mca_msr_reg(bank, reg: MCA_STATUS), | 
|---|
| 853 | msr_addr: mca_msr_reg(bank, reg: MCA_ADDR), misc)) | 
|---|
| 854 | return false; | 
|---|
| 855 |  | 
|---|
| 856 | /* | 
|---|
| 857 | * Non-SMCA systems don't have MCA_DESTAT/MCA_DEADDR registers. | 
|---|
| 858 | * Return true here to avoid accessing these registers. | 
|---|
| 859 | */ | 
|---|
| 860 | if (!mce_flags.smca) | 
|---|
| 861 | return true; | 
|---|
| 862 |  | 
|---|
| 863 | /* Clear MCA_DESTAT if the deferred error was logged from MCA_STATUS. */ | 
|---|
| 864 | wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(bank), val: 0); | 
|---|
| 865 | return true; | 
|---|
| 866 | } | 
|---|
| 867 |  | 
|---|
| 868 | /* | 
|---|
| 869 | * We have three scenarios for checking for Deferred errors: | 
|---|
| 870 | * | 
|---|
| 871 | * 1) Non-SMCA systems check MCA_STATUS and log error if found. | 
|---|
| 872 | * 2) SMCA systems check MCA_STATUS. If error is found then log it and also | 
|---|
| 873 | *    clear MCA_DESTAT. | 
|---|
| 874 | * 3) SMCA systems check MCA_DESTAT, if error was not found in MCA_STATUS, and | 
|---|
| 875 | *    log it. | 
|---|
| 876 | */ | 
|---|
| 877 | static void log_error_deferred(unsigned int bank) | 
|---|
| 878 | { | 
|---|
| 879 | if (_log_error_deferred(bank, misc: 0)) | 
|---|
| 880 | return; | 
|---|
| 881 |  | 
|---|
| 882 | /* | 
|---|
| 883 | * Only deferred errors are logged in MCA_DE{STAT,ADDR} so just check | 
|---|
| 884 | * for a valid error. | 
|---|
| 885 | */ | 
|---|
| 886 | _log_error_bank(bank, MSR_AMD64_SMCA_MCx_DESTAT(bank), | 
|---|
| 887 | MSR_AMD64_SMCA_MCx_DEADDR(bank), misc: 0); | 
|---|
| 888 | } | 
|---|
| 889 |  | 
|---|
| 890 | /* APIC interrupt handler for deferred errors */ | 
|---|
| 891 | static void amd_deferred_error_interrupt(void) | 
|---|
| 892 | { | 
|---|
| 893 | unsigned int bank; | 
|---|
| 894 |  | 
|---|
| 895 | for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) | 
|---|
| 896 | log_error_deferred(bank); | 
|---|
| 897 | } | 
|---|
| 898 |  | 
|---|
| 899 | static void log_error_thresholding(unsigned int bank, u64 misc) | 
|---|
| 900 | { | 
|---|
| 901 | _log_error_deferred(bank, misc); | 
|---|
| 902 | } | 
|---|
| 903 |  | 
|---|
| 904 | static void log_and_reset_block(struct threshold_block *block) | 
|---|
| 905 | { | 
|---|
| 906 | struct thresh_restart tr; | 
|---|
| 907 | u32 low = 0, high = 0; | 
|---|
| 908 |  | 
|---|
| 909 | if (!block) | 
|---|
| 910 | return; | 
|---|
| 911 |  | 
|---|
| 912 | if (rdmsr_safe(block->address, &low, &high)) | 
|---|
| 913 | return; | 
|---|
| 914 |  | 
|---|
| 915 | if (!(high & MASK_OVERFLOW_HI)) | 
|---|
| 916 | return; | 
|---|
| 917 |  | 
|---|
| 918 | /* Log the MCE which caused the threshold event. */ | 
|---|
| 919 | log_error_thresholding(bank: block->bank, misc: ((u64)high << 32) | low); | 
|---|
| 920 |  | 
|---|
| 921 | /* Reset threshold block after logging error. */ | 
|---|
| 922 | memset(s: &tr, c: 0, n: sizeof(tr)); | 
|---|
| 923 | tr.b = block; | 
|---|
| 924 | threshold_restart_block(tr: &tr); | 
|---|
| 925 | } | 
|---|
| 926 |  | 
|---|
| 927 | /* | 
|---|
| 928 | * Threshold interrupt handler will service THRESHOLD_APIC_VECTOR. The interrupt | 
|---|
| 929 | * goes off when error_count reaches threshold_limit. | 
|---|
| 930 | */ | 
|---|
| 931 | static void amd_threshold_interrupt(void) | 
|---|
| 932 | { | 
|---|
| 933 | struct threshold_bank **bp = this_cpu_read(threshold_banks), *thr_bank; | 
|---|
| 934 | unsigned int bank, cpu = smp_processor_id(); | 
|---|
| 935 | struct threshold_block *block, *tmp; | 
|---|
| 936 |  | 
|---|
| 937 | /* | 
|---|
| 938 | * Validate that the threshold bank has been initialized already. The | 
|---|
| 939 | * handler is installed at boot time, but on a hotplug event the | 
|---|
| 940 | * interrupt might fire before the data has been initialized. | 
|---|
| 941 | */ | 
|---|
| 942 | if (!bp) | 
|---|
| 943 | return; | 
|---|
| 944 |  | 
|---|
| 945 | for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) { | 
|---|
| 946 | if (!(per_cpu(bank_map, cpu) & BIT_ULL(bank))) | 
|---|
| 947 | continue; | 
|---|
| 948 |  | 
|---|
| 949 | thr_bank = bp[bank]; | 
|---|
| 950 | if (!thr_bank) | 
|---|
| 951 | continue; | 
|---|
| 952 |  | 
|---|
| 953 | list_for_each_entry_safe(block, tmp, &thr_bank->miscj, miscj) | 
|---|
| 954 | log_and_reset_block(block); | 
|---|
| 955 | } | 
|---|
| 956 | } | 
|---|
| 957 |  | 
|---|
| 958 | void amd_clear_bank(struct mce *m) | 
|---|
| 959 | { | 
|---|
| 960 | mce_wrmsrq(msr: mca_msr_reg(bank: m->bank, reg: MCA_STATUS), v: 0); | 
|---|
| 961 | } | 
|---|
| 962 |  | 
|---|
| 963 | /* | 
|---|
| 964 | * Sysfs Interface | 
|---|
| 965 | */ | 
|---|
| 966 |  | 
|---|
| 967 | struct threshold_attr { | 
|---|
| 968 | struct attribute attr; | 
|---|
| 969 | ssize_t (*show) (struct threshold_block *, char *); | 
|---|
| 970 | ssize_t (*store) (struct threshold_block *, const char *, size_t count); | 
|---|
| 971 | }; | 
|---|
| 972 |  | 
|---|
| 973 | #define SHOW_FIELDS(name)						\ | 
|---|
| 974 | static ssize_t show_ ## name(struct threshold_block *b, char *buf)	\ | 
|---|
| 975 | {									\ | 
|---|
| 976 | return sprintf(buf, "%lu\n", (unsigned long) b->name);		\ | 
|---|
| 977 | } | 
|---|
| 978 | SHOW_FIELDS(interrupt_enable) | 
|---|
| 979 | SHOW_FIELDS(threshold_limit) | 
|---|
| 980 |  | 
|---|
| 981 | static ssize_t | 
|---|
| 982 | store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) | 
|---|
| 983 | { | 
|---|
| 984 | struct thresh_restart tr; | 
|---|
| 985 | unsigned long new; | 
|---|
| 986 |  | 
|---|
| 987 | if (!b->interrupt_capable) | 
|---|
| 988 | return -EINVAL; | 
|---|
| 989 |  | 
|---|
| 990 | if (kstrtoul(s: buf, base: 0, res: &new) < 0) | 
|---|
| 991 | return -EINVAL; | 
|---|
| 992 |  | 
|---|
| 993 | b->interrupt_enable = !!new; | 
|---|
| 994 |  | 
|---|
| 995 | memset(s: &tr, c: 0, n: sizeof(tr)); | 
|---|
| 996 | tr.b		= b; | 
|---|
| 997 |  | 
|---|
| 998 | if (smp_call_function_single(cpuid: b->cpu, func: threshold_restart_block, info: &tr, wait: 1)) | 
|---|
| 999 | return -ENODEV; | 
|---|
| 1000 |  | 
|---|
| 1001 | return size; | 
|---|
| 1002 | } | 
|---|
| 1003 |  | 
|---|
| 1004 | static ssize_t | 
|---|
| 1005 | store_threshold_limit(struct threshold_block *b, const char *buf, size_t size) | 
|---|
| 1006 | { | 
|---|
| 1007 | struct thresh_restart tr; | 
|---|
| 1008 | unsigned long new; | 
|---|
| 1009 |  | 
|---|
| 1010 | if (kstrtoul(s: buf, base: 0, res: &new) < 0) | 
|---|
| 1011 | return -EINVAL; | 
|---|
| 1012 |  | 
|---|
| 1013 | if (new > THRESHOLD_MAX) | 
|---|
| 1014 | new = THRESHOLD_MAX; | 
|---|
| 1015 | if (new < 1) | 
|---|
| 1016 | new = 1; | 
|---|
| 1017 |  | 
|---|
| 1018 | memset(s: &tr, c: 0, n: sizeof(tr)); | 
|---|
| 1019 | tr.old_limit = b->threshold_limit; | 
|---|
| 1020 | b->threshold_limit = new; | 
|---|
| 1021 | tr.b = b; | 
|---|
| 1022 |  | 
|---|
| 1023 | if (smp_call_function_single(cpuid: b->cpu, func: threshold_restart_block, info: &tr, wait: 1)) | 
|---|
| 1024 | return -ENODEV; | 
|---|
| 1025 |  | 
|---|
| 1026 | return size; | 
|---|
| 1027 | } | 
|---|
| 1028 |  | 
|---|
| 1029 | static ssize_t show_error_count(struct threshold_block *b, char *buf) | 
|---|
| 1030 | { | 
|---|
| 1031 | u32 lo, hi; | 
|---|
| 1032 |  | 
|---|
| 1033 | /* CPU might be offline by now */ | 
|---|
| 1034 | if (rdmsr_on_cpu(cpu: b->cpu, msr_no: b->address, l: &lo, h: &hi)) | 
|---|
| 1035 | return -ENODEV; | 
|---|
| 1036 |  | 
|---|
| 1037 | return sprintf(buf, fmt: "%u\n", ((hi & THRESHOLD_MAX) - | 
|---|
| 1038 | (THRESHOLD_MAX - b->threshold_limit))); | 
|---|
| 1039 | } | 
|---|
| 1040 |  | 
|---|
| 1041 | static struct threshold_attr error_count = { | 
|---|
| 1042 | .attr = {.name = __stringify(error_count), .mode = 0444 }, | 
|---|
| 1043 | .show = show_error_count, | 
|---|
| 1044 | }; | 
|---|
| 1045 |  | 
|---|
| 1046 | #define RW_ATTR(val)							\ | 
|---|
| 1047 | static struct threshold_attr val = {					\ | 
|---|
| 1048 | .attr	= {.name = __stringify(val), .mode = 0644 },		\ | 
|---|
| 1049 | .show	= show_## val,						\ | 
|---|
| 1050 | .store	= store_## val,						\ | 
|---|
| 1051 | }; | 
|---|
| 1052 |  | 
|---|
| 1053 | RW_ATTR(interrupt_enable); | 
|---|
| 1054 | RW_ATTR(threshold_limit); | 
|---|
| 1055 |  | 
|---|
| 1056 | static struct attribute *default_attrs[] = { | 
|---|
| 1057 | &threshold_limit.attr, | 
|---|
| 1058 | &error_count.attr, | 
|---|
| 1059 | NULL,	/* possibly interrupt_enable if supported, see below */ | 
|---|
| 1060 | NULL, | 
|---|
| 1061 | }; | 
|---|
| 1062 | ATTRIBUTE_GROUPS(default); | 
|---|
| 1063 |  | 
|---|
| 1064 | #define to_block(k)	container_of(k, struct threshold_block, kobj) | 
|---|
| 1065 | #define to_attr(a)	container_of(a, struct threshold_attr, attr) | 
|---|
| 1066 |  | 
|---|
| 1067 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | 
|---|
| 1068 | { | 
|---|
| 1069 | struct threshold_block *b = to_block(kobj); | 
|---|
| 1070 | struct threshold_attr *a = to_attr(attr); | 
|---|
| 1071 | ssize_t ret; | 
|---|
| 1072 |  | 
|---|
| 1073 | ret = a->show ? a->show(b, buf) : -EIO; | 
|---|
| 1074 |  | 
|---|
| 1075 | return ret; | 
|---|
| 1076 | } | 
|---|
| 1077 |  | 
|---|
| 1078 | static ssize_t store(struct kobject *kobj, struct attribute *attr, | 
|---|
| 1079 | const char *buf, size_t count) | 
|---|
| 1080 | { | 
|---|
| 1081 | struct threshold_block *b = to_block(kobj); | 
|---|
| 1082 | struct threshold_attr *a = to_attr(attr); | 
|---|
| 1083 | ssize_t ret; | 
|---|
| 1084 |  | 
|---|
| 1085 | ret = a->store ? a->store(b, buf, count) : -EIO; | 
|---|
| 1086 |  | 
|---|
| 1087 | return ret; | 
|---|
| 1088 | } | 
|---|
| 1089 |  | 
|---|
| 1090 | static const struct sysfs_ops threshold_ops = { | 
|---|
| 1091 | .show			= show, | 
|---|
| 1092 | .store			= store, | 
|---|
| 1093 | }; | 
|---|
| 1094 |  | 
|---|
| 1095 | static void threshold_block_release(struct kobject *kobj); | 
|---|
| 1096 |  | 
|---|
| 1097 | static const struct kobj_type threshold_ktype = { | 
|---|
| 1098 | .sysfs_ops		= &threshold_ops, | 
|---|
| 1099 | .default_groups		= default_groups, | 
|---|
| 1100 | .release		= threshold_block_release, | 
|---|
| 1101 | }; | 
|---|
| 1102 |  | 
|---|
| 1103 | static const char *get_name(unsigned int cpu, unsigned int bank, struct threshold_block *b) | 
|---|
| 1104 | { | 
|---|
| 1105 | enum smca_bank_types bank_type; | 
|---|
| 1106 |  | 
|---|
| 1107 | if (!mce_flags.smca) { | 
|---|
| 1108 | if (b && bank == 4) | 
|---|
| 1109 | return bank4_names(b); | 
|---|
| 1110 |  | 
|---|
| 1111 | return th_names[bank]; | 
|---|
| 1112 | } | 
|---|
| 1113 |  | 
|---|
| 1114 | bank_type = smca_get_bank_type(cpu, bank); | 
|---|
| 1115 |  | 
|---|
| 1116 | if (b && (bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2)) { | 
|---|
| 1117 | if (b->block < ARRAY_SIZE(smca_umc_block_names)) | 
|---|
| 1118 | return smca_umc_block_names[b->block]; | 
|---|
| 1119 | } | 
|---|
| 1120 |  | 
|---|
| 1121 | if (b && b->block) { | 
|---|
| 1122 | snprintf(buf: buf_mcatype, MAX_MCATYPE_NAME_LEN, fmt: "th_block_%u", b->block); | 
|---|
| 1123 | return buf_mcatype; | 
|---|
| 1124 | } | 
|---|
| 1125 |  | 
|---|
| 1126 | if (bank_type >= N_SMCA_BANK_TYPES) { | 
|---|
| 1127 | snprintf(buf: buf_mcatype, MAX_MCATYPE_NAME_LEN, fmt: "th_bank_%u", bank); | 
|---|
| 1128 | return buf_mcatype; | 
|---|
| 1129 | } | 
|---|
| 1130 |  | 
|---|
| 1131 | if (per_cpu(smca_bank_counts, cpu)[bank_type] == 1) | 
|---|
| 1132 | return smca_get_name(t: bank_type); | 
|---|
| 1133 |  | 
|---|
| 1134 | snprintf(buf: buf_mcatype, MAX_MCATYPE_NAME_LEN, | 
|---|
| 1135 | fmt: "%s_%u", smca_get_name(t: bank_type), | 
|---|
| 1136 | per_cpu(smca_banks, cpu)[bank].sysfs_id); | 
|---|
| 1137 | return buf_mcatype; | 
|---|
| 1138 | } | 
|---|
| 1139 |  | 
|---|
| 1140 | static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb, | 
|---|
| 1141 | unsigned int bank, unsigned int block, | 
|---|
| 1142 | u32 address) | 
|---|
| 1143 | { | 
|---|
| 1144 | struct threshold_block *b = NULL; | 
|---|
| 1145 | u32 low, high; | 
|---|
| 1146 | int err; | 
|---|
| 1147 |  | 
|---|
| 1148 | if ((bank >= this_cpu_read(mce_num_banks)) || (block >= NR_BLOCKS)) | 
|---|
| 1149 | return 0; | 
|---|
| 1150 |  | 
|---|
| 1151 | if (rdmsr_safe(address, &low, &high)) | 
|---|
| 1152 | return 0; | 
|---|
| 1153 |  | 
|---|
| 1154 | if (!(high & MASK_VALID_HI)) { | 
|---|
| 1155 | if (block) | 
|---|
| 1156 | goto recurse; | 
|---|
| 1157 | else | 
|---|
| 1158 | return 0; | 
|---|
| 1159 | } | 
|---|
| 1160 |  | 
|---|
| 1161 | if (!(high & MASK_CNTP_HI)  || | 
|---|
| 1162 | (high & MASK_LOCKED_HI)) | 
|---|
| 1163 | goto recurse; | 
|---|
| 1164 |  | 
|---|
| 1165 | b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL); | 
|---|
| 1166 | if (!b) | 
|---|
| 1167 | return -ENOMEM; | 
|---|
| 1168 |  | 
|---|
| 1169 | b->block		= block; | 
|---|
| 1170 | b->bank			= bank; | 
|---|
| 1171 | b->cpu			= cpu; | 
|---|
| 1172 | b->address		= address; | 
|---|
| 1173 | b->interrupt_enable	= 0; | 
|---|
| 1174 | b->interrupt_capable	= lvt_interrupt_supported(bank, msr_high_bits: high); | 
|---|
| 1175 | b->threshold_limit	= THRESHOLD_MAX; | 
|---|
| 1176 |  | 
|---|
| 1177 | if (b->interrupt_capable) { | 
|---|
| 1178 | default_attrs[2] = &interrupt_enable.attr; | 
|---|
| 1179 | b->interrupt_enable = 1; | 
|---|
| 1180 | } else { | 
|---|
| 1181 | default_attrs[2] = NULL; | 
|---|
| 1182 | } | 
|---|
| 1183 |  | 
|---|
| 1184 | list_add(new: &b->miscj, head: &tb->miscj); | 
|---|
| 1185 |  | 
|---|
| 1186 | err = kobject_init_and_add(kobj: &b->kobj, ktype: &threshold_ktype, parent: tb->kobj, fmt: get_name(cpu, bank, b)); | 
|---|
| 1187 | if (err) | 
|---|
| 1188 | goto out_free; | 
|---|
| 1189 | recurse: | 
|---|
| 1190 | address = get_block_address(current_addr: address, low, high, bank, block: ++block, cpu); | 
|---|
| 1191 | if (!address) | 
|---|
| 1192 | return 0; | 
|---|
| 1193 |  | 
|---|
| 1194 | err = allocate_threshold_blocks(cpu, tb, bank, block, address); | 
|---|
| 1195 | if (err) | 
|---|
| 1196 | goto out_free; | 
|---|
| 1197 |  | 
|---|
| 1198 | if (b) | 
|---|
| 1199 | kobject_uevent(kobj: &b->kobj, action: KOBJ_ADD); | 
|---|
| 1200 |  | 
|---|
| 1201 | return 0; | 
|---|
| 1202 |  | 
|---|
| 1203 | out_free: | 
|---|
| 1204 | if (b) { | 
|---|
| 1205 | list_del(entry: &b->miscj); | 
|---|
| 1206 | kobject_put(kobj: &b->kobj); | 
|---|
| 1207 | } | 
|---|
| 1208 | return err; | 
|---|
| 1209 | } | 
|---|
| 1210 |  | 
|---|
| 1211 | static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu, | 
|---|
| 1212 | unsigned int bank) | 
|---|
| 1213 | { | 
|---|
| 1214 | struct device *dev = this_cpu_read(mce_device); | 
|---|
| 1215 | struct threshold_bank *b = NULL; | 
|---|
| 1216 | const char *name = get_name(cpu, bank, NULL); | 
|---|
| 1217 | int err = 0; | 
|---|
| 1218 |  | 
|---|
| 1219 | if (!dev) | 
|---|
| 1220 | return -ENODEV; | 
|---|
| 1221 |  | 
|---|
| 1222 | b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL); | 
|---|
| 1223 | if (!b) { | 
|---|
| 1224 | err = -ENOMEM; | 
|---|
| 1225 | goto out; | 
|---|
| 1226 | } | 
|---|
| 1227 |  | 
|---|
| 1228 | /* Associate the bank with the per-CPU MCE device */ | 
|---|
| 1229 | b->kobj = kobject_create_and_add(name, parent: &dev->kobj); | 
|---|
| 1230 | if (!b->kobj) { | 
|---|
| 1231 | err = -EINVAL; | 
|---|
| 1232 | goto out_free; | 
|---|
| 1233 | } | 
|---|
| 1234 |  | 
|---|
| 1235 | INIT_LIST_HEAD(list: &b->miscj); | 
|---|
| 1236 |  | 
|---|
| 1237 | err = allocate_threshold_blocks(cpu, tb: b, bank, block: 0, address: mca_msr_reg(bank, reg: MCA_MISC)); | 
|---|
| 1238 | if (err) | 
|---|
| 1239 | goto out_kobj; | 
|---|
| 1240 |  | 
|---|
| 1241 | bp[bank] = b; | 
|---|
| 1242 | return 0; | 
|---|
| 1243 |  | 
|---|
| 1244 | out_kobj: | 
|---|
| 1245 | kobject_put(kobj: b->kobj); | 
|---|
| 1246 | out_free: | 
|---|
| 1247 | kfree(objp: b); | 
|---|
| 1248 | out: | 
|---|
| 1249 | return err; | 
|---|
| 1250 | } | 
|---|
| 1251 |  | 
|---|
| 1252 | static void threshold_block_release(struct kobject *kobj) | 
|---|
| 1253 | { | 
|---|
| 1254 | kfree(to_block(kobj)); | 
|---|
| 1255 | } | 
|---|
| 1256 |  | 
|---|
| 1257 | static void threshold_remove_bank(struct threshold_bank *bank) | 
|---|
| 1258 | { | 
|---|
| 1259 | struct threshold_block *pos, *tmp; | 
|---|
| 1260 |  | 
|---|
| 1261 | list_for_each_entry_safe(pos, tmp, &bank->miscj, miscj) { | 
|---|
| 1262 | list_del(entry: &pos->miscj); | 
|---|
| 1263 | kobject_put(kobj: &pos->kobj); | 
|---|
| 1264 | } | 
|---|
| 1265 |  | 
|---|
| 1266 | kobject_put(kobj: bank->kobj); | 
|---|
| 1267 | kfree(objp: bank); | 
|---|
| 1268 | } | 
|---|
| 1269 |  | 
|---|
| 1270 | static void __threshold_remove_device(struct threshold_bank **bp) | 
|---|
| 1271 | { | 
|---|
| 1272 | unsigned int bank, numbanks = this_cpu_read(mce_num_banks); | 
|---|
| 1273 |  | 
|---|
| 1274 | for (bank = 0; bank < numbanks; bank++) { | 
|---|
| 1275 | if (!bp[bank]) | 
|---|
| 1276 | continue; | 
|---|
| 1277 |  | 
|---|
| 1278 | threshold_remove_bank(bank: bp[bank]); | 
|---|
| 1279 | bp[bank] = NULL; | 
|---|
| 1280 | } | 
|---|
| 1281 | kfree(objp: bp); | 
|---|
| 1282 | } | 
|---|
| 1283 |  | 
|---|
| 1284 | void mce_threshold_remove_device(unsigned int cpu) | 
|---|
| 1285 | { | 
|---|
| 1286 | struct threshold_bank **bp = this_cpu_read(threshold_banks); | 
|---|
| 1287 |  | 
|---|
| 1288 | if (!bp) | 
|---|
| 1289 | return; | 
|---|
| 1290 |  | 
|---|
| 1291 | /* | 
|---|
| 1292 | * Clear the pointer before cleaning up, so that the interrupt won't | 
|---|
| 1293 | * touch anything of this. | 
|---|
| 1294 | */ | 
|---|
| 1295 | this_cpu_write(threshold_banks, NULL); | 
|---|
| 1296 |  | 
|---|
| 1297 | __threshold_remove_device(bp); | 
|---|
| 1298 | return; | 
|---|
| 1299 | } | 
|---|
| 1300 |  | 
|---|
| 1301 | /** | 
|---|
| 1302 | * mce_threshold_create_device - Create the per-CPU MCE threshold device | 
|---|
| 1303 | * @cpu:	The plugged in CPU | 
|---|
| 1304 | * | 
|---|
| 1305 | * Create directories and files for all valid threshold banks. | 
|---|
| 1306 | * | 
|---|
| 1307 | * This is invoked from the CPU hotplug callback which was installed in | 
|---|
| 1308 | * mcheck_init_device(). The invocation happens in context of the hotplug | 
|---|
| 1309 | * thread running on @cpu.  The callback is invoked on all CPUs which are | 
|---|
| 1310 | * online when the callback is installed or during a real hotplug event. | 
|---|
| 1311 | */ | 
|---|
| 1312 | void mce_threshold_create_device(unsigned int cpu) | 
|---|
| 1313 | { | 
|---|
| 1314 | unsigned int numbanks, bank; | 
|---|
| 1315 | struct threshold_bank **bp; | 
|---|
| 1316 |  | 
|---|
| 1317 | if (!mce_flags.amd_threshold) | 
|---|
| 1318 | return; | 
|---|
| 1319 |  | 
|---|
| 1320 | bp = this_cpu_read(threshold_banks); | 
|---|
| 1321 | if (bp) | 
|---|
| 1322 | return; | 
|---|
| 1323 |  | 
|---|
| 1324 | numbanks = this_cpu_read(mce_num_banks); | 
|---|
| 1325 | bp = kcalloc(numbanks, sizeof(*bp), GFP_KERNEL); | 
|---|
| 1326 | if (!bp) | 
|---|
| 1327 | return; | 
|---|
| 1328 |  | 
|---|
| 1329 | for (bank = 0; bank < numbanks; ++bank) { | 
|---|
| 1330 | if (!(this_cpu_read(bank_map) & BIT_ULL(bank))) | 
|---|
| 1331 | continue; | 
|---|
| 1332 | if (threshold_create_bank(bp, cpu, bank)) { | 
|---|
| 1333 | __threshold_remove_device(bp); | 
|---|
| 1334 | return; | 
|---|
| 1335 | } | 
|---|
| 1336 | } | 
|---|
| 1337 | this_cpu_write(threshold_banks, bp); | 
|---|
| 1338 |  | 
|---|
| 1339 | if (thresholding_irq_en) | 
|---|
| 1340 | mce_threshold_vector = amd_threshold_interrupt; | 
|---|
| 1341 | return; | 
|---|
| 1342 | } | 
|---|
| 1343 |  | 
|---|