Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 269041
b: refs/heads/master
c: 42b28ac
h: refs/heads/master
i:
  269039: c4de203
v: v3
  • Loading branch information
Arnaldo Carvalho de Melo committed Oct 7, 2011
1 parent 02a6828 commit 9772a87
Show file tree
Hide file tree
Showing 31 changed files with 762 additions and 1,135 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d48b0e173715f678698d3678fefd40f2893ce798
refs/heads/master: 42b28ac071a1a239d2a48965e9d6be0e061dd103
37 changes: 19 additions & 18 deletions trunk/arch/x86/include/asm/nmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,27 @@ void arch_trigger_all_cpu_backtrace(void);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
#endif

#define NMI_FLAG_FIRST 1

enum {
NMI_LOCAL=0,
NMI_UNKNOWN,
NMI_MAX
};

#define NMI_DONE 0
#define NMI_HANDLED 1

typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);

int register_nmi_handler(unsigned int, nmi_handler_t, unsigned long,
const char *);

void unregister_nmi_handler(unsigned int, const char *);
/*
* Define some priorities for the nmi notifier call chain.
*
* Create a local nmi bit that has a higher priority than
* external nmis, because the local ones are more frequent.
*
* Also setup some default high/normal/low settings for
* subsystems to registers with. Using 4 bits to separate
* the priorities. This can go a lot higher if needed be.
*/

#define NMI_LOCAL_SHIFT 16 /* randomly picked */
#define NMI_LOCAL_BIT (1ULL << NMI_LOCAL_SHIFT)
#define NMI_HIGH_PRIOR (1ULL << 8)
#define NMI_NORMAL_PRIOR (1ULL << 4)
#define NMI_LOW_PRIOR (1ULL << 0)
#define NMI_LOCAL_HIGH_PRIOR (NMI_LOCAL_BIT | NMI_HIGH_PRIOR)
#define NMI_LOCAL_NORMAL_PRIOR (NMI_LOCAL_BIT | NMI_NORMAL_PRIOR)
#define NMI_LOCAL_LOW_PRIOR (NMI_LOCAL_BIT | NMI_LOW_PRIOR)

void stop_nmi(void);
void restart_nmi(void);
void local_touch_nmi(void);

#endif /* _ASM_X86_NMI_H */
55 changes: 3 additions & 52 deletions trunk/arch/x86/include/asm/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
#define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23)
#define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL

#define AMD_PERFMON_EVENTSEL_GUESTONLY (1ULL << 40)
#define AMD_PERFMON_EVENTSEL_HOSTONLY (1ULL << 41)

#define AMD64_EVENTSEL_EVENT \
(ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32))
#define INTEL_ARCH_EVENT_MASK \
Expand All @@ -46,17 +43,14 @@
#define AMD64_RAW_EVENT_MASK \
(X86_RAW_EVENT_MASK | \
AMD64_EVENTSEL_EVENT)
#define AMD64_NUM_COUNTERS 4
#define AMD64_NUM_COUNTERS_F15H 6
#define AMD64_NUM_COUNTERS_MAX AMD64_NUM_COUNTERS_F15H

#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))

#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6
#define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6

/*
* Intel "Architectural Performance Monitoring" CPUID
Expand Down Expand Up @@ -116,35 +110,6 @@ union cpuid10_edx {
*/
#define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16)

/*
* IBS cpuid feature detection
*/

#define IBS_CPUID_FEATURES 0x8000001b

/*
* Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
* bit 0 is used to indicate the existence of IBS.
*/
#define IBS_CAPS_AVAIL (1U<<0)
#define IBS_CAPS_FETCHSAM (1U<<1)
#define IBS_CAPS_OPSAM (1U<<2)
#define IBS_CAPS_RDWROPCNT (1U<<3)
#define IBS_CAPS_OPCNT (1U<<4)
#define IBS_CAPS_BRNTRGT (1U<<5)
#define IBS_CAPS_OPCNTEXT (1U<<6)

#define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \
| IBS_CAPS_FETCHSAM \
| IBS_CAPS_OPSAM)

/*
* IBS APIC setup
*/
#define IBSCTL 0x1cc
#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
#define IBSCTL_LVT_OFFSET_MASK 0x0F

/* IbsFetchCtl bits/masks */
#define IBS_FETCH_RAND_EN (1ULL<<57)
#define IBS_FETCH_VAL (1ULL<<49)
Expand All @@ -159,8 +124,6 @@ union cpuid10_edx {
#define IBS_OP_MAX_CNT 0x0000FFFFULL
#define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */

extern u32 get_ibs_caps(void);

#ifdef CONFIG_PERF_EVENTS
extern void perf_events_lapic_init(void);

Expand Down Expand Up @@ -196,19 +159,7 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
); \
}

struct perf_guest_switch_msr {
unsigned msr;
u64 host, guest;
};

extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
#else
static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
{
*nr = 0;
return NULL;
}

static inline void perf_events_lapic_init(void) { }
#endif

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/include/asm/reboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void machine_real_restart(unsigned int type);
#define MRR_BIOS 0
#define MRR_APM 1

typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
typedef void (*nmi_shootdown_cb)(int, struct die_args*);
void nmi_shootdown_cpus(nmi_shootdown_cb callback);

#endif /* _ASM_X86_REBOOT_H */
2 changes: 1 addition & 1 deletion trunk/arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ endif

obj-y := process_$(BITS).o signal.o entry_$(BITS).o
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o
obj-y += time.o ioport.o ldt.o dumpstack.o
obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
obj-$(CONFIG_IRQ_WORK) += irq_work.o
obj-y += probe_roms.o
Expand Down
27 changes: 22 additions & 5 deletions trunk/arch/x86/kernel/apic/hw_nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,22 @@ void arch_trigger_all_cpu_backtrace(void)
}

static int __kprobes
arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
unsigned long cmd, void *__args)
{
struct die_args *args = __args;
struct pt_regs *regs;
int cpu;

switch (cmd) {
case DIE_NMI:
break;

default:
return NOTIFY_DONE;
}

regs = args->regs;
cpu = smp_processor_id();

if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
Expand All @@ -74,16 +86,21 @@ arch_trigger_all_cpu_backtrace_handler(unsigned int cmd, struct pt_regs *regs)
show_regs(regs);
arch_spin_unlock(&lock);
cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
return NMI_HANDLED;
return NOTIFY_STOP;
}

return NMI_DONE;
return NOTIFY_DONE;
}

static __read_mostly struct notifier_block backtrace_notifier = {
.notifier_call = arch_trigger_all_cpu_backtrace_handler,
.next = NULL,
.priority = NMI_LOCAL_LOW_PRIOR,
};

static int __init register_trigger_all_cpu_backtrace(void)
{
register_nmi_handler(NMI_LOCAL, arch_trigger_all_cpu_backtrace_handler,
0, "arch_bt");
register_die_notifier(&backtrace_notifier);
return 0;
}
early_initcall(register_trigger_all_cpu_backtrace);
Expand Down
20 changes: 16 additions & 4 deletions trunk/arch/x86/kernel/apic/x2apic_uv_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,11 +672,18 @@ void __cpuinit uv_cpu_init(void)
/*
* When NMI is received, print a stack trace.
*/
int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
{
unsigned long real_uv_nmi;
int bid;

if (reason != DIE_NMIUNKNOWN)
return NOTIFY_OK;

if (in_crash_kexec)
/* do nothing if entering the crash kernel */
return NOTIFY_OK;

/*
* Each blade has an MMR that indicates when an NMI has been sent
* to cpus on the blade. If an NMI is detected, atomically
Expand All @@ -697,7 +704,7 @@ int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
}

if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
return NMI_DONE;
return NOTIFY_DONE;

__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;

Expand All @@ -710,12 +717,17 @@ int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
dump_stack();
spin_unlock(&uv_nmi_lock);

return NMI_HANDLED;
return NOTIFY_STOP;
}

static struct notifier_block uv_dump_stack_nmi_nb = {
.notifier_call = uv_handle_nmi,
.priority = NMI_LOCAL_LOW_PRIOR - 1,
};

void uv_register_nmi_notifier(void)
{
if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
if (register_die_notifier(&uv_dump_stack_nmi_nb))
printk(KERN_WARNING "UV NMI handler failed to register\n");
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/kernel/cpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ endif
obj-$(CONFIG_X86_MCE) += mcheck/
obj-$(CONFIG_MTRR) += mtrr/

obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o perf_event_amd_ibs.o
obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o

quiet_cmd_mkcapflags = MKCAP $@
cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
Expand Down
20 changes: 13 additions & 7 deletions trunk/arch/x86/kernel/cpu/mcheck/mce-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,27 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs)

static cpumask_var_t mce_inject_cpumask;

static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
static int mce_raise_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
int cpu = smp_processor_id();
struct mce *m = &__get_cpu_var(injectm);
if (!cpumask_test_cpu(cpu, mce_inject_cpumask))
return NMI_DONE;
if (val != DIE_NMI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
return NOTIFY_DONE;
cpumask_clear_cpu(cpu, mce_inject_cpumask);
if (m->inject_flags & MCJ_EXCEPTION)
raise_exception(m, regs);
raise_exception(m, args->regs);
else if (m->status)
raise_poll(m);
return NMI_HANDLED;
return NOTIFY_STOP;
}

static struct notifier_block mce_raise_nb = {
.notifier_call = mce_raise_notify,
.priority = NMI_LOCAL_NORMAL_PRIOR,
};

/* Inject mce on current CPU */
static int raise_local(void)
{
Expand Down Expand Up @@ -209,8 +216,7 @@ static int inject_init(void)
return -ENOMEM;
printk(KERN_INFO "Machine check injector initialized\n");
mce_chrdev_ops.write = mce_write;
register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
"mce_notify");
register_die_notifier(&mce_raise_nb);
return 0;
}

Expand Down
23 changes: 9 additions & 14 deletions trunk/arch/x86/kernel/cpu/mcheck/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)

percpu_inc(mce_exception_count);

if (notify_die(DIE_NMI, "machine check", regs, error_code,
18, SIGKILL) == NOTIFY_STOP)
goto out;
if (!banks)
goto out;

Expand Down Expand Up @@ -1137,15 +1140,6 @@ static void mce_start_timer(unsigned long data)
add_timer_on(t, smp_processor_id());
}

/* Must not be called in IRQ context where del_timer_sync() can deadlock */
static void mce_timer_delete_all(void)
{
int cpu;

for_each_online_cpu(cpu)
del_timer_sync(&per_cpu(mce_timer, cpu));
}

static void mce_do_trigger(struct work_struct *work)
{
call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
Expand Down Expand Up @@ -1756,6 +1750,7 @@ static struct syscore_ops mce_syscore_ops = {

static void mce_cpu_restart(void *data)
{
del_timer_sync(&__get_cpu_var(mce_timer));
if (!mce_available(__this_cpu_ptr(&cpu_info)))
return;
__mcheck_cpu_init_generic();
Expand All @@ -1765,15 +1760,16 @@ static void mce_cpu_restart(void *data)
/* Reinit MCEs after user configuration changes */
static void mce_restart(void)
{
mce_timer_delete_all();
on_each_cpu(mce_cpu_restart, NULL, 1);
}

/* Toggle features for corrected errors */
static void mce_disable_cmci(void *data)
static void mce_disable_ce(void *all)
{
if (!mce_available(__this_cpu_ptr(&cpu_info)))
return;
if (all)
del_timer_sync(&__get_cpu_var(mce_timer));
cmci_clear();
}

Expand Down Expand Up @@ -1856,8 +1852,7 @@ static ssize_t set_ignore_ce(struct sys_device *s,
if (mce_ignore_ce ^ !!new) {
if (new) {
/* disable ce features */
mce_timer_delete_all();
on_each_cpu(mce_disable_cmci, NULL, 1);
on_each_cpu(mce_disable_ce, (void *)1, 1);
mce_ignore_ce = 1;
} else {
/* enable ce features */
Expand All @@ -1880,7 +1875,7 @@ static ssize_t set_cmci_disabled(struct sys_device *s,
if (mce_cmci_disabled ^ !!new) {
if (new) {
/* disable cmci */
on_each_cpu(mce_disable_cmci, NULL, 1);
on_each_cpu(mce_disable_ce, NULL, 1);
mce_cmci_disabled = 1;
} else {
/* enable cmci */
Expand Down
Loading

0 comments on commit 9772a87

Please sign in to comment.