mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
x86/mce: Stop using 32-bit MSR interfaces
The 32-bit MSR interfaces rdmsr(), wrmsr() and rdmsr_safe() are planned to be removed. Use the related 64-bit variants instead. Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://patch.msgid.link/20260629060526.3638272-9-jgross@suse.com
This commit is contained in:
parent
c69d7feb8d
commit
cff219368b
|
|
@ -280,11 +280,11 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
|
||||||
u8 *bank_counts = this_cpu_ptr(smca_bank_counts);
|
u8 *bank_counts = this_cpu_ptr(smca_bank_counts);
|
||||||
const struct smca_hwid *s_hwid;
|
const struct smca_hwid *s_hwid;
|
||||||
unsigned int i, hwid_mcatype;
|
unsigned int i, hwid_mcatype;
|
||||||
u32 high, low;
|
struct msr val;
|
||||||
u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank);
|
u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank);
|
||||||
|
|
||||||
/* Set appropriate bits in MCA_CONFIG */
|
/* Set appropriate bits in MCA_CONFIG */
|
||||||
if (!rdmsr_safe(smca_config, &low, &high)) {
|
if (!rdmsrq_safe(smca_config, &val.q)) {
|
||||||
/*
|
/*
|
||||||
* OS is required to set the MCAX bit to acknowledge that it is
|
* OS is required to set the MCAX bit to acknowledge that it is
|
||||||
* now using the new MSR ranges and new registers under each
|
* now using the new MSR ranges and new registers under each
|
||||||
|
|
@ -294,7 +294,7 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
|
||||||
*
|
*
|
||||||
* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.)
|
* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.)
|
||||||
*/
|
*/
|
||||||
high |= BIT(0);
|
val.h |= BIT(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMCA sets the Deferred Error Interrupt type per bank.
|
* SMCA sets the Deferred Error Interrupt type per bank.
|
||||||
|
|
@ -307,9 +307,9 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
|
||||||
* APIC based interrupt. First, check that no interrupt has been
|
* APIC based interrupt. First, check that no interrupt has been
|
||||||
* set.
|
* set.
|
||||||
*/
|
*/
|
||||||
if ((low & BIT(5)) && !((high >> 5) & 0x3) && data->dfr_intr_en) {
|
if ((val.l & BIT(5)) && !((val.h >> 5) & 0x3) && data->dfr_intr_en) {
|
||||||
__set_bit(bank, data->dfr_intr_banks);
|
__set_bit(bank, data->dfr_intr_banks);
|
||||||
high |= BIT(5);
|
val.h |= BIT(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -324,33 +324,33 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
|
||||||
* The OS should set this to inform the platform that the OS is ready
|
* The OS should set this to inform the platform that the OS is ready
|
||||||
* to handle the MCA Thresholding interrupt.
|
* to handle the MCA Thresholding interrupt.
|
||||||
*/
|
*/
|
||||||
if ((low & BIT(10)) && data->thr_intr_en) {
|
if ((val.l & BIT(10)) && data->thr_intr_en) {
|
||||||
__set_bit(bank, data->thr_intr_banks);
|
__set_bit(bank, data->thr_intr_banks);
|
||||||
high |= BIT(8);
|
val.h |= BIT(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
this_cpu_ptr(mce_banks_array)[bank].lsb_in_status = !!(low & BIT(8));
|
this_cpu_ptr(mce_banks_array)[bank].lsb_in_status = !!(val.l & BIT(8));
|
||||||
|
|
||||||
if (low & MCI_CONFIG_PADDRV)
|
if (val.l & MCI_CONFIG_PADDRV)
|
||||||
this_cpu_ptr(smca_banks)[bank].paddrv = 1;
|
this_cpu_ptr(smca_banks)[bank].paddrv = 1;
|
||||||
|
|
||||||
wrmsr(smca_config, low, high);
|
wrmsrq(smca_config, val.q);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
|
if (rdmsrq_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &val.q)) {
|
||||||
pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
|
pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID,
|
hwid_mcatype = HWID_MCATYPE(val.h & MCI_IPID_HWID,
|
||||||
(high & MCI_IPID_MCATYPE) >> 16);
|
(val.h & MCI_IPID_MCATYPE) >> 16);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
|
for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
|
||||||
s_hwid = &smca_hwid_mcatypes[i];
|
s_hwid = &smca_hwid_mcatypes[i];
|
||||||
|
|
||||||
if (hwid_mcatype == s_hwid->hwid_mcatype) {
|
if (hwid_mcatype == s_hwid->hwid_mcatype) {
|
||||||
this_cpu_ptr(smca_banks)[bank].hwid = s_hwid;
|
this_cpu_ptr(smca_banks)[bank].hwid = s_hwid;
|
||||||
this_cpu_ptr(smca_banks)[bank].id = low;
|
this_cpu_ptr(smca_banks)[bank].id = val.l;
|
||||||
this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++;
|
this_cpu_ptr(smca_banks)[bank].sysfs_id = bank_counts[s_hwid->bank_type]++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -432,50 +432,50 @@ static bool lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
|
||||||
static void threshold_restart_block(void *_tr)
|
static void threshold_restart_block(void *_tr)
|
||||||
{
|
{
|
||||||
struct thresh_restart *tr = _tr;
|
struct thresh_restart *tr = _tr;
|
||||||
u32 hi, lo;
|
struct msr val;
|
||||||
|
|
||||||
/* sysfs write might race against an offline operation */
|
/* sysfs write might race against an offline operation */
|
||||||
if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off)
|
if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rdmsr(tr->b->address, lo, hi);
|
rdmsrq(tr->b->address, val.q);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset error count and overflow bit.
|
* Reset error count and overflow bit.
|
||||||
* This is done during init or after handling an interrupt.
|
* This is done during init or after handling an interrupt.
|
||||||
*/
|
*/
|
||||||
if (hi & MASK_OVERFLOW_HI || tr->set_lvt_off) {
|
if (val.h & MASK_OVERFLOW_HI || tr->set_lvt_off) {
|
||||||
hi &= ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI);
|
val.h &= ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI);
|
||||||
hi |= THRESHOLD_MAX - tr->b->threshold_limit;
|
val.h |= THRESHOLD_MAX - tr->b->threshold_limit;
|
||||||
} else if (tr->old_limit) { /* change limit w/o reset */
|
} else if (tr->old_limit) { /* change limit w/o reset */
|
||||||
int new_count = (hi & THRESHOLD_MAX) +
|
int new_count = (val.h & THRESHOLD_MAX) +
|
||||||
(tr->old_limit - tr->b->threshold_limit);
|
(tr->old_limit - tr->b->threshold_limit);
|
||||||
|
|
||||||
hi = (hi & ~MASK_ERR_COUNT_HI) |
|
val.h = (val.h & ~MASK_ERR_COUNT_HI) |
|
||||||
(new_count & THRESHOLD_MAX);
|
(new_count & THRESHOLD_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear IntType */
|
/* clear IntType */
|
||||||
hi &= ~MASK_INT_TYPE_HI;
|
val.h &= ~MASK_INT_TYPE_HI;
|
||||||
|
|
||||||
if (!tr->b->interrupt_capable)
|
if (!tr->b->interrupt_capable)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (tr->set_lvt_off) {
|
if (tr->set_lvt_off) {
|
||||||
if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
|
if (lvt_off_valid(tr->b, tr->lvt_off, val.l, val.h)) {
|
||||||
/* set new lvt offset */
|
/* set new lvt offset */
|
||||||
hi &= ~MASK_LVTOFF_HI;
|
val.h &= ~MASK_LVTOFF_HI;
|
||||||
hi |= tr->lvt_off << 20;
|
val.h |= tr->lvt_off << 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr->b->interrupt_enable)
|
if (tr->b->interrupt_enable)
|
||||||
hi |= INT_TYPE_APIC;
|
val.h |= INT_TYPE_APIC;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
hi |= MASK_COUNT_EN_HI;
|
val.h |= MASK_COUNT_EN_HI;
|
||||||
wrmsr(tr->b->address, lo, hi);
|
wrmsrq(tr->b->address, val.q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void threshold_restart_bank(unsigned int bank, bool intr_en)
|
static void threshold_restart_bank(unsigned int bank, bool intr_en)
|
||||||
|
|
@ -726,7 +726,8 @@ static void smca_enable_interrupt_vectors(void)
|
||||||
void mce_amd_feature_init(struct cpuinfo_x86 *c)
|
void mce_amd_feature_init(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
unsigned int bank, block, cpu = smp_processor_id();
|
unsigned int bank, block, cpu = smp_processor_id();
|
||||||
u32 low = 0, high = 0, address = 0;
|
struct msr val = { .q = 0 };
|
||||||
|
u32 address = 0;
|
||||||
int offset = -1;
|
int offset = -1;
|
||||||
|
|
||||||
amd_apply_cpu_quirks(c);
|
amd_apply_cpu_quirks(c);
|
||||||
|
|
@ -746,21 +747,21 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
|
||||||
disable_err_thresholding(c, bank);
|
disable_err_thresholding(c, bank);
|
||||||
|
|
||||||
for (block = 0; block < NR_BLOCKS; ++block) {
|
for (block = 0; block < NR_BLOCKS; ++block) {
|
||||||
address = get_block_address(address, low, high, bank, block, cpu);
|
address = get_block_address(address, val.l, val.h, bank, block, cpu);
|
||||||
if (!address)
|
if (!address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (rdmsr_safe(address, &low, &high))
|
if (rdmsrq_safe(address, &val.q))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(high & MASK_VALID_HI))
|
if (!(val.h & MASK_VALID_HI))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(high & MASK_CNTP_HI) ||
|
if (!(val.h & MASK_CNTP_HI) ||
|
||||||
(high & MASK_LOCKED_HI))
|
(val.h & MASK_LOCKED_HI))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
offset = prepare_threshold_block(bank, block, address, offset, high);
|
offset = prepare_threshold_block(bank, block, address, offset, val.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1083,24 +1084,24 @@ static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb
|
||||||
u32 address)
|
u32 address)
|
||||||
{
|
{
|
||||||
struct threshold_block *b = NULL;
|
struct threshold_block *b = NULL;
|
||||||
u32 low, high;
|
struct msr val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((bank >= this_cpu_read(mce_num_banks)) || (block >= NR_BLOCKS))
|
if ((bank >= this_cpu_read(mce_num_banks)) || (block >= NR_BLOCKS))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rdmsr_safe(address, &low, &high))
|
if (rdmsrq_safe(address, &val.q))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(high & MASK_VALID_HI)) {
|
if (!(val.h & MASK_VALID_HI)) {
|
||||||
if (block)
|
if (block)
|
||||||
goto recurse;
|
goto recurse;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(high & MASK_CNTP_HI) ||
|
if (!(val.h & MASK_CNTP_HI) ||
|
||||||
(high & MASK_LOCKED_HI))
|
(val.h & MASK_LOCKED_HI))
|
||||||
goto recurse;
|
goto recurse;
|
||||||
|
|
||||||
b = kzalloc_obj(struct threshold_block);
|
b = kzalloc_obj(struct threshold_block);
|
||||||
|
|
@ -1112,7 +1113,7 @@ static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb
|
||||||
b->cpu = cpu;
|
b->cpu = cpu;
|
||||||
b->address = address;
|
b->address = address;
|
||||||
b->interrupt_enable = 0;
|
b->interrupt_enable = 0;
|
||||||
b->interrupt_capable = lvt_interrupt_supported(bank, high);
|
b->interrupt_capable = lvt_interrupt_supported(bank, val.h);
|
||||||
b->threshold_limit = get_thr_limit();
|
b->threshold_limit = get_thr_limit();
|
||||||
|
|
||||||
if (b->interrupt_capable) {
|
if (b->interrupt_capable) {
|
||||||
|
|
@ -1124,13 +1125,13 @@ static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb
|
||||||
|
|
||||||
list_add(&b->miscj, &tb->miscj);
|
list_add(&b->miscj, &tb->miscj);
|
||||||
|
|
||||||
mce_threshold_block_init(b, (high & MASK_LVTOFF_HI) >> 20);
|
mce_threshold_block_init(b, (val.h & MASK_LVTOFF_HI) >> 20);
|
||||||
|
|
||||||
err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(cpu, bank, b));
|
err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(cpu, bank, b));
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
recurse:
|
recurse:
|
||||||
address = get_block_address(address, low, high, bank, ++block, cpu);
|
address = get_block_address(address, val.l, val.h, bank, ++block, cpu);
|
||||||
if (!address)
|
if (!address)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1866,7 +1866,7 @@ static void __mcheck_cpu_init_generic(void)
|
||||||
|
|
||||||
rdmsrq(MSR_IA32_MCG_CAP, cap);
|
rdmsrq(MSR_IA32_MCG_CAP, cap);
|
||||||
if (cap & MCG_CTL_P)
|
if (cap & MCG_CTL_P)
|
||||||
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
|
wrmsrq(MSR_IA32_MCG_CTL, ~0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __mcheck_cpu_init_prepare_banks(void)
|
static void __mcheck_cpu_init_prepare_banks(void)
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,16 @@ int mce_p5_enabled __read_mostly;
|
||||||
/* Machine check handler for Pentium class Intel CPUs: */
|
/* Machine check handler for Pentium class Intel CPUs: */
|
||||||
noinstr void pentium_machine_check(struct pt_regs *regs)
|
noinstr void pentium_machine_check(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
u32 loaddr, hi, lotype;
|
u64 addr, type;
|
||||||
|
|
||||||
instrumentation_begin();
|
instrumentation_begin();
|
||||||
rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
|
rdmsrq(MSR_IA32_P5_MC_ADDR, addr);
|
||||||
rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
|
rdmsrq(MSR_IA32_P5_MC_TYPE, type);
|
||||||
|
|
||||||
pr_emerg("CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n",
|
pr_emerg("CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n",
|
||||||
smp_processor_id(), loaddr, lotype);
|
smp_processor_id(), (u32)addr, (u32)type);
|
||||||
|
|
||||||
if (lotype & (1<<5)) {
|
if (type & (1<<5)) {
|
||||||
pr_emerg("CPU#%d: Possible thermal failure (CPU on fire ?).\n",
|
pr_emerg("CPU#%d: Possible thermal failure (CPU on fire ?).\n",
|
||||||
smp_processor_id());
|
smp_processor_id());
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ noinstr void pentium_machine_check(struct pt_regs *regs)
|
||||||
/* Set up machine check reporting for processors with Intel style MCE: */
|
/* Set up machine check reporting for processors with Intel style MCE: */
|
||||||
void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
|
void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u32 l, h;
|
u64 q;
|
||||||
|
|
||||||
/* Default P5 to off as its often misconnected: */
|
/* Default P5 to off as its often misconnected: */
|
||||||
if (!mce_p5_enabled)
|
if (!mce_p5_enabled)
|
||||||
|
|
@ -55,8 +55,8 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Read registers before enabling: */
|
/* Read registers before enabling: */
|
||||||
rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
|
rdmsrq(MSR_IA32_P5_MC_ADDR, q);
|
||||||
rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
|
rdmsrq(MSR_IA32_P5_MC_TYPE, q);
|
||||||
pr_info("Intel old style machine check architecture supported.\n");
|
pr_info("Intel old style machine check architecture supported.\n");
|
||||||
|
|
||||||
/* Enable MCE: */
|
/* Enable MCE: */
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ noinstr void winchip_machine_check(struct pt_regs *regs)
|
||||||
/* Set up machine check reporting on the Winchip C6 series */
|
/* Set up machine check reporting on the Winchip C6 series */
|
||||||
void winchip_mcheck_init(struct cpuinfo_x86 *c)
|
void winchip_mcheck_init(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u32 lo, hi;
|
struct msr val;
|
||||||
|
|
||||||
rdmsr(MSR_IDT_FCR1, lo, hi);
|
rdmsrq(MSR_IDT_FCR1, val.q);
|
||||||
lo |= (1<<2); /* Enable EIERRINT (int 18 MCE) */
|
val.l |= (1<<2); /* Enable EIERRINT (int 18 MCE) */
|
||||||
lo &= ~(1<<4); /* Enable MCE */
|
val.l &= ~(1<<4); /* Enable MCE */
|
||||||
wrmsr(MSR_IDT_FCR1, lo, hi);
|
wrmsrq(MSR_IDT_FCR1, val.q);
|
||||||
|
|
||||||
cr4_set_bits(X86_CR4_MCE);
|
cr4_set_bits(X86_CR4_MCE);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user