Skip to content

Commit

Permalink
x86, MCE, AMD: Use MCG_CAP MSR to find out number of banks on AMD
Browse files Browse the repository at this point in the history
Currently number of error reporting register banks is hardcoded to
6 on AMD processors. This may break in virtualized scenarios when
a hypervisor prefers to report fewer banks than what the physical
HW provides.

Since number of supported banks is reported in MSR_IA32_MCG_CAP[7:0]
that's what we should use.

Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Link: http://lkml.kernel.org/r/1363295441-1859-3-git-send-email-boris.ostrovsky@oracle.com
[ reverse NULL ptr test logic ]
Signed-off-by: Borislav Petkov <bp@suse.de>
  • Loading branch information
Boris Ostrovsky authored and Borislav Petkov committed Mar 22, 2013
1 parent c76e816 commit bafcdd3
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions arch/x86/kernel/cpu/mcheck/mce_amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include <asm/mce.h>
#include <asm/msr.h>

#define NR_BANKS 6
#define NR_BLOCKS 9
#define THRESHOLD_MAX 0xFFF
#define INT_TYPE_APIC 0x00020000
Expand All @@ -57,7 +56,7 @@ static const char * const th_names[] = {
"execution_unit",
};

static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks);
static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */

static void amd_threshold_interrupt(void);
Expand Down Expand Up @@ -215,7 +214,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
unsigned int bank, block;
int offset = -1;

for (bank = 0; bank < NR_BANKS; ++bank) {
for (bank = 0; bank < mca_cfg.banks; ++bank) {
for (block = 0; block < NR_BLOCKS; ++block) {
if (block == 0)
address = MSR_IA32_MC0_MISC + bank * 4;
Expand Down Expand Up @@ -277,7 +276,7 @@ static void amd_threshold_interrupt(void)
mce_setup(&m);

/* assume first bank caused it */
for (bank = 0; bank < NR_BANKS; ++bank) {
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
continue;
for (block = 0; block < NR_BLOCKS; ++block) {
Expand Down Expand Up @@ -468,7 +467,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
u32 low, high;
int err;

if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS))
return 0;

if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
Expand Down Expand Up @@ -636,9 +635,17 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
static __cpuinit int threshold_create_device(unsigned int cpu)
{
unsigned int bank;
struct threshold_bank **bp;
int err = 0;

for (bank = 0; bank < NR_BANKS; ++bank) {
bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
GFP_KERNEL);
if (!bp)
return -ENOMEM;

per_cpu(threshold_banks, cpu) = bp;

for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
err = threshold_create_bank(cpu, bank);
Expand Down Expand Up @@ -720,11 +727,12 @@ static void threshold_remove_device(unsigned int cpu)
{
unsigned int bank;

for (bank = 0; bank < NR_BANKS; ++bank) {
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
threshold_remove_bank(cpu, bank);
}
kfree(per_cpu(threshold_banks, cpu));
}

/* get notified when a cpu comes on/off */
Expand Down

0 comments on commit bafcdd3

Please sign in to comment.