1 | // Copyright 2016-2021 Brian Smith. |
2 | // |
3 | // Permission to use, copy, modify, and/or distribute this software for any |
4 | // purpose with or without fee is hereby granted, provided that the above |
5 | // copyright notice and this permission notice appear in all copies. |
6 | // |
7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | |
15 | #![cfg_attr ( |
16 | not(any(target_arch = "x86" , target_arch = "x86_64" )), |
17 | allow(dead_code) |
18 | )] |
19 | |
20 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
21 | mod abi_assumptions { |
22 | // TOOD: Support targets that do not have SSE and SSE2 enabled, such as |
23 | // x86_64-unknown-linux-none. See |
24 | // https://github.com/briansmith/ring/issues/1793#issuecomment-1793243725, |
25 | // https://github.com/briansmith/ring/issues/1832, |
26 | // https://github.com/briansmith/ring/issues/1833. |
27 | const _ASSUMES_SSE2: () = |
28 | assert!(cfg!(target_feature = "sse" ) && cfg!(target_feature = "sse2" )); |
29 | |
30 | #[cfg (target_arch = "x86_64" )] |
31 | const _ASSUMED_POINTER_SIZE: usize = 8; |
32 | #[cfg (target_arch = "x86" )] |
33 | const _ASSUMED_POINTER_SIZE: usize = 4; |
34 | const _ASSUMED_USIZE_SIZE: () = assert!(core::mem::size_of::<usize>() == _ASSUMED_POINTER_SIZE); |
35 | const _ASSUMED_REF_SIZE: () = |
36 | assert!(core::mem::size_of::<&'static u8>() == _ASSUMED_POINTER_SIZE); |
37 | |
38 | const _ASSUMED_ENDIANNESS: () = assert!(cfg!(target_endian = "little" )); |
39 | } |
40 | |
41 | pub(crate) struct Feature { |
42 | word: usize, |
43 | mask: u32, |
44 | } |
45 | |
46 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
47 | pub(super) unsafe fn init_global_shared_with_assembly() { |
48 | prefixed_extern! { |
49 | fn OPENSSL_cpuid_setup(); |
50 | } |
51 | unsafe { |
52 | OPENSSL_cpuid_setup(); |
53 | } |
54 | } |
55 | |
56 | impl Feature { |
57 | #[allow (clippy::needless_return)] |
58 | #[inline (always)] |
59 | pub fn available(&self, _: super::Features) -> bool { |
60 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
61 | { |
62 | prefixed_extern! { |
63 | static mut OPENSSL_ia32cap_P: [u32; 4]; |
64 | } |
65 | return self.mask == self.mask & unsafe { OPENSSL_ia32cap_P[self.word] }; |
66 | } |
67 | |
68 | #[cfg (not(any(target_arch = "x86" , target_arch = "x86_64" )))] |
69 | { |
70 | return false; |
71 | } |
72 | } |
73 | } |
74 | |
75 | #[allow (dead_code)] |
76 | pub(crate) const ADX: Feature = Feature { |
77 | word: 2, |
78 | mask: 1 << 19, |
79 | }; |
80 | |
81 | #[allow (dead_code)] |
82 | pub(crate) const BMI1: Feature = Feature { |
83 | word: 2, |
84 | mask: 1 << 3, |
85 | }; |
86 | |
87 | #[allow (dead_code)] |
88 | pub(crate) const BMI2: Feature = Feature { |
89 | word: 2, |
90 | mask: 1 << 8, |
91 | }; |
92 | |
93 | pub(crate) const FXSR: Feature = Feature { |
94 | word: 0, |
95 | mask: 1 << 24, |
96 | }; |
97 | |
98 | pub(crate) const PCLMULQDQ: Feature = Feature { |
99 | word: 1, |
100 | mask: 1 << 1, |
101 | }; |
102 | |
103 | pub(crate) const SSSE3: Feature = Feature { |
104 | word: 1, |
105 | mask: 1 << 9, |
106 | }; |
107 | |
108 | #[allow (dead_code)] |
109 | pub(crate) const SSE41: Feature = Feature { |
110 | word: 1, |
111 | mask: 1 << 19, |
112 | }; |
113 | |
114 | #[cfg (target_arch = "x86_64" )] |
115 | pub(crate) const MOVBE: Feature = Feature { |
116 | word: 1, |
117 | mask: 1 << 22, |
118 | }; |
119 | |
120 | pub(crate) const AES: Feature = Feature { |
121 | word: 1, |
122 | mask: 1 << 25, |
123 | }; |
124 | |
125 | #[cfg (target_arch = "x86_64" )] |
126 | pub(crate) const AVX: Feature = Feature { |
127 | word: 1, |
128 | mask: 1 << 28, |
129 | }; |
130 | |
131 | #[cfg (all(target_arch = "x86_64" , test))] |
132 | mod x86_64_tests { |
133 | use super::*; |
134 | |
135 | #[test ] |
136 | fn test_avx_movbe_mask() { |
137 | // This is the OpenSSL style of testing these bits. |
138 | assert_eq!((AVX.mask | MOVBE.mask) >> 22, 0x41); |
139 | } |
140 | } |
141 | |