Skip to content

Commit 4cfce57

Browse files
Alexander AntonovPeter Zijlstra
authored andcommitted
perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server
UPI topology discovery relies on data from KTILP0 (offset 0x94) and KTIPCSTS (offset 0x120) registers which reside under IIO bus(3) on SKX/CLX. This patch enable UPI topology discovery on Skylake Server. Topology is exposed through attributes /sys/devices/uncore_upi_<pmu_idx>/dieX, where dieX is file which holds "upi_<idx1>:die_<idx2>" connected to this UPI link. Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Kan Liang <kan.liang@linux.intel.com> Link: https://lore.kernel.org/r/20221117122833.3103580-7-alexander.antonov@linux.intel.com
1 parent 07813e2 commit 4cfce57

1 file changed

Lines changed: 130 additions & 0 deletions

File tree

arch/x86/events/intel/uncore_snbep.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4253,6 +4253,132 @@ static struct intel_uncore_ops skx_upi_uncore_pci_ops = {
42534253
.read_counter = snbep_uncore_pci_read_counter,
42544254
};
42554255

4256+
static umode_t
4257+
skx_upi_mapping_visible(struct kobject *kobj, struct attribute *attr, int die)
4258+
{
4259+
struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
4260+
4261+
return pmu->type->topology[die][pmu->pmu_idx].upi->enabled ? attr->mode : 0;
4262+
}
4263+
4264+
static ssize_t skx_upi_mapping_show(struct device *dev,
4265+
struct device_attribute *attr, char *buf)
4266+
{
4267+
struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
4268+
struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
4269+
long die = (long)ea->var;
4270+
struct uncore_upi_topology *upi = pmu->type->topology[die][pmu->pmu_idx].upi;
4271+
4272+
return sysfs_emit(buf, "upi_%d,die_%d\n", upi->pmu_idx_to, upi->die_to);
4273+
}
4274+
4275+
#define SKX_UPI_REG_DID 0x2058
4276+
#define SKX_UPI_REGS_ADDR_DEVICE_LINK0 0x0e
4277+
#define SKX_UPI_REGS_ADDR_FUNCTION 0x00
4278+
4279+
/*
4280+
* UPI Link Parameter 0
4281+
* | Bit | Default | Description
4282+
* | 19:16 | 0h | base_nodeid - The NodeID of the sending socket.
4283+
* | 12:8 | 00h | sending_port - The processor die port number of the sending port.
4284+
*/
4285+
#define SKX_KTILP0_OFFSET 0x94
4286+
4287+
/*
4288+
* UPI Pcode Status. This register is used by PCode to store the link training status.
4289+
* | Bit | Default | Description
4290+
* | 4 | 0h | ll_status_valid — Bit indicates the valid training status
4291+
* logged from PCode to the BIOS.
4292+
*/
4293+
#define SKX_KTIPCSTS_OFFSET 0x120
4294+
4295+
static int upi_fill_topology(struct pci_dev *dev, struct intel_uncore_topology *tp,
4296+
int pmu_idx)
4297+
{
4298+
int ret;
4299+
u32 upi_conf;
4300+
struct uncore_upi_topology *upi = tp->upi;
4301+
4302+
tp->pmu_idx = pmu_idx;
4303+
ret = pci_read_config_dword(dev, SKX_KTIPCSTS_OFFSET, &upi_conf);
4304+
if (ret) {
4305+
ret = pcibios_err_to_errno(ret);
4306+
goto err;
4307+
}
4308+
upi->enabled = (upi_conf >> 4) & 1;
4309+
if (upi->enabled) {
4310+
ret = pci_read_config_dword(dev, SKX_KTILP0_OFFSET,
4311+
&upi_conf);
4312+
if (ret) {
4313+
ret = pcibios_err_to_errno(ret);
4314+
goto err;
4315+
}
4316+
upi->die_to = (upi_conf >> 16) & 0xf;
4317+
upi->pmu_idx_to = (upi_conf >> 8) & 0x1f;
4318+
}
4319+
err:
4320+
return ret;
4321+
}
4322+
4323+
static int skx_upi_topology_cb(struct intel_uncore_type *type, int segment,
4324+
int die, u64 cpu_bus_msr)
4325+
{
4326+
int idx, ret;
4327+
struct intel_uncore_topology *upi;
4328+
unsigned int devfn;
4329+
struct pci_dev *dev = NULL;
4330+
u8 bus = cpu_bus_msr >> (3 * BUS_NUM_STRIDE);
4331+
4332+
for (idx = 0; idx < type->num_boxes; idx++) {
4333+
upi = &type->topology[die][idx];
4334+
devfn = PCI_DEVFN(SKX_UPI_REGS_ADDR_DEVICE_LINK0 + idx,
4335+
SKX_UPI_REGS_ADDR_FUNCTION);
4336+
dev = pci_get_domain_bus_and_slot(segment, bus, devfn);
4337+
if (dev) {
4338+
ret = upi_fill_topology(dev, upi, idx);
4339+
if (ret)
4340+
break;
4341+
}
4342+
}
4343+
4344+
pci_dev_put(dev);
4345+
return ret;
4346+
}
4347+
4348+
static int skx_upi_get_topology(struct intel_uncore_type *type)
4349+
{
4350+
/* CPX case is not supported */
4351+
if (boot_cpu_data.x86_stepping == 11)
4352+
return -EPERM;
4353+
4354+
return skx_pmu_get_topology(type, skx_upi_topology_cb);
4355+
}
4356+
4357+
static struct attribute_group skx_upi_mapping_group = {
4358+
.is_visible = skx_upi_mapping_visible,
4359+
};
4360+
4361+
static const struct attribute_group *skx_upi_attr_update[] = {
4362+
&skx_upi_mapping_group,
4363+
NULL
4364+
};
4365+
4366+
static int
4367+
pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
4368+
{
4369+
return pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
4370+
}
4371+
4372+
static int skx_upi_set_mapping(struct intel_uncore_type *type)
4373+
{
4374+
return pmu_upi_set_mapping(type, &skx_upi_mapping_group);
4375+
}
4376+
4377+
static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
4378+
{
4379+
pmu_cleanup_mapping(type, &skx_upi_mapping_group);
4380+
}
4381+
42564382
static struct intel_uncore_type skx_uncore_upi = {
42574383
.name = "upi",
42584384
.num_counters = 4,
@@ -4265,6 +4391,10 @@ static struct intel_uncore_type skx_uncore_upi = {
42654391
.box_ctl = SKX_UPI_PCI_PMON_BOX_CTL,
42664392
.ops = &skx_upi_uncore_pci_ops,
42674393
.format_group = &skx_upi_uncore_format_group,
4394+
.attr_update = skx_upi_attr_update,
4395+
.get_topology = skx_upi_get_topology,
4396+
.set_mapping = skx_upi_set_mapping,
4397+
.cleanup_mapping = skx_upi_cleanup_mapping,
42684398
};
42694399

42704400
static void skx_m2m_uncore_pci_init_box(struct intel_uncore_box *box)

0 commit comments

Comments
 (0)