Commit d620c67f authored by Andi Kleen's avatar Andi Kleen Committed by H. Peter Anvin

x86, mce: support more than 256 CPUs in struct mce

The old struct mce had a limitation to 256 CPUs. But x86 Linux supports
more than that now with x2apic. Add a new field extcpu to report the
extended number.
Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
Signed-off-by: default avatarHidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent f6fb0ac0
...@@ -40,9 +40,9 @@ struct mce { ...@@ -40,9 +40,9 @@ struct mce {
__u64 res2; /* dito. */ __u64 res2; /* dito. */
__u8 cs; /* code segment */ __u8 cs; /* code segment */
__u8 bank; /* machine check bank */ __u8 bank; /* machine check bank */
__u8 cpu; /* cpu that raised the error */ __u8 cpu; /* cpu number; obsolete; use extcpu now */
__u8 finished; /* entry is valid */ __u8 finished; /* entry is valid */
__u32 pad; __u32 extcpu; /* linux cpu number that detected the error */
}; };
/* /*
......
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
/* Update fake mce registers on current CPU. */ /* Update fake mce registers on current CPU. */
static void inject_mce(struct mce *m) static void inject_mce(struct mce *m)
{ {
struct mce *i = &per_cpu(injectm, m->cpu); struct mce *i = &per_cpu(injectm, m->extcpu);
/* Make sure noone reads partially written injectm */ /* Make sure noone reads partially written injectm */
i->finished = 0; i->finished = 0;
mb(); mb();
m->finished = 0; m->finished = 0;
/* First set the fields after finished */ /* First set the fields after finished */
i->cpu = m->cpu; i->extcpu = m->extcpu;
mb(); mb();
/* Now write record in order, finished last (except above) */ /* Now write record in order, finished last (except above) */
memcpy(i, m, sizeof(struct mce)); memcpy(i, m, sizeof(struct mce));
...@@ -49,7 +49,7 @@ static void raise_mce(unsigned long data) ...@@ -49,7 +49,7 @@ static void raise_mce(unsigned long data)
{ {
struct delayed_mce *dm = (struct delayed_mce *)data; struct delayed_mce *dm = (struct delayed_mce *)data;
struct mce *m = &dm->m; struct mce *m = &dm->m;
int cpu = m->cpu; int cpu = m->extcpu;
inject_mce(m); inject_mce(m);
if (m->status & MCI_STATUS_UC) { if (m->status & MCI_STATUS_UC) {
...@@ -93,7 +93,7 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf, ...@@ -93,7 +93,7 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf,
if (copy_from_user(&m, ubuf, usize)) if (copy_from_user(&m, ubuf, usize))
return -EFAULT; return -EFAULT;
if (m.cpu >= num_possible_cpus() || !cpu_online(m.cpu)) if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu))
return -EINVAL; return -EINVAL;
dm = kmalloc(sizeof(struct delayed_mce), GFP_KERNEL); dm = kmalloc(sizeof(struct delayed_mce), GFP_KERNEL);
...@@ -108,7 +108,7 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf, ...@@ -108,7 +108,7 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf,
memcpy(&dm->m, &m, sizeof(struct mce)); memcpy(&dm->m, &m, sizeof(struct mce));
setup_timer(&dm->timer, raise_mce, (unsigned long)dm); setup_timer(&dm->timer, raise_mce, (unsigned long)dm);
dm->timer.expires = jiffies + 2; dm->timer.expires = jiffies + 2;
add_timer_on(&dm->timer, m.cpu); add_timer_on(&dm->timer, m.extcpu);
return usize; return usize;
} }
......
...@@ -94,7 +94,7 @@ static inline int skip_bank_init(int i) ...@@ -94,7 +94,7 @@ static inline int skip_bank_init(int i)
void mce_setup(struct mce *m) void mce_setup(struct mce *m)
{ {
memset(m, 0, sizeof(struct mce)); memset(m, 0, sizeof(struct mce));
m->cpu = smp_processor_id(); m->cpu = m->extcpu = smp_processor_id();
rdtscll(m->tsc); rdtscll(m->tsc);
} }
...@@ -158,7 +158,7 @@ static void print_mce(struct mce *m) ...@@ -158,7 +158,7 @@ static void print_mce(struct mce *m)
KERN_EMERG "HARDWARE ERROR\n" KERN_EMERG "HARDWARE ERROR\n"
KERN_EMERG KERN_EMERG
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
m->cpu, m->mcgstatus, m->bank, m->status); m->extcpu, m->mcgstatus, m->bank, m->status);
if (m->ip) { if (m->ip) {
printk(KERN_EMERG "RIP%s %02x:<%016Lx> ", printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment