Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -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 */
};
};


/*
/*
+5 −5
Original line number Original line Diff line number Diff line
@@ -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)
{
{
	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,
	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,
	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;
}
}


+2 −2
Original line number Original line Diff line number Diff line
@@ -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)
	       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!" : "",