zx/
system.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{sys, Status};
6use bitflags::bitflags;
7
8/// Retrieve the system memory page size in bytes.
9///
10/// Wraps the
11/// [zx_system_get_page_size](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_page_size.md)
12/// syscall.
13pub fn system_get_page_size() -> u32 {
14    unsafe { sys::zx_system_get_page_size() }
15}
16
17/// Get the amount of physical memory on the system, in bytes.
18///
19/// Wraps the
20/// [zx_system_get_physmem](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_physmem)
21/// syscall.
22pub fn system_get_physmem() -> u64 {
23    unsafe { sys::zx_system_get_physmem() }
24}
25
26/// Get number of logical processors on the system.
27///
28/// Wraps the
29/// [zx_system_get_num_cpus](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_num_cpus)
30/// syscall.
31pub fn system_get_num_cpus() -> u32 {
32    unsafe { sys::zx_system_get_num_cpus() }
33}
34
35/// The types of system features that may be requested.
36#[derive(Debug, Copy, Clone, Eq, PartialEq)]
37#[repr(u32)]
38pub enum FeatureKind {
39    HardwareBreakpointCount = sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
40    HardwareWatchpointCount = sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
41}
42
43impl Into<u32> for FeatureKind {
44    fn into(self) -> u32 {
45        match self {
46            FeatureKind::HardwareBreakpointCount => sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
47            FeatureKind::HardwareWatchpointCount => sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
48        }
49    }
50}
51
52// We use a placeholder type to disallow any other implementations
53// of the FeatureFlags trait below.
54mod private {
55    pub struct Internal;
56}
57
58// Trait which encodes the FeatureKind with the bitflags.
59pub trait FeatureFlags: bitflags::Flags {
60    fn kind(_: private::Internal) -> u32;
61}
62
63bitflags! {
64    #[repr(transparent)]
65    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
66    pub struct VirtualMemoryFeatureFlags: u32 {
67        // VirtualMemoryKind flags
68        const VM_CAN_MAP_XOM = (1<<0);
69
70        // Allow the source to set any bits.
71        const _ = !0;
72    }
73}
74
75impl FeatureFlags for VirtualMemoryFeatureFlags {
76    fn kind(_: private::Internal) -> u32 {
77        sys::ZX_FEATURE_KIND_VM
78    }
79}
80
81bitflags! {
82    #[repr(transparent)]
83    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
84    pub struct CpuFeatureFlags: u32 {
85
86        // CpuFeatureKind flags
87        const HAS_CPU_FEATURES = (1<<0);
88
89        // Target-architecture CpuFeatureKind flags
90        #[cfg(target_arch = "aarch64")]
91        const ARM64_FEATURE_ISA_FP = sys::ZX_ARM64_FEATURE_ISA_FP;
92        #[cfg(target_arch = "aarch64")]
93        const ARM64_FEATURE_ISA_ASIMD = sys::ZX_ARM64_FEATURE_ISA_ASIMD;
94        #[cfg(target_arch = "aarch64")]
95        const ARM64_FEATURE_ISA_AES = sys::ZX_ARM64_FEATURE_ISA_AES;
96        #[cfg(target_arch = "aarch64")]
97        const ARM64_FEATURE_ISA_PMULL = sys::ZX_ARM64_FEATURE_ISA_PMULL;
98        #[cfg(target_arch = "aarch64")]
99        const ARM64_FEATURE_ISA_SHA1 = sys::ZX_ARM64_FEATURE_ISA_SHA1;
100        #[cfg(target_arch = "aarch64")]
101        const ARM64_FEATURE_ISA_SHA256 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
102        #[cfg(target_arch = "aarch64")]
103        const ARM64_FEATURE_ISA_CRC32 = sys::ZX_ARM64_FEATURE_ISA_CRC32;
104        #[cfg(target_arch = "aarch64")]
105        const ARM64_FEATURE_ISA_ATOMICS = sys::ZX_ARM64_FEATURE_ISA_ATOMICS;
106        #[cfg(target_arch = "aarch64")]
107        const ARM64_FEATURE_ISA_RDM = sys::ZX_ARM64_FEATURE_ISA_RDM;
108        #[cfg(target_arch = "aarch64")]
109        const ARM64_FEATURE_ISA_SHA3 = sys::ZX_ARM64_FEATURE_ISA_SHA3;
110        #[cfg(target_arch = "aarch64")]
111        const ARM64_FEATURE_ISA_SM3 = sys::ZX_ARM64_FEATURE_ISA_SM3;
112        #[cfg(target_arch = "aarch64")]
113        const ARM64_FEATURE_ISA_SM4 = sys::ZX_ARM64_FEATURE_ISA_SM4;
114        #[cfg(target_arch = "aarch64")]
115        const ARM64_FEATURE_ISA_DP = sys::ZX_ARM64_FEATURE_ISA_DP;
116        #[cfg(target_arch = "aarch64")]
117        const ARM64_FEATURE_ISA_DPB = sys::ZX_ARM64_FEATURE_ISA_DPB;
118        #[cfg(target_arch = "aarch64")]
119        const ARM64_FEATURE_ISA_FHM = sys::ZX_ARM64_FEATURE_ISA_FHM;
120        #[cfg(target_arch = "aarch64")]
121        const ARM64_FEATURE_ISA_TS = sys::ZX_ARM64_FEATURE_ISA_TS;
122        #[cfg(target_arch = "aarch64")]
123        const ARM64_FEATURE_ISA_RNDR = sys::ZX_ARM64_FEATURE_ISA_RNDR;
124        #[cfg(target_arch = "aarch64")]
125        const ARM64_FEATURE_ISA_SHA512 = sys::ZX_ARM64_FEATURE_ISA_SHA512;
126        #[cfg(target_arch = "aarch64")]
127        const ARM64_FEATURE_ISA_I8MM = sys::ZX_ARM64_FEATURE_ISA_I8MM;
128        #[cfg(target_arch = "aarch64")]
129        const ARM64_FEATURE_ISA_SVE = sys::ZX_ARM64_FEATURE_ISA_SVE;
130        #[cfg(target_arch = "aarch64")]
131        const ARM64_FEATURE_ISA_ARM32 = sys::ZX_ARM64_FEATURE_ISA_ARM32;
132
133        // This is an obsolete name for the same thing.
134        #[cfg(target_arch = "aarch64")]
135        const ARM64_FEATURE_ISA_SHA2 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
136
137        // Allow the source to set any bits.
138        const _ = !0;
139    }
140}
141
142impl FeatureFlags for CpuFeatureFlags {
143    fn kind(_: private::Internal) -> u32 {
144        sys::ZX_FEATURE_KIND_CPU
145    }
146}
147
148bitflags! {
149    #[repr(transparent)]
150    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
151    pub struct AddressTaggingFeatureFlags: u32 {
152        // arm64 address-tagging features
153        #[cfg(target_arch = "aarch64")]
154        const ARM64_FEATURE_ADDRESS_TAGGING_TBI = sys::ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI;
155
156        // Allow the source to set any bits.
157        const _ = !0;
158    }
159}
160
161impl FeatureFlags for AddressTaggingFeatureFlags {
162    fn kind(_: private::Internal) -> u32 {
163        sys::ZX_FEATURE_KIND_ADDRESS_TAGGING
164    }
165}
166
167/// Get supported hardware capabilities bitflags.
168///
169/// Wraps the
170/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
171/// syscall.
172pub fn system_get_feature_flags<F: FeatureFlags>() -> Result<F, Status>
173where
174    F: bitflags::Flags<Bits = u32>,
175{
176    let mut raw_features: u32 = 0;
177    let access = private::Internal;
178    Status::ok(unsafe {
179        sys::zx_system_get_features(F::kind(access), &mut raw_features as *mut u32)
180    })
181    .and_then(|_status| Ok(F::from_bits_retain(raw_features)))
182}
183
184/// Get supported hardware capabilities counts.
185///
186/// Wraps the
187/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
188/// syscall.
189pub fn system_get_feature_count(kind: FeatureKind) -> Result<u32, Status> {
190    let mut raw_features: u32 = 0;
191    Status::ok(unsafe { sys::zx_system_get_features(kind as u32, &mut raw_features as *mut u32) })
192        .and_then(|_status| Ok(raw_features))
193}
194
195#[cfg(test)]
196mod tests {
197    use super::*;
198
199    #[test]
200    fn system_get_features_cpu_kind() {
201        // Clear extra CPU feature flags
202        let result = system_get_feature_flags()
203            .map(|flags: CpuFeatureFlags| flags & CpuFeatureFlags::HAS_CPU_FEATURES);
204
205        // Only aarch64 should return Ok.
206        #[cfg(target_arch = "aarch64")]
207        assert_eq!(result, Ok(CpuFeatureFlags::HAS_CPU_FEATURES));
208
209        #[cfg(not(target_arch = "aarch64"))]
210        assert_eq!(result, Err(Status::NOT_SUPPORTED));
211    }
212
213    #[test]
214    fn system_get_features_other_kinds() {
215        assert!(system_get_feature_flags::<VirtualMemoryFeatureFlags>().is_ok());
216        assert!(system_get_feature_flags::<AddressTaggingFeatureFlags>().is_ok());
217        assert!(system_get_feature_count(FeatureKind::HardwareBreakpointCount).is_ok());
218        assert!(system_get_feature_count(FeatureKind::HardwareWatchpointCount).is_ok());
219    }
220}