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

Merge tag 'perf-urgent-2024-05-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf event updates from Ingo Molnar:

 - Extend the x86 instruction decoder with APX and
   other new instructions

 - Misc cleanups

* tag 'perf-urgent-2024-05-18' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/cstate: Remove unused 'struct perf_cstate_msr'
  perf/x86/rapl: Rename 'maxdie' to nr_rapl_pmu and 'dieid' to rapl_pmu_idx
  x86/insn: Add support for APX EVEX instructions to the opcode map
  x86/insn: Add support for APX EVEX to the instruction decoder logic
  x86/insn: x86/insn: Add support for REX2 prefix to the instruction decoder opcode map
  x86/insn: Add support for REX2 prefix to the instruction decoder logic
  x86/insn: Add misc new Intel instructions
  x86/insn: Add VEX versions of VPDPBUSD, VPDPBUSDS, VPDPWSSD and VPDPWSSDS
  x86/insn: Fix PUSH instruction in x86 instruction decoder opcode map
  x86/insn: Add Key Locker instructions to the opcode map
parents 61307b7b 9d351132
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -143,12 +143,6 @@ struct cstate_model {
#define SLM_PKG_C6_USE_C7_MSR	(1UL << 0)
#define KNL_CORE_C6_MSR		(1UL << 1)

struct perf_cstate_msr {
	u64	msr;
	struct	perf_pmu_events_attr *attr;
};


/* cstate_core PMU */
static struct pmu cstate_core_pmu;
static bool has_cstate_core;
+8 −8
Original line number Diff line number Diff line
@@ -114,8 +114,8 @@ struct rapl_pmu {

struct rapl_pmus {
	struct pmu		pmu;
	unsigned int		maxdie;
	struct rapl_pmu		*pmus[] __counted_by(maxdie);
	unsigned int		nr_rapl_pmu;
	struct rapl_pmu		*pmus[] __counted_by(nr_rapl_pmu);
};

enum rapl_unit_quirk {
@@ -141,13 +141,13 @@ static struct perf_msr *rapl_msrs;

static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
{
	unsigned int dieid = topology_logical_die_id(cpu);
	unsigned int rapl_pmu_idx = topology_logical_die_id(cpu);

	/*
	 * The unsigned check also catches the '-1' return value for non
	 * existent mappings in the topology map.
	 */
	return dieid < rapl_pmus->maxdie ? rapl_pmus->pmus[dieid] : NULL;
	return rapl_pmu_idx < rapl_pmus->nr_rapl_pmu ? rapl_pmus->pmus[rapl_pmu_idx] : NULL;
}

static inline u64 rapl_read_counter(struct perf_event *event)
@@ -658,7 +658,7 @@ static void cleanup_rapl_pmus(void)
{
	int i;

	for (i = 0; i < rapl_pmus->maxdie; i++)
	for (i = 0; i < rapl_pmus->nr_rapl_pmu; i++)
		kfree(rapl_pmus->pmus[i]);
	kfree(rapl_pmus);
}
@@ -674,13 +674,13 @@ static const struct attribute_group *rapl_attr_update[] = {

static int __init init_rapl_pmus(void)
{
	int maxdie = topology_max_packages() * topology_max_dies_per_package();
	int nr_rapl_pmu = topology_max_packages() * topology_max_dies_per_package();

	rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, maxdie), GFP_KERNEL);
	rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, nr_rapl_pmu), GFP_KERNEL);
	if (!rapl_pmus)
		return -ENOMEM;

	rapl_pmus->maxdie		= maxdie;
	rapl_pmus->nr_rapl_pmu		= nr_rapl_pmu;
	rapl_pmus->pmu.attr_groups	= rapl_attr_groups;
	rapl_pmus->pmu.attr_update	= rapl_attr_update;
	rapl_pmus->pmu.task_ctx_nr	= perf_invalid_context;
+16 −1
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@
#define INAT_PFX_VEX2	13	/* 2-bytes VEX prefix */
#define INAT_PFX_VEX3	14	/* 3-bytes VEX prefix */
#define INAT_PFX_EVEX	15	/* EVEX prefix */
/* x86-64 REX2 prefix */
#define INAT_PFX_REX2	16	/* 0xD5 */

#define INAT_LSTPFX_MAX	3
#define INAT_LGCPFX_MAX	11
@@ -50,7 +52,7 @@

/* Legacy prefix */
#define INAT_PFX_OFFS	0
#define INAT_PFX_BITS	4
#define INAT_PFX_BITS	5
#define INAT_PFX_MAX    ((1 << INAT_PFX_BITS) - 1)
#define INAT_PFX_MASK	(INAT_PFX_MAX << INAT_PFX_OFFS)
/* Escape opcodes */
@@ -77,6 +79,9 @@
#define INAT_VEXOK	(1 << (INAT_FLAG_OFFS + 5))
#define INAT_VEXONLY	(1 << (INAT_FLAG_OFFS + 6))
#define INAT_EVEXONLY	(1 << (INAT_FLAG_OFFS + 7))
#define INAT_NO_REX2	(1 << (INAT_FLAG_OFFS + 8))
#define INAT_REX2_VARIANT	(1 << (INAT_FLAG_OFFS + 9))
#define INAT_EVEX_SCALABLE	(1 << (INAT_FLAG_OFFS + 10))
/* Attribute making macros for attribute tables */
#define INAT_MAKE_PREFIX(pfx)	(pfx << INAT_PFX_OFFS)
#define INAT_MAKE_ESCAPE(esc)	(esc << INAT_ESC_OFFS)
@@ -128,6 +133,11 @@ static inline int inat_is_rex_prefix(insn_attr_t attr)
	return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
}

static inline int inat_is_rex2_prefix(insn_attr_t attr)
{
	return (attr & INAT_PFX_MASK) == INAT_PFX_REX2;
}

static inline int inat_last_prefix_id(insn_attr_t attr)
{
	if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
@@ -227,4 +237,9 @@ static inline int inat_must_evex(insn_attr_t attr)
{
	return attr & INAT_EVEXONLY;
}

static inline int inat_evex_scalable(insn_attr_t attr)
{
	return attr & INAT_EVEX_SCALABLE;
}
#endif
+28 −4
Original line number Diff line number Diff line
@@ -112,10 +112,15 @@ struct insn {
#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
#define X86_SIB_BASE(sib) ((sib) & 0x07)

#define X86_REX_W(rex) ((rex) & 8)
#define X86_REX_R(rex) ((rex) & 4)
#define X86_REX_X(rex) ((rex) & 2)
#define X86_REX_B(rex) ((rex) & 1)
#define X86_REX2_M(rex) ((rex) & 0x80)	/* REX2 M0 */
#define X86_REX2_R(rex) ((rex) & 0x40)	/* REX2 R4 */
#define X86_REX2_X(rex) ((rex) & 0x20)	/* REX2 X4 */
#define X86_REX2_B(rex) ((rex) & 0x10)	/* REX2 B4 */

#define X86_REX_W(rex) ((rex) & 8)	/* REX or REX2 W */
#define X86_REX_R(rex) ((rex) & 4)	/* REX or REX2 R3 */
#define X86_REX_X(rex) ((rex) & 2)	/* REX or REX2 X3 */
#define X86_REX_B(rex) ((rex) & 1)	/* REX or REX2 B3 */

/* VEX bit flags  */
#define X86_VEX_W(vex)	((vex) & 0x80)	/* VEX3 Byte2 */
@@ -161,6 +166,18 @@ static inline void insn_get_attribute(struct insn *insn)
/* Instruction uses RIP-relative addressing */
extern int insn_rip_relative(struct insn *insn);

static inline int insn_is_rex2(struct insn *insn)
{
	if (!insn->prefixes.got)
		insn_get_prefixes(insn);
	return insn->rex_prefix.nbytes == 2;
}

static inline insn_byte_t insn_rex2_m_bit(struct insn *insn)
{
	return X86_REX2_M(insn->rex_prefix.bytes[1]);
}

static inline int insn_is_avx(struct insn *insn)
{
	if (!insn->prefixes.got)
@@ -198,6 +215,13 @@ static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
		return X86_VEX_P(insn->vex_prefix.bytes[2]);
}

static inline insn_byte_t insn_vex_w_bit(struct insn *insn)
{
	if (insn->vex_prefix.nbytes < 3)
		return 0;
	return X86_VEX_W(insn->vex_prefix.bytes[2]);
}

/* Get the last prefix id from last prefix or VEX prefix */
static inline int insn_last_prefix_id(struct insn *insn)
{
+29 −0
Original line number Diff line number Diff line
@@ -185,6 +185,17 @@ int insn_get_prefixes(struct insn *insn)
			if (X86_REX_W(b))
				/* REX.W overrides opnd_size */
				insn->opnd_bytes = 8;
		} else if (inat_is_rex2_prefix(attr)) {
			insn_set_byte(&insn->rex_prefix, 0, b);
			b = peek_nbyte_next(insn_byte_t, insn, 1);
			insn_set_byte(&insn->rex_prefix, 1, b);
			insn->rex_prefix.nbytes = 2;
			insn->next_byte += 2;
			if (X86_REX_W(b))
				/* REX.W overrides opnd_size */
				insn->opnd_bytes = 8;
			insn->rex_prefix.got = 1;
			goto vex_end;
		}
	}
	insn->rex_prefix.got = 1;
@@ -283,6 +294,10 @@ int insn_get_opcode(struct insn *insn)
		m = insn_vex_m_bits(insn);
		p = insn_vex_p_bits(insn);
		insn->attr = inat_get_avx_attribute(op, m, p);
		/* SCALABLE EVEX uses p bits to encode operand size */
		if (inat_evex_scalable(insn->attr) && !insn_vex_w_bit(insn) &&
		    p == INAT_PFX_OPNDSZ)
			insn->opnd_bytes = 2;
		if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
		    (!inat_accept_vex(insn->attr) &&
		     !inat_is_group(insn->attr))) {
@@ -294,6 +309,20 @@ int insn_get_opcode(struct insn *insn)
		goto end;
	}

	/* Check if there is REX2 prefix or not */
	if (insn_is_rex2(insn)) {
		if (insn_rex2_m_bit(insn)) {
			/* map 1 is escape 0x0f */
			insn_attr_t esc_attr = inat_get_opcode_attribute(0x0f);

			pfx_id = insn_last_prefix_id(insn);
			insn->attr = inat_get_escape_attribute(op, pfx_id, esc_attr);
		} else {
			insn->attr = inat_get_opcode_attribute(op);
		}
		goto end;
	}

	insn->attr = inat_get_opcode_attribute(op);
	while (inat_is_escape(insn->attr)) {
		/* Get escaped opcode */
Loading