wasmtime_internal_core/mpk.rs
1//! Detection of Memory Protection Keys (MPK) support on the host system.
2//!
3//! This is the single source of truth for whether Wasmtime's MPK
4//! implementation can be used on the current target. The runtime in the
5//! `wasmtime` crate consults [`is_supported`], and `examples/mpk-available.rs`
6//! exposes it as a CLI exit code so CI can decide whether to set
7//! `WASMTIME_TEST_FORCE_MPK=1`.
8
9/// Returns `true` if Wasmtime's MPK support can be used on this host.
10pub fn is_supported() -> bool {
11 cfg!(target_os = "linux") && cpuid_pku_bit_set()
12}
13
14/// Check the `ECX.PKU` flag (bit 3, zero-based) of the `07h` `CPUID` leaf; see
15/// the Intel Software Development Manual, vol 3a, section 2.7. This flag is
16/// only set on Intel CPUs, so this function also checks the `CPUID` vendor
17/// string.
18#[cfg(target_arch = "x86_64")]
19fn cpuid_pku_bit_set() -> bool {
20 is_intel_cpu() && {
21 #[allow(
22 unused_unsafe,
23 reason = "rust is transitioning to `__cpuid` being a safe function"
24 )]
25 let result = unsafe { core::arch::x86_64::__cpuid(0x07) };
26 (result.ecx & 0b1000) != 0
27 }
28}
29
30#[cfg(not(target_arch = "x86_64"))]
31fn cpuid_pku_bit_set() -> bool {
32 false
33}
34
35/// Check the `CPUID` vendor string for `GenuineIntel`; see the Intel Software
36/// Development Manual, vol 2a, `CPUID` description.
37#[cfg(target_arch = "x86_64")]
38fn is_intel_cpu() -> bool {
39 #[allow(unused_unsafe, reason = "see above about __cpuid")]
40 let result = unsafe { core::arch::x86_64::__cpuid(0) };
41 result.ebx == u32::from_le_bytes(*b"Genu")
42 && result.edx == u32::from_le_bytes(*b"ineI")
43 && result.ecx == u32::from_le_bytes(*b"ntel")
44}