diff options
author | Don Zickus <dzickus@redhat.com> | 2006-09-26 04:52:26 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:26 -0400 |
commit | cb9c448c661d40ce2efbce8e9c19cc4d420d8ccc (patch) | |
tree | 2aa5614f06e57e8f5266f91ccfff1a92fa9f3792 /arch/i386/oprofile/nmi_int.c | |
parent | 828f0afda123a96ff4e8078f057a302f4b4232ae (diff) |
[PATCH] i386: Utilize performance counter reservation framework in oprofile
Incorporates the new performance counter reservation system in oprofile.
Also cleans up a lot of the initialization code. The code original zero'd
out every register associated with performance counters regardless if those
registers were used or not. This causes issues with the nmi watchdog.
Now oprofile tries to reserve registers and gives up if it can't get them.
Cc: levon@movementarian.org
Cc: oprofile-list@lists.sf.net
Signed-off-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/oprofile/nmi_int.c')
-rw-r--r-- | arch/i386/oprofile/nmi_int.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index 5f8dc8a21bd7..8710ca081b1e 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c | |||
@@ -98,15 +98,19 @@ static void nmi_cpu_save_registers(struct op_msrs * msrs) | |||
98 | unsigned int i; | 98 | unsigned int i; |
99 | 99 | ||
100 | for (i = 0; i < nr_ctrs; ++i) { | 100 | for (i = 0; i < nr_ctrs; ++i) { |
101 | rdmsr(counters[i].addr, | 101 | if (counters[i].addr){ |
102 | counters[i].saved.low, | 102 | rdmsr(counters[i].addr, |
103 | counters[i].saved.high); | 103 | counters[i].saved.low, |
104 | counters[i].saved.high); | ||
105 | } | ||
104 | } | 106 | } |
105 | 107 | ||
106 | for (i = 0; i < nr_ctrls; ++i) { | 108 | for (i = 0; i < nr_ctrls; ++i) { |
107 | rdmsr(controls[i].addr, | 109 | if (controls[i].addr){ |
108 | controls[i].saved.low, | 110 | rdmsr(controls[i].addr, |
109 | controls[i].saved.high); | 111 | controls[i].saved.low, |
112 | controls[i].saved.high); | ||
113 | } | ||
110 | } | 114 | } |
111 | } | 115 | } |
112 | 116 | ||
@@ -205,15 +209,19 @@ static void nmi_restore_registers(struct op_msrs * msrs) | |||
205 | unsigned int i; | 209 | unsigned int i; |
206 | 210 | ||
207 | for (i = 0; i < nr_ctrls; ++i) { | 211 | for (i = 0; i < nr_ctrls; ++i) { |
208 | wrmsr(controls[i].addr, | 212 | if (controls[i].addr){ |
209 | controls[i].saved.low, | 213 | wrmsr(controls[i].addr, |
210 | controls[i].saved.high); | 214 | controls[i].saved.low, |
215 | controls[i].saved.high); | ||
216 | } | ||
211 | } | 217 | } |
212 | 218 | ||
213 | for (i = 0; i < nr_ctrs; ++i) { | 219 | for (i = 0; i < nr_ctrs; ++i) { |
214 | wrmsr(counters[i].addr, | 220 | if (counters[i].addr){ |
215 | counters[i].saved.low, | 221 | wrmsr(counters[i].addr, |
216 | counters[i].saved.high); | 222 | counters[i].saved.low, |
223 | counters[i].saved.high); | ||
224 | } | ||
217 | } | 225 | } |
218 | } | 226 | } |
219 | 227 | ||
@@ -234,6 +242,7 @@ static void nmi_cpu_shutdown(void * dummy) | |||
234 | apic_write(APIC_LVTPC, saved_lvtpc[cpu]); | 242 | apic_write(APIC_LVTPC, saved_lvtpc[cpu]); |
235 | apic_write(APIC_LVTERR, v); | 243 | apic_write(APIC_LVTERR, v); |
236 | nmi_restore_registers(msrs); | 244 | nmi_restore_registers(msrs); |
245 | model->shutdown(msrs); | ||
237 | } | 246 | } |
238 | 247 | ||
239 | 248 | ||
@@ -284,6 +293,14 @@ static int nmi_create_files(struct super_block * sb, struct dentry * root) | |||
284 | struct dentry * dir; | 293 | struct dentry * dir; |
285 | char buf[4]; | 294 | char buf[4]; |
286 | 295 | ||
296 | /* quick little hack to _not_ expose a counter if it is not | ||
297 | * available for use. This should protect userspace app. | ||
298 | * NOTE: assumes 1:1 mapping here (that counters are organized | ||
299 | * sequentially in their struct assignment). | ||
300 | */ | ||
301 | if (unlikely(!avail_to_resrv_perfctr_nmi_bit(i))) | ||
302 | continue; | ||
303 | |||
287 | snprintf(buf, sizeof(buf), "%d", i); | 304 | snprintf(buf, sizeof(buf), "%d", i); |
288 | dir = oprofilefs_mkdir(sb, root, buf); | 305 | dir = oprofilefs_mkdir(sb, root, buf); |
289 | oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); | 306 | oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); |