1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Identify CPU vendors, chips, and cores.
//!
//! Provides lookup tables for the names of CPU manufacturers and designers, CPU chip designs, and CPU core microarchitectures.
//! The following instruction set architectures are supported:
//!
//! - **x86** (both 32-bit and 64-bit CPUs)
//! - **ARM**
//! - **RISC-V**
//!
//! # Quickstart
//!
//! Add `libcpuname` to your project as a dependency:
//! ```shell
//! cargo add libcpuname
//! ```
//!
//! # Features
//!
//! The module corresponding to the host's target architecture is enabled by default via the `native` feature.
//! Other architectures can be enabled individually or wholesale.
//! The following features are available:
//!
//! - `std` *(enabled by default)*: Link against the [`std`] crate. This enables impls of [`std::error::Error`]
//! - `native` *(enabled by default)*: Exposes the module that matches the host's target triple
//! - `arm`: Exposes the [`arm`] module
//! - `riscv`: Exposes the [`riscv`] module
//! - `x86`: Exposes the [`x86`] module
/// Lookup functions for ARM CPUs.
///
/// ARM architectures going back to at least ARMv4 implement the `MIDR` register.
/// This register is segmented into bitfields that can be used to identify the CPU core on which the register is read.
/// This means that, unlike the CPUID instruction on x86, the host CPU's chip name cannot be determined.
/// Additionally, this register is only available at execution level 1 and above, meaning that only privileged contexts are permitted to read it.
///
/// For the purposes of this crate, the host CPU core reports the following information via the `MIDR` register:
///
/// - An 8-bit unsigned integer corresponding to the core's "[implementer](`arm::Implementer`)" (e.g. `0x41` for ARM Holdings)
/// - A 12-bit unsigned integer corresponding to the core's "partnum" (e.g. `0xD40` for Neoverse V1)
/// - A 4-bit unsigned integer corresponding to the core's "variant"
///
/// This module provides functions to translate the above values into implementer and core names.
///
/// # Example
///
/// ```rust
/// # fn main() -> Result<(), libcpuname::arm::err::Error> {
/// let implementer = libcpuname::arm::Implementer::try_from(0x41)?;
/// let core = libcpuname::arm::core_name(implementer, 0xD03, 0x0)?;
/// println!("implementer='{implementer}', core='{core}'");
/// # Ok(())
/// # }
/// ```
/// Lookup functions for RISC-V CPUs.
///
/// The standard RISC-V ISA contains address space for control and status registers, or CSRs.
/// Among these are two registers that can be used to identify the microarchitecture of a given hardware thread (or "hart"):
///
/// - `mvendorid` describes the hart's vendor and encodes either 0 (for [non-commercial][`riscv::Vendor::NonCommercial`] vendors) or a JEDEC company code
/// - `marchid` describes the hart's microarchitecture.
/// If the hart's microarchitecture is open-source, `marchid` is assigned by RISC-V International.
/// If the hart's microarchitecture is proprietary, `marchid`'s most significant bit will be set to 1 and the remaining bits may be in any vendor-defined format.
/// The width of this register is dependent on MXLEN, which matches the bit-width of the underlying hart (32 bits for RV32, 64 bits for RV64).
/// The RISC-V ISA specification mandates that the lower LEN-1 bits must not be zero.
///
/// This module provides functions to translate the above values into vendor and core names.
/// Note that no authoritative source for vendor-specific `marchid` values is known to the author of this software, and thus only open-source cores will provide core names as of time of writing.
/// If you have a source for proprietary `marchid` values for one or more vendors, please open an issue or pull request on this project's source repository.
///
/// # Example
///
/// ```rust
/// # fn main() -> Result<(), libcpuname::riscv::err::Error> {
/// let mvendorid = 0;
/// let marchid = 24;
/// let vendor = libcpuname::riscv::Vendor::try_from(mvendorid)?;
/// let core = libcpuname::riscv::core_name_rv32(vendor, marchid)?;
/// println!("vendor='{vendor}', core='{core}'");
/// # Ok(())
/// # }
/// ```
/// Lookup functions for x86 and x86-64 CPUs.
///
/// With the release of Pentium, Intel introduced the [CPUID](https://en.wikipedia.org/wiki/CPUID) instruction as part of x86.
/// This instruction can be used to determine various properties of the host CPU.
///
/// For the purposes of this crate, the host CPU can report the following information via CPUID:
///
/// - A 12-chraacter ASCII string corresponding to the CPU's "vendor" (e.g. `GenuineIntel` for Intel)
/// - An unsigned integer from `0..=30` corresponding to the CPU's "family" (e.g. `0x06` for most P6-based Intel processors)
/// - An 8-bit unsigned integer corresponding to the CPU's "model" (e.g. `0x2A` for the Intel Sandy Bridge microarchitecture)
/// - A 4-bit unsigned integer corresponding to the CPU's "stepping" (e.g. `0x5` for Intel's Sandy Bridge-E/EP processors)
///
/// This module provides functions to translate the above values into vendor names, chip names, and core names.
/// The `raw_cpuid` crate can be used to fetch the above values from the host CPU for lookup.
///
/// # Example
/// ```rust
/// # fn main() -> Result<(), libcpuname::x86::err::Error> {
/// let vendor = "GenuineIntel".parse::<libcpuname::x86::Vendor>()?;
/// let chip = libcpuname::x86::chip_name(vendor, 0x06, 0x2A, 0x0)?;
/// let uarch = libcpuname::x86::core_name(vendor, 0x06, 0x2A)?;
/// println!("vendor='{vendor}', chip='{chip}', uarch='{uarch}'");
/// # Ok(())
/// # }
/// ```