Skip to main content

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}