Skip to content

Commit eec2113

Browse files
ChangSeokBaesuryasaimadhu
authored andcommitted
x86/fpu/amx: Define AMX state components and have it used for boot-time checks
The XSTATE initialization uses check_xstate_against_struct() to sanity check the size of XSTATE-enabled features. AMX is a XSAVE-enabled feature, and its size is not hard-coded but discoverable at run-time via CPUID. The AMX state is composed of state components 17 and 18, which are all user state components. The first component is the XTILECFG state of a 64-byte tile-related control register. The state component 18, called XTILEDATA, contains the actual tile data, and the state size varies on implementations. The architectural maximum, as defined in the CPUID(0x1d, 1): EAX[15:0], is a byte less than 64KB. The first implementation supports 8KB. Check the XTILEDATA state size dynamically. The feature introduces the new tile register, TMM. Define one register struct only and read the number of registers from CPUID. Cross-check the overall size with CPUID again. Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 70c3f16 commit eec2113

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@
299299
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
300300
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
301301
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
302+
#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
302303

303304
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
304305
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */

arch/x86/include/asm/fpu/types.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ enum xfeature {
120120
XFEATURE_RSRVD_COMP_13,
121121
XFEATURE_RSRVD_COMP_14,
122122
XFEATURE_LBR,
123+
XFEATURE_RSRVD_COMP_16,
124+
XFEATURE_XTILE_CFG,
125+
XFEATURE_XTILE_DATA,
123126

124127
XFEATURE_MAX,
125128
};
@@ -136,12 +139,21 @@ enum xfeature {
136139
#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)
137140
#define XFEATURE_MASK_PASID (1 << XFEATURE_PASID)
138141
#define XFEATURE_MASK_LBR (1 << XFEATURE_LBR)
142+
#define XFEATURE_MASK_XTILE_CFG (1 << XFEATURE_XTILE_CFG)
143+
#define XFEATURE_MASK_XTILE_DATA (1 << XFEATURE_XTILE_DATA)
139144

140145
#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
141146
#define XFEATURE_MASK_AVX512 (XFEATURE_MASK_OPMASK \
142147
| XFEATURE_MASK_ZMM_Hi256 \
143148
| XFEATURE_MASK_Hi16_ZMM)
144149

150+
#ifdef CONFIG_X86_64
151+
# define XFEATURE_MASK_XTILE (XFEATURE_MASK_XTILE_DATA \
152+
| XFEATURE_MASK_XTILE_CFG)
153+
#else
154+
# define XFEATURE_MASK_XTILE (0)
155+
#endif
156+
145157
#define FIRST_EXTENDED_XFEATURE XFEATURE_YMM
146158

147159
struct reg_128_bit {
@@ -153,6 +165,9 @@ struct reg_256_bit {
153165
struct reg_512_bit {
154166
u8 regbytes[512/8];
155167
};
168+
struct reg_1024_byte {
169+
u8 regbytes[1024];
170+
};
156171

157172
/*
158173
* State component 2:
@@ -255,6 +270,23 @@ struct arch_lbr_state {
255270
u64 ler_to;
256271
u64 ler_info;
257272
struct lbr_entry entries[];
273+
};
274+
275+
/*
276+
* State component 17: 64-byte tile configuration register.
277+
*/
278+
struct xtile_cfg {
279+
u64 tcfg[8];
280+
} __packed;
281+
282+
/*
283+
* State component 18: 1KB tile data register.
284+
* Each register represents 16 64-byte rows of the matrix
285+
* data. But the number of registers depends on the actual
286+
* implementation.
287+
*/
288+
struct xtile_data {
289+
struct reg_1024_byte tmm;
258290
} __packed;
259291

260292
/*

arch/x86/include/asm/fpu/xstate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#define XSTATE_CPUID 0x0000000d
1616

17+
#define TILE_CPUID 0x0000001d
18+
1719
#define FXSAVE_SIZE 512
1820

1921
#define XSAVE_HDR_SIZE 64

arch/x86/kernel/fpu/xstate.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ static const char *xfeature_names[] =
5151
"Protection Keys User registers",
5252
"PASID state",
5353
"unknown xstate feature" ,
54+
"unknown xstate feature" ,
55+
"unknown xstate feature" ,
56+
"unknown xstate feature" ,
57+
"unknown xstate feature" ,
58+
"unknown xstate feature" ,
59+
"AMX Tile config" ,
60+
"AMX Tile data" ,
61+
"unknown xstate feature" ,
5462
};
5563

5664
static unsigned short xsave_cpuid_features[] __initdata = {
@@ -65,6 +73,8 @@ static unsigned short xsave_cpuid_features[] __initdata = {
6573
[XFEATURE_PT_UNIMPLEMENTED_SO_FAR] = X86_FEATURE_INTEL_PT,
6674
[XFEATURE_PKRU] = X86_FEATURE_PKU,
6775
[XFEATURE_PASID] = X86_FEATURE_ENQCMD,
76+
[XFEATURE_XTILE_CFG] = X86_FEATURE_AMX_TILE,
77+
[XFEATURE_XTILE_DATA] = X86_FEATURE_AMX_TILE,
6878
};
6979

7080
static unsigned int xstate_offsets[XFEATURE_MAX] __ro_after_init =
@@ -240,6 +250,8 @@ static void __init print_xstate_features(void)
240250
print_xstate_feature(XFEATURE_MASK_Hi16_ZMM);
241251
print_xstate_feature(XFEATURE_MASK_PKRU);
242252
print_xstate_feature(XFEATURE_MASK_PASID);
253+
print_xstate_feature(XFEATURE_MASK_XTILE_CFG);
254+
print_xstate_feature(XFEATURE_MASK_XTILE_DATA);
243255
}
244256

245257
/*
@@ -523,6 +535,67 @@ static void __init __xstate_dump_leaves(void)
523535
} \
524536
} while (0)
525537

538+
/**
539+
* check_xtile_data_against_struct - Check tile data state size.
540+
*
541+
* Calculate the state size by multiplying the single tile size which is
542+
* recorded in a C struct, and the number of tiles that the CPU informs.
543+
* Compare the provided size with the calculation.
544+
*
545+
* @size: The tile data state size
546+
*
547+
* Returns: 0 on success, -EINVAL on mismatch.
548+
*/
549+
static int __init check_xtile_data_against_struct(int size)
550+
{
551+
u32 max_palid, palid, state_size;
552+
u32 eax, ebx, ecx, edx;
553+
u16 max_tile;
554+
555+
/*
556+
* Check the maximum palette id:
557+
* eax: the highest numbered palette subleaf.
558+
*/
559+
cpuid_count(TILE_CPUID, 0, &max_palid, &ebx, &ecx, &edx);
560+
561+
/*
562+
* Cross-check each tile size and find the maximum number of
563+
* supported tiles.
564+
*/
565+
for (palid = 1, max_tile = 0; palid <= max_palid; palid++) {
566+
u16 tile_size, max;
567+
568+
/*
569+
* Check the tile size info:
570+
* eax[31:16]: bytes per title
571+
* ebx[31:16]: the max names (or max number of tiles)
572+
*/
573+
cpuid_count(TILE_CPUID, palid, &eax, &ebx, &edx, &edx);
574+
tile_size = eax >> 16;
575+
max = ebx >> 16;
576+
577+
if (tile_size != sizeof(struct xtile_data)) {
578+
pr_err("%s: struct is %zu bytes, cpu xtile %d bytes\n",
579+
__stringify(XFEATURE_XTILE_DATA),
580+
sizeof(struct xtile_data), tile_size);
581+
__xstate_dump_leaves();
582+
return -EINVAL;
583+
}
584+
585+
if (max > max_tile)
586+
max_tile = max;
587+
}
588+
589+
state_size = sizeof(struct xtile_data) * max_tile;
590+
if (size != state_size) {
591+
pr_err("%s: calculated size is %u bytes, cpu state %d bytes\n",
592+
__stringify(XFEATURE_XTILE_DATA), state_size, size);
593+
__xstate_dump_leaves();
594+
return -EINVAL;
595+
}
596+
return 0;
597+
}
598+
526599
/*
527600
* We have a C struct for each 'xstate'. We need to ensure
528601
* that our software representation matches what the CPU
@@ -546,6 +619,11 @@ static bool __init check_xstate_against_struct(int nr)
546619
XCHECK_SZ(sz, nr, XFEATURE_Hi16_ZMM, struct avx_512_hi16_state);
547620
XCHECK_SZ(sz, nr, XFEATURE_PKRU, struct pkru_state);
548621
XCHECK_SZ(sz, nr, XFEATURE_PASID, struct ia32_pasid_state);
622+
XCHECK_SZ(sz, nr, XFEATURE_XTILE_CFG, struct xtile_cfg);
623+
624+
/* The tile data size varies between implementations. */
625+
if (nr == XFEATURE_XTILE_DATA)
626+
check_xtile_data_against_struct(sz);
549627

550628
/*
551629
* Make *SURE* to add any feature numbers in below if
@@ -555,7 +633,7 @@ static bool __init check_xstate_against_struct(int nr)
555633
if ((nr < XFEATURE_YMM) ||
556634
(nr >= XFEATURE_MAX) ||
557635
(nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR) ||
558-
((nr >= XFEATURE_RSRVD_COMP_11) && (nr <= XFEATURE_LBR))) {
636+
((nr >= XFEATURE_RSRVD_COMP_11) && (nr <= XFEATURE_RSRVD_COMP_16))) {
559637
WARN_ONCE(1, "no structure for xstate: %d\n", nr);
560638
XSTATE_WARN_ON(1);
561639
return false;

0 commit comments

Comments
 (0)