blob: 173dc070653c4b136e300d8f3211d58f460b7bad [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::{sys, Status};
use bitflags::bitflags;
/// Retrieve the system memory page size in bytes.
///
/// Wraps the
/// [zx_system_get_page_size](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_page_size.md)
/// syscall.
pub fn system_get_page_size() -> u32 {
unsafe { sys::zx_system_get_page_size() }
}
/// Get the amount of physical memory on the system, in bytes.
///
/// Wraps the
/// [zx_system_get_physmem](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_physmem)
/// syscall.
pub fn system_get_physmem() -> u64 {
unsafe { sys::zx_system_get_physmem() }
}
/// Get number of logical processors on the system.
///
/// Wraps the
/// [zx_system_get_num_cpus](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_num_cpus)
/// syscall.
pub fn system_get_num_cpus() -> u32 {
unsafe { sys::zx_system_get_num_cpus() }
}
/// The types of system features that may be requested.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
pub enum FeatureKind {
HardwareBreakpointCount = sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
HardwareWatchpointCount = sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
}
impl Into<u32> for FeatureKind {
fn into(self) -> u32 {
match self {
FeatureKind::HardwareBreakpointCount => sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
FeatureKind::HardwareWatchpointCount => sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
}
}
}
// We use a placeholder type to disallow any other implementations
// of the FeatureFlags trait below.
mod private {
pub struct Internal;
}
// Trait which encodes the FeatureKind with the bitflags.
pub trait FeatureFlags: bitflags::Flags {
fn kind(_: private::Internal) -> u32;
}
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VirtualMemoryFeatureFlags: u32 {
// VirtualMemoryKind flags
const VM_CAN_MAP_XOM = (1<<0);
// Allow the source to set any bits.
const _ = !0;
}
}
impl FeatureFlags for VirtualMemoryFeatureFlags {
fn kind(_: private::Internal) -> u32 {
sys::ZX_FEATURE_KIND_VM
}
}
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CpuFeatureFlags: u32 {
// CpuFeatureKind flags
const HAS_CPU_FEATURES = (1<<0);
// Target-architecture CpuFeatureKind flags
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_FP = sys::ZX_ARM64_FEATURE_ISA_FP;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_ASIMD = sys::ZX_ARM64_FEATURE_ISA_ASIMD;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_AES = sys::ZX_ARM64_FEATURE_ISA_AES;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_PMULL = sys::ZX_ARM64_FEATURE_ISA_PMULL;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SHA1 = sys::ZX_ARM64_FEATURE_ISA_SHA1;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SHA256 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_CRC32 = sys::ZX_ARM64_FEATURE_ISA_CRC32;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_ATOMICS = sys::ZX_ARM64_FEATURE_ISA_ATOMICS;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_RDM = sys::ZX_ARM64_FEATURE_ISA_RDM;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SHA3 = sys::ZX_ARM64_FEATURE_ISA_SHA3;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SM3 = sys::ZX_ARM64_FEATURE_ISA_SM3;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SM4 = sys::ZX_ARM64_FEATURE_ISA_SM4;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_DP = sys::ZX_ARM64_FEATURE_ISA_DP;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_DPB = sys::ZX_ARM64_FEATURE_ISA_DPB;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_FHM = sys::ZX_ARM64_FEATURE_ISA_FHM;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_TS = sys::ZX_ARM64_FEATURE_ISA_TS;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_RNDR = sys::ZX_ARM64_FEATURE_ISA_RNDR;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SHA512 = sys::ZX_ARM64_FEATURE_ISA_SHA512;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_I8MM = sys::ZX_ARM64_FEATURE_ISA_I8MM;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SVE = sys::ZX_ARM64_FEATURE_ISA_SVE;
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_ARM32 = sys::ZX_ARM64_FEATURE_ISA_ARM32;
// This is an obsolete name for the same thing.
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ISA_SHA2 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
// Allow the source to set any bits.
const _ = !0;
}
}
impl FeatureFlags for CpuFeatureFlags {
fn kind(_: private::Internal) -> u32 {
sys::ZX_FEATURE_KIND_CPU
}
}
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AddressTaggingFeatureFlags: u32 {
// arm64 address-tagging features
#[cfg(target_arch = "aarch64")]
const ARM64_FEATURE_ADDRESS_TAGGING_TBI = sys::ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI;
// Allow the source to set any bits.
const _ = !0;
}
}
impl FeatureFlags for AddressTaggingFeatureFlags {
fn kind(_: private::Internal) -> u32 {
sys::ZX_FEATURE_KIND_ADDRESS_TAGGING
}
}
/// Get supported hardware capabilities bitflags.
///
/// Wraps the
/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
/// syscall.
pub fn system_get_feature_flags<F: FeatureFlags>() -> Result<F, Status>
where
F: bitflags::Flags<Bits = u32>,
{
let mut raw_features: u32 = 0;
let access = private::Internal;
Status::ok(unsafe {
sys::zx_system_get_features(F::kind(access), &mut raw_features as *mut u32)
})
.and_then(|_status| Ok(F::from_bits_retain(raw_features)))
}
/// Get supported hardware capabilities counts.
///
/// Wraps the
/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
/// syscall.
pub fn system_get_feature_count(kind: FeatureKind) -> Result<u32, Status> {
let mut raw_features: u32 = 0;
Status::ok(unsafe { sys::zx_system_get_features(kind as u32, &mut raw_features as *mut u32) })
.and_then(|_status| Ok(raw_features))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn system_get_features_cpu_kind() {
// Clear extra CPU feature flags
let result = system_get_feature_flags()
.map(|flags: CpuFeatureFlags| flags & CpuFeatureFlags::HAS_CPU_FEATURES);
// Only aarch64 should return Ok.
#[cfg(target_arch = "aarch64")]
assert_eq!(result, Ok(CpuFeatureFlags::HAS_CPU_FEATURES));
#[cfg(not(target_arch = "aarch64"))]
assert_eq!(result, Err(Status::NOT_SUPPORTED));
}
#[test]
fn system_get_features_other_kinds() {
assert!(system_get_feature_flags::<VirtualMemoryFeatureFlags>().is_ok());
assert!(system_get_feature_flags::<AddressTaggingFeatureFlags>().is_ok());
assert!(system_get_feature_count(FeatureKind::HardwareBreakpointCount).is_ok());
assert!(system_get_feature_count(FeatureKind::HardwareWatchpointCount).is_ok());
}
}