Skip to content

Commit

Permalink
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (28 commits)
  perf session: Fix infinite loop in __perf_session__process_events
  perf evsel: Support perf_evsel__open(cpus > 1 && threads > 1)
  perf sched: Use PTHREAD_STACK_MIN to avoid pthread_attr_setstacksize() fail
  perf tools: Emit clearer message for sys_perf_event_open ENOENT return
  perf stat: better error message for unsupported events
  perf sched: Fix allocation result check
  perf, x86: P4 PMU - Fix unflagged overflows handling
  dynamic debug: Fix build issue with older gcc
  tracing: Fix TRACE_EVENT power tracepoint creation
  tracing: Fix preempt count leak
  tracepoint: Add __rcu annotation
  tracing: remove duplicate null-pointer check in skb tracepoint
  tracing/trivial: Add missing comma in TRACE_EVENT comment
  tracing: Include module.h in define_trace.h
  x86: Save rbp in pt_regs on irq entry
  x86, dumpstack: Fix unused variable warning
  x86, NMI: Clean-up default_do_nmi()
  x86, NMI: Allow NMI reason io port (0x61) to be processed on any CPU
  x86, NMI: Remove DIE_NMI_IPI
  x86, NMI: Add priorities to handlers
  ...
  • Loading branch information
torvalds committed Jan 11, 2011
2 parents edb2877 + 3d03e2e commit 4277616
Show file tree
Hide file tree
Showing 38 changed files with 442 additions and 248 deletions.
1 change: 0 additions & 1 deletion arch/x86/include/asm/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ enum die_val {
DIE_TRAP,
DIE_GPF,
DIE_CALL,
DIE_NMI_IPI,
DIE_PAGE_FAULT,
DIE_NMIUNKNOWN,
};
Expand Down
12 changes: 11 additions & 1 deletion arch/x86/include/asm/mach_traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@

#include <asm/mc146818rtc.h>

#define NMI_REASON_PORT 0x61

#define NMI_REASON_SERR 0x80
#define NMI_REASON_IOCHK 0x40
#define NMI_REASON_MASK (NMI_REASON_SERR | NMI_REASON_IOCHK)

#define NMI_REASON_CLEAR_SERR 0x04
#define NMI_REASON_CLEAR_IOCHK 0x08
#define NMI_REASON_CLEAR_MASK 0x0f

static inline unsigned char get_nmi_reason(void)
{
return inb(0x61);
return inb(NMI_REASON_PORT);
}

static inline void reassert_nmi(void)
Expand Down
20 changes: 20 additions & 0 deletions arch/x86/include/asm/nmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ void arch_trigger_all_cpu_backtrace(void);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
#endif

/*
* 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 seperate
* the priorities. This can go alot 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);

Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/perf_event_p4.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR)
#define ARCH_P4_MAX_CCCR (18)

#define ARCH_P4_CNTRVAL_BITS (40)
#define ARCH_P4_CNTRVAL_MASK ((1ULL << ARCH_P4_CNTRVAL_BITS) - 1)

#define P4_ESCR_EVENT_MASK 0x7e000000U
#define P4_ESCR_EVENT_SHIFT 25
#define P4_ESCR_EVENTMASK_MASK 0x01fffe00U
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/apic/hw_nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,

switch (cmd) {
case DIE_NMI:
case DIE_NMI_IPI:
break;

default:
Expand Down Expand Up @@ -96,7 +95,7 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
static __read_mostly struct notifier_block backtrace_notifier = {
.notifier_call = arch_trigger_all_cpu_backtrace_handler,
.next = NULL,
.priority = 1
.priority = NMI_LOCAL_LOW_PRIOR,
};

static int __init register_trigger_all_cpu_backtrace(void)
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/apic/x2apic_uv_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ void __cpuinit uv_cpu_init(void)
*/
int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
{
if (reason != DIE_NMI_IPI)
if (reason != DIE_NMIUNKNOWN)
return NOTIFY_OK;

if (in_crash_kexec)
Expand Down
5 changes: 3 additions & 2 deletions arch/x86/kernel/cpu/mcheck/mce-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/gfp.h>
#include <asm/mce.h>
#include <asm/apic.h>
#include <asm/nmi.h>

/* Update fake mce registers on current CPU. */
static void inject_mce(struct mce *m)
Expand Down Expand Up @@ -83,7 +84,7 @@ static int mce_raise_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int cpu = smp_processor_id();
struct mce *m = &__get_cpu_var(injectm);
if (val != DIE_NMI_IPI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
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)
Expand All @@ -95,7 +96,7 @@ static int mce_raise_notify(struct notifier_block *self,

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

/* Inject mce on current CPU */
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,6 @@ perf_event_nmi_handler(struct notifier_block *self,

switch (cmd) {
case DIE_NMI:
case DIE_NMI_IPI:
break;
case DIE_NMIUNKNOWN:
this_nmi = percpu_read(irq_stat.__nmi_count);
Expand Down Expand Up @@ -1317,7 +1316,7 @@ perf_event_nmi_handler(struct notifier_block *self,
static __read_mostly struct notifier_block perf_event_nmi_notifier = {
.notifier_call = perf_event_nmi_handler,
.next = NULL,
.priority = 1
.priority = NMI_LOCAL_LOW_PRIOR,
};

static struct event_constraint unconstrained;
Expand Down
28 changes: 15 additions & 13 deletions arch/x86/kernel/cpu/perf_event_p4.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,19 +753,21 @@ static int p4_hw_config(struct perf_event *event)

static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
{
int overflow = 0;
u32 low, high;
u64 v;

rdmsr(hwc->config_base + hwc->idx, low, high);

/* we need to check high bit for unflagged overflows */
if ((low & P4_CCCR_OVF) || !(high & (1 << 31))) {
overflow = 1;
(void)checking_wrmsrl(hwc->config_base + hwc->idx,
((u64)low) & ~P4_CCCR_OVF);
/* an official way for overflow indication */
rdmsrl(hwc->config_base + hwc->idx, v);
if (v & P4_CCCR_OVF) {
wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF);
return 1;
}

return overflow;
/* it might be unflagged overflow */
rdmsrl(hwc->event_base + hwc->idx, v);
if (!(v & ARCH_P4_CNTRVAL_MASK))
return 1;

return 0;
}

static void p4_pmu_disable_pebs(void)
Expand Down Expand Up @@ -1152,9 +1154,9 @@ static __initconst const struct x86_pmu p4_pmu = {
*/
.num_counters = ARCH_P4_MAX_CCCR,
.apic = 1,
.cntval_bits = 40,
.cntval_mask = (1ULL << 40) - 1,
.max_period = (1ULL << 39) - 1,
.cntval_bits = ARCH_P4_CNTRVAL_BITS,
.cntval_mask = ARCH_P4_CNTRVAL_MASK,
.max_period = (1ULL << (ARCH_P4_CNTRVAL_BITS - 1)) - 1,
.hw_config = p4_hw_config,
.schedule_events = p4_pmu_schedule_events,
/*
Expand Down
6 changes: 0 additions & 6 deletions arch/x86/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
*/
void dump_stack(void)
{
unsigned long bp = 0;
unsigned long stack;

#ifdef CONFIG_FRAME_POINTER
if (!bp)
get_bp(bp);
#endif

printk("Pid: %d, comm: %.20s %s %s %.*s\n",
current->pid, current->comm, print_tainted(),
init_utsname()->release,
Expand Down
36 changes: 23 additions & 13 deletions arch/x86/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,21 @@ ENDPROC(native_usergs_sysret64)
ENTRY(save_args)
XCPT_FRAME
cld
movq_cfi rdi, RDI+16-ARGOFFSET
movq_cfi rsi, RSI+16-ARGOFFSET
movq_cfi rdx, RDX+16-ARGOFFSET
movq_cfi rcx, RCX+16-ARGOFFSET
movq_cfi rax, RAX+16-ARGOFFSET
movq_cfi r8, R8+16-ARGOFFSET
movq_cfi r9, R9+16-ARGOFFSET
movq_cfi r10, R10+16-ARGOFFSET
movq_cfi r11, R11+16-ARGOFFSET

leaq -ARGOFFSET+16(%rsp),%rdi /* arg1 for handler */
/*
* start from rbp in pt_regs and jump over
* return address.
*/
movq_cfi rdi, RDI+8-RBP
movq_cfi rsi, RSI+8-RBP
movq_cfi rdx, RDX+8-RBP
movq_cfi rcx, RCX+8-RBP
movq_cfi rax, RAX+8-RBP
movq_cfi r8, R8+8-RBP
movq_cfi r9, R9+8-RBP
movq_cfi r10, R10+8-RBP
movq_cfi r11, R11+8-RBP

leaq -RBP+8(%rsp),%rdi /* arg1 for handler */
movq_cfi rbp, 8 /* push %rbp */
leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
testl $3, CS(%rdi)
Expand Down Expand Up @@ -782,8 +786,9 @@ END(interrupt)

/* 0(%rsp): ~(interrupt number) */
.macro interrupt func
subq $ORIG_RAX-ARGOFFSET+8, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-ARGOFFSET+8
/* reserve pt_regs for scratch regs and rbp */
subq $ORIG_RAX-RBP, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
call save_args
PARTIAL_FRAME 0
call \func
Expand All @@ -808,9 +813,14 @@ ret_from_intr:
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
leaveq

CFI_RESTORE rbp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8

/* we did not save rbx, restore only from ARGOFFSET */
addq $8, %rsp
CFI_ADJUST_CFA_OFFSET -8
exit_intr:
GET_THREAD_INFO(%rcx)
testl $3,CS-ARGOFFSET(%rsp)
Expand Down
7 changes: 2 additions & 5 deletions arch/x86/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include <asm/apicdef.h>
#include <asm/system.h>
#include <asm/apic.h>
#include <asm/nmi.h>

struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
{
Expand Down Expand Up @@ -525,10 +526,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
}
return NOTIFY_DONE;

case DIE_NMI_IPI:
/* Just ignore, we will handle the roundup on DIE_NMI. */
return NOTIFY_DONE;

case DIE_NMIUNKNOWN:
if (was_in_debug_nmi[raw_smp_processor_id()]) {
was_in_debug_nmi[raw_smp_processor_id()] = 0;
Expand Down Expand Up @@ -606,7 +603,7 @@ static struct notifier_block kgdb_notifier = {
/*
* Lowest-prio notifier priority, we want to be notified last:
*/
.priority = -INT_MAX,
.priority = NMI_LOCAL_LOW_PRIOR,
};

/**
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/kernel/reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <asm/pci_x86.h>
#include <asm/virtext.h>
#include <asm/cpu.h>
#include <asm/nmi.h>

#ifdef CONFIG_X86_32
# include <linux/ctype.h>
Expand Down Expand Up @@ -747,7 +748,7 @@ static int crash_nmi_callback(struct notifier_block *self,
{
int cpu;

if (val != DIE_NMI_IPI)
if (val != DIE_NMI)
return NOTIFY_OK;

cpu = raw_smp_processor_id();
Expand Down Expand Up @@ -778,6 +779,8 @@ static void smp_send_nmi_allbutself(void)

static struct notifier_block crash_nmi_nb = {
.notifier_call = crash_nmi_callback,
/* we want to be the first one called */
.priority = NMI_LOCAL_HIGH_PRIOR+1,
};

/* Halt all other CPUs, calling the specified function on each of them
Expand Down
Loading

0 comments on commit 4277616

Please sign in to comment.