Skip to content

Commit

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

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (61 commits)
  tracing: Add __used annotation to event variable
  perf, trace: Fix !x86 build bug
  perf report: Support multiple events on the TUI
  perf annotate: Fix up usage of the build id cache
  x86/mmiotrace: Remove redundant instruction prefix checks
  perf annotate: Add TUI interface
  perf tui: Remove annotate from popup menu after failure
  perf report: Don't start the TUI if -D is used
  perf: Fix getline undeclared
  perf: Optimize perf_tp_event_match()
  perf: Remove more code from the fastpath
  perf: Optimize the !vmalloc backed buffer
  perf: Optimize perf_output_copy()
  perf: Fix wakeup storm for RO mmap()s
  perf-record: Share per-cpu buffers
  perf-record: Remove -M
  perf: Ensure that IOC_OUTPUT isn't used to create multi-writer buffers
  perf, trace: Optimize tracepoints by using per-tracepoint-per-cpu hlist to track events
  perf, trace: Optimize tracepoints by removing IRQ-disable from perf/tracepoint interaction
  perf tui: Allow disabling the TUI on a per command basis in ~/.perfconfig
  ...
  • Loading branch information
torvalds committed May 27, 2010
2 parents cad719d + 49c1774 commit c5617b2
Show file tree
Hide file tree
Showing 75 changed files with 1,847 additions and 3,147 deletions.
108 changes: 61 additions & 47 deletions arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ struct cpu_hw_events {

/* Enabled/disable state. */
int enabled;

unsigned int group_flag;
};
DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };

Expand Down Expand Up @@ -981,53 +983,6 @@ static int collect_events(struct perf_event *group, int max_count,
return n;
}

static void event_sched_in(struct perf_event *event)
{
event->state = PERF_EVENT_STATE_ACTIVE;
event->oncpu = smp_processor_id();
event->tstamp_running += event->ctx->time - event->tstamp_stopped;
if (is_software_event(event))
event->pmu->enable(event);
}

int hw_perf_group_sched_in(struct perf_event *group_leader,
struct perf_cpu_context *cpuctx,
struct perf_event_context *ctx)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct perf_event *sub;
int n0, n;

if (!sparc_pmu)
return 0;

n0 = cpuc->n_events;
n = collect_events(group_leader, perf_max_events - n0,
&cpuc->event[n0], &cpuc->events[n0],
&cpuc->current_idx[n0]);
if (n < 0)
return -EAGAIN;
if (check_excludes(cpuc->event, n0, n))
return -EINVAL;
if (sparc_check_constraints(cpuc->event, cpuc->events, n + n0))
return -EAGAIN;
cpuc->n_events = n0 + n;
cpuc->n_added += n;

cpuctx->active_oncpu += n;
n = 1;
event_sched_in(group_leader);
list_for_each_entry(sub, &group_leader->sibling_list, group_entry) {
if (sub->state != PERF_EVENT_STATE_OFF) {
event_sched_in(sub);
n++;
}
}
ctx->nr_active += n;

return 1;
}

static int sparc_pmu_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
Expand All @@ -1045,11 +1000,20 @@ static int sparc_pmu_enable(struct perf_event *event)
cpuc->events[n0] = event->hw.event_base;
cpuc->current_idx[n0] = PIC_NO_INDEX;

/*
* If group events scheduling transaction was started,
* skip the schedulability test here, it will be peformed
* at commit time(->commit_txn) as a whole
*/
if (cpuc->group_flag & PERF_EVENT_TXN_STARTED)
goto nocheck;

if (check_excludes(cpuc->event, n0, 1))
goto out;
if (sparc_check_constraints(cpuc->event, cpuc->events, n0 + 1))
goto out;

nocheck:
cpuc->n_events++;
cpuc->n_added++;

Expand Down Expand Up @@ -1129,11 +1093,61 @@ static int __hw_perf_event_init(struct perf_event *event)
return 0;
}

/*
* Start group events scheduling transaction
* Set the flag to make pmu::enable() not perform the
* schedulability test, it will be performed at commit time
*/
static void sparc_pmu_start_txn(const struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

cpuhw->group_flag |= PERF_EVENT_TXN_STARTED;
}

/*
* Stop group events scheduling transaction
* Clear the flag and pmu::enable() will perform the
* schedulability test.
*/
static void sparc_pmu_cancel_txn(const struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

cpuhw->group_flag &= ~PERF_EVENT_TXN_STARTED;
}

/*
* Commit group events scheduling transaction
* Perform the group schedulability test as a whole
* Return 0 if success
*/
static int sparc_pmu_commit_txn(const struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int n;

if (!sparc_pmu)
return -EINVAL;

cpuc = &__get_cpu_var(cpu_hw_events);
n = cpuc->n_events;
if (check_excludes(cpuc->event, 0, n))
return -EINVAL;
if (sparc_check_constraints(cpuc->event, cpuc->events, n))
return -EAGAIN;

return 0;
}

static const struct pmu pmu = {
.enable = sparc_pmu_enable,
.disable = sparc_pmu_disable,
.read = sparc_pmu_read,
.unthrottle = sparc_pmu_unthrottle,
.start_txn = sparc_pmu_start_txn,
.cancel_txn = sparc_pmu_cancel_txn,
.commit_txn = sparc_pmu_commit_txn,
};

const struct pmu *hw_perf_event_init(struct perf_event *event)
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/include/asm/perf_event_p4.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@
P4_CCCR_ENABLE)

/* HT mask */
#define P4_CCCR_MASK_HT (P4_CCCR_MASK | P4_CCCR_THREAD_ANY)
#define P4_CCCR_MASK_HT \
(P4_CCCR_MASK | P4_CCCR_OVF_PMI_T1 | P4_CCCR_THREAD_ANY)

#define P4_GEN_ESCR_EMASK(class, name, bit) \
class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT)
Expand Down
6 changes: 5 additions & 1 deletion arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,11 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski
*/
regs->bp = rewind_frame_pointer(skip + 1);
regs->cs = __KERNEL_CS;
local_save_flags(regs->flags);
/*
* We abuse bit 3 to pass exact information, see perf_misc_flags
* and the comment with PERF_EFLAGS_EXACT.
*/
regs->flags = 0;
}

unsigned long perf_instruction_pointer(struct pt_regs *regs)
Expand Down
41 changes: 21 additions & 20 deletions arch/x86/kernel/cpu/perf_event_p4.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,15 +465,21 @@ static int p4_hw_config(struct perf_event *event)
return rc;
}

static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
{
unsigned long dummy;
int overflow = 0;
u32 low, high;

rdmsrl(hwc->config_base + hwc->idx, dummy);
if (dummy & P4_CCCR_OVF) {
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)dummy) & ~P4_CCCR_OVF);
((u64)low) & ~P4_CCCR_OVF);
}

return overflow;
}

static inline void p4_pmu_disable_event(struct perf_event *event)
Expand Down Expand Up @@ -584,21 +590,15 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)

WARN_ON_ONCE(hwc->idx != idx);

/*
* FIXME: Redundant call, actually not needed
* but just to check if we're screwed
*/
p4_pmu_clear_cccr_ovf(hwc);
/* it might be unflagged overflow */
handled = p4_pmu_clear_cccr_ovf(hwc);

val = x86_perf_event_update(event);
if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
continue;

/*
* event overflow
*/
handled = 1;
data.period = event->hw.last_period;
/* event overflow for sure */
data.period = event->hw.last_period;

if (!x86_perf_event_set_period(event))
continue;
Expand Down Expand Up @@ -670,7 +670,7 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu)

/*
* ESCR address hashing is tricky, ESCRs are not sequential
* in memory but all starts from MSR_P4_BSU_ESCR0 (0x03e0) and
* in memory but all starts from MSR_P4_BSU_ESCR0 (0x03a0) and
* the metric between any ESCRs is laid in range [0xa0,0xe1]
*
* so we make ~70% filled hashtable
Expand Down Expand Up @@ -735,8 +735,9 @@ static int p4_get_escr_idx(unsigned int addr)
{
unsigned int idx = P4_ESCR_MSR_IDX(addr);

if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE ||
!p4_escr_table[idx])) {
if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE ||
!p4_escr_table[idx] ||
p4_escr_table[idx] != addr)) {
WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr);
return -1;
}
Expand All @@ -762,7 +763,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
{
unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)];
int cpu = raw_smp_processor_id();
int cpu = smp_processor_id();
struct hw_perf_event *hwc;
struct p4_event_bind *bind;
unsigned int i, thread, num;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/pf_in.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
/* IA32 Manual 3, 2-1 */
static unsigned char prefix_codes[] = {
0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64,
0x65, 0x2E, 0x3E, 0x66, 0x67
0x65, 0x66, 0x67
};
/* IA32 Manual 3, 3-432*/
static unsigned int reg_rop[] = {
Expand Down
Loading

0 comments on commit c5617b2

Please sign in to comment.