Tested-by: Steve Wahl <steve.w...@hpe.com>

On Thu, Apr 15, 2021 at 02:22:43PM -0700, kan.li...@linux.intel.com wrote:
> From: Kan Liang <kan.li...@linux.intel.com>
> 
> There may be a kernel panic on the Haswell server and the Broadwell
> server, if the snbep_pci2phy_map_init() return error.
> 
> The uncore_extra_pci_dev[HSWEP_PCI_PCU_3] is used in the cpu_init() to
> detect the existence of the SBOX, which is a MSR type of PMON unit.
> The uncore_extra_pci_dev is allocated in the uncore_pci_init(). If the
> snbep_pci2phy_map_init() returns error, perf doesn't initialize the
> PCI type of the PMON units, so the uncore_extra_pci_dev will not be
> allocated. But perf may continue initializing the MSR type of PMON
> units. A null dereference kernel panic will be triggered.
> 
> The sockets in a Haswell server or a Broadwell server are identical.
> Only need to detect the existence of the SBOX once.
> Current perf probes all available PCU devices and stores them into the
> uncore_extra_pci_dev. It's unnecessary.
> Use the pci_get_device() to replace the uncore_extra_pci_dev. Only
> detect the existence of the SBOX on the first available PCU device once.
> 
> Factor out hswep_has_limit_sbox(), since the Haswell server and the
> Broadwell server uses the same way to detect the existence of the SBOX.
> 
> Add some macros to replace the magic number.
> 
> Fixes: 5306c31c5733 ("perf/x86/uncore/hsw-ep: Handle systems with only two 
> SBOXes")
> Reported-by: Steve Wahl <steve.w...@hpe.com>
> Signed-off-by: Kan Liang <kan.li...@linux.intel.com>
> ---
>  arch/x86/events/intel/uncore_snbep.c | 61 
> +++++++++++++++---------------------
>  1 file changed, 26 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/x86/events/intel/uncore_snbep.c 
> b/arch/x86/events/intel/uncore_snbep.c
> index b79951d..9b89376 100644
> --- a/arch/x86/events/intel/uncore_snbep.c
> +++ b/arch/x86/events/intel/uncore_snbep.c
> @@ -1159,7 +1159,6 @@ enum {
>       SNBEP_PCI_QPI_PORT0_FILTER,
>       SNBEP_PCI_QPI_PORT1_FILTER,
>       BDX_PCI_QPI_PORT2_FILTER,
> -     HSWEP_PCI_PCU_3,
>  };
>  
>  static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct 
> perf_event *event)
> @@ -2857,22 +2856,33 @@ static struct intel_uncore_type *hswep_msr_uncores[] 
> = {
>       NULL,
>  };
>  
> -void hswep_uncore_cpu_init(void)
> +#define HSWEP_PCU_DID                        0x2fc0
> +#define HSWEP_PCU_CAPID4_OFFET               0x94
> +#define hswep_get_chop(_cap)         (((_cap) >> 6) & 0x3)
> +
> +static bool hswep_has_limit_sbox(unsigned int device)
>  {
> -     int pkg = boot_cpu_data.logical_proc_id;
> +     struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
> +     u32 capid4;
> +
> +     if (!dev)
> +             return false;
> +
> +     pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4);
> +     if (!hswep_get_chop(capid4))
> +             return true;
>  
> +     return false;
> +}
> +
> +void hswep_uncore_cpu_init(void)
> +{
>       if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
>               hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
>  
>       /* Detect 6-8 core systems with only two SBOXes */
> -     if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
> -             u32 capid4;
> -
> -             
> pci_read_config_dword(uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3],
> -                                   0x94, &capid4);
> -             if (((capid4 >> 6) & 0x3) == 0)
> -                     hswep_uncore_sbox.num_boxes = 2;
> -     }
> +     if (hswep_has_limit_sbox(HSWEP_PCU_DID))
> +             hswep_uncore_sbox.num_boxes = 2;
>  
>       uncore_msr_uncores = hswep_msr_uncores;
>  }
> @@ -3135,11 +3145,6 @@ static const struct pci_device_id 
> hswep_uncore_pci_ids[] = {
>               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
>                                                  SNBEP_PCI_QPI_PORT1_FILTER),
>       },
> -     { /* PCU.3 (for Capability registers) */
> -             PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0),
> -             .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
> -                                                HSWEP_PCI_PCU_3),
> -     },
>       { /* end: all zeroes */ }
>  };
>  
> @@ -3231,27 +3236,18 @@ static struct event_constraint 
> bdx_uncore_pcu_constraints[] = {
>       EVENT_CONSTRAINT_END
>  };
>  
> +#define BDX_PCU_DID                  0x6fc0
> +
>  void bdx_uncore_cpu_init(void)
>  {
> -     int pkg = topology_phys_to_logical_pkg(boot_cpu_data.phys_proc_id);
> -
>       if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
>               bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
>       uncore_msr_uncores = bdx_msr_uncores;
>  
> -     /* BDX-DE doesn't have SBOX */
> -     if (boot_cpu_data.x86_model == 86) {
> -             uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
>       /* Detect systems with no SBOXes */
> -     } else if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
> -             struct pci_dev *pdev;
> -             u32 capid4;
> -
> -             pdev = uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3];
> -             pci_read_config_dword(pdev, 0x94, &capid4);
> -             if (((capid4 >> 6) & 0x3) == 0)
> -                     bdx_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
> -     }
> +     if ((boot_cpu_data.x86_model == 86) || 
> hswep_has_limit_sbox(BDX_PCU_DID))
> +             uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
> +
>       hswep_uncore_pcu.constraints = bdx_uncore_pcu_constraints;
>  }
>  
> @@ -3472,11 +3468,6 @@ static const struct pci_device_id bdx_uncore_pci_ids[] 
> = {
>               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
>                                                  BDX_PCI_QPI_PORT2_FILTER),
>       },
> -     { /* PCU.3 (for Capability registers) */
> -             PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fc0),
> -             .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
> -                                                HSWEP_PCI_PCU_3),
> -     },
>       { /* end: all zeroes */ }
>  };
>  
> -- 
> 2.7.4
> 

-- 
Steve Wahl, Hewlett Packard Enterprise

Reply via email to