Commit 5f67329c authored by Andrii Nakryiko's avatar Andrii Nakryiko
Browse files

Merge tag 'perf-core-for-bpf-next' from tip tree



Stable tag for bpf-next's uprobe work.

Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
parents 1850ce1b dd1a7567
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ config KPROBES_ON_FTRACE
config UPROBES
	def_bool n
	depends on ARCH_SUPPORTS_UPROBES
	select TASKS_TRACE_RCU
	help
	  Uprobes is the user-space counterpart to kprobes: they
	  enable instrumentation applications (such as 'perf probe')
+8 −2
Original line number Diff line number Diff line
@@ -943,11 +943,12 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u
static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
	static atomic64_t status_warned = ATOMIC64_INIT(0);
	u64 reserved, status, mask, new_bits, prev_bits;
	struct perf_sample_data data;
	struct hw_perf_event *hwc;
	struct perf_event *event;
	int handled = 0, idx;
	u64 reserved, status, mask;
	bool pmu_enabled;

	/*
@@ -1012,7 +1013,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
	 * the corresponding PMCs are expected to be inactive according to the
	 * active_mask
	 */
	WARN_ON(status > 0);
	if (status > 0) {
		prev_bits = atomic64_fetch_or(status, &status_warned);
		// A new bit was set for the very first time.
		new_bits = status & ~prev_bits;
		WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits);
	}

	/* Clear overflow and freeze bits */
	amd_pmu_ack_global_status(~status);
+121 −12
Original line number Diff line number Diff line
@@ -4599,6 +4599,28 @@ static inline bool erratum_hsw11(struct perf_event *event)
		X86_CONFIG(.event=0xc0, .umask=0x01);
}

static struct event_constraint *
arl_h_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
			  struct perf_event *event)
{
	struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);

	if (pmu->pmu_type == hybrid_tiny)
		return cmt_get_event_constraints(cpuc, idx, event);

	return mtl_get_event_constraints(cpuc, idx, event);
}

static int arl_h_hw_config(struct perf_event *event)
{
	struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);

	if (pmu->pmu_type == hybrid_tiny)
		return intel_pmu_hw_config(event);

	return adl_hw_config(event);
}

/*
 * The HSW11 requires a period larger than 100 which is the same as the BDM11.
 * A minimum period of 128 is enforced as well for the INST_RETIRED.ALL.
@@ -4924,18 +4946,27 @@ static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void)

	/*
	 * This essentially just maps between the 'hybrid_cpu_type'
	 * and 'hybrid_pmu_type' enums:
	 * and 'hybrid_pmu_type' enums except for ARL-H processor
	 * which needs to compare atom uarch native id since ARL-H
	 * contains two different atom uarchs.
	 */
	for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
		enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type;
		u32 native_id;

		if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big)
			return &x86_pmu.hybrid_pmu[i];
		if (cpu_type == HYBRID_INTEL_ATOM) {
			if (x86_pmu.num_hybrid_pmus == 2 && pmu_type == hybrid_small)
				return &x86_pmu.hybrid_pmu[i];

		if (cpu_type == HYBRID_INTEL_CORE &&
		    pmu_type == hybrid_big)
			native_id = get_this_hybrid_cpu_native_id();
			if (native_id == skt_native_id && pmu_type == hybrid_small)
				return &x86_pmu.hybrid_pmu[i];
		if (cpu_type == HYBRID_INTEL_ATOM &&
		    pmu_type == hybrid_small)
			if (native_id == cmt_native_id && pmu_type == hybrid_tiny)
				return &x86_pmu.hybrid_pmu[i];
		}
	}

	return NULL;
}
@@ -5965,6 +5996,37 @@ static struct attribute *lnl_hybrid_events_attrs[] = {
	NULL
};

/* The event string must be in PMU IDX order. */
EVENT_ATTR_STR_HYBRID(topdown-retiring,
		      td_retiring_arl_h,
		      "event=0xc2,umask=0x02;event=0x00,umask=0x80;event=0xc2,umask=0x0",
		      hybrid_big_small_tiny);
EVENT_ATTR_STR_HYBRID(topdown-bad-spec,
		      td_bad_spec_arl_h,
		      "event=0x73,umask=0x0;event=0x00,umask=0x81;event=0x73,umask=0x0",
		      hybrid_big_small_tiny);
EVENT_ATTR_STR_HYBRID(topdown-fe-bound,
		      td_fe_bound_arl_h,
		      "event=0x9c,umask=0x01;event=0x00,umask=0x82;event=0x71,umask=0x0",
		      hybrid_big_small_tiny);
EVENT_ATTR_STR_HYBRID(topdown-be-bound,
		      td_be_bound_arl_h,
		      "event=0xa4,umask=0x02;event=0x00,umask=0x83;event=0x74,umask=0x0",
		      hybrid_big_small_tiny);

static struct attribute *arl_h_hybrid_events_attrs[] = {
	EVENT_PTR(slots_adl),
	EVENT_PTR(td_retiring_arl_h),
	EVENT_PTR(td_bad_spec_arl_h),
	EVENT_PTR(td_fe_bound_arl_h),
	EVENT_PTR(td_be_bound_arl_h),
	EVENT_PTR(td_heavy_ops_adl),
	EVENT_PTR(td_br_mis_adl),
	EVENT_PTR(td_fetch_lat_adl),
	EVENT_PTR(td_mem_bound_adl),
	NULL,
};

/* Must be in IDX order */
EVENT_ATTR_STR_HYBRID(mem-loads,     mem_ld_adl,     "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3", hybrid_big_small);
EVENT_ATTR_STR_HYBRID(mem-stores,    mem_st_adl,     "event=0xd0,umask=0x6;event=0xcd,umask=0x2",                 hybrid_big_small);
@@ -5983,6 +6045,21 @@ static struct attribute *mtl_hybrid_mem_attrs[] = {
	NULL
};

EVENT_ATTR_STR_HYBRID(mem-loads,
		      mem_ld_arl_h,
		      "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3;event=0xd0,umask=0x5,ldlat=3",
		      hybrid_big_small_tiny);
EVENT_ATTR_STR_HYBRID(mem-stores,
		      mem_st_arl_h,
		      "event=0xd0,umask=0x6;event=0xcd,umask=0x2;event=0xd0,umask=0x6",
		      hybrid_big_small_tiny);

static struct attribute *arl_h_hybrid_mem_attrs[] = {
	EVENT_PTR(mem_ld_arl_h),
	EVENT_PTR(mem_st_arl_h),
	NULL,
};

EVENT_ATTR_STR_HYBRID(tx-start,          tx_start_adl,          "event=0xc9,umask=0x1",          hybrid_big);
EVENT_ATTR_STR_HYBRID(tx-commit,         tx_commit_adl,         "event=0xc9,umask=0x2",          hybrid_big);
EVENT_ATTR_STR_HYBRID(tx-abort,          tx_abort_adl,          "event=0xc9,umask=0x4",          hybrid_big);
@@ -6006,8 +6083,8 @@ static struct attribute *adl_hybrid_tsx_attrs[] = {

FORMAT_ATTR_HYBRID(in_tx,       hybrid_big);
FORMAT_ATTR_HYBRID(in_tx_cp,    hybrid_big);
FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small);
FORMAT_ATTR_HYBRID(ldlat,       hybrid_big_small);
FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small_tiny);
FORMAT_ATTR_HYBRID(ldlat,       hybrid_big_small_tiny);
FORMAT_ATTR_HYBRID(frontend,    hybrid_big);

#define ADL_HYBRID_RTM_FORMAT_ATTR	\
@@ -6030,7 +6107,7 @@ static struct attribute *adl_hybrid_extra_attr[] = {
	NULL
};

FORMAT_ATTR_HYBRID(snoop_rsp,	hybrid_small);
FORMAT_ATTR_HYBRID(snoop_rsp,	hybrid_small_tiny);

static struct attribute *mtl_hybrid_extra_attr_rtm[] = {
	ADL_HYBRID_RTM_FORMAT_ATTR,
@@ -6240,6 +6317,7 @@ static inline int intel_pmu_v6_addr_offset(int index, bool eventsel)
static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = {
	{ hybrid_small,	"cpu_atom" },
	{ hybrid_big,	"cpu_core" },
	{ hybrid_tiny,	"cpu_lowpower" },
};

static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
@@ -6272,7 +6350,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
							0, x86_pmu_num_counters(&pmu->pmu), 0, 0);

		pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
		if (pmu->pmu_type & hybrid_small) {
		if (pmu->pmu_type & hybrid_small_tiny) {
			pmu->intel_cap.perf_metrics = 0;
			pmu->intel_cap.pebs_output_pt_available = 1;
			pmu->mid_ack = true;
@@ -7111,6 +7189,37 @@ __init int intel_pmu_init(void)
		name = "lunarlake_hybrid";
		break;

	case INTEL_ARROWLAKE_H:
		intel_pmu_init_hybrid(hybrid_big_small_tiny);

		x86_pmu.pebs_latency_data = arl_h_latency_data;
		x86_pmu.get_event_constraints = arl_h_get_event_constraints;
		x86_pmu.hw_config = arl_h_hw_config;

		td_attr = arl_h_hybrid_events_attrs;
		mem_attr = arl_h_hybrid_mem_attrs;
		tsx_attr = adl_hybrid_tsx_attrs;
		extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
			mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr;

		/* Initialize big core specific PerfMon capabilities. */
		pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
		intel_pmu_init_lnc(&pmu->pmu);

		/* Initialize Atom core specific PerfMon capabilities. */
		pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX];
		intel_pmu_init_skt(&pmu->pmu);

		/* Initialize Lower Power Atom specific PerfMon capabilities. */
		pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX];
		intel_pmu_init_grt(&pmu->pmu);
		pmu->extra_regs = intel_cmt_extra_regs;

		intel_pmu_pebs_data_source_arl_h();
		pr_cont("ArrowLake-H Hybrid events, ");
		name = "arrowlake_h_hybrid";
		break;

	default:
		switch (x86_pmu.version) {
		case 1:
+21 −0
Original line number Diff line number Diff line
@@ -177,6 +177,17 @@ void __init intel_pmu_pebs_data_source_mtl(void)
	__intel_pmu_pebs_data_source_cmt(data_source);
}

void __init intel_pmu_pebs_data_source_arl_h(void)
{
	u64 *data_source;

	intel_pmu_pebs_data_source_lnl();

	data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX].pebs_data_source;
	memcpy(data_source, pebs_data_source, sizeof(pebs_data_source));
	__intel_pmu_pebs_data_source_cmt(data_source);
}

void __init intel_pmu_pebs_data_source_cmt(void)
{
	__intel_pmu_pebs_data_source_cmt(pebs_data_source);
@@ -388,6 +399,16 @@ u64 lnl_latency_data(struct perf_event *event, u64 status)
	return lnc_latency_data(event, status);
}

u64 arl_h_latency_data(struct perf_event *event, u64 status)
{
	struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);

	if (pmu->pmu_type == hybrid_tiny)
		return cmt_latency_data(event, status);

	return lnl_latency_data(event, status);
}

static u64 load_latency_data(struct perf_event *event, u64 status)
{
	union intel_x86_pebs_dse dse;
+26 −8
Original line number Diff line number Diff line
@@ -668,24 +668,38 @@ enum {
#define PERF_PEBS_DATA_SOURCE_GRT_MAX	0x10
#define PERF_PEBS_DATA_SOURCE_GRT_MASK	(PERF_PEBS_DATA_SOURCE_GRT_MAX - 1)

/*
 * CPUID.1AH.EAX[31:0] uniquely identifies the microarchitecture
 * of the core. Bits 31-24 indicates its core type (Core or Atom)
 * and Bits [23:0] indicates the native model ID of the core.
 * Core type and native model ID are defined in below enumerations.
 */
enum hybrid_cpu_type {
	HYBRID_INTEL_NONE,
	HYBRID_INTEL_ATOM	= 0x20,
	HYBRID_INTEL_CORE	= 0x40,
};

#define X86_HYBRID_PMU_ATOM_IDX		0
#define X86_HYBRID_PMU_CORE_IDX		1
#define X86_HYBRID_PMU_TINY_IDX		2

enum hybrid_pmu_type {
	not_hybrid,
	hybrid_small		= BIT(0),
	hybrid_big		= BIT(1),

	hybrid_big_small	= hybrid_big | hybrid_small, /* only used for matching */
	hybrid_small		= BIT(X86_HYBRID_PMU_ATOM_IDX),
	hybrid_big		= BIT(X86_HYBRID_PMU_CORE_IDX),
	hybrid_tiny		= BIT(X86_HYBRID_PMU_TINY_IDX),

	/* The belows are only used for matching */
	hybrid_big_small	= hybrid_big   | hybrid_small,
	hybrid_small_tiny	= hybrid_small | hybrid_tiny,
	hybrid_big_small_tiny	= hybrid_big   | hybrid_small_tiny,
};

#define X86_HYBRID_PMU_ATOM_IDX		0
#define X86_HYBRID_PMU_CORE_IDX		1

#define X86_HYBRID_NUM_PMUS		2
enum atom_native_id {
	cmt_native_id           = 0x2,  /* Crestmont */
	skt_native_id           = 0x3,  /* Skymont */
};

struct x86_hybrid_pmu {
	struct pmu			pmu;
@@ -1578,6 +1592,8 @@ u64 cmt_latency_data(struct perf_event *event, u64 status);

u64 lnl_latency_data(struct perf_event *event, u64 status);

u64 arl_h_latency_data(struct perf_event *event, u64 status);

extern struct event_constraint intel_core2_pebs_event_constraints[];

extern struct event_constraint intel_atom_pebs_event_constraints[];
@@ -1697,6 +1713,8 @@ void intel_pmu_pebs_data_source_grt(void);

void intel_pmu_pebs_data_source_mtl(void);

void intel_pmu_pebs_data_source_arl_h(void);

void intel_pmu_pebs_data_source_cmt(void);

void intel_pmu_pebs_data_source_lnl(void);
Loading