Skip to content

Commit 87a55a0

Browse files
[cpuid] properly mask out all AVX-512 features
Before we were only masking AVX-512 features found on a Broadwell. We should disable all know AVX-512 features to make sure that when moving to a newer x86_64 platform the c3 & t2 templates are still showing the same features. Also set the xsave area size to 0 for AVX-512 instructions. Signed-off-by: Andreea Florescu <[email protected]>
1 parent b5751f5 commit 87a55a0

File tree

4 files changed

+122
-8
lines changed

4 files changed

+122
-8
lines changed

cpuid/src/cpu_leaf.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,37 +129,59 @@ pub mod leaf_0x7 {
129129
pub const RDT_A_SHIFT: u32 = 15;
130130
// AVX-512 Foundation instructions
131131
pub const AVX512F_SHIFT: u32 = 16;
132+
// AVX-512 Doubleword and Quadword Instructions
133+
pub const AVX512DQ_SHIFT: u32 = 17;
132134
pub const RDSEED_SHIFT: u32 = 18;
133135
pub const ADX_SHIFT: u32 = 19;
134136
// 20 = SMAP (Supervisor-Mode Access Prevention)
135-
// 21 & 22 reserved
137+
// AVX512IFMA = AVX-512 Integer Fused Multiply-Add Instructions
138+
pub const AVX512IFMA_SHIFT: u32 = 21;
139+
// 21 = PCOMMIT intruction
136140
// 23 = CLFLUSH_OPT (flushing multiple cache lines in parallel within a single logical processor)
137141
// 24 = CLWB (Cache Line Write Back)
138142
// PT = Intel Processor Trace
139143
pub const PT_SHIFT: u32 = 25;
140-
// AVX512CD = AVX512 Conflict Detection
144+
// AVX512PF = AVX512 Prefetch Instructions
145+
pub const AVX512PF_SHIFT: u32 = 26;
146+
// AVX512ER = AVX-512 Exponential and Reciprocal Instructions
147+
pub const AVX512ER_SHIFT: u32 = 27;
148+
// AVX512CD = AVX-512 Conflict Detection Instructions
141149
pub const AVX512CD_SHIFT: u32 = 28;
142150
// Intel Secure Hash Algorithm Extensions
143151
pub const SHA_SHIFT: u32 = 29;
144-
// 30 - 32 reserved
152+
// AVX-512 Byte and Word Instructions
153+
pub const AVX512BW_SHIFT: u32 = 30;
154+
// AVX-512 Vector Length Extensions
155+
pub const AVX512VL_SHIFT: u32 = 31;
145156
}
146157

147158
pub mod ecx {
148159
// 0 = PREFETCHWT1 (move data closer to the processor in anticipation of future use)
149-
// 1 = reserved
160+
// AVX512_VBMI = AVX-512 Vector Byte Manipulation Instructions
161+
pub const AVX512_VBMI_SHIFT: u32 = 1;
150162
// 2 = UMIP (User Mode Instruction Prevention)
151163
// 3 = PKU (Protection Keys for user-mode pages)
152164
// 4 = OSPKE (If 1, OS has set CR4.PKE to enable protection keys)
153-
// 5- 16 reserved
165+
// 5 = WAITPKG
166+
// 7-6 reserved
167+
// 8 = GFNI
168+
// 13-09 reserved
169+
// AVX512_VPOPCNTDQ = Vector population count instruction (Intel® Xeon Phi™ only.)
170+
pub const AVX512_VPOPCNTDQ_SHIFT: u32 = 14;
154171
// 21 - 17 = The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode.
155-
pub const RDPID_SHIFT: u32 = 22; // Read Processor ID
156-
// 23 - 29 reserved
157-
// SGX_LC = SGX Launch Configuration
172+
// Read Processor ID
173+
pub const RDPID_SHIFT: u32 = 22;
174+
// 23 - 29 reserved
175+
// SGX_LC = SGX Launch Configuration
158176
pub const SGX_LC_SHIFT: u32 = 30;
159177
// 31 reserved
160178
}
161179

162180
pub mod edx {
181+
// AVX-512 4-register Neural Network Instructions
182+
pub const AVX512_4VNNIW_SHIFT: u32 = 2;
183+
// AVX-512 4-register Multiply Accumulation Single precision
184+
pub const AVX512_4FMAPS_SHIFT: u32 = 3;
163185
pub const ARCH_CAPABILITIES_BITINDEX: u32 = 29;
164186
}
165187
}
@@ -201,6 +223,17 @@ pub mod leaf_0xb {
201223
}
202224
}
203225

226+
// Processor Extended State Enumeration Sub-leaves
227+
pub mod leaf_0xd {
228+
pub const LEAF_NUM: u32 = 0xd;
229+
230+
pub mod eax {
231+
use bit_helper::BitRange;
232+
233+
pub const AVX512_STATE_BITRANGE: BitRange = bit_range!(7, 5);
234+
}
235+
}
236+
204237
pub mod leaf_0x80000000 {
205238
pub const LEAF_NUM: u32 = 0x8000_0000;
206239

cpuid/src/template/c3.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use bit_helper::BitHelper;
45
use cpu_leaf::*;
56
use kvm_bindings::kvm_cpuid_entry2;
67

@@ -66,16 +67,34 @@ pub fn set_cpuid_entries(entries: &mut [kvm_cpuid_entry2]) {
6667
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDT_M_SHIFT);
6768
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDT_A_SHIFT);
6869
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512F_SHIFT);
70+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512DQ_SHIFT);
6971
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDSEED_SHIFT);
7072
entry.ebx &= !(1 << leaf_0x7::index0::ebx::ADX_SHIFT);
73+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512IFMA_SHIFT);
7174
entry.ebx &= !(1 << leaf_0x7::index0::ebx::PT_SHIFT);
75+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512PF_SHIFT);
76+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512ER_SHIFT);
7277
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512CD_SHIFT);
7378
entry.ebx &= !(1 << leaf_0x7::index0::ebx::SHA_SHIFT);
79+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512BW_SHIFT);
80+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512VL_SHIFT);
7481

82+
entry.ecx &= !(1 << leaf_0x7::index0::ecx::AVX512_VBMI_SHIFT);
83+
entry.ecx &= !(1 << leaf_0x7::index0::ecx::AVX512_VPOPCNTDQ_SHIFT);
7584
entry.ecx &= !(1 << leaf_0x7::index0::ecx::RDPID_SHIFT);
7685
entry.ecx &= !(1 << leaf_0x7::index0::ecx::SGX_LC_SHIFT);
86+
87+
entry.edx &= !(1 << leaf_0x7::index0::edx::AVX512_4VNNIW_SHIFT);
88+
entry.edx &= !(1 << leaf_0x7::index0::edx::AVX512_4FMAPS_SHIFT);
7789
}
7890
}
91+
leaf_0xd::LEAF_NUM => {
92+
// AVX-512 instructions are masked out with the C3 template so the size in bytes
93+
// of the save area should be 0 (or invalid).
94+
entry
95+
.eax
96+
.write_bits_in_range(&leaf_0xd::eax::AVX512_STATE_BITRANGE, 0);
97+
}
7998
leaf_0x80000001::LEAF_NUM => {
8099
entry.ecx &= !(1 << leaf_0x80000001::ecx::PREFETCH_SHIFT);
81100
entry.ecx &= !(1 << leaf_0x80000001::ecx::LZCNT_SHIFT);

cpuid/src/template/t2.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use bit_helper::BitHelper;
45
use cpu_leaf::*;
56
use kvm_bindings::kvm_cpuid_entry2;
67

@@ -59,16 +60,34 @@ pub fn set_cpuid_entries(entries: &mut [kvm_cpuid_entry2]) {
5960
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDT_M_SHIFT);
6061
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDT_A_SHIFT);
6162
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512F_SHIFT);
63+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512DQ_SHIFT);
6264
entry.ebx &= !(1 << leaf_0x7::index0::ebx::RDSEED_SHIFT);
6365
entry.ebx &= !(1 << leaf_0x7::index0::ebx::ADX_SHIFT);
66+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512IFMA_SHIFT);
6467
entry.ebx &= !(1 << leaf_0x7::index0::ebx::PT_SHIFT);
68+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512PF_SHIFT);
69+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512ER_SHIFT);
6570
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512CD_SHIFT);
6671
entry.ebx &= !(1 << leaf_0x7::index0::ebx::SHA_SHIFT);
72+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512BW_SHIFT);
73+
entry.ebx &= !(1 << leaf_0x7::index0::ebx::AVX512VL_SHIFT);
6774

75+
entry.ecx &= !(1 << leaf_0x7::index0::ecx::AVX512_VBMI_SHIFT);
76+
entry.ecx &= !(1 << leaf_0x7::index0::ecx::AVX512_VPOPCNTDQ_SHIFT);
6877
entry.ecx &= !(1 << leaf_0x7::index0::ecx::RDPID_SHIFT);
6978
entry.ecx &= !(1 << leaf_0x7::index0::ecx::SGX_LC_SHIFT);
79+
80+
entry.edx &= !(1 << leaf_0x7::index0::edx::AVX512_4VNNIW_SHIFT);
81+
entry.edx &= !(1 << leaf_0x7::index0::edx::AVX512_4FMAPS_SHIFT);
7082
}
7183
}
84+
leaf_0xd::LEAF_NUM => {
85+
// AVX-512 instructions are masked out with the T2 template so the size in bytes
86+
// of the save area should be 0 (or invalid).
87+
entry
88+
.eax
89+
.write_bits_in_range(&leaf_0xd::eax::AVX512_STATE_BITRANGE, 0);
90+
}
7291
leaf_0x80000001::LEAF_NUM => {
7392
entry.ecx &= !(1 << leaf_0x80000001::ecx::PREFETCH_SHIFT);
7493
entry.edx &= !(1 << leaf_0x80000001::edx::PDPE1GB_SHIFT);

tests/integration_tests/functional/test_cpu_features.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,46 @@ def test_brand_string(test_microvm_with_ssh, network_config):
301301
expected_guest_brand_string += " @ " + mo.group(0)
302302

303303
assert guest_brand_string == expected_guest_brand_string
304+
305+
306+
@pytest.mark.skipif(
307+
platform.machine() != "x86_64",
308+
reason="AVX features are only available on x86_64"
309+
)
310+
@pytest.mark.parametrize("cpu_template", ["T2", "C3"])
311+
def test_avx_disabled(test_microvm_with_ssh, network_config, cpu_template):
312+
"""Check that AVX2 & AVX512 instructions are disabled.
313+
314+
This is a rather dummy test for checking that no AVX2 or AVX512
315+
instructions are exposed. It is a first step into checking the t2 & c3
316+
templates. In a next iteration we should check **all** cpuid entries, not
317+
just the AVX family instructions. We can achieve this with a template
318+
containing all features on a t2/c3 instance and check that the cpuid in
319+
the guest is an exact match of the template.
320+
"""
321+
test_microvm = test_microvm_with_ssh
322+
test_microvm.spawn()
323+
324+
test_microvm.basic_config(vcpu_count=1)
325+
# Set the template to T2.
326+
response = test_microvm.machine_cfg.put(
327+
vcpu_count=1,
328+
mem_size_mib=256,
329+
ht_enabled=False,
330+
cpu_template=cpu_template,
331+
)
332+
assert test_microvm.api_session.is_status_no_content(response.status_code)
333+
_tap, _, _ = test_microvm.ssh_network_config(network_config, '1')
334+
test_microvm.start()
335+
336+
ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)
337+
guest_cmd = "cat /proc/cpuinfo | grep 'flags' | head -1"
338+
_, stdout, stderr = ssh_connection.execute_command(guest_cmd)
339+
assert stderr.read().decode("utf-8") == ''
340+
341+
cpu_flags_output = stdout.readline().decode('utf-8').rstrip()
342+
# On C3 there's no AVX2. Check that it is masked out.
343+
if cpu_template == "C3":
344+
assert not "avx2" in cpu_flags_output
345+
# Check that AVX-512 is masked out with both C3 and T2 templates
346+
assert not "avx512" in cpu_flags_output

0 commit comments

Comments
 (0)