1 /** 2 * @file op_nmi.c 3 * Setup and handling of NMI PMC interrupts 4 * 5 * @remark Copyright 2002 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author John Levon 9 * @author Philippe Elie 10 */ 11 12 #include "oprofile.h" 13 #include "op_msr.h" 14 #include "op_apic.h" 15 #include "op_util.h" 16 #include "op_x86_model.h" 17 18 static struct op_msrs cpu_msrs[NR_CPUS]; 19 static struct op_x86_model_spec const * model = NULL; 20 21 static struct op_x86_model_spec const * get_model(void) 22 { 23 if (!model) { 24 /* pick out our per-model function table */ 25 switch (sysctl.cpu_type) { 26 case CPU_ATHLON: 27 case CPU_HAMMER: 28 model = &op_athlon_spec; 29 break; 30 case CPU_P4: 31 model = &op_p4_spec; 32 break; 33 #ifdef HT_SUPPORT 34 case CPU_P4_HT2: 35 model = &op_p4_ht2_spec; 36 break; 37 #endif 38 default: 39 model = &op_ppro_spec; 40 break; 41 } 42 } 43 return model; 44 } 45 46 asmlinkage void op_do_nmi(struct pt_regs * regs) 47 { 48 uint const cpu = op_cpu_id(); 49 struct op_msrs const * const msrs = &cpu_msrs[cpu]; 50 51 model->check_ctrs(cpu, msrs, regs); 52 } 53 54 /* ---------------- PMC setup ------------------ */ 55 56 static void pmc_setup_ctr(void * dummy) 57 { 58 uint const cpu = op_cpu_id(); 59 struct op_msrs const * const msrs = &cpu_msrs[cpu]; 60 get_model()->setup_ctrs(msrs); 61 } 62 63 64 static int pmc_setup_all(void) 65 { 66 if (smp_call_function(pmc_setup_ctr, NULL, 0, 1)) 67 return -EFAULT; 68 pmc_setup_ctr(NULL); 69 return 0; 70 } 71 72 73 static void pmc_start(void * info) 74 { 75 uint const cpu = op_cpu_id(); 76 struct op_msrs const * const msrs = &cpu_msrs[cpu]; 77 78 if (info && (*((uint *)info) != cpu)) 79 return; 80 81 get_model()->start(msrs); 82 } 83 84 85 static void pmc_stop(void * info) 86 { 87 uint const cpu = op_cpu_id(); 88 struct op_msrs const * const msrs = &cpu_msrs[cpu]; 89 90 if (info && (*((uint *)info) != cpu)) 91 return; 92 93 get_model()->stop(msrs); 94 } 95 96 97 static void pmc_select_start(uint cpu) 98 { 99 if (cpu == op_cpu_id()) 100 pmc_start(NULL); 101 else 102 smp_call_function(pmc_start, &cpu, 0, 1); 103 } 104 105 106 static void pmc_select_stop(uint cpu) 107 { 108 if (cpu == op_cpu_id()) 109 pmc_stop(NULL); 110 else 111 smp_call_function(pmc_stop, &cpu, 0, 1); 112 } 113 114 115 static void pmc_start_all(void) 116 { 117 int cpu, i; 118 119 for (cpu = 0 ; cpu < smp_num_cpus; cpu++) { 120 struct _oprof_data * data = &oprof_data[cpu]; 121 122 for (i = 0 ; i < get_model()->num_counters ; ++i) { 123 if (sysctl.ctr[i].enabled) 124 data->ctr_count[i] = sysctl.ctr[i].count; 125 else 126 data->ctr_count[i] = 0; 127 } 128 } 129 130 install_nmi(); 131 smp_call_function(pmc_start, NULL, 0, 1); 132 pmc_start(NULL); 133 } 134 135 136 static void pmc_stop_all(void) 137 { 138 smp_call_function(pmc_stop, NULL, 0, 1); 139 pmc_stop(NULL); 140 restore_nmi(); 141 } 142 143 144 static int pmc_check_params(void) 145 { 146 int i; 147 int enabled = 0; 148 149 for (i = 0; i < get_model()->num_counters; i++) { 150 if (!sysctl.ctr[i].enabled) 151 continue; 152 153 enabled = 1; 154 155 if (!sysctl.ctr[i].user && !sysctl.ctr[i].kernel) { 156 printk(KERN_ERR "oprofile: neither kernel nor user " 157 "set for counter %d\n", i); 158 return -EINVAL; 159 } 160 161 if (check_range(sysctl.ctr[i].count, 1, OP_MAX_PERF_COUNT, 162 "ctr count value %d not in range (%d %ld)\n")) 163 return -EINVAL; 164 165 } 166 167 if (!enabled) { 168 printk(KERN_ERR "oprofile: no counters have been enabled.\n"); 169 return -EINVAL; 170 } 171 172 return 0; 173 } 174 175 176 static void free_msr_group(struct op_msr_group * group) 177 { 178 if (group->addrs) 179 kfree(group->addrs); 180 if (group->saved) 181 kfree(group->saved); 182 group->addrs = NULL; 183 group->saved = NULL; 184 } 185 186 187 static void pmc_save_registers(void * dummy) 188 { 189 uint i; 190 uint const cpu = op_cpu_id(); 191 uint const nr_ctrs = get_model()->num_counters; 192 uint const nr_ctrls = get_model()->num_controls; 193 struct op_msr_group * counters = &cpu_msrs[cpu].counters; 194 struct op_msr_group * controls = &cpu_msrs[cpu].controls; 195 196 counters->addrs = NULL; 197 counters->saved = NULL; 198 controls->addrs = NULL; 199 controls->saved = NULL; 200 201 counters->addrs = kmalloc(nr_ctrs * sizeof(uint), GFP_KERNEL); 202 if (!counters->addrs) 203 goto fault; 204 205 counters->saved = kmalloc( 206 nr_ctrs * sizeof(struct op_saved_msr), GFP_KERNEL); 207 if (!counters->saved) 208 goto fault; 209 210 controls->addrs = kmalloc(nr_ctrls * sizeof(uint), GFP_KERNEL); 211 if (!controls->addrs) 212 goto fault; 213 214 controls->saved = kmalloc( 215 nr_ctrls * sizeof(struct op_saved_msr), GFP_KERNEL); 216 if (!controls->saved) 217 goto fault; 218 219 model->fill_in_addresses(&cpu_msrs[cpu]); 220 221 for (i = 0; i < nr_ctrs; ++i) { 222 rdmsr(counters->addrs[i], 223 counters->saved[i].low, 224 counters->saved[i].high); 225 } 226 227 for (i = 0; i < nr_ctrls; ++i) { 228 rdmsr(controls->addrs[i], 229 controls->saved[i].low, 230 controls->saved[i].high); 231 } 232 return; 233 234 fault: 235 free_msr_group(counters); 236 free_msr_group(controls); 237 } 238 239 240 static void pmc_restore_registers(void * dummy) 241 { 242 uint i; 243 uint const cpu = op_cpu_id(); 244 uint const nr_ctrs = get_model()->num_counters; 245 uint const nr_ctrls = get_model()->num_controls; 246 struct op_msr_group * counters = &cpu_msrs[cpu].counters; 247 struct op_msr_group * controls = &cpu_msrs[cpu].controls; 248 249 if (controls->addrs) { 250 for (i = 0; i < nr_ctrls; ++i) { 251 wrmsr(controls->addrs[i], 252 controls->saved[i].low, 253 controls->saved[i].high); 254 } 255 } 256 257 if (counters->addrs) { 258 for (i = 0; i < nr_ctrs; ++i) { 259 wrmsr(counters->addrs[i], 260 counters->saved[i].low, 261 counters->saved[i].high); 262 } 263 } 264 265 free_msr_group(counters); 266 free_msr_group(controls); 267 } 268 269 270 static int pmc_init(void) 271 { 272 int err = 0; 273 274 if ((err = smp_call_function(pmc_save_registers, NULL, 0, 1))) 275 goto out; 276 277 pmc_save_registers(NULL); 278 279 if ((err = apic_setup())) 280 goto out_restore; 281 282 if ((err = smp_call_function(lvtpc_apic_setup, NULL, 0, 1))) { 283 lvtpc_apic_restore(NULL); 284 goto out_restore; 285 } 286 287 out: 288 return err; 289 out_restore: 290 smp_call_function(pmc_restore_registers, NULL, 0, 1); 291 pmc_restore_registers(NULL); 292 goto out; 293 } 294 295 296 static void pmc_deinit(void) 297 { 298 smp_call_function(lvtpc_apic_restore, NULL, 0, 1); 299 lvtpc_apic_restore(NULL); 300 301 apic_restore(); 302 303 smp_call_function(pmc_restore_registers, NULL, 0, 1); 304 pmc_restore_registers(NULL); 305 } 306 307 308 static char * names[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8"}; 309 310 static int pmc_add_sysctls(ctl_table * next) 311 { 312 ctl_table * start = next; 313 ctl_table * tab; 314 int i, j; 315 316 /* now init the sysctls */ 317 for (i=0; i < get_model()->num_counters; i++) { 318 next->ctl_name = 1; 319 next->procname = names[i]; 320 next->mode = 0755; 321 322 if (!(tab = kmalloc(sizeof(ctl_table)*7, GFP_KERNEL))) 323 goto cleanup; 324 325 next->child = tab; 326 327 memset(tab, 0, sizeof(ctl_table)*7); 328 tab[0] = ((ctl_table) { 1, "enabled", &sysctl_parms.ctr[i].enabled, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 329 tab[1] = ((ctl_table) { 1, "event", &sysctl_parms.ctr[i].event, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 330 tab[2] = ((ctl_table) { 1, "count", &sysctl_parms.ctr[i].count, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 331 tab[3] = ((ctl_table) { 1, "unit_mask", &sysctl_parms.ctr[i].unit_mask, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 332 tab[4] = ((ctl_table) { 1, "kernel", &sysctl_parms.ctr[i].kernel, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 333 tab[5] = ((ctl_table) { 1, "user", &sysctl_parms.ctr[i].user, sizeof(int), 0644, NULL, lproc_dointvec, NULL, }); 334 next++; 335 } 336 337 return 0; 338 339 cleanup: 340 next = start; 341 for (j = 0; j < i; j++) { 342 kfree(next->child); 343 next++; 344 } 345 return -EFAULT; 346 } 347 348 349 static void pmc_remove_sysctls(ctl_table * next) 350 { 351 int i; 352 for (i=0; i < get_model()->num_counters; i++) { 353 kfree(next->child); 354 next++; 355 } 356 } 357 358 359 static struct op_int_operations op_nmi_ops = { 360 init: pmc_init, 361 deinit: pmc_deinit, 362 add_sysctls: pmc_add_sysctls, 363 remove_sysctls: pmc_remove_sysctls, 364 check_params: pmc_check_params, 365 setup: pmc_setup_all, 366 start: pmc_start_all, 367 stop: pmc_stop_all, 368 start_cpu: pmc_select_start, 369 stop_cpu: pmc_select_stop, 370 }; 371 372 373 struct op_int_operations const * op_int_interface() 374 { 375 return &op_nmi_ops; 376 } 377