Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bae663bc authored by Robert Richter's avatar Robert Richter
Browse files

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: default avatarRobert Richter <robert.richter@amd.com>
parent 3de668ee
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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)
@@ -769,6 +771,4 @@ void op_nmi_exit(void)
{
	if (using_nmi)
		exit_sysfs();
	if (model->exit)
		model->exit();
}
+16 −38
Original line number Diff line number Diff line
@@ -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,
@@ -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;
@@ -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;
	}
@@ -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)
@@ -566,17 +549,12 @@ 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,
@@ -584,9 +562,9 @@ struct op_x86_model_spec op_amd_spec = {
	.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,
+1 −1
Original line number Diff line number Diff line
@@ -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);