Lines Matching +full:cpu +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0-only
3 * (c) 2005-2016 Advanced Micro Devices, Inc.
5 * Written by Jacob Shin - AMD, Inc.
17 #include <linux/cpu.h>
52 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
131 enum smca_bank_types smca_get_bank_type(unsigned int cpu, unsigned int bank) in smca_get_bank_type() argument
138 b = &per_cpu(smca_banks, cpu)[bank]; in smca_get_bank_type()
139 if (!b->hwid) in smca_get_bank_type()
142 return b->hwid->bank_type; in smca_get_bank_type()
212 * So to define a unique name for each bank, we use a temp c-string to append
226 /* CPU which controls this block's MCA bank. */
227 unsigned int cpu; member
251 * A list of the banks enabled on each logical CPU. Controls which respective
265 static void smca_configure(unsigned int bank, unsigned int cpu) in smca_configure() argument
316 if (hwid_mcatype == s_hwid->hwid_mcatype) { in smca_configure()
319 this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++; in smca_configure()
334 switch (b->address) { in bank4_names()
346 WARN(1, "Funny MSR: 0x%08x\n", b->address); in bank4_names()
372 pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt " in lvt_off_valid()
373 "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, in lvt_off_valid()
374 b->bank, b->block, b->address, hi, lo); in lvt_off_valid()
380 * On SMCA CPUs, LVT offset is programmed at a different MSR, and in lvt_off_valid()
381 * the BIOS provides the value. The original field where LVT offset in lvt_off_valid()
387 pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " in lvt_off_valid()
389 b->cpu, apic, b->bank, b->block, b->address, hi, lo); in lvt_off_valid()
403 if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off) in threshold_restart_block()
406 rdmsr(tr->b->address, lo, hi); in threshold_restart_block()
412 if (hi & MASK_OVERFLOW_HI || tr->set_lvt_off) { in threshold_restart_block()
414 hi |= THRESHOLD_MAX - tr->b->threshold_limit; in threshold_restart_block()
415 } else if (tr->old_limit) { /* change limit w/o reset */ in threshold_restart_block()
417 (tr->old_limit - tr->b->threshold_limit); in threshold_restart_block()
426 if (!tr->b->interrupt_capable) in threshold_restart_block()
429 if (tr->set_lvt_off) { in threshold_restart_block()
430 if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { in threshold_restart_block()
431 /* set new lvt offset */ in threshold_restart_block()
433 hi |= tr->lvt_off << 20; in threshold_restart_block()
437 if (tr->b->interrupt_enable) in threshold_restart_block()
443 wrmsr(tr->b->address, lo, hi); in threshold_restart_block()
446 static void mce_threshold_block_init(struct threshold_block *b, int offset) in mce_threshold_block_init() argument
451 .lvt_off = offset, in mce_threshold_block_init()
454 b->threshold_limit = THRESHOLD_MAX; in mce_threshold_block_init()
479 int def_offset = -1, def_new; in deferred_error_interrupt_enable()
486 pr_err(FW_BUG "Your BIOS is not setting up LVT offset 0x2 for deferred error IRQs correctly.\n"); in deferred_error_interrupt_enable()
504 unsigned int cpu) in get_block_address() argument
506 u32 addr = 0, offset = 0; in get_block_address() local
508 if ((bank >= per_cpu(mce_num_banks, cpu)) || (block >= NR_BLOCKS)) in get_block_address()
518 return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1); in get_block_address()
527 offset = ((low & MASK_BLKPTR_LO) >> 21); in get_block_address()
528 if (offset) in get_block_address()
529 addr = MCG_XBLK_ADDR + offset; in get_block_address()
539 int offset, u32 misc_high) in prepare_threshold_block() argument
541 unsigned int cpu = smp_processor_id(); in prepare_threshold_block() local
547 per_cpu(bank_map, cpu) |= BIT_ULL(bank); in prepare_threshold_block()
550 b.cpu = cpu; in prepare_threshold_block()
566 /* Gather LVT offset for thresholding: */ in prepare_threshold_block()
573 offset = setup_APIC_mce_threshold(offset, new); in prepare_threshold_block()
574 if (offset == new) in prepare_threshold_block()
578 mce_threshold_block_init(&b, offset); in prepare_threshold_block()
581 return offset; in prepare_threshold_block()
586 enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank); in amd_filter_mce()
589 /* See Family 17h Models 10h-2Fh Erratum #1114. */ in amd_filter_mce()
590 if (c->x86 == 0x17 && in amd_filter_mce()
591 c->x86_model >= 0x10 && c->x86_model <= 0x2F && in amd_filter_mce()
592 bank_type == SMCA_IF && XEC(m->status, 0x3f) == 10) in amd_filter_mce()
596 if (c->x86 < 0x17) { in amd_filter_mce()
597 if (m->bank == 4 && XEC(m->status, 0x1f) == 0x5) in amd_filter_mce()
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.
617 if (c->x86 == 0x15 && bank == 4) { in disable_err_thresholding()
621 } else if (c->x86 == 0x17 && in disable_err_thresholding()
622 (c->x86_model >= 0x10 && c->x86_model <= 0x2F)) { in disable_err_thresholding()
654 if (c->x86 == 15 && this_cpu_read(mce_num_banks) > 4) { in amd_apply_cpu_quirks()
667 if (c->x86 == 6 && this_cpu_read(mce_num_banks)) in amd_apply_cpu_quirks()
671 /* cpu init entry point, called from mce.c with preempt off */
674 unsigned int bank, block, cpu = smp_processor_id(); in mce_amd_feature_init() local
676 int offset = -1; in mce_amd_feature_init() local
684 smca_configure(bank, cpu); in mce_amd_feature_init()
689 address = get_block_address(address, low, high, bank, block, cpu); in mce_amd_feature_init()
703 offset = prepare_threshold_block(bank, block, address, offset, high); in mce_amd_feature_init()
723 return m->bank == 4 && XEC(m->status, 0x1f) == 8; in legacy_mce_is_memory_error()
734 if (XEC(m->status, 0x3f)) in smca_mce_is_memory_error()
737 bank_type = smca_get_bank_type(m->extcpu, m->bank); in smca_mce_is_memory_error()
776 else if (m->bank == 4) in amd_mce_usable_address()
781 if (m->status & MCI_STATUS_POISON) in amd_mce_usable_address()
795 m->status = status; in __log_error()
796 m->misc = misc; in __log_error()
797 m->bank = bank; in __log_error()
798 m->tsc = rdtsc(); in __log_error()
800 if (m->status & MCI_STATUS_ADDRV) { in __log_error()
801 m->addr = addr; in __log_error()
807 rdmsrq(MSR_AMD64_SMCA_MCx_IPID(bank), m->ipid); in __log_error()
809 if (m->status & MCI_STATUS_SYNDV) { in __log_error()
810 rdmsrq(MSR_AMD64_SMCA_MCx_SYND(bank), m->synd); in __log_error()
857 * Non-SMCA systems don't have MCA_DESTAT/MCA_DEADDR registers. in _log_error_deferred()
871 * 1) Non-SMCA systems check MCA_STATUS and log error if found.
912 if (rdmsr_safe(block->address, &low, &high)) in log_and_reset_block()
919 log_error_thresholding(block->bank, ((u64)high << 32) | low); in log_and_reset_block()
934 unsigned int bank, cpu = smp_processor_id(); in amd_threshold_interrupt() local
946 if (!(per_cpu(bank_map, cpu) & BIT_ULL(bank))) in amd_threshold_interrupt()
953 list_for_each_entry_safe(block, tmp, &thr_bank->miscj, miscj) in amd_threshold_interrupt()
960 mce_wrmsrq(mca_msr_reg(m->bank, MCA_STATUS), 0); in amd_clear_bank()
976 return sprintf(buf, "%lu\n", (unsigned long) b->name); \
987 if (!b->interrupt_capable) in SHOW_FIELDS()
988 return -EINVAL; in SHOW_FIELDS()
991 return -EINVAL; in SHOW_FIELDS()
993 b->interrupt_enable = !!new; in SHOW_FIELDS()
998 if (smp_call_function_single(b->cpu, threshold_restart_block, &tr, 1)) in SHOW_FIELDS()
999 return -ENODEV; in SHOW_FIELDS()
1011 return -EINVAL; in store_threshold_limit()
1019 tr.old_limit = b->threshold_limit; in store_threshold_limit()
1020 b->threshold_limit = new; in store_threshold_limit()
1023 if (smp_call_function_single(b->cpu, threshold_restart_block, &tr, 1)) in store_threshold_limit()
1024 return -ENODEV; in store_threshold_limit()
1033 /* CPU might be offline by now */ in show_error_count()
1034 if (rdmsr_on_cpu(b->cpu, b->address, &lo, &hi)) in show_error_count()
1035 return -ENODEV; in show_error_count()
1037 return sprintf(buf, "%u\n", ((hi & THRESHOLD_MAX) - in show_error_count()
1038 (THRESHOLD_MAX - b->threshold_limit))); in show_error_count()
1073 ret = a->show ? a->show(b, buf) : -EIO; in show()
1085 ret = a->store ? a->store(b, buf, count) : -EIO; in store()
1103 static const char *get_name(unsigned int cpu, unsigned int bank, struct threshold_block *b) in get_name() argument
1114 bank_type = smca_get_bank_type(cpu, bank); in get_name()
1117 if (b->block < ARRAY_SIZE(smca_umc_block_names)) in get_name()
1118 return smca_umc_block_names[b->block]; in get_name()
1121 if (b && b->block) { in get_name()
1122 snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN, "th_block_%u", b->block); in get_name()
1131 if (per_cpu(smca_bank_counts, cpu)[bank_type] == 1) in get_name()
1136 per_cpu(smca_banks, cpu)[bank].sysfs_id); in get_name()
1140 static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb, in allocate_threshold_blocks() argument
1167 return -ENOMEM; in allocate_threshold_blocks()
1169 b->block = block; in allocate_threshold_blocks()
1170 b->bank = bank; in allocate_threshold_blocks()
1171 b->cpu = cpu; in allocate_threshold_blocks()
1172 b->address = address; in allocate_threshold_blocks()
1173 b->interrupt_enable = 0; in allocate_threshold_blocks()
1174 b->interrupt_capable = lvt_interrupt_supported(bank, high); in allocate_threshold_blocks()
1175 b->threshold_limit = THRESHOLD_MAX; in allocate_threshold_blocks()
1177 if (b->interrupt_capable) { in allocate_threshold_blocks()
1179 b->interrupt_enable = 1; in allocate_threshold_blocks()
1184 list_add(&b->miscj, &tb->miscj); in allocate_threshold_blocks()
1186 err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(cpu, bank, b)); in allocate_threshold_blocks()
1190 address = get_block_address(address, low, high, bank, ++block, cpu); in allocate_threshold_blocks()
1194 err = allocate_threshold_blocks(cpu, tb, bank, block, address); in allocate_threshold_blocks()
1199 kobject_uevent(&b->kobj, KOBJ_ADD); in allocate_threshold_blocks()
1205 list_del(&b->miscj); in allocate_threshold_blocks()
1206 kobject_put(&b->kobj); in allocate_threshold_blocks()
1211 static int threshold_create_bank(struct threshold_bank **bp, unsigned int cpu, in threshold_create_bank() argument
1216 const char *name = get_name(cpu, bank, NULL); in threshold_create_bank()
1220 return -ENODEV; in threshold_create_bank()
1224 err = -ENOMEM; in threshold_create_bank()
1228 /* Associate the bank with the per-CPU MCE device */ in threshold_create_bank()
1229 b->kobj = kobject_create_and_add(name, &dev->kobj); in threshold_create_bank()
1230 if (!b->kobj) { in threshold_create_bank()
1231 err = -EINVAL; in threshold_create_bank()
1235 INIT_LIST_HEAD(&b->miscj); in threshold_create_bank()
1237 err = allocate_threshold_blocks(cpu, b, bank, 0, mca_msr_reg(bank, MCA_MISC)); in threshold_create_bank()
1245 kobject_put(b->kobj); in threshold_create_bank()
1261 list_for_each_entry_safe(pos, tmp, &bank->miscj, miscj) { in threshold_remove_bank()
1262 list_del(&pos->miscj); in threshold_remove_bank()
1263 kobject_put(&pos->kobj); in threshold_remove_bank()
1266 kobject_put(bank->kobj); in threshold_remove_bank()
1284 void mce_threshold_remove_device(unsigned int cpu) in mce_threshold_remove_device() argument
1302 * mce_threshold_create_device - Create the per-CPU MCE threshold device
1303 * @cpu: The plugged in CPU
1307 * This is invoked from the CPU hotplug callback which was installed in
1309 * thread running on @cpu. The callback is invoked on all CPUs which are
1312 void mce_threshold_create_device(unsigned int cpu) in mce_threshold_create_device() argument
1332 if (threshold_create_bank(bp, cpu, bank)) { in mce_threshold_create_device()