aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2010-05-05 11:47:17 -0400
committerRobert Richter <robert.richter@amd.com>2010-05-06 09:11:15 -0400
commitbae663bc635e2726c7c5228dbf0f2051e16d1c81 (patch)
tree4330eb087e99c223d7d60d806d9fcf786482686b
parent3de668ee8d5b1e08da3200f926ff5a28aeb99bc2 (diff)
oprofile/x86: make AMD IBS hotplug capable
Current IBS code is not hotplug capable. An offline cpu might not be initialized or deinitialized properly. This patch fixes this by removing on_each_cpu() functions. The IBS init/deinit code is executed in the per-cpu functions model->setup_ctrs() and model->cpu_down() which are also called by hotplug notifiers. model->cpu_down() replaces model->exit() that became obsolete. Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Robert Richter <robert.richter@amd.com>
-rw-r--r--arch/x86/oprofile/nmi_int.c4
-rw-r--r--arch/x86/oprofile/op_model_amd.c54
-rw-r--r--arch/x86/oprofile/op_x86_model.h2
3 files changed, 19 insertions, 41 deletions
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 2a086726cad1..b28d2f1253bb 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -397,6 +397,8 @@ static void nmi_cpu_shutdown(void *dummy)
397 apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu)); 397 apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
398 apic_write(APIC_LVTERR, v); 398 apic_write(APIC_LVTERR, v);
399 nmi_cpu_restore_registers(msrs); 399 nmi_cpu_restore_registers(msrs);
400 if (model->cpu_down)
401 model->cpu_down();
400} 402}
401 403
402static void nmi_cpu_up(void *dummy) 404static void nmi_cpu_up(void *dummy)
@@ -769,6 +771,4 @@ void op_nmi_exit(void)
769{ 771{
770 if (using_nmi) 772 if (using_nmi)
771 exit_sysfs(); 773 exit_sysfs();
772 if (model->exit)
773 model->exit();
774} 774}
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 384c52410480..b67a6b5aa8d4 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -374,6 +374,15 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
374 val |= op_x86_get_ctrl(model, &counter_config[virt]); 374 val |= op_x86_get_ctrl(model, &counter_config[virt]);
375 wrmsrl(msrs->controls[i].addr, val); 375 wrmsrl(msrs->controls[i].addr, val);
376 } 376 }
377
378 if (ibs_caps)
379 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
380}
381
382static void op_amd_cpu_shutdown(void)
383{
384 if (ibs_caps)
385 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
377} 386}
378 387
379static int op_amd_check_ctrs(struct pt_regs * const regs, 388static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -436,28 +445,16 @@ static void op_amd_stop(struct op_msrs const * const msrs)
436 op_amd_stop_ibs(); 445 op_amd_stop_ibs();
437} 446}
438 447
439static u8 ibs_eilvt_off; 448static int __init_ibs_nmi(void)
440
441static inline void apic_init_ibs_nmi_per_cpu(void *arg)
442{
443 ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
444}
445
446static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
447{
448 setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
449}
450
451static int init_ibs_nmi(void)
452{ 449{
453#define IBSCTL_LVTOFFSETVAL (1 << 8) 450#define IBSCTL_LVTOFFSETVAL (1 << 8)
454#define IBSCTL 0x1cc 451#define IBSCTL 0x1cc
455 struct pci_dev *cpu_cfg; 452 struct pci_dev *cpu_cfg;
456 int nodes; 453 int nodes;
457 u32 value = 0; 454 u32 value = 0;
455 u8 ibs_eilvt_off;
458 456
459 /* per CPU setup */ 457 ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
460 on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1);
461 458
462 nodes = 0; 459 nodes = 0;
463 cpu_cfg = NULL; 460 cpu_cfg = NULL;
@@ -487,21 +484,15 @@ static int init_ibs_nmi(void)
487 return 0; 484 return 0;
488} 485}
489 486
490/* uninitialize the APIC for the IBS interrupts if needed */
491static void clear_ibs_nmi(void)
492{
493 on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
494}
495
496/* initialize the APIC for the IBS interrupts if available */ 487/* initialize the APIC for the IBS interrupts if available */
497static void ibs_init(void) 488static void init_ibs(void)
498{ 489{
499 ibs_caps = get_ibs_caps(); 490 ibs_caps = get_ibs_caps();
500 491
501 if (!ibs_caps) 492 if (!ibs_caps)
502 return; 493 return;
503 494
504 if (init_ibs_nmi()) { 495 if (__init_ibs_nmi()) {
505 ibs_caps = 0; 496 ibs_caps = 0;
506 return; 497 return;
507 } 498 }
@@ -510,14 +501,6 @@ static void ibs_init(void)
510 (unsigned)ibs_caps); 501 (unsigned)ibs_caps);
511} 502}
512 503
513static void ibs_exit(void)
514{
515 if (!ibs_caps)
516 return;
517
518 clear_ibs_nmi();
519}
520
521static int (*create_arch_files)(struct super_block *sb, struct dentry *root); 504static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
522 505
523static int setup_ibs_files(struct super_block *sb, struct dentry *root) 506static int setup_ibs_files(struct super_block *sb, struct dentry *root)
@@ -566,17 +549,12 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
566 549
567static int op_amd_init(struct oprofile_operations *ops) 550static int op_amd_init(struct oprofile_operations *ops)
568{ 551{
569 ibs_init(); 552 init_ibs();
570 create_arch_files = ops->create_files; 553 create_arch_files = ops->create_files;
571 ops->create_files = setup_ibs_files; 554 ops->create_files = setup_ibs_files;
572 return 0; 555 return 0;
573} 556}
574 557
575static void op_amd_exit(void)
576{
577 ibs_exit();
578}
579
580struct op_x86_model_spec op_amd_spec = { 558struct op_x86_model_spec op_amd_spec = {
581 .num_counters = NUM_COUNTERS, 559 .num_counters = NUM_COUNTERS,
582 .num_controls = NUM_COUNTERS, 560 .num_controls = NUM_COUNTERS,
@@ -584,9 +562,9 @@ struct op_x86_model_spec op_amd_spec = {
584 .reserved = MSR_AMD_EVENTSEL_RESERVED, 562 .reserved = MSR_AMD_EVENTSEL_RESERVED,
585 .event_mask = OP_EVENT_MASK, 563 .event_mask = OP_EVENT_MASK,
586 .init = op_amd_init, 564 .init = op_amd_init,
587 .exit = op_amd_exit,
588 .fill_in_addresses = &op_amd_fill_in_addresses, 565 .fill_in_addresses = &op_amd_fill_in_addresses,
589 .setup_ctrs = &op_amd_setup_ctrs, 566 .setup_ctrs = &op_amd_setup_ctrs,
567 .cpu_down = &op_amd_cpu_shutdown,
590 .check_ctrs = &op_amd_check_ctrs, 568 .check_ctrs = &op_amd_check_ctrs,
591 .start = &op_amd_start, 569 .start = &op_amd_start,
592 .stop = &op_amd_stop, 570 .stop = &op_amd_stop,
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h
index 551401398fba..89017fa1fd63 100644
--- a/arch/x86/oprofile/op_x86_model.h
+++ b/arch/x86/oprofile/op_x86_model.h
@@ -40,10 +40,10 @@ struct op_x86_model_spec {
40 u64 reserved; 40 u64 reserved;
41 u16 event_mask; 41 u16 event_mask;
42 int (*init)(struct oprofile_operations *ops); 42 int (*init)(struct oprofile_operations *ops);
43 void (*exit)(void);
44 int (*fill_in_addresses)(struct op_msrs * const msrs); 43 int (*fill_in_addresses)(struct op_msrs * const msrs);
45 void (*setup_ctrs)(struct op_x86_model_spec const *model, 44 void (*setup_ctrs)(struct op_x86_model_spec const *model,
46 struct op_msrs const * const msrs); 45 struct op_msrs const * const msrs);
46 void (*cpu_down)(void);
47 int (*check_ctrs)(struct pt_regs * const regs, 47 int (*check_ctrs)(struct pt_regs * const regs,
48 struct op_msrs const * const msrs); 48 struct op_msrs const * const msrs);
49 void (*start)(struct op_msrs const * const msrs); 49 void (*start)(struct op_msrs const * const msrs);