Lines Matching +full:high +full:- +full:threshold
1 // SPDX-License-Identifier: GPL-2.0-only
3 * (c) 2005-2016 Advanced Micro Devices, Inc.
5 * Written by Jacob Shin - AMD, Inc.
55 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
92 const char *long_name; /* Long name for pretty-printing */
153 if (!b->hwid) in smca_get_bank_type()
156 return b->hwid->bank_type; in smca_get_bank_type()
223 * So to define a unique name for each bank, we use a temp c-string to append
254 u32 low, high; in smca_set_misc_banks_map() local
258 * (MCx_MISC0) indicates presence of additional MISC regs set (MISC1-4). in smca_set_misc_banks_map()
260 if (rdmsr_safe(MSR_AMD64_SMCA_MCx_CONFIG(bank), &low, &high)) in smca_set_misc_banks_map()
266 if (rdmsr_safe(MSR_AMD64_SMCA_MCx_MISC(bank), &low, &high)) in smca_set_misc_banks_map()
279 u32 high, low; in smca_configure() local
283 if (!rdmsr_safe(smca_config, &low, &high)) { in smca_configure()
291 * MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.) in smca_configure()
293 high |= BIT(0); in smca_configure()
302 * high portion of the MSR). OS should set this to 0x1 to enable in smca_configure()
306 if ((low & BIT(5)) && !((high >> 5) & 0x3)) in smca_configure()
307 high |= BIT(5); in smca_configure()
309 wrmsr(smca_config, low, high); in smca_configure()
314 if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) { in smca_configure()
319 hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID, in smca_configure()
320 (high & MCI_IPID_MCATYPE) >> 16); in smca_configure()
325 if (hwid_mcatype == s_hwid->hwid_mcatype) { in smca_configure()
328 this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++; in smca_configure()
357 switch (b->address) { in bank4_names()
369 WARN(1, "Funny MSR: 0x%08x\n", b->address); in bank4_names()
395 pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt " in lvt_off_valid()
396 "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, in lvt_off_valid()
397 b->bank, b->block, b->address, hi, lo); in lvt_off_valid()
410 pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " in lvt_off_valid()
412 b->cpu, apic, b->bank, b->block, b->address, hi, lo); in lvt_off_valid()
419 /* Reprogram MCx_MISC MSR behind this threshold bank. */
426 if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off) in threshold_restart_bank()
429 rdmsr(tr->b->address, lo, hi); in threshold_restart_bank()
431 if (tr->b->threshold_limit < (hi & THRESHOLD_MAX)) in threshold_restart_bank()
432 tr->reset = 1; /* limit cannot be lower than err count */ in threshold_restart_bank()
434 if (tr->reset) { /* reset err count and overflow bit */ in threshold_restart_bank()
437 (THRESHOLD_MAX - tr->b->threshold_limit); in threshold_restart_bank()
438 } else if (tr->old_limit) { /* change limit w/o reset */ in threshold_restart_bank()
440 (tr->old_limit - tr->b->threshold_limit); in threshold_restart_bank()
449 if (!tr->b->interrupt_capable) in threshold_restart_bank()
452 if (tr->set_lvt_off) { in threshold_restart_bank()
453 if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { in threshold_restart_bank()
456 hi |= tr->lvt_off << 20; in threshold_restart_bank()
460 if (tr->b->interrupt_enable) in threshold_restart_bank()
466 wrmsr(tr->b->address, lo, hi); in threshold_restart_bank()
477 b->threshold_limit = THRESHOLD_MAX; in mce_threshold_block_init()
501 u32 low = 0, high = 0; in deferred_error_interrupt_enable() local
502 int def_offset = -1, def_new; in deferred_error_interrupt_enable()
504 if (rdmsr_safe(MSR_CU_DEF_ERR, &low, &high)) in deferred_error_interrupt_enable()
522 wrmsr(MSR_CU_DEF_ERR, low, high); in deferred_error_interrupt_enable()
534 return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1); in smca_get_block_address()
537 static u32 get_block_address(u32 current_addr, u32 low, u32 high, in get_block_address() argument
614 enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank); in amd_filter_mce()
617 /* See Family 17h Models 10h-2Fh Erratum #1114. */ in amd_filter_mce()
618 if (c->x86 == 0x17 && in amd_filter_mce()
619 c->x86_model >= 0x10 && c->x86_model <= 0x2F && in amd_filter_mce()
620 bank_type == SMCA_IF && XEC(m->status, 0x3f) == 10) in amd_filter_mce()
624 if (c->x86 < 0x17) { in amd_filter_mce()
625 if (m->bank == 4 && XEC(m->status, 0x1f) == 0x5) in amd_filter_mce()
634 * - MC4_MISC thresholding is not supported on Family 0x15.
635 * - Prevent possible spurious interrupts from the IF bank on Family 0x17
636 * Models 0x10-0x2F due to Erratum #1114.
645 if (c->x86 == 0x15 && bank == 4) { in disable_err_thresholding()
649 } else if (c->x86 == 0x17 && in disable_err_thresholding()
650 (c->x86_model >= 0x10 && c->x86_model <= 0x2F)) { in disable_err_thresholding()
681 u32 low = 0, high = 0, address = 0; in mce_amd_feature_init() local
682 int offset = -1; in mce_amd_feature_init()
692 address = get_block_address(address, low, high, bank, block, cpu); in mce_amd_feature_init()
696 if (rdmsr_safe(address, &low, &high)) in mce_amd_feature_init()
699 if (!(high & MASK_VALID_HI)) in mce_amd_feature_init()
702 if (!(high & MASK_CNTP_HI) || in mce_amd_feature_init()
703 (high & MASK_LOCKED_HI)) in mce_amd_feature_init()
706 offset = prepare_threshold_block(bank, block, address, offset, high); in mce_amd_feature_init()
717 u8 xec = (m->status >> 16) & 0x1f; in amd_mce_is_memory_error()
720 return smca_get_bank_type(m->extcpu, m->bank) == SMCA_UMC && xec == 0x0; in amd_mce_is_memory_error()
722 return m->bank == 4 && xec == 0x8; in amd_mce_is_memory_error()
794 * 1) Non-SMCA systems check MCA_STATUS and log error if found.
841 u32 low = 0, high = 0; in log_and_reset_block() local
846 if (rdmsr_safe(block->address, &low, &high)) in log_and_reset_block()
849 if (!(high & MASK_OVERFLOW_HI)) in log_and_reset_block()
852 /* Log the MCE which caused the threshold event. */ in log_and_reset_block()
853 log_error_thresholding(block->bank, ((u64)high << 32) | low); in log_and_reset_block()
855 /* Reset threshold block after logging error. */ in log_and_reset_block()
862 * Threshold interrupt handler will service THRESHOLD_APIC_VECTOR. The interrupt
872 * Validate that the threshold bank has been initialized already. The in amd_threshold_interrupt()
883 first_block = bp[bank]->blocks; in amd_threshold_interrupt()
892 list_for_each_entry_safe(block, tmp, &first_block->miscj, miscj) in amd_threshold_interrupt()
910 return sprintf(buf, "%lu\n", (unsigned long) b->name); \
921 if (!b->interrupt_capable) in SHOW_FIELDS()
922 return -EINVAL; in SHOW_FIELDS()
925 return -EINVAL; in SHOW_FIELDS()
927 b->interrupt_enable = !!new; in SHOW_FIELDS()
932 if (smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1)) in SHOW_FIELDS()
933 return -ENODEV; in SHOW_FIELDS()
945 return -EINVAL; in store_threshold_limit()
953 tr.old_limit = b->threshold_limit; in store_threshold_limit()
954 b->threshold_limit = new; in store_threshold_limit()
957 if (smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1)) in store_threshold_limit()
958 return -ENODEV; in store_threshold_limit()
968 if (rdmsr_on_cpu(b->cpu, b->address, &lo, &hi)) in show_error_count()
969 return -ENODEV; in show_error_count()
971 return sprintf(buf, "%u\n", ((hi & THRESHOLD_MAX) - in show_error_count()
972 (THRESHOLD_MAX - b->threshold_limit))); in show_error_count()
1007 ret = a->show ? a->show(b, buf) : -EIO; in show()
1019 ret = a->store ? a->store(b, buf, count) : -EIO; in store()
1053 if (b->block < ARRAY_SIZE(smca_umc_block_names)) in get_name()
1054 return smca_umc_block_names[b->block]; in get_name()
1072 u32 low, high; in allocate_threshold_blocks() local
1078 if (rdmsr_safe(address, &low, &high)) in allocate_threshold_blocks()
1081 if (!(high & MASK_VALID_HI)) { in allocate_threshold_blocks()
1088 if (!(high & MASK_CNTP_HI) || in allocate_threshold_blocks()
1089 (high & MASK_LOCKED_HI)) in allocate_threshold_blocks()
1094 return -ENOMEM; in allocate_threshold_blocks()
1096 b->block = block; in allocate_threshold_blocks()
1097 b->bank = bank; in allocate_threshold_blocks()
1098 b->cpu = cpu; in allocate_threshold_blocks()
1099 b->address = address; in allocate_threshold_blocks()
1100 b->interrupt_enable = 0; in allocate_threshold_blocks()
1101 b->interrupt_capable = lvt_interrupt_supported(bank, high); in allocate_threshold_blocks()
1102 b->threshold_limit = THRESHOLD_MAX; in allocate_threshold_blocks()
1104 if (b->interrupt_capable) { in allocate_threshold_blocks()
1106 b->interrupt_enable = 1; in allocate_threshold_blocks()
1111 INIT_LIST_HEAD(&b->miscj); in allocate_threshold_blocks()
1114 if (tb->blocks) in allocate_threshold_blocks()
1115 list_add(&b->miscj, &tb->blocks->miscj); in allocate_threshold_blocks()
1117 tb->blocks = b; in allocate_threshold_blocks()
1119 err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(cpu, bank, b)); in allocate_threshold_blocks()
1123 address = get_block_address(address, low, high, bank, ++block, cpu); in allocate_threshold_blocks()
1132 kobject_uevent(&b->kobj, KOBJ_ADD); in allocate_threshold_blocks()
1138 list_del(&b->miscj); in allocate_threshold_blocks()
1139 kobject_put(&b->kobj); in allocate_threshold_blocks()
1146 struct list_head *head = &b->blocks->miscj; in __threshold_add_blocks()
1151 err = kobject_add(&b->blocks->kobj, b->kobj, b->blocks->kobj.name); in __threshold_add_blocks()
1157 err = kobject_add(&pos->kobj, b->kobj, pos->kobj.name); in __threshold_add_blocks()
1160 kobject_del(&pos->kobj); in __threshold_add_blocks()
1178 return -ENODEV; in threshold_create_bank()
1183 /* threshold descriptor already initialized on this node? */ in threshold_create_bank()
1184 if (nb && nb->bank4) { in threshold_create_bank()
1186 b = nb->bank4; in threshold_create_bank()
1187 err = kobject_add(b->kobj, &dev->kobj, name); in threshold_create_bank()
1192 refcount_inc(&b->cpus); in threshold_create_bank()
1202 err = -ENOMEM; in threshold_create_bank()
1206 /* Associate the bank with the per-CPU MCE device */ in threshold_create_bank()
1207 b->kobj = kobject_create_and_add(name, &dev->kobj); in threshold_create_bank()
1208 if (!b->kobj) { in threshold_create_bank()
1209 err = -EINVAL; in threshold_create_bank()
1214 b->shared = 1; in threshold_create_bank()
1215 refcount_set(&b->cpus, 1); in threshold_create_bank()
1219 WARN_ON(nb->bank4); in threshold_create_bank()
1220 nb->bank4 = b; in threshold_create_bank()
1232 kobject_put(b->kobj); in threshold_create_bank()
1248 list_for_each_entry_safe(pos, tmp, &bank->blocks->miscj, miscj) { in deallocate_threshold_blocks()
1249 list_del(&pos->miscj); in deallocate_threshold_blocks()
1250 kobject_put(&pos->kobj); in deallocate_threshold_blocks()
1253 kobject_put(&bank->blocks->kobj); in deallocate_threshold_blocks()
1261 kobject_del(b->kobj); in __threshold_remove_blocks()
1263 list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj) in __threshold_remove_blocks()
1264 kobject_del(&pos->kobj); in __threshold_remove_blocks()
1271 if (!bank->blocks) in threshold_remove_bank()
1274 if (!bank->shared) in threshold_remove_bank()
1277 if (!refcount_dec_and_test(&bank->cpus)) { in threshold_remove_bank()
1286 nb->bank4 = NULL; in threshold_remove_bank()
1293 kobject_put(bank->kobj); in threshold_remove_bank()
1329 * mce_threshold_create_device - Create the per-CPU MCE threshold device
1332 * Create directories and files for all valid threshold banks.
1355 return -ENOMEM; in mce_threshold_create_device()