diff options
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); |