Skip to content

Commit

Permalink
mpk: reenable MPK support with vendor string check
Browse files Browse the repository at this point in the history
In bytecodealliance#7446 I disabled MPK support temporarily due to failures in CI runs.
Looking into this further in bytecodealliance#7445, I discovered that it is due to how
`has_cpuid_bit_set` works on different x86 machines: Intel's `CPUID`
instruction reports support for MPK in a certain leaf bit, AMD does it
some other (unknown?) way. The CI problem boiled down to occasional runs
on AMD machines that would fail with `SIGILL` because the AMD machine
reported that it had MPK support when it really did not. This change
fixes the issue by first checking if the CPU vendor string is
`GenuineIntel` before inspecting the MPK `CPUID` leaf bit.

Closes bytecodealliance#7445.
  • Loading branch information
abrown committed Nov 9, 2023
1 parent 12296fa commit 998c766
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions crates/runtime/src/mpk/pkru.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,24 @@ pub fn write(pkru: u32) {
}
}

/// Check the `ECX.PKU` flag (bit 3) of the `07h` `CPUID` leaf; see the
/// Intel Software Development Manual, vol 3a, section 2.7.
/// Check the `ECX.PKU` flag (bit 3) of the `07h` `CPUID` leaf; see the Intel
/// Software Development Manual, vol 3a, section 2.7. This flag is only set on
/// Intel CPUs, so this function also checks the `CPUID` vendor string.
pub fn has_cpuid_bit_set() -> bool {
// TODO: disable MPK support until the following issue is resolved:
// https://github.com/bytecodealliance/wasmtime/issues/7445
if true {
return false;
}
let result = unsafe { std::arch::x86_64::__cpuid(0x07) };
(result.ecx & 0b100) != 0
is_intel_cpu() && (result.ecx & 0b100) != 0
}

/// Check the `CPUID` vendor string for `GenuineIntel`; see the Intel Software
/// Development Manual, vol 2a, `CPUID` description.
pub fn is_intel_cpu() -> bool {
// To read the CPU vendor string, we pass 0 in EAX and read 12 ASCII bytes
// from EBX, EDX, and ECX (in that order).
let result = unsafe { std::arch::x86_64::__cpuid(0) };
// Then we check if the string matches "GenuineIntel".
result.ebx == 0x756e6547 /* "Genu" */
&& result.edx == 0x49656e69 /* "ineI" */
&& result.ecx == 0x6c65746e /* "ntel" */
}

#[cfg(test)]
Expand Down

0 comments on commit 998c766

Please sign in to comment.