Commit 9e2f3099 authored by Kan Liang's avatar Kan Liang Committed by Yunying Sun
Browse files

perf/x86/uncore: Add a quirk for UPI on SPR

mainline inclusion
from mainline-v6.3-rc1
commit 65248a9a
category: bugfix
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I7H29Y
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65248a9a9ee1ea2e6aad8f35253ffd9096ab81b7



Intel-SIG: commit 65248a9a perf/x86/uncore: Add a quirk for UPI on SPR
Backport SPR MCC UPI uncore discovery warning fixes to OLK-5.10.

-------------------------------------

The discovery table of UPI on some SPR variants, e.g., MCC, is broken.
The third UPI table may includes a wrong address which points to a
non-exists device. The bug impacts both UPI and M3UPI uncore PMON.

Use a pre-defined UPI and M3UPI table to replace the broken table.

Different BIOS may populate a device into a different domain or a
different BUS. The accurate location can only be retrieved at load time.
Add spr_update_device_location() to update the location of the UPI and
M3UPI in the pre-defined table.

Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: default avatarMichael Petlan <mpetlan@redhat.com>
Link: https://lore.kernel.org/r/20230112200105.733466-5-kan.liang@linux.intel.com


Signed-off-by: default avatarYunying Sun <yunying.sun@intel.com>
parent b369c7b7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1788,6 +1788,7 @@ static const struct intel_uncore_init_fun spr_uncore_init __initconst = {
	.pci_init = spr_uncore_pci_init,
	.mmio_init = spr_uncore_mmio_init,
	.use_discovery = true,
	.uncore_units_ignore = spr_uncore_units_ignore,
};

static const struct intel_uncore_init_fun generic_uncore_init __initconst = {
+1 −0
Original line number Diff line number Diff line
@@ -568,6 +568,7 @@ extern raw_spinlock_t pci2phy_map_lock;
extern struct list_head pci2phy_map_head;
extern struct pci_extra_dev *uncore_extra_pci_dev;
extern struct event_constraint uncore_constraint_empty;
extern int spr_uncore_units_ignore[];

/* uncore_snb.c */
int snb_uncore_pci_init(void);
+9 −3
Original line number Diff line number Diff line
@@ -23,9 +23,15 @@
/* Global discovery table size */
#define UNCORE_DISCOVERY_GLOBAL_MAP_SIZE	0x20

#define UNCORE_DISCOVERY_PCI_DOMAIN(data)	((data >> 28) & 0x7)
#define UNCORE_DISCOVERY_PCI_BUS(data)		((data >> 20) & 0xff)
#define UNCORE_DISCOVERY_PCI_DEVFN(data)	((data >> 12) & 0xff)
#define UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET	28
#define UNCORE_DISCOVERY_PCI_DOMAIN(data)			\
		((data >> UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET) & 0x7)
#define UNCORE_DISCOVERY_PCI_BUS_OFFSET		20
#define UNCORE_DISCOVERY_PCI_BUS(data)				\
		((data >> UNCORE_DISCOVERY_PCI_BUS_OFFSET) & 0xff)
#define UNCORE_DISCOVERY_PCI_DEVFN_OFFSET	12
#define UNCORE_DISCOVERY_PCI_DEVFN(data)			\
		((data >> UNCORE_DISCOVERY_PCI_DEVFN_OFFSET) & 0xff)
#define UNCORE_DISCOVERY_PCI_BOX_CTRL(data)	(data & 0xfff)


+118 −14
Original line number Diff line number Diff line
@@ -5591,17 +5591,6 @@ static struct intel_uncore_type spr_uncore_m2m = {
	.name			= "m2m",
};

static struct intel_uncore_type spr_uncore_upi = {
	SPR_UNCORE_PCI_COMMON_FORMAT(),
	.name			= "upi",
};

static struct intel_uncore_type spr_uncore_m3upi = {
	SPR_UNCORE_PCI_COMMON_FORMAT(),
	.name			= "m3upi",
	.constraints		= icx_uncore_m3upi_constraints,
};

static struct intel_uncore_type spr_uncore_mdf = {
	SPR_UNCORE_COMMON_FORMAT(),
	.name			= "mdf",
@@ -5610,7 +5599,13 @@ static struct intel_uncore_type spr_uncore_mdf = {
#define UNCORE_SPR_NUM_UNCORE_TYPES		12
#define UNCORE_SPR_IIO				1
#define UNCORE_SPR_IMC				6
#define UNCORE_SPR_UPI				8
#define UNCORE_SPR_M3UPI			9

/*
 * The uncore units, which are supported by the discovery table,
 * are defined here.
 */
static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
	&spr_uncore_chabox,
	&spr_uncore_iio,
@@ -5620,12 +5615,49 @@ static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
	NULL,
	&spr_uncore_imc,
	&spr_uncore_m2m,
	&spr_uncore_upi,
	&spr_uncore_m3upi,
	NULL,
	NULL,
	NULL,
	&spr_uncore_mdf,
};

/*
 * The uncore units, which are not supported by the discovery table,
 * are implemented from here.
 */
#define SPR_UNCORE_UPI_NUM_BOXES	4

static unsigned int spr_upi_pci_offsets[SPR_UNCORE_UPI_NUM_BOXES] = {
	0, 0x8000, 0x10000, 0x18000
};

static struct intel_uncore_type spr_uncore_upi = {
       SPR_UNCORE_PCI_COMMON_FORMAT(),
       .name                   = "upi",
       .type_id                = UNCORE_SPR_UPI,
       .num_counters           = 4,
       .num_boxes              = SPR_UNCORE_UPI_NUM_BOXES,
       .perf_ctr_bits          = 48,
       .perf_ctr               = ICX_UPI_PCI_PMON_CTR0,
       .event_ctl              = ICX_UPI_PCI_PMON_CTL0,
       .box_ctl                = ICX_UPI_PCI_PMON_BOX_CTL,
       .pci_offsets            = spr_upi_pci_offsets,
};

static struct intel_uncore_type spr_uncore_m3upi = {
       SPR_UNCORE_PCI_COMMON_FORMAT(),
       .name                   = "m3upi",
       .type_id                = UNCORE_SPR_M3UPI,
       .num_counters           = 4,
       .num_boxes              = SPR_UNCORE_UPI_NUM_BOXES,
       .perf_ctr_bits          = 48,
       .perf_ctr               = ICX_M3UPI_PCI_PMON_CTR0,
       .event_ctl              = ICX_M3UPI_PCI_PMON_CTL0,
       .box_ctl                = ICX_M3UPI_PCI_PMON_BOX_CTL,
       .pci_offsets            = spr_upi_pci_offsets,
       .constraints            = icx_uncore_m3upi_constraints,
};

enum perf_uncore_spr_iio_freerunning_type_id {
	SPR_IIO_MSR_IOCLK,
	SPR_IIO_MSR_BW_IN,
@@ -5756,6 +5788,7 @@ static struct intel_uncore_type spr_uncore_imc_free_running = {

#define UNCORE_SPR_MSR_EXTRA_UNCORES		1
#define UNCORE_SPR_MMIO_EXTRA_UNCORES		1
#define UNCORE_SPR_PCI_EXTRA_UNCORES		2

static struct intel_uncore_type *spr_msr_uncores[UNCORE_SPR_MSR_EXTRA_UNCORES] = {
	&spr_uncore_iio_free_running,
@@ -5765,6 +5798,17 @@ static struct intel_uncore_type *spr_mmio_uncores[UNCORE_SPR_MMIO_EXTRA_UNCORES]
	&spr_uncore_imc_free_running,
};

static struct intel_uncore_type *spr_pci_uncores[UNCORE_SPR_PCI_EXTRA_UNCORES] = {
	&spr_uncore_upi,
	&spr_uncore_m3upi
};

int spr_uncore_units_ignore[] = {
	UNCORE_SPR_UPI,
	UNCORE_SPR_M3UPI,
	UNCORE_IGNORE_END
};

static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
					struct intel_uncore_type *from_type)
{
@@ -5859,9 +5903,69 @@ void spr_uncore_cpu_init(void)
	spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO);
}

#define SPR_UNCORE_UPI_PCIID		0x3241
#define SPR_UNCORE_UPI0_DEVFN		0x9
#define SPR_UNCORE_M3UPI_PCIID		0x3246
#define SPR_UNCORE_M3UPI0_DEVFN		0x29

static void spr_update_device_location(int type_id)
{
	struct intel_uncore_type *type;
	struct pci_dev *dev = NULL;
	u32 device, devfn;
	u64 *ctls;
	int die;

	if (type_id == UNCORE_SPR_UPI) {
		type = &spr_uncore_upi;
		device = SPR_UNCORE_UPI_PCIID;
		devfn = SPR_UNCORE_UPI0_DEVFN;
	} else if (type_id == UNCORE_SPR_M3UPI) {
		type = &spr_uncore_m3upi;
		device = SPR_UNCORE_M3UPI_PCIID;
		devfn = SPR_UNCORE_M3UPI0_DEVFN;
	} else
		return;

	ctls = kcalloc(__uncore_max_dies, sizeof(u64), GFP_KERNEL);
	if (!ctls) {
		type->num_boxes = 0;
		return;
	}

	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, dev)) != NULL) {
		if (devfn != dev->devfn)
			continue;

		die = uncore_device_to_die(dev);
		if (die < 0)
			continue;

		ctls[die] = pci_domain_nr(dev->bus) << UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET |
			    dev->bus->number << UNCORE_DISCOVERY_PCI_BUS_OFFSET |
			    devfn << UNCORE_DISCOVERY_PCI_DEVFN_OFFSET |
			    type->box_ctl;
	}

	type->box_ctls = ctls;
}

int spr_uncore_pci_init(void)
{
	uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI, 0, NULL);
	/*
	 * The discovery table of UPI on some SPR variant is broken,
	 * which impacts the detection of both UPI and M3UPI uncore PMON.
	 * Use the pre-defined UPI and M3UPI table to replace.
	 *
	 * The accurate location, e.g., domain and BUS number,
	 * can only be retrieved at load time.
	 * Update the location of UPI and M3UPI.
	 */
	spr_update_device_location(UNCORE_SPR_UPI);
	spr_update_device_location(UNCORE_SPR_M3UPI);
	uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI,
						UNCORE_SPR_PCI_EXTRA_UNCORES,
						spr_pci_uncores);
	return 0;
}