Skip to content

Commit 65248a9

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
perf/x86/uncore: Add a quirk for UPI on SPR
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: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Michael Petlan <mpetlan@redhat.com> Link: https://lore.kernel.org/r/20230112200105.733466-5-kan.liang@linux.intel.com
1 parent bd9514a commit 65248a9

File tree

4 files changed

+136
-24
lines changed

4 files changed

+136
-24
lines changed

arch/x86/events/intel/uncore.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,7 @@ static const struct intel_uncore_init_fun spr_uncore_init __initconst = {
18061806
.pci_init = spr_uncore_pci_init,
18071807
.mmio_init = spr_uncore_mmio_init,
18081808
.use_discovery = true,
1809+
.uncore_units_ignore = spr_uncore_units_ignore,
18091810
};
18101811

18111812
static const struct intel_uncore_init_fun generic_uncore_init __initconst = {

arch/x86/events/intel/uncore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ extern raw_spinlock_t pci2phy_map_lock;
592592
extern struct list_head pci2phy_map_head;
593593
extern struct pci_extra_dev *uncore_extra_pci_dev;
594594
extern struct event_constraint uncore_constraint_empty;
595+
extern int spr_uncore_units_ignore[];
595596

596597
/* uncore_snb.c */
597598
int snb_uncore_pci_init(void);

arch/x86/events/intel/uncore_discovery.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@
2121
/* Global discovery table size */
2222
#define UNCORE_DISCOVERY_GLOBAL_MAP_SIZE 0x20
2323

24-
#define UNCORE_DISCOVERY_PCI_DOMAIN(data) ((data >> 28) & 0x7)
25-
#define UNCORE_DISCOVERY_PCI_BUS(data) ((data >> 20) & 0xff)
26-
#define UNCORE_DISCOVERY_PCI_DEVFN(data) ((data >> 12) & 0xff)
24+
#define UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET 28
25+
#define UNCORE_DISCOVERY_PCI_DOMAIN(data) \
26+
((data >> UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET) & 0x7)
27+
#define UNCORE_DISCOVERY_PCI_BUS_OFFSET 20
28+
#define UNCORE_DISCOVERY_PCI_BUS(data) \
29+
((data >> UNCORE_DISCOVERY_PCI_BUS_OFFSET) & 0xff)
30+
#define UNCORE_DISCOVERY_PCI_DEVFN_OFFSET 12
31+
#define UNCORE_DISCOVERY_PCI_DEVFN(data) \
32+
((data >> UNCORE_DISCOVERY_PCI_DEVFN_OFFSET) & 0xff)
2733
#define UNCORE_DISCOVERY_PCI_BOX_CTRL(data) (data & 0xfff)
2834

2935

arch/x86/events/intel/uncore_snbep.c

Lines changed: 125 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6132,24 +6132,6 @@ static int spr_upi_get_topology(struct intel_uncore_type *type)
61326132
return discover_upi_topology(type, SPR_UBOX_DID, SPR_UPI_REGS_ADDR_DEVICE_LINK0);
61336133
}
61346134

6135-
static struct intel_uncore_type spr_uncore_upi = {
6136-
.event_mask = SNBEP_PMON_RAW_EVENT_MASK,
6137-
.event_mask_ext = SPR_RAW_EVENT_MASK_EXT,
6138-
.format_group = &spr_uncore_raw_format_group,
6139-
.ops = &spr_uncore_pci_ops,
6140-
.name = "upi",
6141-
.attr_update = spr_upi_attr_update,
6142-
.get_topology = spr_upi_get_topology,
6143-
.set_mapping = spr_upi_set_mapping,
6144-
.cleanup_mapping = spr_upi_cleanup_mapping,
6145-
};
6146-
6147-
static struct intel_uncore_type spr_uncore_m3upi = {
6148-
SPR_UNCORE_PCI_COMMON_FORMAT(),
6149-
.name = "m3upi",
6150-
.constraints = icx_uncore_m3upi_constraints,
6151-
};
6152-
61536135
static struct intel_uncore_type spr_uncore_mdf = {
61546136
SPR_UNCORE_COMMON_FORMAT(),
61556137
.name = "mdf",
@@ -6158,7 +6140,13 @@ static struct intel_uncore_type spr_uncore_mdf = {
61586140
#define UNCORE_SPR_NUM_UNCORE_TYPES 12
61596141
#define UNCORE_SPR_IIO 1
61606142
#define UNCORE_SPR_IMC 6
6143+
#define UNCORE_SPR_UPI 8
6144+
#define UNCORE_SPR_M3UPI 9
61616145

6146+
/*
6147+
* The uncore units, which are supported by the discovery table,
6148+
* are defined here.
6149+
*/
61626150
static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
61636151
&spr_uncore_chabox,
61646152
&spr_uncore_iio,
@@ -6168,12 +6156,56 @@ static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
61686156
NULL,
61696157
&spr_uncore_imc,
61706158
&spr_uncore_m2m,
6171-
&spr_uncore_upi,
6172-
&spr_uncore_m3upi,
6159+
NULL,
6160+
NULL,
61736161
NULL,
61746162
&spr_uncore_mdf,
61756163
};
61766164

6165+
/*
6166+
* The uncore units, which are not supported by the discovery table,
6167+
* are implemented from here.
6168+
*/
6169+
#define SPR_UNCORE_UPI_NUM_BOXES 4
6170+
6171+
static unsigned int spr_upi_pci_offsets[SPR_UNCORE_UPI_NUM_BOXES] = {
6172+
0, 0x8000, 0x10000, 0x18000
6173+
};
6174+
6175+
static struct intel_uncore_type spr_uncore_upi = {
6176+
.event_mask = SNBEP_PMON_RAW_EVENT_MASK,
6177+
.event_mask_ext = SPR_RAW_EVENT_MASK_EXT,
6178+
.format_group = &spr_uncore_raw_format_group,
6179+
.ops = &spr_uncore_pci_ops,
6180+
.name = "upi",
6181+
.attr_update = spr_upi_attr_update,
6182+
.get_topology = spr_upi_get_topology,
6183+
.set_mapping = spr_upi_set_mapping,
6184+
.cleanup_mapping = spr_upi_cleanup_mapping,
6185+
.type_id = UNCORE_SPR_UPI,
6186+
.num_counters = 4,
6187+
.num_boxes = SPR_UNCORE_UPI_NUM_BOXES,
6188+
.perf_ctr_bits = 48,
6189+
.perf_ctr = ICX_UPI_PCI_PMON_CTR0,
6190+
.event_ctl = ICX_UPI_PCI_PMON_CTL0,
6191+
.box_ctl = ICX_UPI_PCI_PMON_BOX_CTL,
6192+
.pci_offsets = spr_upi_pci_offsets,
6193+
};
6194+
6195+
static struct intel_uncore_type spr_uncore_m3upi = {
6196+
SPR_UNCORE_PCI_COMMON_FORMAT(),
6197+
.name = "m3upi",
6198+
.type_id = UNCORE_SPR_M3UPI,
6199+
.num_counters = 4,
6200+
.num_boxes = SPR_UNCORE_UPI_NUM_BOXES,
6201+
.perf_ctr_bits = 48,
6202+
.perf_ctr = ICX_M3UPI_PCI_PMON_CTR0,
6203+
.event_ctl = ICX_M3UPI_PCI_PMON_CTL0,
6204+
.box_ctl = ICX_M3UPI_PCI_PMON_BOX_CTL,
6205+
.pci_offsets = spr_upi_pci_offsets,
6206+
.constraints = icx_uncore_m3upi_constraints,
6207+
};
6208+
61776209
enum perf_uncore_spr_iio_freerunning_type_id {
61786210
SPR_IIO_MSR_IOCLK,
61796211
SPR_IIO_MSR_BW_IN,
@@ -6304,6 +6336,7 @@ static struct intel_uncore_type spr_uncore_imc_free_running = {
63046336

63056337
#define UNCORE_SPR_MSR_EXTRA_UNCORES 1
63066338
#define UNCORE_SPR_MMIO_EXTRA_UNCORES 1
6339+
#define UNCORE_SPR_PCI_EXTRA_UNCORES 2
63076340

63086341
static struct intel_uncore_type *spr_msr_uncores[UNCORE_SPR_MSR_EXTRA_UNCORES] = {
63096342
&spr_uncore_iio_free_running,
@@ -6313,6 +6346,17 @@ static struct intel_uncore_type *spr_mmio_uncores[UNCORE_SPR_MMIO_EXTRA_UNCORES]
63136346
&spr_uncore_imc_free_running,
63146347
};
63156348

6349+
static struct intel_uncore_type *spr_pci_uncores[UNCORE_SPR_PCI_EXTRA_UNCORES] = {
6350+
&spr_uncore_upi,
6351+
&spr_uncore_m3upi
6352+
};
6353+
6354+
int spr_uncore_units_ignore[] = {
6355+
UNCORE_SPR_UPI,
6356+
UNCORE_SPR_M3UPI,
6357+
UNCORE_IGNORE_END
6358+
};
6359+
63166360
static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
63176361
struct intel_uncore_type *from_type)
63186362
{
@@ -6413,9 +6457,69 @@ void spr_uncore_cpu_init(void)
64136457
spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO);
64146458
}
64156459

6460+
#define SPR_UNCORE_UPI_PCIID 0x3241
6461+
#define SPR_UNCORE_UPI0_DEVFN 0x9
6462+
#define SPR_UNCORE_M3UPI_PCIID 0x3246
6463+
#define SPR_UNCORE_M3UPI0_DEVFN 0x29
6464+
6465+
static void spr_update_device_location(int type_id)
6466+
{
6467+
struct intel_uncore_type *type;
6468+
struct pci_dev *dev = NULL;
6469+
u32 device, devfn;
6470+
u64 *ctls;
6471+
int die;
6472+
6473+
if (type_id == UNCORE_SPR_UPI) {
6474+
type = &spr_uncore_upi;
6475+
device = SPR_UNCORE_UPI_PCIID;
6476+
devfn = SPR_UNCORE_UPI0_DEVFN;
6477+
} else if (type_id == UNCORE_SPR_M3UPI) {
6478+
type = &spr_uncore_m3upi;
6479+
device = SPR_UNCORE_M3UPI_PCIID;
6480+
devfn = SPR_UNCORE_M3UPI0_DEVFN;
6481+
} else
6482+
return;
6483+
6484+
ctls = kcalloc(__uncore_max_dies, sizeof(u64), GFP_KERNEL);
6485+
if (!ctls) {
6486+
type->num_boxes = 0;
6487+
return;
6488+
}
6489+
6490+
while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, dev)) != NULL) {
6491+
if (devfn != dev->devfn)
6492+
continue;
6493+
6494+
die = uncore_device_to_die(dev);
6495+
if (die < 0)
6496+
continue;
6497+
6498+
ctls[die] = pci_domain_nr(dev->bus) << UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET |
6499+
dev->bus->number << UNCORE_DISCOVERY_PCI_BUS_OFFSET |
6500+
devfn << UNCORE_DISCOVERY_PCI_DEVFN_OFFSET |
6501+
type->box_ctl;
6502+
}
6503+
6504+
type->box_ctls = ctls;
6505+
}
6506+
64166507
int spr_uncore_pci_init(void)
64176508
{
6418-
uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI, 0, NULL);
6509+
/*
6510+
* The discovery table of UPI on some SPR variant is broken,
6511+
* which impacts the detection of both UPI and M3UPI uncore PMON.
6512+
* Use the pre-defined UPI and M3UPI table to replace.
6513+
*
6514+
* The accurate location, e.g., domain and BUS number,
6515+
* can only be retrieved at load time.
6516+
* Update the location of UPI and M3UPI.
6517+
*/
6518+
spr_update_device_location(UNCORE_SPR_UPI);
6519+
spr_update_device_location(UNCORE_SPR_M3UPI);
6520+
uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI,
6521+
UNCORE_SPR_PCI_EXTRA_UNCORES,
6522+
spr_pci_uncores);
64196523
return 0;
64206524
}
64216525

0 commit comments

Comments
 (0)