perf/x86/intel/uncore: Record the size of mapped area
authorKan Liang <kan.liang@linux.intel.com>
Thu, 28 May 2020 15:19:28 +0000 (08:19 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 15 Jun 2020 12:09:50 +0000 (14:09 +0200)
Perf cannot validate an address before the actual access to MMIO space
of some uncore units, e.g. IMC on TGL. Accessing an invalid address,
which exceeds mapped area, can trigger oops.

Perf never records the size of mapped area. Generic functions, e.g.
uncore_mmio_read_counter(), cannot get the correct size for address
validation.

Add mmio_map_size in intel_uncore_type to record the size of mapped
area. Print warning message if ioremap fails.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1590679169-61823-2-git-send-email-kan.liang@linux.intel.com
arch/x86/events/intel/uncore.h
arch/x86/events/intel/uncore_snb.c
arch/x86/events/intel/uncore_snbep.c

index b469ddd45515c86ff3ed1d20dec76492e2945bc0..79ff626b7ea6c576dc8d697f4dac804507e97816 100644 (file)
@@ -61,6 +61,7 @@ struct intel_uncore_type {
                unsigned msr_offset;
                unsigned mmio_offset;
        };
+       unsigned mmio_map_size;
        unsigned num_shared_regs:8;
        unsigned single_fixed:1;
        unsigned pair_ctr_ctl:1;
index d5ae3a822193287a5d82b3971d34d8f63da02d1a..cb94ba86efd28f5ef1e69bcd4ac0976f29e17965 100644 (file)
@@ -426,6 +426,7 @@ static const struct attribute_group snb_uncore_imc_format_group = {
 
 static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
 {
+       struct intel_uncore_type *type = box->pmu->type;
        struct pci_dev *pdev = box->pci_dev;
        int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
        resource_size_t addr;
@@ -441,7 +442,10 @@ static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
 
        addr &= ~(PAGE_SIZE - 1);
 
-       box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
+       box->io_addr = ioremap(addr, type->mmio_map_size);
+       if (!box->io_addr)
+               pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
+
        box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
 }
 
@@ -597,6 +601,7 @@ static struct intel_uncore_type snb_uncore_imc = {
        .num_counters   = 2,
        .num_boxes      = 1,
        .num_freerunning_types  = SNB_PCI_UNCORE_IMC_FREERUNNING_TYPE_MAX,
+       .mmio_map_size  = SNB_UNCORE_PCI_IMC_MAP_SIZE,
        .freerunning    = snb_uncore_imc_freerunning,
        .event_descs    = snb_uncore_imc_events,
        .format_group   = &snb_uncore_imc_format_group,
@@ -1157,6 +1162,7 @@ static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = tgl_uncore_get_mc_dev();
        struct intel_uncore_pmu *pmu = box->pmu;
+       struct intel_uncore_type *type = pmu->type;
        resource_size_t addr;
        u32 mch_bar;
 
@@ -1179,7 +1185,9 @@ static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
        addr |= ((resource_size_t)mch_bar << 32);
 #endif
 
-       box->io_addr = ioremap(addr, TGL_UNCORE_PCI_IMC_MAP_SIZE);
+       box->io_addr = ioremap(addr, type->mmio_map_size);
+       if (!box->io_addr)
+               pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
 }
 
 static struct intel_uncore_ops tgl_uncore_imc_freerunning_ops = {
@@ -1205,6 +1213,7 @@ static struct intel_uncore_type tgl_uncore_imc_free_running = {
        .num_counters           = 3,
        .num_boxes              = 2,
        .num_freerunning_types  = TGL_MMIO_UNCORE_IMC_FREERUNNING_TYPE_MAX,
+       .mmio_map_size          = TGL_UNCORE_PCI_IMC_MAP_SIZE,
        .freerunning            = tgl_uncore_imc_freerunning,
        .ops                    = &tgl_uncore_imc_freerunning_ops,
        .event_descs            = tgl_uncore_imc_events,
index 07652fa20ebbe9cd551eb87f71c17c506ee55030..bffb7554f4fbd510a976af8465cedef7b2dcbcae 100644 (file)
@@ -4421,6 +4421,7 @@ static void __snr_uncore_mmio_init_box(struct intel_uncore_box *box,
                                       unsigned int box_ctl, int mem_offset)
 {
        struct pci_dev *pdev = snr_uncore_get_mc_dev(box->dieid);
+       struct intel_uncore_type *type = box->pmu->type;
        resource_size_t addr;
        u32 pci_dword;
 
@@ -4435,9 +4436,11 @@ static void __snr_uncore_mmio_init_box(struct intel_uncore_box *box,
 
        addr += box_ctl;
 
-       box->io_addr = ioremap(addr, SNR_IMC_MMIO_SIZE);
-       if (!box->io_addr)
+       box->io_addr = ioremap(addr, type->mmio_map_size);
+       if (!box->io_addr) {
+               pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
                return;
+       }
 
        writel(IVBEP_PMON_BOX_CTL_INT, box->io_addr);
 }
@@ -4530,6 +4533,7 @@ static struct intel_uncore_type snr_uncore_imc = {
        .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,
        .box_ctl        = SNR_IMC_MMIO_PMON_BOX_CTL,
        .mmio_offset    = SNR_IMC_MMIO_OFFSET,
+       .mmio_map_size  = SNR_IMC_MMIO_SIZE,
        .ops            = &snr_uncore_mmio_ops,
        .format_group   = &skx_uncore_format_group,
 };
@@ -4570,6 +4574,7 @@ static struct intel_uncore_type snr_uncore_imc_free_running = {
        .num_counters           = 3,
        .num_boxes              = 1,
        .num_freerunning_types  = SNR_IMC_FREERUNNING_TYPE_MAX,
+       .mmio_map_size          = SNR_IMC_MMIO_SIZE,
        .freerunning            = snr_imc_freerunning,
        .ops                    = &snr_uncore_imc_freerunning_ops,
        .event_descs            = snr_uncore_imc_freerunning_events,
@@ -4987,6 +4992,7 @@ static struct intel_uncore_type icx_uncore_imc = {
        .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,
        .box_ctl        = SNR_IMC_MMIO_PMON_BOX_CTL,
        .mmio_offset    = SNR_IMC_MMIO_OFFSET,
+       .mmio_map_size  = SNR_IMC_MMIO_SIZE,
        .ops            = &icx_uncore_mmio_ops,
        .format_group   = &skx_uncore_format_group,
 };
@@ -5044,6 +5050,7 @@ static struct intel_uncore_type icx_uncore_imc_free_running = {
        .num_counters           = 5,
        .num_boxes              = 4,
        .num_freerunning_types  = ICX_IMC_FREERUNNING_TYPE_MAX,
+       .mmio_map_size          = SNR_IMC_MMIO_SIZE,
        .freerunning            = icx_imc_freerunning,
        .ops                    = &icx_uncore_imc_freerunning_ops,
        .event_descs            = icx_uncore_imc_freerunning_events,