Not sure what the patch prefence is for the mailing list. This patch applies
to the fedpkg kernel git tree. Better changelog below.
Waiting on test feedback.
Cheers,
Don
---
kernel.spec | 2 +
x86-p4-make-watchdog-and-perf-work-together.patch | 267 +++++++++++++++++++++
2 files changed, 269 insertions(+), 0 deletions(-)
create mode 100644 x86-p4-make-watchdog-and-perf-work-together.patch
diff --git a/kernel.spec b/kernel.spec
index 176dbfc..f6eccf6 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -649,6 +649,7 @@ Patch12016: disable-i8042-check-on-apple-mac.patch
Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch
Patch12024: usb-add-quirk-for-logitech-webcams.patch
Patch12025: crypto-register-cryptd-first.patch
+Patch12026: x86-p4-make-watchdog-and-perf-work-together.patch
# Runtime power management
Patch12203: linux-2.6-usb-pci-autosuspend.patch
@@ -1240,6 +1241,7 @@ ApplyPatch add-appleir-usb-driver.patch
ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch
ApplyPatch usb-add-quirk-for-logitech-webcams.patch
ApplyPatch crypto-register-cryptd-first.patch
+ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch
# rhbz#605888
ApplyPatch dmar-disable-when-ricoh-multifunction.patch
diff --git a/x86-p4-make-watchdog-and-perf-work-together.patch
b/x86-p4-make-watchdog-and-perf-work-together.patch
new file mode 100644
index 0000000..9ef049b
--- /dev/null
+++ b/x86-p4-make-watchdog-and-perf-work-together.patch
@@ -0,0 +1,267 @@
+BZ
https://bugzilla.redhat.com/show_bug.cgi?id=713675
+
+Let nmi watchdog and perf work together on a P4. Combination of the following 3.1
+upstream commits (the second commit reverts the first one).
+
+commit 1880c4ae182afb5650c5678949ecfe7ff66a724e
+Author: Cyrill Gorcunov <gorcunov(a)gmail.com>
+Date: Thu Jun 23 16:49:18 2011 +0400
+
+ perf, x86: Add hw_watchdog_set_attr() in a sake of nmi-watchdog on P4
+
+ Due to restriction and specifics of Netburst PMU we need a separated
+ event for NMI watchdog. In particular every Netburst event
+ consumes not just a counter and a config register, but also an
+ additional ESCR register.
+
+ Since ESCR registers are grouped upon counters (i.e. if ESCR is occupied
+ for some event there is no room for another event to enter until its
+ released) we need to pick up the "least" used ESCR (or the most available
+ one) for nmi-watchdog purposes -- so MSR_P4_CRU_ESCR2/3 was chosen.
+
+ With this patch nmi-watchdog and perf top should be able to run simultaneously.
+
+ Signed-off-by: Cyrill Gorcunov <gorcunov(a)openvz.org>
+ CC: Lin Ming <ming.m.lin(a)intel.com>
+ CC: Arnaldo Carvalho de Melo <acme(a)redhat.com>
+ CC: Frederic Weisbecker <fweisbec(a)gmail.com>
+ Tested-and-reviewed-by: Don Zickus <dzickus(a)redhat.com>
+ Tested-and-reviewed-by: Stephane Eranian <eranian(a)google.com>
+ Signed-off-by: Peter Zijlstra <a.p.zijlstra(a)chello.nl>
+ Link:
http://lkml.kernel.org/r/20110623124918.GC13050@sun
+ Signed-off-by: Ingo Molnar <mingo(a)elte.hu>
+
+commit f91298709790b9a483752ca3c967845537df2af3
+Author: Cyrill Gorcunov <gorcunov(a)openvz.org>
+Date: Sat Jul 9 00:17:12 2011 +0400
+
+ perf, x86: P4 PMU - Introduce event alias feature
+
+ Instead of hw_nmi_watchdog_set_attr() weak function
+ and appropriate x86_pmu::hw_watchdog_set_attr() call
+ we introduce even alias mechanism which allow us
+ to drop this routines completely and isolate quirks
+ of Netburst architecture inside P4 PMU code only.
+
+ The main idea remains the same though -- to allow
+ nmi-watchdog and perf top run simultaneously.
+
+ Note the aliasing mechanism applies to generic
+ PERF_COUNT_HW_CPU_CYCLES event only because arbitrary
+ event (say passed as RAW initially) might have some
+ additional bits set inside ESCR register changing
+ the behaviour of event and we can't guarantee anymore
+ that alias event will give the same result.
+
+ P.S. Thanks a huge to Don and Steven for for testing
+ and early review.
+
+ Acked-by: Don Zickus <dzickus(a)redhat.com>
+ Tested-by: Steven Rostedt <rostedt(a)goodmis.org>
+ Signed-off-by: Cyrill Gorcunov <gorcunov(a)openvz.org>
+ CC: Ingo Molnar <mingo(a)elte.hu>
+ CC: Peter Zijlstra <a.p.zijlstra(a)chello.nl>
+ CC: Stephane Eranian <eranian(a)google.com>
+ CC: Lin Ming <ming.m.lin(a)intel.com>
+ CC: Arnaldo Carvalho de Melo <acme(a)redhat.com>
+ CC: Frederic Weisbecker <fweisbec(a)gmail.com>
+ Link:
http://lkml.kernel.org/r/20110708201712.GS23657@sun
+ Signed-off-by: Steven Rostedt <rostedt(a)goodmis.org>
+
+
+diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
+index 56fd9e3..4d86c86 100644
+--- a/arch/x86/include/asm/perf_event_p4.h
++++ b/arch/x86/include/asm/perf_event_p4.h
+@@ -102,6 +102,14 @@
+ #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT)
+
+ /*
++ * If an event has alias it should be marked
++ * with a special bit. (Don't forget to check
++ * P4_PEBS_CONFIG_MASK and related bits on
++ * modification.)
++ */
++#define P4_CONFIG_ALIASABLE (1 << 9)
++
++/*
+ * The bits we allow to pass for RAW events
+ */
+ #define P4_CONFIG_MASK_ESCR \
+@@ -123,6 +131,31 @@
+ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR)) | \
+ (p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
+
++/*
++ * In case of event aliasing we need to preserve some
++ * caller bits otherwise the mapping won't be complete.
++ */
++#define P4_CONFIG_EVENT_ALIAS_MASK \
++ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR) | \
++ p4_config_pack_cccr(P4_CCCR_EDGE | \
++ P4_CCCR_THRESHOLD_MASK | \
++ P4_CCCR_COMPLEMENT | \
++ P4_CCCR_COMPARE))
++
++#define P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS \
++ ((P4_CONFIG_HT) | \
++ p4_config_pack_escr(P4_ESCR_T0_OS | \
++ P4_ESCR_T0_USR | \
++ P4_ESCR_T1_OS | \
++ P4_ESCR_T1_USR) | \
++ p4_config_pack_cccr(P4_CCCR_OVF | \
++ P4_CCCR_CASCADE | \
++ P4_CCCR_FORCE_OVF | \
++ P4_CCCR_THREAD_ANY | \
++ P4_CCCR_OVF_PMI_T0 | \
++ P4_CCCR_OVF_PMI_T1 | \
++ P4_CONFIG_ALIASABLE))
++
+ static inline bool p4_is_event_cascaded(u64 config)
+ {
+ u32 cccr = p4_config_unpack_cccr(config);
+diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
+index ead584f..0c4071a 100644
+--- a/arch/x86/kernel/cpu/perf_event_p4.c
++++ b/arch/x86/kernel/cpu/perf_event_p4.c
+@@ -556,11 +556,92 @@ static __initconst const u64 p4_hw_cache_event_ids
+ },
+ };
+
++/*
++ * Because of Netburst being quite restricted in now
++ * many same events can run simultaneously, we use
++ * event aliases, ie different events which have the
++ * same functionallity but use non-intersected resources
++ * (ESCR/CCCR/couter registers). This allow us to run
++ * two or more semi-same events together. It is done
++ * transparently to a user space.
++ *
++ * Never set any cusom internal bits such as P4_CONFIG_HT,
++ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are
++ * either up-to-dated automatically either not appliable
++ * at all.
++ *
++ * And be really carefull choosing aliases!
++ */
++struct p4_event_alias {
++ u64 orig;
++ u64 alter;
++} p4_event_aliases[] = {
++ {
++ /*
++ * Non-halted cycles can be substituted with
++ * non-sleeping cycles (see Intel SDM Vol3b for
++ * details).
++ */
++ .orig =
++ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) |
++ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
++ .alter =
++ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT) |
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)|
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)|
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)|
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)|
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) |
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) |
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) |
++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))|
++ p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT |
++ P4_CCCR_COMPARE),
++ },
++};
++
++static u64 p4_get_alias_event(u64 config)
++{
++ u64 config_match;
++ int i;
++
++ /*
++ * Probably we're lucky and don't have to do
++ * matching over all config bits.
++ */
++ if (!(config & P4_CONFIG_ALIASABLE))
++ return 0;
++
++ config_match = config & P4_CONFIG_EVENT_ALIAS_MASK;
++
++ /*
++ * If an event was previously swapped to the alter config
++ * we should swap it back otherwise contnention on registers
++ * will return back.
++ */
++ for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) {
++ if (config_match == p4_event_aliases[i].orig) {
++ config_match = p4_event_aliases[i].alter;
++ break;
++ } else if (config_match == p4_event_aliases[i].alter) {
++ config_match = p4_event_aliases[i].orig;
++ break;
++ }
++ }
++
++ if (i >= ARRAY_SIZE(p4_event_aliases))
++ return 0;
++
++ return config_match |
++ (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS);
++}
++
+ static u64 p4_general_events[PERF_COUNT_HW_MAX] = {
+ /* non-halted CPU clocks */
+ [PERF_COUNT_HW_CPU_CYCLES] =
+ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) |
+- P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
++ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)) |
++ P4_CONFIG_ALIASABLE,
+
+ /*
+ * retired instructions
+@@ -1120,6 +1201,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int
n, int *assign
+ struct p4_event_bind *bind;
+ unsigned int i, thread, num;
+ int cntr_idx, escr_idx;
++ u64 config_alias;
++ int pass;
+
+ bitmap_zero(used_mask, X86_PMC_IDX_MAX);
+ bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE);
+@@ -1128,6 +1211,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int
n, int *assign
+
+ hwc = &cpuc->event_list[i]->hw;
+ thread = p4_ht_thread(cpu);
++ pass = 0;
++
++again:
++ /*
++ * Aliases are swappable so we may hit circular
++ * lock if both original config and alias need
++ * resources (MSR registers) which already busy.
++ */
++ if (pass > 2)
++ goto done;
++
+ bind = p4_config_get_bind(hwc->config);
+ escr_idx = p4_get_escr_idx(bind->escr_msr[thread]);
+ if (unlikely(escr_idx == -1))
+@@ -1141,8 +1235,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int
n, int *assign
+ }
+
+ cntr_idx = p4_next_cntr(thread, used_mask, bind);
+- if (cntr_idx == -1 || test_bit(escr_idx, escr_mask))
+- goto done;
++ if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) {
++ /*
++ * Probably an event alias is still available.
++ */
++ config_alias = p4_get_alias_event(hwc->config);
++ if (!config_alias)
++ goto done;
++ hwc->config = config_alias;
++ pass++;
++ goto again;
++ }
+
+ p4_pmu_swap_config_ts(hwc, cpu);
+ if (assign)
--
1.7.6.4