lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 17 Oct 2017 01:20:15 +0000
From:   "Liang, Kan" <kan.liang@...el.com>
To:     "peterz@...radead.org" <peterz@...radead.org>,
        "tglx@...utronix.de" <tglx@...utronix.de>,
        "mingo@...hat.com" <mingo@...hat.com>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
CC:     "acme@...nel.org" <acme@...nel.org>,
        "eranian@...gle.com" <eranian@...gle.com>,
        "ak@...ux.intel.com" <ak@...ux.intel.com>
Subject: RE: [PATCH 2/2] perf/x86/intel/uncore: support IIO freerunning
 counter for SKX


Ping.
Any comments for this patch?

Thanks,
Kan
> 
> From: Kan Liang <Kan.liang@...el.com>
> 
> As of Skylake Server, there are a number of free-running counters in
> each IIO Box that collect counts for per box IO clocks and per Port
> Input/Output x BW/Utilization.
> 
> The event code of free running event is shared with fixed event, which
> is 0xff.
> The umask of free running event starts from 0x10. The umask less than
> 0x10 is reserved for fixed event.
> 
> The Free running counters could have different MSR location and offset.
> Accordingly, they are divided into different types. Each type is limited
> to only have at most 16 events.
> So the umask of the first free running events type starts from 0x10. The
> umask of the second starts from 0x20. The rest can be done in the same
> manner.
> 
> Freerunning counters cannot be written by SW. Counting will be suspended
> only when the IIO Box is powered down. They are specially handled in
> uncore_pmu_event_add/del/start/stop and not added in box->events list.
> 
> The bit width of freerunning counter is 36-bit.
> 
> Signed-off-by: Kan Liang <Kan.liang@...el.com>
> ---
>  arch/x86/events/intel/uncore.c       | 33 +++++++++++++++++-
>  arch/x86/events/intel/uncore.h       | 67
> +++++++++++++++++++++++++++++++++++-
>  arch/x86/events/intel/uncore_snbep.c | 58
> +++++++++++++++++++++++++++++++
>  3 files changed, 156 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
> index 1c5390f..8d3e46c 100644
> --- a/arch/x86/events/intel/uncore.c
> +++ b/arch/x86/events/intel/uncore.c
> @@ -218,7 +218,9 @@ void uncore_perf_event_update(struct
> intel_uncore_box *box, struct perf_event *e
>  	u64 prev_count, new_count, delta;
>  	int shift;
> 
> -	if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
> +	if (event->hw.idx >= UNCORE_PMC_IDX_FREERUNNING)
> +		shift = 64 - uncore_free_running_bits(box, event);
> +	else if (event->hw.idx == UNCORE_PMC_IDX_FIXED)
>  		shift = 64 - uncore_fixed_ctr_bits(box);
>  	else
>  		shift = 64 - uncore_perf_ctr_bits(box);
> @@ -362,6 +364,9 @@ uncore_collect_events(struct intel_uncore_box *box,
> struct perf_event *leader,
>  		if (n >= max_count)
>  			return -EINVAL;
> 
> +		if (event->hw.idx == UNCORE_PMC_IDX_FREERUNNING)
> +			continue;
> +
>  		box->event_list[n] = event;
>  		n++;
>  	}
> @@ -454,6 +459,12 @@ static void uncore_pmu_event_start(struct
> perf_event *event, int flags)
>  	struct intel_uncore_box *box = uncore_event_to_box(event);
>  	int idx = event->hw.idx;
> 
> +	if (event->hw.idx == UNCORE_PMC_IDX_FREERUNNING) {
> +		local64_set(&event->hw.prev_count,
> +			    uncore_read_counter(box, event));
> +		return;
> +	}
> +
>  	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
>  		return;
> 
> @@ -479,6 +490,11 @@ static void uncore_pmu_event_stop(struct
> perf_event *event, int flags)
>  	struct intel_uncore_box *box = uncore_event_to_box(event);
>  	struct hw_perf_event *hwc = &event->hw;
> 
> +	if (hwc->idx == UNCORE_PMC_IDX_FREERUNNING) {
> +		uncore_perf_event_update(box, event);
> +		return;
> +	}
> +
>  	if (__test_and_clear_bit(hwc->idx, box->active_mask)) {
>  		uncore_disable_event(box, event);
>  		box->n_active--;
> @@ -512,6 +528,13 @@ static int uncore_pmu_event_add(struct perf_event
> *event, int flags)
>  	if (!box)
>  		return -ENODEV;
> 
> +	if (hwc->idx == UNCORE_PMC_IDX_FREERUNNING) {
> +		event->hw.event_base = uncore_free_running_msr(box,
> event);
> +		if (flags & PERF_EF_START)
> +			uncore_pmu_event_start(event, 0);
> +		return 0;
> +	}
> +
>  	ret = n = uncore_collect_events(box, event, false);
>  	if (ret < 0)
>  		return ret;
> @@ -570,6 +593,9 @@ static void uncore_pmu_event_del(struct perf_event
> *event, int flags)
> 
>  	uncore_pmu_event_stop(event, PERF_EF_UPDATE);
> 
> +	if (event->hw.idx == UNCORE_PMC_IDX_FREERUNNING)
> +		return;
> +
>  	for (i = 0; i < box->n_events; i++) {
>  		if (event == box->event_list[i]) {
>  			uncore_put_event_constraint(box, event);
> @@ -690,6 +716,11 @@ static int uncore_pmu_event_init(struct perf_event
> *event)
> 
>  		/* fixed counters have event field hardcoded to zero */
>  		hwc->config = 0ULL;
> +	} else if (is_free_running_event(event)) {
> +		if (UNCORE_FREE_RUNNING_MSR_IDX(event->attr.config) >
> +		    uncore_num_free_running(box, event))
> +			return -EINVAL;
> +		event->hw.idx = UNCORE_PMC_IDX_FREERUNNING;
>  	} else {
>  		hwc->config = event->attr.config &
>  			      (pmu->type->event_mask | ((u64)pmu->type-
> >event_mask_ext << 32));
> diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
> index df5989f..3e60686 100644
> --- a/arch/x86/events/intel/uncore.h
> +++ b/arch/x86/events/intel/uncore.h
> @@ -12,7 +12,25 @@
>  #define UNCORE_FIXED_EVENT		0xff
>  #define UNCORE_PMC_IDX_MAX_GENERIC	8
>  #define UNCORE_PMC_IDX_FIXED
> 	UNCORE_PMC_IDX_MAX_GENERIC
> -#define UNCORE_PMC_IDX_MAX		(UNCORE_PMC_IDX_FIXED +
> 1)
> +#define UNCORE_PMC_IDX_FREERUNNING	(UNCORE_PMC_IDX_FIXED +
> 1)
> +#define UNCORE_PMC_IDX_MAX
> 	(UNCORE_PMC_IDX_FREERUNNING + 1)
> +
> +/*
> + * Free running MSR events have the same event code 0xff as fixed events.
> + * The Free running events umask starts from 0x10.
> + * The umask which is less than 0x10 is reserved for fixed events.
> + *
> + * The Free running events are divided into different types according to
> + * MSR location, bit width or definition. Each type is limited to only have
> + * at most 16 events.
> + * So the umask of first type starts from 0x10, the second starts from 0x20,
> + * the rest can be done in the same manner.
> + */
> +#define UNCORE_FREE_RUNNING_MSR_START			0x10
> +#define UNCORE_FREE_RUNNING_MSR_IDX(config)		((config >> 8)
> & 0xf)
> +#define UNCORE_FREE_RUNNING_MSR_TYPE_IDX(config)	\
> +		((((config >> 8) - UNCORE_FREE_RUNNING_MSR_START) >> 4)
> & 0xf)
> +
> 
>  #define UNCORE_PCI_DEV_FULL_DATA(dev, func, type, idx)	\
>  		((dev << 24) | (func << 16) | (type << 8) | idx)
> @@ -34,6 +52,7 @@ struct intel_uncore_ops;
>  struct intel_uncore_pmu;
>  struct intel_uncore_box;
>  struct uncore_event_desc;
> +struct free_running_msr;
> 
>  struct intel_uncore_type {
>  	const char *name;
> @@ -41,6 +60,7 @@ struct intel_uncore_type {
>  	int num_boxes;
>  	int perf_ctr_bits;
>  	int fixed_ctr_bits;
> +	int num_free_running_type;
>  	unsigned perf_ctr;
>  	unsigned event_ctl;
>  	unsigned event_mask;
> @@ -58,6 +78,7 @@ struct intel_uncore_type {
>  	struct intel_uncore_pmu *pmus;
>  	struct intel_uncore_ops *ops;
>  	struct uncore_event_desc *event_descs;
> +	struct free_running_msr *free_running;
>  	const struct attribute_group *attr_groups[4];
>  	struct pmu *pmu; /* for custom pmu ops */
>  };
> @@ -128,6 +149,13 @@ struct uncore_event_desc {
>  	const char *config;
>  };
> 
> +struct free_running_msr {
> +	unsigned msr_base;
> +	unsigned msr_off;
> +	unsigned num_counters;
> +	unsigned bits;
> +};
> +
>  struct pci2phy_map {
>  	struct list_head list;
>  	int segment;
> @@ -214,6 +242,18 @@ static inline unsigned uncore_msr_fixed_ctr(struct
> intel_uncore_box *box)
>  }
> 
>  static inline
> +unsigned uncore_free_running_msr(struct intel_uncore_box *box,
> +				 struct perf_event *event)
> +{
> +	unsigned type = UNCORE_FREE_RUNNING_MSR_TYPE_IDX(event-
> >attr.config);
> +	unsigned idx = UNCORE_FREE_RUNNING_MSR_IDX(event-
> >attr.config);
> +	struct intel_uncore_pmu *pmu = box->pmu;
> +
> +	return pmu->type->free_running[type].msr_base + idx +
> +	       pmu->type->free_running[type].msr_off * pmu->pmu_idx;
> +}
> +
> +static inline
>  unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
>  {
>  	return box->pmu->type->event_ctl +
> @@ -275,11 +315,36 @@ static inline int uncore_fixed_ctr_bits(struct
> intel_uncore_box *box)
>  	return box->pmu->type->fixed_ctr_bits;
>  }
> 
> +static inline unsigned
> +uncore_free_running_bits(struct intel_uncore_box *box,
> +			 struct perf_event *event)
> +{
> +	unsigned idx = UNCORE_FREE_RUNNING_MSR_TYPE_IDX(event-
> >attr.config);
> +
> +	return box->pmu->type->free_running[idx].bits;
> +}
> +
> +static inline int uncore_num_free_running(struct intel_uncore_box *box,
> +					  struct perf_event *event)
> +{
> +	unsigned idx = UNCORE_FREE_RUNNING_MSR_TYPE_IDX(event-
> >attr.config);
> +
> +	return box->pmu->type->free_running[idx].num_counters;
> +}
> +
>  static inline int uncore_num_counters(struct intel_uncore_box *box)
>  {
>  	return box->pmu->type->num_counters;
>  }
> 
> +static inline bool is_free_running_event(struct perf_event *event)
> +{
> +	u64 cfg = event->attr.config;
> +
> +	return (((cfg & UNCORE_FIXED_EVENT) == UNCORE_FIXED_EVENT)
> &&
> +		(((cfg >> 8) & 0xff) >=
> UNCORE_FREE_RUNNING_MSR_START));
> +}
> +
>  static inline void uncore_disable_box(struct intel_uncore_box *box)
>  {
>  	if (box->pmu->type->ops->disable_box)
> diff --git a/arch/x86/events/intel/uncore_snbep.c
> b/arch/x86/events/intel/uncore_snbep.c
> index a719681..cbd6061 100644
> --- a/arch/x86/events/intel/uncore_snbep.c
> +++ b/arch/x86/events/intel/uncore_snbep.c
> @@ -3459,6 +3459,61 @@ static struct intel_uncore_ops
> skx_uncore_iio_ops = {
>  	.read_counter		= uncore_msr_read_counter,
>  };
> 
> +enum perf_uncore_iio_free_running_msr_type_id {
> +	SKX_IIO_MSR_IOCLK			= 0,
> +	SKX_IIO_MSR_BW				= 1,
> +	SKX_IIO_MSR_UTIL			= 2,
> +
> +	SKX_IIO_FREE_RUNNING_MSR_TYPE_MAX,
> +};
> +
> +
> +static struct free_running_msr skx_iio_free_running_msr[] = {
> +	[SKX_IIO_MSR_IOCLK]	= { 0xa45, 0x20, 1, 36 },
> +	[SKX_IIO_MSR_BW]	= { 0xb00, 0x10, 8, 36 },
> +	[SKX_IIO_MSR_UTIL]	= { 0xb08, 0x10, 8, 36 },
> +};
> +
> +static struct uncore_event_desc skx_uncore_iio_events[] = {
> +	/* Free-Running IO CLOCKS Counter */
> +	INTEL_UNCORE_EVENT_DESC(ioclk,
> 	"event=0xff,umask=0x10"),
> +	/* Free-Running IIO Bandwidth Counters */
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port0,
> 	"event=0xff,umask=0x20"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port0.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port0.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port1,
> 	"event=0xff,umask=0x21"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port1.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port1.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port2,
> 	"event=0xff,umask=0x22"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port2.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port2.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port3,
> 	"event=0xff,umask=0x23"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port3.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_in_port3.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port0,
> 	"event=0xff,umask=0x24"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port0.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port0.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port1,
> 	"event=0xff,umask=0x25"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port1.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port1.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port2,
> 	"event=0xff,umask=0x26"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port2.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port2.unit,	"MiB"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port3,
> 	"event=0xff,umask=0x27"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port3.scale,
> 	"3.814697266e-6"),
> +	INTEL_UNCORE_EVENT_DESC(bw_out_port3.unit,	"MiB"),
> +	/* Free-running IIO Utilization Counters */
> +	INTEL_UNCORE_EVENT_DESC(util_in_port0,
> 	"event=0xff,umask=0x30"),
> +	INTEL_UNCORE_EVENT_DESC(util_out_port0,
> 	"event=0xff,umask=0x31"),
> +	INTEL_UNCORE_EVENT_DESC(util_in_port1,
> 	"event=0xff,umask=0x32"),
> +	INTEL_UNCORE_EVENT_DESC(util_out_port1,
> 	"event=0xff,umask=0x33"),
> +	INTEL_UNCORE_EVENT_DESC(util_in_port2,
> 	"event=0xff,umask=0x34"),
> +	INTEL_UNCORE_EVENT_DESC(util_out_port2,
> 	"event=0xff,umask=0x35"),
> +	INTEL_UNCORE_EVENT_DESC(util_in_port3,
> 	"event=0xff,umask=0x36"),
> +	INTEL_UNCORE_EVENT_DESC(util_out_port3,
> 	"event=0xff,umask=0x37"),
> +	{ /* end: all zeroes */ },
> +};
> +
>  static struct intel_uncore_type skx_uncore_iio = {
>  	.name			= "iio",
>  	.num_counters		= 4,
> @@ -3470,8 +3525,11 @@ static struct intel_uncore_type skx_uncore_iio = {
>  	.event_mask_ext		=
> SKX_IIO_PMON_RAW_EVENT_MASK_EXT,
>  	.box_ctl		= SKX_IIO0_MSR_PMON_BOX_CTL,
>  	.msr_offset		= SKX_IIO_MSR_OFFSET,
> +	.num_free_running_type	=
> SKX_IIO_FREE_RUNNING_MSR_TYPE_MAX,
> +	.free_running		= skx_iio_free_running_msr,
>  	.constraints		= skx_uncore_iio_constraints,
>  	.ops			= &skx_uncore_iio_ops,
> +	.event_descs		= skx_uncore_iio_events,
>  	.format_group		= &skx_uncore_iio_format_group,
>  };
> 
> --
> 2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ