diff options
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 26 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 2 |
3 files changed, 27 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index afc2413ba00c..9e581c5cf6d0 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -726,6 +726,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
726 | { | 726 | { |
727 | struct event_constraint *c; | 727 | struct event_constraint *c; |
728 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 728 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
729 | struct perf_event *e; | ||
729 | int i, wmin, wmax, num = 0; | 730 | int i, wmin, wmax, num = 0; |
730 | struct hw_perf_event *hwc; | 731 | struct hw_perf_event *hwc; |
731 | 732 | ||
@@ -770,13 +771,31 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
770 | wmax, assign); | 771 | wmax, assign); |
771 | 772 | ||
772 | /* | 773 | /* |
774 | * Mark the event as committed, so we do not put_constraint() | ||
775 | * in case new events are added and fail scheduling. | ||
776 | */ | ||
777 | if (!num && assign) { | ||
778 | for (i = 0; i < n; i++) { | ||
779 | e = cpuc->event_list[i]; | ||
780 | e->hw.flags |= PERF_X86_EVENT_COMMITTED; | ||
781 | } | ||
782 | } | ||
783 | /* | ||
773 | * scheduling failed or is just a simulation, | 784 | * scheduling failed or is just a simulation, |
774 | * free resources if necessary | 785 | * free resources if necessary |
775 | */ | 786 | */ |
776 | if (!assign || num) { | 787 | if (!assign || num) { |
777 | for (i = 0; i < n; i++) { | 788 | for (i = 0; i < n; i++) { |
789 | e = cpuc->event_list[i]; | ||
790 | /* | ||
791 | * do not put_constraint() on comitted events, | ||
792 | * because they are good to go | ||
793 | */ | ||
794 | if ((e->hw.flags & PERF_X86_EVENT_COMMITTED)) | ||
795 | continue; | ||
796 | |||
778 | if (x86_pmu.put_event_constraints) | 797 | if (x86_pmu.put_event_constraints) |
779 | x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]); | 798 | x86_pmu.put_event_constraints(cpuc, e); |
780 | } | 799 | } |
781 | } | 800 | } |
782 | return num ? -EINVAL : 0; | 801 | return num ? -EINVAL : 0; |
@@ -1156,6 +1175,11 @@ static void x86_pmu_del(struct perf_event *event, int flags) | |||
1156 | int i; | 1175 | int i; |
1157 | 1176 | ||
1158 | /* | 1177 | /* |
1178 | * event is descheduled | ||
1179 | */ | ||
1180 | event->hw.flags &= ~PERF_X86_EVENT_COMMITTED; | ||
1181 | |||
1182 | /* | ||
1159 | * If we're called during a txn, we don't need to do anything. | 1183 | * If we're called during a txn, we don't need to do anything. |
1160 | * The events never got scheduled and ->cancel_txn will truncate | 1184 | * The events never got scheduled and ->cancel_txn will truncate |
1161 | * the event_list. | 1185 | * the event_list. |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 4809f075d977..97e557bc4c91 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -63,11 +63,12 @@ struct event_constraint { | |||
63 | int flags; | 63 | int flags; |
64 | }; | 64 | }; |
65 | /* | 65 | /* |
66 | * struct event_constraint flags | 66 | * struct hw_perf_event.flags flags |
67 | */ | 67 | */ |
68 | #define PERF_X86_EVENT_PEBS_LDLAT 0x1 /* ld+ldlat data address sampling */ | 68 | #define PERF_X86_EVENT_PEBS_LDLAT 0x1 /* ld+ldlat data address sampling */ |
69 | #define PERF_X86_EVENT_PEBS_ST 0x2 /* st data address sampling */ | 69 | #define PERF_X86_EVENT_PEBS_ST 0x2 /* st data address sampling */ |
70 | #define PERF_X86_EVENT_PEBS_ST_HSW 0x4 /* haswell style st data sampling */ | 70 | #define PERF_X86_EVENT_PEBS_ST_HSW 0x4 /* haswell style st data sampling */ |
71 | #define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */ | ||
71 | 72 | ||
72 | struct amd_nb { | 73 | struct amd_nb { |
73 | int nb_id; /* NorthBridge id */ | 74 | int nb_id; /* NorthBridge id */ |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 5877f372b03d..fbc9210b45bc 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1450,7 +1450,6 @@ x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) | |||
1450 | if (x86_pmu.event_constraints) { | 1450 | if (x86_pmu.event_constraints) { |
1451 | for_each_event_constraint(c, x86_pmu.event_constraints) { | 1451 | for_each_event_constraint(c, x86_pmu.event_constraints) { |
1452 | if ((event->hw.config & c->cmask) == c->code) { | 1452 | if ((event->hw.config & c->cmask) == c->code) { |
1453 | /* hw.flags zeroed at initialization */ | ||
1454 | event->hw.flags |= c->flags; | 1453 | event->hw.flags |= c->flags; |
1455 | return c; | 1454 | return c; |
1456 | } | 1455 | } |
@@ -1498,7 +1497,6 @@ intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc, | |||
1498 | static void intel_put_event_constraints(struct cpu_hw_events *cpuc, | 1497 | static void intel_put_event_constraints(struct cpu_hw_events *cpuc, |
1499 | struct perf_event *event) | 1498 | struct perf_event *event) |
1500 | { | 1499 | { |
1501 | event->hw.flags = 0; | ||
1502 | intel_put_shared_regs_event_constraints(cpuc, event); | 1500 | intel_put_shared_regs_event_constraints(cpuc, event); |
1503 | } | 1501 | } |
1504 | 1502 | ||