Skip to content

Commit

Permalink
oprofile/x86: make AMD IBS hotplug capable
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Robert Richter committed May 6, 2010
1 parent 3de668e commit bae663b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 41 deletions.
4 changes: 2 additions & 2 deletions arch/x86/oprofile/nmi_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ static void nmi_cpu_shutdown(void *dummy)
apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
apic_write(APIC_LVTERR, v);
nmi_cpu_restore_registers(msrs);
if (model->cpu_down)
model->cpu_down();
}

static void nmi_cpu_up(void *dummy)
Expand Down Expand Up @@ -769,6 +771,4 @@ void op_nmi_exit(void)
{
if (using_nmi)
exit_sysfs();
if (model->exit)
model->exit();
}
54 changes: 16 additions & 38 deletions arch/x86/oprofile/op_model_amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,15 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
val |= op_x86_get_ctrl(model, &counter_config[virt]);
wrmsrl(msrs->controls[i].addr, val);
}

if (ibs_caps)
setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
}

static void op_amd_cpu_shutdown(void)
{
if (ibs_caps)
setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
}

static int op_amd_check_ctrs(struct pt_regs * const regs,
Expand Down Expand Up @@ -436,28 +445,16 @@ static void op_amd_stop(struct op_msrs const * const msrs)
op_amd_stop_ibs();
}

static u8 ibs_eilvt_off;

static inline void apic_init_ibs_nmi_per_cpu(void *arg)
{
ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
}

static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
{
setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
}

static int init_ibs_nmi(void)
static int __init_ibs_nmi(void)
{
#define IBSCTL_LVTOFFSETVAL (1 << 8)
#define IBSCTL 0x1cc
struct pci_dev *cpu_cfg;
int nodes;
u32 value = 0;
u8 ibs_eilvt_off;

/* per CPU setup */
on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1);
ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);

nodes = 0;
cpu_cfg = NULL;
Expand Down Expand Up @@ -487,21 +484,15 @@ static int init_ibs_nmi(void)
return 0;
}

/* uninitialize the APIC for the IBS interrupts if needed */
static void clear_ibs_nmi(void)
{
on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
}

/* initialize the APIC for the IBS interrupts if available */
static void ibs_init(void)
static void init_ibs(void)
{
ibs_caps = get_ibs_caps();

if (!ibs_caps)
return;

if (init_ibs_nmi()) {
if (__init_ibs_nmi()) {
ibs_caps = 0;
return;
}
Expand All @@ -510,14 +501,6 @@ static void ibs_init(void)
(unsigned)ibs_caps);
}

static void ibs_exit(void)
{
if (!ibs_caps)
return;

clear_ibs_nmi();
}

static int (*create_arch_files)(struct super_block *sb, struct dentry *root);

static int setup_ibs_files(struct super_block *sb, struct dentry *root)
Expand Down Expand Up @@ -566,27 +549,22 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)

static int op_amd_init(struct oprofile_operations *ops)
{
ibs_init();
init_ibs();
create_arch_files = ops->create_files;
ops->create_files = setup_ibs_files;
return 0;
}

static void op_amd_exit(void)
{
ibs_exit();
}

struct op_x86_model_spec op_amd_spec = {
.num_counters = NUM_COUNTERS,
.num_controls = NUM_COUNTERS,
.num_virt_counters = NUM_VIRT_COUNTERS,
.reserved = MSR_AMD_EVENTSEL_RESERVED,
.event_mask = OP_EVENT_MASK,
.init = op_amd_init,
.exit = op_amd_exit,
.fill_in_addresses = &op_amd_fill_in_addresses,
.setup_ctrs = &op_amd_setup_ctrs,
.cpu_down = &op_amd_cpu_shutdown,
.check_ctrs = &op_amd_check_ctrs,
.start = &op_amd_start,
.stop = &op_amd_stop,
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/oprofile/op_x86_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ struct op_x86_model_spec {
u64 reserved;
u16 event_mask;
int (*init)(struct oprofile_operations *ops);
void (*exit)(void);
int (*fill_in_addresses)(struct op_msrs * const msrs);
void (*setup_ctrs)(struct op_x86_model_spec const *model,
struct op_msrs const * const msrs);
void (*cpu_down)(void);
int (*check_ctrs)(struct pt_regs * const regs,
struct op_msrs const * const msrs);
void (*start)(struct op_msrs const * const msrs);
Expand Down

0 comments on commit bae663b

Please sign in to comment.