perf/x86/intel/uncore: Support IMC free-running counters on Sapphire Rapids server
authorKan Liang <kan.liang@linux.intel.com>
Wed, 30 Jun 2021 21:08:39 +0000 (14:08 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 2 Jul 2021 13:58:42 +0000 (15:58 +0200)
Several free-running counters for IMC uncore blocks are supported on
Sapphire Rapids server.

They are not enumerated in the discovery tables. The number of the
free-running counter boxes is calculated from the number of
corresponding standard boxes.

The snbep_pci2phy_map_init() is invoked to setup the mapping from a PCI
BUS to a Die ID, which is used to locate the corresponding MC device of
a IMC uncore unit in the spr_uncore_imc_freerunning_init_box().

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Link: https://lore.kernel.org/r/1625087320-194204-16-git-send-email-kan.liang@linux.intel.com
arch/x86/events/intel/uncore_snbep.c

index 9882549..2558e26 100644 (file)
@@ -5753,6 +5753,7 @@ 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
 
 static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
        &spr_uncore_chabox,
@@ -5849,12 +5850,65 @@ static struct intel_uncore_type spr_uncore_iio_free_running = {
        .format_group           = &skx_uncore_iio_freerunning_format_group,
 };
 
+enum perf_uncore_spr_imc_freerunning_type_id {
+       SPR_IMC_DCLK,
+       SPR_IMC_PQ_CYCLES,
+
+       SPR_IMC_FREERUNNING_TYPE_MAX,
+};
+
+static struct freerunning_counters spr_imc_freerunning[] = {
+       [SPR_IMC_DCLK]          = { 0x22b0, 0x0, 0, 1, 48 },
+       [SPR_IMC_PQ_CYCLES]     = { 0x2318, 0x8, 0, 2, 48 },
+};
+
+static struct uncore_event_desc spr_uncore_imc_freerunning_events[] = {
+       INTEL_UNCORE_EVENT_DESC(dclk,                   "event=0xff,umask=0x10"),
+
+       INTEL_UNCORE_EVENT_DESC(rpq_cycles,             "event=0xff,umask=0x20"),
+       INTEL_UNCORE_EVENT_DESC(wpq_cycles,             "event=0xff,umask=0x21"),
+       { /* end: all zeroes */ },
+};
+
+#define SPR_MC_DEVICE_ID       0x3251
+
+static void spr_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
+{
+       int mem_offset = box->pmu->pmu_idx * ICX_IMC_MEM_STRIDE + SNR_IMC_MMIO_MEM0_OFFSET;
+
+       snr_uncore_mmio_map(box, uncore_mmio_box_ctl(box),
+                           mem_offset, SPR_MC_DEVICE_ID);
+}
+
+static struct intel_uncore_ops spr_uncore_imc_freerunning_ops = {
+       .init_box       = spr_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 spr_uncore_imc_free_running = {
+       .name                   = "imc_free_running",
+       .num_counters           = 3,
+       .mmio_map_size          = SNR_IMC_MMIO_SIZE,
+       .num_freerunning_types  = SPR_IMC_FREERUNNING_TYPE_MAX,
+       .freerunning            = spr_imc_freerunning,
+       .ops                    = &spr_uncore_imc_freerunning_ops,
+       .event_descs            = spr_uncore_imc_freerunning_events,
+       .format_group           = &skx_uncore_iio_freerunning_format_group,
+};
+
 #define UNCORE_SPR_MSR_EXTRA_UNCORES           1
+#define UNCORE_SPR_MMIO_EXTRA_UNCORES          1
 
 static struct intel_uncore_type *spr_msr_uncores[UNCORE_SPR_MSR_EXTRA_UNCORES] = {
        &spr_uncore_iio_free_running,
 };
 
+static struct intel_uncore_type *spr_mmio_uncores[UNCORE_SPR_MMIO_EXTRA_UNCORES] = {
+       &spr_uncore_imc_free_running,
+};
+
 static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
                                        struct intel_uncore_type *from_type)
 {
@@ -5957,7 +6011,17 @@ int spr_uncore_pci_init(void)
 
 void spr_uncore_mmio_init(void)
 {
-       uncore_mmio_uncores = uncore_get_uncores(UNCORE_ACCESS_MMIO, 0, NULL);
+       int ret = snbep_pci2phy_map_init(0x3250, SKX_CPUNODEID, SKX_GIDNIDMAP, true);
+
+       if (ret)
+               uncore_mmio_uncores = uncore_get_uncores(UNCORE_ACCESS_MMIO, 0, NULL);
+       else {
+               uncore_mmio_uncores = uncore_get_uncores(UNCORE_ACCESS_MMIO,
+                                                        UNCORE_SPR_MMIO_EXTRA_UNCORES,
+                                                        spr_mmio_uncores);
+
+               spr_uncore_imc_free_running.num_boxes = uncore_type_max_boxes(uncore_mmio_uncores, UNCORE_SPR_IMC) / 2;
+       }
 }
 
 /* end of SPR uncore support */