4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kan Liang <kan.li...@linux.intel.com>

commit 320b0651f32b830add6497fcdcfdcb6ae8c7b8a0 upstream.

The number of CHAs is miscalculated on multi-domain PCI Skylake server systems,
resulting in an uncore driver initialization error.

Gary Kroening explains:

 "For systems with a single PCI segment, it is sufficient to look for the
  bus number to change in order to determine that all of the CHa's have
  been counted for a single socket.

  However, for multi PCI segment systems, each socket is given a new
  segment and the bus number does NOT change.  So looking only for the
  bus number to change ends up counting all of the CHa's on all sockets
  in the system.  This leads to writing CPU MSRs beyond a valid range and
  causes an error in ivbep_uncore_msr_init_box()."

To fix this bug, query the number of CHAs from the CAPID6 register:
it should read bits 27:0 in the CAPID6 register located at
Device 30, Function 3, Offset 0x9C. These 28 bits form a bit vector
of available LLC slices and the CHAs that manage those slices.

Reported-by: Kroening, Gary <gary.kroen...@hpe.com>
Tested-by: Kroening, Gary <gary.kroen...@hpe.com>
Signed-off-by: Kan Liang <kan.li...@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Reviewed-by: Andy Shevchenko <andy.shevche...@gmail.com>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <eran...@google.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Vince Weaver <vincent.wea...@maine.edu>
Cc: aban...@hpe.com
Cc: dimitri.sivan...@hpe.com
Cc: h...@zytor.com
Cc: mike.tra...@hpe.com
Cc: russ.ander...@hpe.com
Fixes: cd34cd97b7b4 ("perf/x86/intel/uncore: Add Skylake server uncore support")
Link: 
http://lkml.kernel.org/r/1520967094-13219-1-git-send-email-kan.li...@linux.intel.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 arch/x86/events/intel/uncore_snbep.c |   31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3522,24 +3522,27 @@ static struct intel_uncore_type *skx_msr
        NULL,
 };
 
+/*
+ * To determine the number of CHAs, it should read bits 27:0 in the CAPID6
+ * register which located at Device 30, Function 3, Offset 0x9C. PCI ID 0x2083.
+ */
+#define SKX_CAPID6             0x9c
+#define SKX_CHA_BIT_MASK       GENMASK(27, 0)
+
 static int skx_count_chabox(void)
 {
-       struct pci_dev *chabox_dev = NULL;
-       int bus, count = 0;
+       struct pci_dev *dev = NULL;
+       u32 val = 0;
 
-       while (1) {
-               chabox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x208d, 
chabox_dev);
-               if (!chabox_dev)
-                       break;
-               if (count == 0)
-                       bus = chabox_dev->bus->number;
-               if (bus != chabox_dev->bus->number)
-                       break;
-               count++;
-       }
+       dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x2083, dev);
+       if (!dev)
+               goto out;
 
-       pci_dev_put(chabox_dev);
-       return count;
+       pci_read_config_dword(dev, SKX_CAPID6, &val);
+       val &= SKX_CHA_BIT_MASK;
+out:
+       pci_dev_put(dev);
+       return hweight32(val);
 }
 
 void skx_uncore_cpu_init(void)


Reply via email to