Commit bcb48dd3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'perf-core-2025-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 performance events updates from Ingo Molnar:
 "Intel uncore driver enhancements (Kan Liang):

   - Support MSR portal for discovery tables

   - Support customized MMIO map size

   - Add Panther Lake support

   - Add IMC freerunning support for Panther Lake"

* tag 'perf-core-2025-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/intel/uncore: Add iMC freerunning for Panther Lake
  perf/x86/intel/uncore: Add Panther Lake support
  perf/x86/intel/uncore: Support customized MMIO map size
  perf/x86/intel/uncore: Support MSR portal for discovery tables
parents bf76f23a 829f5a63
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1807,6 +1807,12 @@ static const struct intel_uncore_init_fun lnl_uncore_init __initconst = {
	.mmio_init = lnl_uncore_mmio_init,
};

static const struct intel_uncore_init_fun ptl_uncore_init __initconst = {
	.cpu_init = ptl_uncore_cpu_init,
	.mmio_init = ptl_uncore_mmio_init,
	.use_discovery = true,
};

static const struct intel_uncore_init_fun icx_uncore_init __initconst = {
	.cpu_init = icx_uncore_cpu_init,
	.pci_init = icx_uncore_pci_init,
@@ -1888,6 +1894,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
	X86_MATCH_VFM(INTEL_ARROWLAKE_U,	&mtl_uncore_init),
	X86_MATCH_VFM(INTEL_ARROWLAKE_H,	&mtl_uncore_init),
	X86_MATCH_VFM(INTEL_LUNARLAKE_M,	&lnl_uncore_init),
	X86_MATCH_VFM(INTEL_PANTHERLAKE_L,	&ptl_uncore_init),
	X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X,	&spr_uncore_init),
	X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X,	&spr_uncore_init),
	X86_MATCH_VFM(INTEL_GRANITERAPIDS_X,	&gnr_uncore_init),
+2 −0
Original line number Diff line number Diff line
@@ -612,10 +612,12 @@ void tgl_uncore_cpu_init(void);
void adl_uncore_cpu_init(void);
void lnl_uncore_cpu_init(void);
void mtl_uncore_cpu_init(void);
void ptl_uncore_cpu_init(void);
void tgl_uncore_mmio_init(void);
void tgl_l_uncore_mmio_init(void);
void adl_uncore_mmio_init(void);
void lnl_uncore_mmio_init(void);
void ptl_uncore_mmio_init(void);
int snb_pci2phy_map_init(int devid);

/* uncore_snbep.c */
+68 −21
Original line number Diff line number Diff line
@@ -274,32 +274,15 @@ uncore_ignore_unit(struct uncore_unit_discovery *unit, int *ignore)
	return false;
}

static int parse_discovery_table(struct pci_dev *dev, int die,
				 u32 bar_offset, bool *parsed,
				 int *ignore)
static int __parse_discovery_table(resource_size_t addr, int die,
				   bool *parsed, int *ignore)
{
	struct uncore_global_discovery global;
	struct uncore_unit_discovery unit;
	void __iomem *io_addr;
	resource_size_t addr;
	unsigned long size;
	u32 val;
	int i;

	pci_read_config_dword(dev, bar_offset, &val);

	if (val & ~PCI_BASE_ADDRESS_MEM_MASK & ~PCI_BASE_ADDRESS_MEM_TYPE_64)
		return -EINVAL;

	addr = (resource_size_t)(val & PCI_BASE_ADDRESS_MEM_MASK);
#ifdef CONFIG_PHYS_ADDR_T_64BIT
	if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
		u32 val2;

		pci_read_config_dword(dev, bar_offset + 4, &val2);
		addr |= ((resource_size_t)val2) << 32;
	}
#endif
	size = UNCORE_DISCOVERY_GLOBAL_MAP_SIZE;
	io_addr = ioremap(addr, size);
	if (!io_addr)
@@ -342,7 +325,32 @@ static int parse_discovery_table(struct pci_dev *dev, int die,
	return 0;
}

bool intel_uncore_has_discovery_tables(int *ignore)
static int parse_discovery_table(struct pci_dev *dev, int die,
				 u32 bar_offset, bool *parsed,
				 int *ignore)
{
	resource_size_t addr;
	u32 val;

	pci_read_config_dword(dev, bar_offset, &val);

	if (val & ~PCI_BASE_ADDRESS_MEM_MASK & ~PCI_BASE_ADDRESS_MEM_TYPE_64)
		return -EINVAL;

	addr = (resource_size_t)(val & PCI_BASE_ADDRESS_MEM_MASK);
#ifdef CONFIG_PHYS_ADDR_T_64BIT
	if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
		u32 val2;

		pci_read_config_dword(dev, bar_offset + 4, &val2);
		addr |= ((resource_size_t)val2) << 32;
	}
#endif

	return __parse_discovery_table(addr, die, parsed, ignore);
}

static bool intel_uncore_has_discovery_tables_pci(int *ignore)
{
	u32 device, val, entry_id, bar_offset;
	int die, dvsec = 0, ret = true;
@@ -391,6 +399,45 @@ bool intel_uncore_has_discovery_tables(int *ignore)
	return ret;
}

static bool intel_uncore_has_discovery_tables_msr(int *ignore)
{
	unsigned long *die_mask;
	bool parsed = false;
	int cpu, die;
	u64 base;

	die_mask = kcalloc(BITS_TO_LONGS(uncore_max_dies()),
			   sizeof(unsigned long), GFP_KERNEL);
	if (!die_mask)
		return false;

	cpus_read_lock();
	for_each_online_cpu(cpu) {
		die = topology_logical_die_id(cpu);
		if (__test_and_set_bit(die, die_mask))
			continue;

		if (rdmsrq_safe_on_cpu(cpu, UNCORE_DISCOVERY_MSR, &base))
			continue;

		if (!base)
			continue;

		__parse_discovery_table(base, die, &parsed, ignore);
	}

	cpus_read_unlock();

	kfree(die_mask);
	return parsed;
}

bool intel_uncore_has_discovery_tables(int *ignore)
{
	return intel_uncore_has_discovery_tables_msr(ignore) ||
	       intel_uncore_has_discovery_tables_pci(ignore);
}

void intel_uncore_clear_discovery_tables(void)
{
	struct intel_uncore_discovery_type *type, *next;
@@ -604,7 +651,7 @@ void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box)
	}

	addr = unit->addr;
	box->io_addr = ioremap(addr, UNCORE_GENERIC_MMIO_SIZE);
	box->io_addr = ioremap(addr, type->mmio_map_size);
	if (!box->io_addr) {
		pr_warn("Uncore type %d box %d: ioremap error for 0x%llx.\n",
			type->type_id, unit->id, (unsigned long long)addr);
+7 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */

/* Store the full address of the global discovery table */
#define UNCORE_DISCOVERY_MSR			0x201e

/* Generic device ID of a discovery table device */
#define UNCORE_DISCOVERY_TABLE_DEVICE		0x09a7
/* Capability ID for a discovery table device */
@@ -168,3 +171,7 @@ bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
					  struct intel_uncore_box *box);
void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
			  struct rb_root *root, u16 *num_units);
struct intel_uncore_type **
uncore_get_uncores(enum uncore_access_type type_id, int num_extra,
		   struct intel_uncore_type **extra, int max_num_types,
		   struct intel_uncore_type **uncores);
+79 −0
Original line number Diff line number Diff line
@@ -1855,3 +1855,82 @@ void lnl_uncore_mmio_init(void)
}

/* end of Lunar Lake MMIO uncore support */

/* Panther Lake uncore support */

#define UNCORE_PTL_MAX_NUM_UNCORE_TYPES		42
#define UNCORE_PTL_TYPE_IMC			6
#define UNCORE_PTL_TYPE_SNCU			34
#define UNCORE_PTL_TYPE_HBO			41

#define PTL_UNCORE_GLOBAL_CTL_OFFSET		0x380

static struct intel_uncore_type ptl_uncore_imc = {
	.name			= "imc",
	.mmio_map_size		= 0xf00,
};

static void ptl_uncore_sncu_init_box(struct intel_uncore_box *box)
{
	intel_generic_uncore_mmio_init_box(box);

	/* Clear the global freeze bit */
	if (box->io_addr)
		writel(0, box->io_addr + PTL_UNCORE_GLOBAL_CTL_OFFSET);
}

static struct intel_uncore_ops ptl_uncore_sncu_ops = {
	.init_box		= ptl_uncore_sncu_init_box,
	.exit_box		= uncore_mmio_exit_box,
	.disable_box		= intel_generic_uncore_mmio_disable_box,
	.enable_box		= intel_generic_uncore_mmio_enable_box,
	.disable_event		= intel_generic_uncore_mmio_disable_event,
	.enable_event		= intel_generic_uncore_mmio_enable_event,
	.read_counter		= uncore_mmio_read_counter,
};

static struct intel_uncore_type ptl_uncore_sncu = {
	.name			= "sncu",
	.ops			= &ptl_uncore_sncu_ops,
	.mmio_map_size		= 0xf00,
};

static struct intel_uncore_type ptl_uncore_hbo = {
	.name			= "hbo",
	.mmio_map_size		= 0xf00,
};

static struct intel_uncore_type *ptl_uncores[UNCORE_PTL_MAX_NUM_UNCORE_TYPES] = {
	[UNCORE_PTL_TYPE_IMC] = &ptl_uncore_imc,
	[UNCORE_PTL_TYPE_SNCU] = &ptl_uncore_sncu,
	[UNCORE_PTL_TYPE_HBO] = &ptl_uncore_hbo,
};

#define UNCORE_PTL_MMIO_EXTRA_UNCORES		1

static struct intel_uncore_type *ptl_mmio_extra_uncores[UNCORE_PTL_MMIO_EXTRA_UNCORES] = {
	&adl_uncore_imc_free_running,
};

void ptl_uncore_mmio_init(void)
{
	uncore_mmio_uncores = uncore_get_uncores(UNCORE_ACCESS_MMIO,
						 UNCORE_PTL_MMIO_EXTRA_UNCORES,
						 ptl_mmio_extra_uncores,
						 UNCORE_PTL_MAX_NUM_UNCORE_TYPES,
						 ptl_uncores);
}

static struct intel_uncore_type *ptl_msr_uncores[] = {
	&mtl_uncore_cbox,
	NULL
};

void ptl_uncore_cpu_init(void)
{
	mtl_uncore_cbox.num_boxes = 6;
	mtl_uncore_cbox.ops = &lnl_uncore_msr_ops;
	uncore_msr_uncores = ptl_msr_uncores;
}

/* end of Panther Lake uncore support */
Loading