#define ICX_UPI_PCI_PMON_CTR0                  0x320
 #define ICX_UPI_PCI_PMON_BOX_CTL               0x318
 #define ICX_UPI_CTL_UMASK_EXT                  0xffffff
+#define ICX_UBOX_DID                           0x3450
 
 /* ICX M3UPI*/
 #define ICX_M3UPI_PCI_PMON_CTL0                        0xd8
        .attrs = icx_upi_uncore_formats_attr,
 };
 
+#define ICX_UPI_REGS_ADDR_DEVICE_LINK0 0x02
+#define ICX_UPI_REGS_ADDR_FUNCTION     0x01
+
+static int discover_upi_topology(struct intel_uncore_type *type, int ubox_did, int dev_link0)
+{
+       struct pci_dev *ubox = NULL;
+       struct pci_dev *dev = NULL;
+       u32 nid, gid;
+       int i, idx, ret = -EPERM;
+       struct intel_uncore_topology *upi;
+       unsigned int devfn;
+
+       /* GIDNIDMAP method supports machines which have less than 8 sockets. */
+       if (uncore_max_dies() > 8)
+               goto err;
+
+       while ((ubox = pci_get_device(PCI_VENDOR_ID_INTEL, ubox_did, ubox))) {
+               ret = upi_nodeid_groupid(ubox, SKX_CPUNODEID, SKX_GIDNIDMAP, &nid, &gid);
+               if (ret) {
+                       ret = pcibios_err_to_errno(ret);
+                       break;
+               }
+
+               for (i = 0; i < 8; i++) {
+                       if (nid != GIDNIDMAP(gid, i))
+                               continue;
+                       for (idx = 0; idx < type->num_boxes; idx++) {
+                               upi = &type->topology[nid][idx];
+                               devfn = PCI_DEVFN(dev_link0 + idx, ICX_UPI_REGS_ADDR_FUNCTION);
+                               dev = pci_get_domain_bus_and_slot(pci_domain_nr(ubox->bus),
+                                                                 ubox->bus->number,
+                                                                 devfn);
+                               if (dev) {
+                                       ret = upi_fill_topology(dev, upi, idx);
+                                       if (ret)
+                                               goto err;
+                               }
+                       }
+               }
+       }
+err:
+       pci_dev_put(ubox);
+       pci_dev_put(dev);
+       return ret;
+}
+
+static int icx_upi_get_topology(struct intel_uncore_type *type)
+{
+       return discover_upi_topology(type, ICX_UBOX_DID, ICX_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
+static struct attribute_group icx_upi_mapping_group = {
+       .is_visible     = skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *icx_upi_attr_update[] = {
+       &icx_upi_mapping_group,
+       NULL
+};
+
+static int icx_upi_set_mapping(struct intel_uncore_type *type)
+{
+       return pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+}
+
+static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+       pmu_cleanup_mapping(type, &icx_upi_mapping_group);
+}
+
 static struct intel_uncore_type icx_uncore_upi = {
        .name           = "upi",
        .num_counters   = 4,
        .box_ctl        = ICX_UPI_PCI_PMON_BOX_CTL,
        .ops            = &skx_upi_uncore_pci_ops,
        .format_group   = &icx_upi_uncore_format_group,
+       .attr_update    = icx_upi_attr_update,
+       .get_topology   = icx_upi_get_topology,
+       .set_mapping    = icx_upi_set_mapping,
+       .cleanup_mapping = icx_upi_cleanup_mapping,
 };
 
 static struct event_constraint icx_uncore_m3upi_constraints[] = {