diff --git a/.travis.yml b/.travis.yml index 916dcb30..8480b7f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,11 @@ language: rust os: linux -# Targets that we just build (rather than run and test) env: global: + # All of the supported x86 Linux targets + - LINUX_TARGETS="x86_64-unknown-linux-gnu x86_64-unknown-linux-musl i686-unknown-linux-gnu i686-unknown-linux-musl" + # Targets that we just build (rather than run and test) - STD_TARGETS="x86_64-sun-solaris x86_64-unknown-cloudabi x86_64-unknown-freebsd x86_64-fuchsia x86_64-unknown-netbsd x86_64-unknown-redox x86_64-fortanix-unknown-sgx" - NO_STD_TARGETS="x86_64-unknown-uefi x86_64-unknown-hermit x86_64-unknown-l4re-uclibc x86_64-uwp-windows-gnu x86_64-wrs-vxworks" @@ -112,6 +114,18 @@ jobs: name: "OSX, nightly, docs" os: osx + - name: "cross-platform tests" + rust: nightly + addons: + apt: + packages: + - gcc-multilib + install: + - echo $LINUX_TARGETS | xargs -n1 rustup target add + script: + # We run tests for all supported x86 Linux targets + - echo $LINUX_TARGETS | xargs -t -n1 cargo test --target + - name: "cross-platform build only" rust: nightly install: diff --git a/src/lib.rs b/src/lib.rs index 98dcff67..5104f5e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -185,7 +185,8 @@ cfg_if! { #[path = "rdrand.rs"] mod imp; } else if #[cfg(feature = "custom")] { use custom as imp; - } else if #[cfg(all(feature = "cpu", target_arch = "x86_64"))] { + } else if #[cfg(all(feature = "cpu", + any(target_arch = "x86_64", target_arch = "x86")))] { #[path = "rdrand.rs"] mod imp; } else { compile_error!("\ diff --git a/src/rdrand.rs b/src/rdrand.rs index d8dfc7f2..1df21e5d 100644 --- a/src/rdrand.rs +++ b/src/rdrand.rs @@ -7,23 +7,30 @@ // except according to those terms. //! Implementation for SGX using RDRAND instruction -#[cfg(not(target_feature = "rdrand"))] -use crate::util::LazyBool; use crate::Error; -use core::arch::x86_64::_rdrand64_step; use core::mem; +cfg_if! { + if #[cfg(target_arch = "x86_64")] { + use core::arch::x86_64 as arch; + use arch::_rdrand64_step as rdrand_step; + } else if #[cfg(target_arch = "x86")] { + use core::arch::x86 as arch; + use arch::_rdrand32_step as rdrand_step; + } +} + // Recommendation from "Intel® Digital Random Number Generator (DRNG) Software // Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures // Software Developer’s Manual" - Volume 1 - Section 7.3.17.1. const RETRY_LIMIT: usize = 10; -const WORD_SIZE: usize = mem::size_of::(); +const WORD_SIZE: usize = mem::size_of::(); #[target_feature(enable = "rdrand")] unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> { for _ in 0..RETRY_LIMIT { let mut el = mem::zeroed(); - if _rdrand64_step(&mut el) == 1 { + if rdrand_step(&mut el) == 1 { // AMD CPUs from families 14h to 16h (pre Ryzen) sometimes fail to // set CF on bogus random data, so we check these values explicitly. // See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505 @@ -53,11 +60,13 @@ fn is_rdrand_supported() -> bool { // https://github.com/rust-lang-nursery/stdsimd/issues/464 #[cfg(not(target_feature = "rdrand"))] fn is_rdrand_supported() -> bool { - use core::arch::x86_64::__cpuid; - // SAFETY: All x86_64 CPUs support CPUID leaf 1 + use crate::util::LazyBool; + + // SAFETY: All Rust x86 targets are new enough to have CPUID, and if CPUID + // is supported, CPUID leaf 1 is always supported. const FLAG: u32 = 1 << 30; static HAS_RDRAND: LazyBool = LazyBool::new(); - HAS_RDRAND.unsync_init(|| unsafe { (__cpuid(1).ecx & FLAG) != 0 }) + HAS_RDRAND.unsync_init(|| unsafe { (arch::__cpuid(1).ecx & FLAG) != 0 }) } pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { diff --git a/src/test_cpu.rs b/src/test_cpu.rs index efcb1c83..7a9a0669 100644 --- a/src/test_cpu.rs +++ b/src/test_cpu.rs @@ -1,5 +1,5 @@ // We only test the CPU-based RNG source on supported architectures. -#![cfg(target_arch = "x86_64")] +#![cfg(any(target_arch = "x86_64", target_arch = "x86"))] #[path = "rdrand.rs"] mod rdrand;