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

Commit cb37af77 authored by Yan, Zheng's avatar Yan, Zheng Committed by Thomas Gleixner
Browse files

perf/x86: Add Intel Westmere-EX uncore support



The Westmere-EX uncore is similar to the Nehalem-EX uncore. The
differences are:
 - Westmere-EX uncore has 10 instances of Cbox. The MSRs for Cbox8
   and Cbox9 in the Westmere-EX aren't contiguous with Cbox 0~7.
 - The fvid field in the ZDP_CTL_FVC register in the Mbox is
   different. It's 5 bits in the Nehalem-EX, 6 bits in the
   Westmere-EX.

Signed-off-by: default avatarYan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1344229882-3907-3-git-send-email-zheng.z.yan@intel.com


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent ebb6cc03
Loading
Loading
Loading
Loading
+47 −9
Original line number Diff line number Diff line
@@ -901,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = {
	.attrs = nhmex_uncore_cbox_formats_attr,
};

/* msr offset for each instance of cbox */
static unsigned nhmex_cbox_msr_offsets[] = {
	0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0,
};

static struct intel_uncore_type nhmex_uncore_cbox = {
	.name			= "cbox",
	.num_counters		= 6,
	.num_boxes		= 8,
	.num_boxes		= 10,
	.perf_ctr_bits		= 48,
	.event_ctl		= NHMEX_C0_MSR_PMON_EV_SEL0,
	.perf_ctr		= NHMEX_C0_MSR_PMON_CTR0,
	.event_mask		= NHMEX_PMON_RAW_EVENT_MASK,
	.box_ctl		= NHMEX_C0_MSR_PMON_GLOBAL_CTL,
	.msr_offset		= NHMEX_C_MSR_OFFSET,
	.msr_offsets		= nhmex_cbox_msr_offsets,
	.pair_ctr_ctl		= 1,
	.ops			= &nhmex_uncore_ops,
	.format_group		= &nhmex_uncore_cbox_format_group
@@ -1138,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {
	EVENT_EXTRA_END
};

/* Nehalem-EX or Westmere-EX ? */
bool uncore_nhmex;

static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)
{
	struct intel_uncore_extra_reg *er;
@@ -1167,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64
		return false;

	/* mask of the shared fields */
	if (uncore_nhmex)
		mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK;
	else
		mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;
	er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];

	raw_spin_lock_irqsave(&er->lock, flags);
	/* add mask of the non-shared field if it's in use */
	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8))
	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) {
		if (uncore_nhmex)
			mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
		else
			mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
	}

	if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {
		atomic_add(1 << (idx * 8), &er->ref);
		if (uncore_nhmex)
			mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK |
				NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
		else
			mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK |
				WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
		er->config &= ~mask;
		er->config |= (config & mask);
		ret = true;
@@ -1212,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)

	/* get the non-shared control bits and shift them */
	idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
	if (uncore_nhmex)
		config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
	else
		config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
	if (new_idx > orig_idx) {
		idx = new_idx - orig_idx;
		config <<= 3 * idx;
@@ -1222,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)
	}

	/* add the shared control bits back */
	if (uncore_nhmex)
		config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
	else
		config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
	config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
	if (modify) {
		/* adjust the main event selector */
@@ -1480,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = {
	{ /* end: all zeroes */ },
};

static struct uncore_event_desc wsmex_uncore_mbox_events[] = {
	INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"),
	INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"),
	{ /* end: all zeroes */ },
};

static struct intel_uncore_ops nhmex_uncore_mbox_ops = {
	NHMEX_UNCORE_OPS_COMMON_INIT(),
	.enable_event	= nhmex_mbox_msr_enable_event,
@@ -2791,7 +2823,13 @@ static int __init uncore_cpu_init(void)
			snbep_uncore_cbox.num_boxes = max_cores;
		msr_uncores = snbep_msr_uncores;
		break;
	case 46:
	case 46: /* Nehalem-EX */
		uncore_nhmex = true;
	case 47: /* Westmere-EX aka. Xeon E7 */
		if (!uncore_nhmex)
			nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events;
		if (nhmex_uncore_cbox.num_boxes > max_cores)
			nhmex_uncore_cbox.num_boxes = max_cores;
		msr_uncores = nhmex_msr_uncores;
		break;
	default:
+21 −24
Original line number Diff line number Diff line
@@ -276,18 +276,12 @@
		 NHMEX_M_PMON_CTL_INC_SEL_MASK |	\
		 NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK)


#define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK	0x1f
#define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK	(0x7 << 5)
#define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK	(0x7 << 8)
#define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR	(1 << 23)
#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK			\
		(NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK |	\
		 NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK |	\
		 NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK  |	\
		 NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR)
#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 11) - 1) | (1 << 23))
#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (11 + 3 * (n)))

#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 12) - 1) | (1 << 24))
#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (12 + 3 * (n)))

/*
 * use the 9~13 bits to select event If the 7th bit is not set,
 * otherwise use the 19~21 bits to select event.
@@ -369,6 +363,7 @@ struct intel_uncore_type {
	unsigned num_shared_regs:8;
	unsigned single_fixed:1;
	unsigned pair_ctr_ctl:1;
	unsigned *msr_offsets;
	struct event_constraint unconstrainted;
	struct event_constraint *constraints;
	struct intel_uncore_pmu *pmus;
@@ -486,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
	return idx * 8 + box->pmu->type->perf_ctr;
}

static inline
unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box)
{
	struct intel_uncore_pmu *pmu = box->pmu;
	return pmu->type->msr_offsets ?
		pmu->type->msr_offsets[pmu->pmu_idx] :
		pmu->type->msr_offset * pmu->pmu_idx;
}

static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
{
	if (!box->pmu->type->box_ctl)
		return 0;
	return box->pmu->type->box_ctl +
		box->pmu->type->msr_offset * box->pmu->pmu_idx;
	return box->pmu->type->box_ctl + uncore_msr_box_offset(box);
}

static inline
unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
{
	if (!box->pmu->type->fixed_ctl)
		return 0;
	return box->pmu->type->fixed_ctl +
		box->pmu->type->msr_offset * box->pmu->pmu_idx;
	return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box);
}

static inline
unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
{
	return box->pmu->type->fixed_ctr +
		box->pmu->type->msr_offset * box->pmu->pmu_idx;
	return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box);
}

static inline
@@ -516,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
{
	return box->pmu->type->event_ctl +
		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
		box->pmu->type->msr_offset * box->pmu->pmu_idx;
		uncore_msr_box_offset(box);
}

static inline
@@ -524,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
{
	return box->pmu->type->perf_ctr +
		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
		box->pmu->type->msr_offset * box->pmu->pmu_idx;
		uncore_msr_box_offset(box);
}

static inline