Skip to content

Commit 9f9427e

Browse files
committed
use and to test the 21st bit
1 parent 6ee5955 commit 9f9427e

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

coresimd/x86/cpuid.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,36 @@ pub fn has_cpuid() -> bool {
9696
let result: u32;
9797
let _temp: u32;
9898
asm!(r#"
99-
# Read eflags into $0 and copy into $1:
99+
# Read eflags into $0 and copy it into $1:
100100
pushfd
101101
pop $0
102102
mov $1, $0
103-
# Flip 21st bit:
103+
# Flip 21st bit of $0.
104104
xor $0, 0x200000
105-
# Set eflags:
105+
# Set eflags to the value of $0
106+
#
107+
# Bit 21st can only be modified if cpuid is available
106108
push $0
107-
popfd
108-
# Read eflags again, if cpuid is available
109-
# the 21st bit will be flipped, otherwise it
110-
# it will have the same value as the original in $1:
111-
pushfd
109+
popfd # A
110+
# Read eflags into $0:
111+
pushfd # B
112112
pop $0
113-
# Xor'ing with the original eflags should have the
114-
# 21st bit set to true if cpuid is available and zero
115-
# otherwise. All other bits have not been modified and
116-
# are zero:
113+
# xor with the original eflags sets the bits that
114+
# have been modified:
117115
xor $0, $1
116+
# There is a race between popfd (A) and pushfd (B)
117+
# where other bits beyond 21st may have been modified due to
118+
# interrupts, a debugger stepping through the asm, etc.
119+
#
120+
# Therefore, explicitly check whether the 21st bit
121+
# was modified or not:
122+
and $0, 0x200000
118123
"#
119124
: "=r"(result), "=r"(_temp)
120125
:
121126
: "cc", "memory"
122127
: "intel");
123-
// Therefore, if result is 0, the bit was not modified and cpuid is
128+
// If result == 0, the 21st bit was not modified and cpuid is
124129
// not available. If cpuid is available, the bit was modified and
125130
// result != 0.
126131
result != 0

0 commit comments

Comments
 (0)