Commit 5a4487f9 authored by Kan Liang's avatar Kan Liang Committed by Peter Zijlstra
Browse files

perf/x86/intel/uncore: Add IMC uncore support for ADL



Current ADL uncore code only supports the legacy IMC (memory controller)
free-running counters. Besides the free-running counters, ADL also
supports several general purpose-counters.

The general-purpose counters can also be accessed via MMIO but in a
different location. Factor out __uncore_imc_init_box() with offset as a
parameter. The function can be shared between ADL and TGL.

The event format and the layout of the control registers are a little
bit different from other uncore counters.

The intel_generic_uncore_mmio_enable_event() can be shared with client
IMC uncore. Expose the function.

Add more PCI IDs for ADL machines.

Fixes: 772ed05f ("perf/x86/intel/uncore: Add Alder Lake support")
Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1642111554-118524-1-git-send-email-kan.liang@linux.intel.com
parent 6b19788d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1762,7 +1762,7 @@ static const struct intel_uncore_init_fun rkl_uncore_init __initconst = {

static const struct intel_uncore_init_fun adl_uncore_init __initconst = {
	.cpu_init = adl_uncore_cpu_init,
	.mmio_init = tgl_uncore_mmio_init,
	.mmio_init = adl_uncore_mmio_init,
};

static const struct intel_uncore_init_fun icx_uncore_init __initconst = {
+2 −1
Original line number Diff line number Diff line
@@ -584,10 +584,11 @@ void snb_uncore_cpu_init(void);
void nhm_uncore_cpu_init(void);
void skl_uncore_cpu_init(void);
void icl_uncore_cpu_init(void);
void adl_uncore_cpu_init(void);
void tgl_uncore_cpu_init(void);
void adl_uncore_cpu_init(void);
void tgl_uncore_mmio_init(void);
void tgl_l_uncore_mmio_init(void);
void adl_uncore_mmio_init(void);
int snb_pci2phy_map_init(int devid);

/* uncore_snbep.c */
+2 −2
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box)
	writel(0, box->io_addr);
}

static void intel_generic_uncore_mmio_enable_event(struct intel_uncore_box *box,
void intel_generic_uncore_mmio_enable_event(struct intel_uncore_box *box,
					    struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;
+2 −0
Original line number Diff line number Diff line
@@ -139,6 +139,8 @@ void intel_generic_uncore_mmio_disable_box(struct intel_uncore_box *box);
void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box);
void intel_generic_uncore_mmio_disable_event(struct intel_uncore_box *box,
					     struct perf_event *event);
void intel_generic_uncore_mmio_enable_event(struct intel_uncore_box *box,
					    struct perf_event *event);

void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box);
void intel_generic_uncore_pci_disable_box(struct intel_uncore_box *box);
+213 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Nehalem/SandBridge/Haswell/Broadwell/Skylake uncore support */
#include "uncore.h"
#include "uncore_discovery.h"

/* Uncore IMC PCI IDs */
#define PCI_DEVICE_ID_INTEL_SNB_IMC		0x0100
@@ -64,6 +65,20 @@
#define PCI_DEVICE_ID_INTEL_RKL_2_IMC		0x4c53
#define PCI_DEVICE_ID_INTEL_ADL_1_IMC		0x4660
#define PCI_DEVICE_ID_INTEL_ADL_2_IMC		0x4641
#define PCI_DEVICE_ID_INTEL_ADL_3_IMC		0x4601
#define PCI_DEVICE_ID_INTEL_ADL_4_IMC		0x4602
#define PCI_DEVICE_ID_INTEL_ADL_5_IMC		0x4609
#define PCI_DEVICE_ID_INTEL_ADL_6_IMC		0x460a
#define PCI_DEVICE_ID_INTEL_ADL_7_IMC		0x4621
#define PCI_DEVICE_ID_INTEL_ADL_8_IMC		0x4623
#define PCI_DEVICE_ID_INTEL_ADL_9_IMC		0x4629
#define PCI_DEVICE_ID_INTEL_ADL_10_IMC		0x4637
#define PCI_DEVICE_ID_INTEL_ADL_11_IMC		0x463b
#define PCI_DEVICE_ID_INTEL_ADL_12_IMC		0x4648
#define PCI_DEVICE_ID_INTEL_ADL_13_IMC		0x4649
#define PCI_DEVICE_ID_INTEL_ADL_14_IMC		0x4650
#define PCI_DEVICE_ID_INTEL_ADL_15_IMC		0x4668
#define PCI_DEVICE_ID_INTEL_ADL_16_IMC		0x4670

/* SNB event control */
#define SNB_UNC_CTL_EV_SEL_MASK			0x000000ff
@@ -155,6 +170,7 @@

DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
DEFINE_UNCORE_FORMAT_ATTR(chmask, chmask, "config:8-11");
DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
@@ -1334,6 +1350,62 @@ static const struct pci_device_id tgl_uncore_pci_ids[] = {
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_2_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_3_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_4_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_5_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_6_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_7_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_8_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_9_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_10_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_11_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_12_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_13_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_14_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_15_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* IMC */
		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ADL_16_IMC),
		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
	},
	{ /* end: all zeroes */ }
};

@@ -1390,7 +1462,8 @@ static struct pci_dev *tgl_uncore_get_mc_dev(void)
#define TGL_UNCORE_MMIO_IMC_MEM_OFFSET		0x10000
#define TGL_UNCORE_PCI_IMC_MAP_SIZE		0xe000

static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
static void __uncore_imc_init_box(struct intel_uncore_box *box,
				  unsigned int base_offset)
{
	struct pci_dev *pdev = tgl_uncore_get_mc_dev();
	struct intel_uncore_pmu *pmu = box->pmu;
@@ -1417,11 +1490,17 @@ static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
	addr |= ((resource_size_t)mch_bar << 32);
#endif

	addr += base_offset;
	box->io_addr = ioremap(addr, type->mmio_map_size);
	if (!box->io_addr)
		pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
}

static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
{
	__uncore_imc_init_box(box, 0);
}

static struct intel_uncore_ops tgl_uncore_imc_freerunning_ops = {
	.init_box	= tgl_uncore_imc_freerunning_init_box,
	.exit_box	= uncore_mmio_exit_box,
@@ -1469,3 +1548,136 @@ void tgl_uncore_mmio_init(void)
}

/* end of Tiger Lake MMIO uncore support */

/* Alder Lake MMIO uncore support */
#define ADL_UNCORE_IMC_BASE			0xd900
#define ADL_UNCORE_IMC_MAP_SIZE			0x200
#define ADL_UNCORE_IMC_CTR			0xe8
#define ADL_UNCORE_IMC_CTRL			0xd0
#define ADL_UNCORE_IMC_GLOBAL_CTL		0xc0
#define ADL_UNCORE_IMC_BOX_CTL			0xc4
#define ADL_UNCORE_IMC_FREERUNNING_BASE		0xd800
#define ADL_UNCORE_IMC_FREERUNNING_MAP_SIZE	0x100

#define ADL_UNCORE_IMC_CTL_FRZ			(1 << 0)
#define ADL_UNCORE_IMC_CTL_RST_CTRL		(1 << 1)
#define ADL_UNCORE_IMC_CTL_RST_CTRS		(1 << 2)
#define ADL_UNCORE_IMC_CTL_INT			(ADL_UNCORE_IMC_CTL_RST_CTRL | \
						ADL_UNCORE_IMC_CTL_RST_CTRS)

static void adl_uncore_imc_init_box(struct intel_uncore_box *box)
{
	__uncore_imc_init_box(box, ADL_UNCORE_IMC_BASE);

	/* The global control in MC1 can control both MCs. */
	if (box->io_addr && (box->pmu->pmu_idx == 1))
		writel(ADL_UNCORE_IMC_CTL_INT, box->io_addr + ADL_UNCORE_IMC_GLOBAL_CTL);
}

static void adl_uncore_mmio_disable_box(struct intel_uncore_box *box)
{
	if (!box->io_addr)
		return;

	writel(ADL_UNCORE_IMC_CTL_FRZ, box->io_addr + uncore_mmio_box_ctl(box));
}

static void adl_uncore_mmio_enable_box(struct intel_uncore_box *box)
{
	if (!box->io_addr)
		return;

	writel(0, box->io_addr + uncore_mmio_box_ctl(box));
}

static struct intel_uncore_ops adl_uncore_mmio_ops = {
	.init_box	= adl_uncore_imc_init_box,
	.exit_box	= uncore_mmio_exit_box,
	.disable_box	= adl_uncore_mmio_disable_box,
	.enable_box	= adl_uncore_mmio_enable_box,
	.disable_event	= intel_generic_uncore_mmio_disable_event,
	.enable_event	= intel_generic_uncore_mmio_enable_event,
	.read_counter	= uncore_mmio_read_counter,
};

#define ADL_UNC_CTL_CHMASK_MASK			0x00000f00
#define ADL_UNC_IMC_EVENT_MASK			(SNB_UNC_CTL_EV_SEL_MASK | \
						 ADL_UNC_CTL_CHMASK_MASK | \
						 SNB_UNC_CTL_EDGE_DET)

static struct attribute *adl_uncore_imc_formats_attr[] = {
	&format_attr_event.attr,
	&format_attr_chmask.attr,
	&format_attr_edge.attr,
	NULL,
};

static const struct attribute_group adl_uncore_imc_format_group = {
	.name		= "format",
	.attrs		= adl_uncore_imc_formats_attr,
};

static struct intel_uncore_type adl_uncore_imc = {
	.name		= "imc",
	.num_counters   = 5,
	.num_boxes	= 2,
	.perf_ctr_bits	= 64,
	.perf_ctr	= ADL_UNCORE_IMC_CTR,
	.event_ctl	= ADL_UNCORE_IMC_CTRL,
	.event_mask	= ADL_UNC_IMC_EVENT_MASK,
	.box_ctl	= ADL_UNCORE_IMC_BOX_CTL,
	.mmio_offset	= 0,
	.mmio_map_size	= ADL_UNCORE_IMC_MAP_SIZE,
	.ops		= &adl_uncore_mmio_ops,
	.format_group	= &adl_uncore_imc_format_group,
};

enum perf_adl_uncore_imc_freerunning_types {
	ADL_MMIO_UNCORE_IMC_DATA_TOTAL,
	ADL_MMIO_UNCORE_IMC_DATA_READ,
	ADL_MMIO_UNCORE_IMC_DATA_WRITE,
	ADL_MMIO_UNCORE_IMC_FREERUNNING_TYPE_MAX
};

static struct freerunning_counters adl_uncore_imc_freerunning[] = {
	[ADL_MMIO_UNCORE_IMC_DATA_TOTAL]	= { 0x40, 0x0, 0x0, 1, 64 },
	[ADL_MMIO_UNCORE_IMC_DATA_READ]		= { 0x58, 0x0, 0x0, 1, 64 },
	[ADL_MMIO_UNCORE_IMC_DATA_WRITE]	= { 0xA0, 0x0, 0x0, 1, 64 },
};

static void adl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
{
	__uncore_imc_init_box(box, ADL_UNCORE_IMC_FREERUNNING_BASE);
}

static struct intel_uncore_ops adl_uncore_imc_freerunning_ops = {
	.init_box	= adl_uncore_imc_freerunning_init_box,
	.exit_box	= uncore_mmio_exit_box,
	.read_counter	= uncore_mmio_read_counter,
	.hw_config	= uncore_freerunning_hw_config,
};

static struct intel_uncore_type adl_uncore_imc_free_running = {
	.name			= "imc_free_running",
	.num_counters		= 3,
	.num_boxes		= 2,
	.num_freerunning_types	= ADL_MMIO_UNCORE_IMC_FREERUNNING_TYPE_MAX,
	.mmio_map_size		= ADL_UNCORE_IMC_FREERUNNING_MAP_SIZE,
	.freerunning		= adl_uncore_imc_freerunning,
	.ops			= &adl_uncore_imc_freerunning_ops,
	.event_descs		= tgl_uncore_imc_events,
	.format_group		= &tgl_uncore_imc_format_group,
};

static struct intel_uncore_type *adl_mmio_uncores[] = {
	&adl_uncore_imc,
	&adl_uncore_imc_free_running,
	NULL
};

void adl_uncore_mmio_init(void)
{
	uncore_mmio_uncores = adl_mmio_uncores;
}

/* end of Alder Lake MMIO uncore support */