Skip to content

Commit fe0d43f

Browse files
committed
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
2 parents 61307b7 + 9d35113 commit fe0d43f

File tree

12 files changed

+630
-208
lines changed

12 files changed

+630
-208
lines changed

arch/x86/events/intel/cstate.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,6 @@ struct cstate_model {
143143
#define SLM_PKG_C6_USE_C7_MSR (1UL << 0)
144144
#define KNL_CORE_C6_MSR (1UL << 1)
145145

146-
struct perf_cstate_msr {
147-
u64 msr;
148-
struct perf_pmu_events_attr *attr;
149-
};
150-
151-
152146
/* cstate_core PMU */
153147
static struct pmu cstate_core_pmu;
154148
static bool has_cstate_core;

arch/x86/events/rapl.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ struct rapl_pmu {
114114

115115
struct rapl_pmus {
116116
struct pmu pmu;
117-
unsigned int maxdie;
118-
struct rapl_pmu *pmus[] __counted_by(maxdie);
117+
unsigned int nr_rapl_pmu;
118+
struct rapl_pmu *pmus[] __counted_by(nr_rapl_pmu);
119119
};
120120

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

142142
static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
143143
{
144-
unsigned int dieid = topology_logical_die_id(cpu);
144+
unsigned int rapl_pmu_idx = topology_logical_die_id(cpu);
145145

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

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

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

675675
static int __init init_rapl_pmus(void)
676676
{
677-
int maxdie = topology_max_packages() * topology_max_dies_per_package();
677+
int nr_rapl_pmu = topology_max_packages() * topology_max_dies_per_package();
678678

679-
rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, maxdie), GFP_KERNEL);
679+
rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, nr_rapl_pmu), GFP_KERNEL);
680680
if (!rapl_pmus)
681681
return -ENOMEM;
682682

683-
rapl_pmus->maxdie = maxdie;
683+
rapl_pmus->nr_rapl_pmu = nr_rapl_pmu;
684684
rapl_pmus->pmu.attr_groups = rapl_attr_groups;
685685
rapl_pmus->pmu.attr_update = rapl_attr_update;
686686
rapl_pmus->pmu.task_ctx_nr = perf_invalid_context;

arch/x86/include/asm/inat.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
3636
#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
3737
#define INAT_PFX_EVEX 15 /* EVEX prefix */
38+
/* x86-64 REX2 prefix */
39+
#define INAT_PFX_REX2 16 /* 0xD5 */
3840

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

5153
/* Legacy prefix */
5254
#define INAT_PFX_OFFS 0
53-
#define INAT_PFX_BITS 4
55+
#define INAT_PFX_BITS 5
5456
#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
5557
#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
5658
/* Escape opcodes */
@@ -77,6 +79,9 @@
7779
#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
7880
#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
7981
#define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7))
82+
#define INAT_NO_REX2 (1 << (INAT_FLAG_OFFS + 8))
83+
#define INAT_REX2_VARIANT (1 << (INAT_FLAG_OFFS + 9))
84+
#define INAT_EVEX_SCALABLE (1 << (INAT_FLAG_OFFS + 10))
8085
/* Attribute making macros for attribute tables */
8186
#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
8287
#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
@@ -128,6 +133,11 @@ static inline int inat_is_rex_prefix(insn_attr_t attr)
128133
return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
129134
}
130135

136+
static inline int inat_is_rex2_prefix(insn_attr_t attr)
137+
{
138+
return (attr & INAT_PFX_MASK) == INAT_PFX_REX2;
139+
}
140+
131141
static inline int inat_last_prefix_id(insn_attr_t attr)
132142
{
133143
if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
@@ -227,4 +237,9 @@ static inline int inat_must_evex(insn_attr_t attr)
227237
{
228238
return attr & INAT_EVEXONLY;
229239
}
240+
241+
static inline int inat_evex_scalable(insn_attr_t attr)
242+
{
243+
return attr & INAT_EVEX_SCALABLE;
244+
}
230245
#endif

arch/x86/include/asm/insn.h

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,15 @@ struct insn {
112112
#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
113113
#define X86_SIB_BASE(sib) ((sib) & 0x07)
114114

115-
#define X86_REX_W(rex) ((rex) & 8)
116-
#define X86_REX_R(rex) ((rex) & 4)
117-
#define X86_REX_X(rex) ((rex) & 2)
118-
#define X86_REX_B(rex) ((rex) & 1)
115+
#define X86_REX2_M(rex) ((rex) & 0x80) /* REX2 M0 */
116+
#define X86_REX2_R(rex) ((rex) & 0x40) /* REX2 R4 */
117+
#define X86_REX2_X(rex) ((rex) & 0x20) /* REX2 X4 */
118+
#define X86_REX2_B(rex) ((rex) & 0x10) /* REX2 B4 */
119+
120+
#define X86_REX_W(rex) ((rex) & 8) /* REX or REX2 W */
121+
#define X86_REX_R(rex) ((rex) & 4) /* REX or REX2 R3 */
122+
#define X86_REX_X(rex) ((rex) & 2) /* REX or REX2 X3 */
123+
#define X86_REX_B(rex) ((rex) & 1) /* REX or REX2 B3 */
119124

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

169+
static inline int insn_is_rex2(struct insn *insn)
170+
{
171+
if (!insn->prefixes.got)
172+
insn_get_prefixes(insn);
173+
return insn->rex_prefix.nbytes == 2;
174+
}
175+
176+
static inline insn_byte_t insn_rex2_m_bit(struct insn *insn)
177+
{
178+
return X86_REX2_M(insn->rex_prefix.bytes[1]);
179+
}
180+
164181
static inline int insn_is_avx(struct insn *insn)
165182
{
166183
if (!insn->prefixes.got)
@@ -198,6 +215,13 @@ static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
198215
return X86_VEX_P(insn->vex_prefix.bytes[2]);
199216
}
200217

218+
static inline insn_byte_t insn_vex_w_bit(struct insn *insn)
219+
{
220+
if (insn->vex_prefix.nbytes < 3)
221+
return 0;
222+
return X86_VEX_W(insn->vex_prefix.bytes[2]);
223+
}
224+
201225
/* Get the last prefix id from last prefix or VEX prefix */
202226
static inline int insn_last_prefix_id(struct insn *insn)
203227
{

arch/x86/lib/insn.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,17 @@ int insn_get_prefixes(struct insn *insn)
185185
if (X86_REX_W(b))
186186
/* REX.W overrides opnd_size */
187187
insn->opnd_bytes = 8;
188+
} else if (inat_is_rex2_prefix(attr)) {
189+
insn_set_byte(&insn->rex_prefix, 0, b);
190+
b = peek_nbyte_next(insn_byte_t, insn, 1);
191+
insn_set_byte(&insn->rex_prefix, 1, b);
192+
insn->rex_prefix.nbytes = 2;
193+
insn->next_byte += 2;
194+
if (X86_REX_W(b))
195+
/* REX.W overrides opnd_size */
196+
insn->opnd_bytes = 8;
197+
insn->rex_prefix.got = 1;
198+
goto vex_end;
188199
}
189200
}
190201
insn->rex_prefix.got = 1;
@@ -283,6 +294,10 @@ int insn_get_opcode(struct insn *insn)
283294
m = insn_vex_m_bits(insn);
284295
p = insn_vex_p_bits(insn);
285296
insn->attr = inat_get_avx_attribute(op, m, p);
297+
/* SCALABLE EVEX uses p bits to encode operand size */
298+
if (inat_evex_scalable(insn->attr) && !insn_vex_w_bit(insn) &&
299+
p == INAT_PFX_OPNDSZ)
300+
insn->opnd_bytes = 2;
286301
if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
287302
(!inat_accept_vex(insn->attr) &&
288303
!inat_is_group(insn->attr))) {
@@ -294,6 +309,20 @@ int insn_get_opcode(struct insn *insn)
294309
goto end;
295310
}
296311

312+
/* Check if there is REX2 prefix or not */
313+
if (insn_is_rex2(insn)) {
314+
if (insn_rex2_m_bit(insn)) {
315+
/* map 1 is escape 0x0f */
316+
insn_attr_t esc_attr = inat_get_opcode_attribute(0x0f);
317+
318+
pfx_id = insn_last_prefix_id(insn);
319+
insn->attr = inat_get_escape_attribute(op, pfx_id, esc_attr);
320+
} else {
321+
insn->attr = inat_get_opcode_attribute(op);
322+
}
323+
goto end;
324+
}
325+
297326
insn->attr = inat_get_opcode_attribute(op);
298327
while (inat_is_escape(insn->attr)) {
299328
/* Get escaped opcode */

0 commit comments

Comments
 (0)