Skip to content

Commit c7e9e7c

Browse files
committed
Make cpuid safe and update docs
1 parent fc5ac13 commit c7e9e7c

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

crates/core_arch/src/x86/cpuid.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,19 @@ pub struct CpuidResult {
2828
/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
2929
/// and `sub_leaf` (`ECX`).
3030
///
31-
/// The highest-supported leaf value is returned by the first tuple argument of
32-
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containing
33-
/// sub-leaves, the second tuple argument returns the highest-supported
34-
/// sub-leaf value.
31+
/// There are 2 types of information leafs - basic leafs (with `leaf < 0x8000000`)
32+
/// and extended leafs (with `leaf >= 0x80000000`). The highest supported basic and
33+
/// extended leafs can be obtained by calling CPUID with `0` and `0x80000000`,
34+
/// respectively, and reading the value in the `EAX` register. If the leaf supports
35+
/// more than one sub-leafs, then the procedure of obtaining the highest supported
36+
/// sub-leaf, as well as the behavior if a invalid sub-leaf value is passed, depends
37+
/// on the specific leaf.
38+
///
39+
/// If the `leaf` value is higher than the maximum supported basic or extended leaf
40+
/// for the processor, this returns the information for the highest supported basic
41+
/// information leaf (with the passed `sub_leaf` value). If the `leaf` value is less
42+
/// than or equal to the highest basic or extended leaf value, but the leaf is not
43+
/// supported on the processor, all zeros are returned.
3544
///
3645
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
3746
/// information using the `EAX` and `ECX` registers, and the interpretation of
@@ -49,7 +58,7 @@ pub struct CpuidResult {
4958
#[inline]
5059
#[cfg_attr(test, assert_instr(cpuid))]
5160
#[stable(feature = "simd_x86", since = "1.27.0")]
52-
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
61+
pub fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
5362
let eax;
5463
let ebx;
5564
let ecx;
@@ -58,7 +67,7 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
5867
// LLVM sometimes reserves `ebx` for its internal use, we so we need to use
5968
// a scratch register for it instead.
6069
#[cfg(target_arch = "x86")]
61-
{
70+
unsafe {
6271
asm!(
6372
"mov {0}, ebx",
6473
"cpuid",
@@ -71,7 +80,7 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
7180
);
7281
}
7382
#[cfg(target_arch = "x86_64")]
74-
{
83+
unsafe {
7584
asm!(
7685
"mov {0:r}, rbx",
7786
"cpuid",
@@ -86,27 +95,26 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
8695
CpuidResult { eax, ebx, ecx, edx }
8796
}
8897

98+
/// Calls CPUID with the provided `leaf` value, with `sub_leaf` set to 0.
8999
/// See [`__cpuid_count`](fn.__cpuid_count.html).
90100
#[inline]
91101
#[cfg_attr(test, assert_instr(cpuid))]
92102
#[stable(feature = "simd_x86", since = "1.27.0")]
93-
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
103+
pub fn __cpuid(leaf: u32) -> CpuidResult {
94104
__cpuid_count(leaf, 0)
95105
}
96106

97-
/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
98-
/// values.
107+
/// Returns the EAX and EBX register after calling CPUID with the provided `leaf`,
108+
/// with `sub_leaf` set to 0.
99109
///
100-
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
101-
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
102-
/// containing sub-leafs, the second tuple argument contains the
103-
/// highest-supported sub-leaf value.
110+
/// If `leaf` if 0 or `0x80000000`, the first tuple argument contains the maximum
111+
/// supported basic or extended leaf, respectively.
104112
///
105113
/// See also [`__cpuid`](fn.__cpuid.html) and
106114
/// [`__cpuid_count`](fn.__cpuid_count.html).
107115
#[inline]
108116
#[stable(feature = "simd_x86", since = "1.27.0")]
109-
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
117+
pub fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
110118
let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
111119
(eax, ebx)
112120
}

0 commit comments

Comments
 (0)