libcpuname 0.1.3

Identify CPU vendors, chips, and cores across multiple architectures
Documentation
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(clippy::cargo)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::missing_panics_doc)]
#![warn(rustdoc::all)]

//! 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

#[cfg(any(
    docsrs,
    feature = "arm",
    all(
        feature = "native",
        any(target_arch = "arm", target_arch = "arm64ec", target_arch = "aarch64")
    )
))]
/// 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(())
/// # }
/// ```
pub mod arm;

#[cfg(any(
    docsrs,
    feature = "riscv",
    all(
        feature = "native",
        any(target_arch = "riscv32", target_arch = "riscv64")
    )
))]
/// 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(())
/// # }
/// ```
pub mod riscv;

#[cfg(any(
    docsrs,
    feature = "x86",
    all(feature = "native", any(target_arch = "x86", target_arch = "x86_64"))
))]
/// 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(())
/// # }
/// ```
pub mod x86;