diff options
| author | Robert Richter <robert.richter@amd.com> | 2010-03-23 14:33:21 -0400 |
|---|---|---|
| committer | Robert Richter <robert.richter@amd.com> | 2010-05-04 05:35:26 -0400 |
| commit | d0e4120fda6f87eead438eed4d49032e12060e58 (patch) | |
| tree | 57f3ab727aa12bc63f19437a0a026e2ea5bd6d67 | |
| parent | 8f5a2dd83a1f8e89fdc17eb0f2f07c2e713e635a (diff) | |
oprofile/x86: reserve counter msrs pairwise
For AMD's and Intel's P6 generic performance counters have pairwise
counter and control msrs. This patch changes the counter reservation
in a way that both msrs must be registered. It joins some counter
loops and also removes the unnecessary NUM_CONTROLS macro in the AMD
implementation.
Signed-off-by: Robert Richter <robert.richter@amd.com>
| -rw-r--r-- | arch/x86/oprofile/op_model_amd.c | 43 | ||||
| -rw-r--r-- | arch/x86/oprofile/op_model_ppro.c | 36 |
2 files changed, 36 insertions, 43 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 090cbbec7dbd..2e2bc902b867 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
| @@ -30,13 +30,10 @@ | |||
| 30 | #include "op_counter.h" | 30 | #include "op_counter.h" |
| 31 | 31 | ||
| 32 | #define NUM_COUNTERS 4 | 32 | #define NUM_COUNTERS 4 |
| 33 | #define NUM_CONTROLS 4 | ||
| 34 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX | 33 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX |
| 35 | #define NUM_VIRT_COUNTERS 32 | 34 | #define NUM_VIRT_COUNTERS 32 |
| 36 | #define NUM_VIRT_CONTROLS 32 | ||
| 37 | #else | 35 | #else |
| 38 | #define NUM_VIRT_COUNTERS NUM_COUNTERS | 36 | #define NUM_VIRT_COUNTERS NUM_COUNTERS |
| 39 | #define NUM_VIRT_CONTROLS NUM_CONTROLS | ||
| 40 | #endif | 37 | #endif |
| 41 | 38 | ||
| 42 | #define OP_EVENT_MASK 0x0FFF | 39 | #define OP_EVENT_MASK 0x0FFF |
| @@ -134,13 +131,15 @@ static void op_amd_fill_in_addresses(struct op_msrs * const msrs) | |||
| 134 | int i; | 131 | int i; |
| 135 | 132 | ||
| 136 | for (i = 0; i < NUM_COUNTERS; i++) { | 133 | for (i = 0; i < NUM_COUNTERS; i++) { |
| 137 | if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) | 134 | if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) |
| 138 | msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; | 135 | continue; |
| 139 | } | 136 | if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { |
| 140 | 137 | release_perfctr_nmi(MSR_K7_PERFCTR0 + i); | |
| 141 | for (i = 0; i < NUM_CONTROLS; i++) { | 138 | continue; |
| 142 | if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) | 139 | } |
| 143 | msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; | 140 | /* both registers must be reserved */ |
| 141 | msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; | ||
| 142 | msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; | ||
| 144 | } | 143 | } |
| 145 | } | 144 | } |
| 146 | 145 | ||
| @@ -160,7 +159,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, | |||
| 160 | } | 159 | } |
| 161 | 160 | ||
| 162 | /* clear all counters */ | 161 | /* clear all counters */ |
| 163 | for (i = 0; i < NUM_CONTROLS; ++i) { | 162 | for (i = 0; i < NUM_COUNTERS; ++i) { |
| 164 | if (unlikely(!msrs->controls[i].addr)) { | 163 | if (unlikely(!msrs->controls[i].addr)) { |
| 165 | if (counter_config[i].enabled && !smp_processor_id()) | 164 | if (counter_config[i].enabled && !smp_processor_id()) |
| 166 | /* | 165 | /* |
| @@ -175,12 +174,10 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, | |||
| 175 | op_x86_warn_in_use(i); | 174 | op_x86_warn_in_use(i); |
| 176 | val &= model->reserved; | 175 | val &= model->reserved; |
| 177 | wrmsrl(msrs->controls[i].addr, val); | 176 | wrmsrl(msrs->controls[i].addr, val); |
| 178 | } | 177 | /* |
| 179 | 178 | * avoid a false detection of ctr overflows in NMI | |
| 180 | /* avoid a false detection of ctr overflows in NMI handler */ | 179 | * handler |
| 181 | for (i = 0; i < NUM_COUNTERS; ++i) { | 180 | */ |
| 182 | if (unlikely(!msrs->counters[i].addr)) | ||
| 183 | continue; | ||
| 184 | wrmsrl(msrs->counters[i].addr, -1LL); | 181 | wrmsrl(msrs->counters[i].addr, -1LL); |
| 185 | } | 182 | } |
| 186 | 183 | ||
| @@ -430,12 +427,10 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) | |||
| 430 | int i; | 427 | int i; |
| 431 | 428 | ||
| 432 | for (i = 0; i < NUM_COUNTERS; ++i) { | 429 | for (i = 0; i < NUM_COUNTERS; ++i) { |
| 433 | if (msrs->counters[i].addr) | 430 | if (!msrs->counters[i].addr) |
| 434 | release_perfctr_nmi(MSR_K7_PERFCTR0 + i); | 431 | continue; |
| 435 | } | 432 | release_perfctr_nmi(MSR_K7_PERFCTR0 + i); |
| 436 | for (i = 0; i < NUM_CONTROLS; ++i) { | 433 | release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); |
| 437 | if (msrs->controls[i].addr) | ||
| 438 | release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); | ||
| 439 | } | 434 | } |
| 440 | } | 435 | } |
| 441 | 436 | ||
| @@ -583,7 +578,7 @@ static void op_amd_exit(void) | |||
| 583 | 578 | ||
| 584 | struct op_x86_model_spec op_amd_spec = { | 579 | struct op_x86_model_spec op_amd_spec = { |
| 585 | .num_counters = NUM_COUNTERS, | 580 | .num_counters = NUM_COUNTERS, |
| 586 | .num_controls = NUM_CONTROLS, | 581 | .num_controls = NUM_COUNTERS, |
| 587 | .num_virt_counters = NUM_VIRT_COUNTERS, | 582 | .num_virt_counters = NUM_VIRT_COUNTERS, |
| 588 | .reserved = MSR_AMD_EVENTSEL_RESERVED, | 583 | .reserved = MSR_AMD_EVENTSEL_RESERVED, |
| 589 | .event_mask = OP_EVENT_MASK, | 584 | .event_mask = OP_EVENT_MASK, |
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index 2bf90fafa7b5..f8e268e8e992 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c | |||
| @@ -35,13 +35,15 @@ static void ppro_fill_in_addresses(struct op_msrs * const msrs) | |||
| 35 | int i; | 35 | int i; |
| 36 | 36 | ||
| 37 | for (i = 0; i < num_counters; i++) { | 37 | for (i = 0; i < num_counters; i++) { |
| 38 | if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i)) | 38 | if (!reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i)) |
| 39 | msrs->counters[i].addr = MSR_P6_PERFCTR0 + i; | 39 | continue; |
| 40 | } | 40 | if (!reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) { |
| 41 | 41 | release_perfctr_nmi(MSR_P6_PERFCTR0 + i); | |
| 42 | for (i = 0; i < num_counters; i++) { | 42 | continue; |
| 43 | if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) | 43 | } |
| 44 | msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i; | 44 | /* both registers must be reserved */ |
| 45 | msrs->counters[i].addr = MSR_P6_PERFCTR0 + i; | ||
| 46 | msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i; | ||
| 45 | } | 47 | } |
| 46 | } | 48 | } |
| 47 | 49 | ||
| @@ -92,12 +94,10 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, | |||
| 92 | op_x86_warn_in_use(i); | 94 | op_x86_warn_in_use(i); |
| 93 | val &= model->reserved; | 95 | val &= model->reserved; |
| 94 | wrmsrl(msrs->controls[i].addr, val); | 96 | wrmsrl(msrs->controls[i].addr, val); |
| 95 | } | 97 | /* |
| 96 | 98 | * avoid a false detection of ctr overflows in NMI * | |
| 97 | /* avoid a false detection of ctr overflows in NMI handler */ | 99 | * handler |
| 98 | for (i = 0; i < num_counters; ++i) { | 100 | */ |
| 99 | if (unlikely(!msrs->counters[i].addr)) | ||
| 100 | continue; | ||
| 101 | wrmsrl(msrs->counters[i].addr, -1LL); | 101 | wrmsrl(msrs->counters[i].addr, -1LL); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| @@ -194,12 +194,10 @@ static void ppro_shutdown(struct op_msrs const * const msrs) | |||
| 194 | int i; | 194 | int i; |
| 195 | 195 | ||
| 196 | for (i = 0; i < num_counters; ++i) { | 196 | for (i = 0; i < num_counters; ++i) { |
| 197 | if (msrs->counters[i].addr) | 197 | if (!msrs->counters[i].addr) |
| 198 | release_perfctr_nmi(MSR_P6_PERFCTR0 + i); | 198 | continue; |
| 199 | } | 199 | release_perfctr_nmi(MSR_P6_PERFCTR0 + i); |
| 200 | for (i = 0; i < num_counters; ++i) { | 200 | release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); |
| 201 | if (msrs->controls[i].addr) | ||
| 202 | release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); | ||
| 203 | } | 201 | } |
| 204 | if (reset_value) { | 202 | if (reset_value) { |
| 205 | kfree(reset_value); | 203 | kfree(reset_value); |
