Skip to main content

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::{Status, sys};
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/// Retrieve the system cache line size in bytes.
18///
19/// Wraps the
20/// [zx_system_get_dcache_line_size](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_dcache_line_size.md)
21/// syscall.
22pub fn system_get_dcache_line_size() -> u32 {
23    unsafe { sys::zx_system_get_dcache_line_size() }
24}
25
26/// Get the amount of physical memory on the system, in bytes.
27///
28/// Wraps the
29/// [zx_system_get_physmem](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_physmem)
30/// syscall.
31pub fn system_get_physmem() -> u64 {
32    unsafe { sys::zx_system_get_physmem() }
33}
34
35/// Get number of logical processors on the system.
36///
37/// Wraps the
38/// [zx_system_get_num_cpus](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_num_cpus)
39/// syscall.
40pub fn system_get_num_cpus() -> u32 {
41    unsafe { sys::zx_system_get_num_cpus() }
42}
43
44/// The types of system features that may be requested.
45#[derive(Debug, Copy, Clone, Eq, PartialEq)]
46#[repr(u32)]
47pub enum FeatureKind {
48    HardwareBreakpointCount = sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
49    HardwareWatchpointCount = sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
50}
51
52impl Into<u32> for FeatureKind {
53    fn into(self) -> u32 {
54        match self {
55            FeatureKind::HardwareBreakpointCount => sys::ZX_FEATURE_KIND_HW_BREAKPOINT_COUNT,
56            FeatureKind::HardwareWatchpointCount => sys::ZX_FEATURE_KIND_HW_WATCHPOINT_COUNT,
57        }
58    }
59}
60
61// We use a placeholder type to disallow any other implementations
62// of the FeatureFlags trait below.
63mod private {
64    pub struct Internal;
65}
66
67// Trait which encodes the FeatureKind with the bitflags.
68pub trait FeatureFlags: bitflags::Flags {
69    fn kind(_: private::Internal) -> u32;
70}
71
72bitflags! {
73    #[repr(transparent)]
74    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
75    pub struct VirtualMemoryFeatureFlags: u32 {
76        // VirtualMemoryKind flags
77        const VM_CAN_MAP_XOM = (1<<0);
78
79        // Allow the source to set any bits.
80        const _ = !0;
81    }
82}
83
84impl FeatureFlags for VirtualMemoryFeatureFlags {
85    fn kind(_: private::Internal) -> u32 {
86        sys::ZX_FEATURE_KIND_VM
87    }
88}
89
90bitflags! {
91    #[repr(transparent)]
92    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
93    pub struct CpuFeatureFlags: u32 {
94
95        // CpuFeatureKind flags
96        const HAS_CPU_FEATURES = (1<<0);
97
98        // Target-architecture CpuFeatureKind flags
99        #[cfg(target_arch = "aarch64")]
100        const ARM64_FEATURE_ISA_FP = sys::ZX_ARM64_FEATURE_ISA_FP;
101        #[cfg(target_arch = "aarch64")]
102        const ARM64_FEATURE_ISA_ASIMD = sys::ZX_ARM64_FEATURE_ISA_ASIMD;
103        #[cfg(target_arch = "aarch64")]
104        const ARM64_FEATURE_ISA_AES = sys::ZX_ARM64_FEATURE_ISA_AES;
105        #[cfg(target_arch = "aarch64")]
106        const ARM64_FEATURE_ISA_PMULL = sys::ZX_ARM64_FEATURE_ISA_PMULL;
107        #[cfg(target_arch = "aarch64")]
108        const ARM64_FEATURE_ISA_SHA1 = sys::ZX_ARM64_FEATURE_ISA_SHA1;
109        #[cfg(target_arch = "aarch64")]
110        const ARM64_FEATURE_ISA_SHA256 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
111        #[cfg(target_arch = "aarch64")]
112        const ARM64_FEATURE_ISA_CRC32 = sys::ZX_ARM64_FEATURE_ISA_CRC32;
113        #[cfg(target_arch = "aarch64")]
114        const ARM64_FEATURE_ISA_ATOMICS = sys::ZX_ARM64_FEATURE_ISA_ATOMICS;
115        #[cfg(target_arch = "aarch64")]
116        const ARM64_FEATURE_ISA_RDM = sys::ZX_ARM64_FEATURE_ISA_RDM;
117        #[cfg(target_arch = "aarch64")]
118        const ARM64_FEATURE_ISA_SHA3 = sys::ZX_ARM64_FEATURE_ISA_SHA3;
119        #[cfg(target_arch = "aarch64")]
120        const ARM64_FEATURE_ISA_SM3 = sys::ZX_ARM64_FEATURE_ISA_SM3;
121        #[cfg(target_arch = "aarch64")]
122        const ARM64_FEATURE_ISA_SM4 = sys::ZX_ARM64_FEATURE_ISA_SM4;
123        #[cfg(target_arch = "aarch64")]
124        const ARM64_FEATURE_ISA_DP = sys::ZX_ARM64_FEATURE_ISA_DP;
125        #[cfg(target_arch = "aarch64")]
126        const ARM64_FEATURE_ISA_DPB = sys::ZX_ARM64_FEATURE_ISA_DPB;
127        #[cfg(target_arch = "aarch64")]
128        const ARM64_FEATURE_ISA_FHM = sys::ZX_ARM64_FEATURE_ISA_FHM;
129        #[cfg(target_arch = "aarch64")]
130        const ARM64_FEATURE_ISA_TS = sys::ZX_ARM64_FEATURE_ISA_TS;
131        #[cfg(target_arch = "aarch64")]
132        const ARM64_FEATURE_ISA_RNDR = sys::ZX_ARM64_FEATURE_ISA_RNDR;
133        #[cfg(target_arch = "aarch64")]
134        const ARM64_FEATURE_ISA_SHA512 = sys::ZX_ARM64_FEATURE_ISA_SHA512;
135        #[cfg(target_arch = "aarch64")]
136        const ARM64_FEATURE_ISA_I8MM = sys::ZX_ARM64_FEATURE_ISA_I8MM;
137        #[cfg(target_arch = "aarch64")]
138        const ARM64_FEATURE_ISA_SVE = sys::ZX_ARM64_FEATURE_ISA_SVE;
139        #[cfg(target_arch = "aarch64")]
140        const ARM64_FEATURE_ISA_ARM32 = sys::ZX_ARM64_FEATURE_ISA_ARM32;
141        #[cfg(target_arch = "aarch64")]
142        const ARM64_FEATURE_ISA_MOPS = sys::ZX_ARM64_FEATURE_ISA_MOPS;
143
144        // This is an obsolete name for the same thing.
145        #[cfg(target_arch = "aarch64")]
146        const ARM64_FEATURE_ISA_SHA2 = sys::ZX_ARM64_FEATURE_ISA_SHA256;
147
148        // Allow the source to set any bits.
149        const _ = !0;
150    }
151}
152
153impl FeatureFlags for CpuFeatureFlags {
154    fn kind(_: private::Internal) -> u32 {
155        sys::ZX_FEATURE_KIND_CPU
156    }
157}
158
159bitflags! {
160    /// ARM64 SVE CPU feature flags retrieved via `ZX_FEATURE_KIND_CPU_SVE`.
161    #[repr(transparent)]
162    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
163    pub struct CpuSveFeatureFlags: u32 {
164        // arm64 SVE CPU features
165        #[cfg(target_arch = "aarch64")]
166        const ARM64_FEATURE_ISA_SVEI8MM = sys::ZX_ARM64_FEATURE_ISA_SVEI8MM;
167        #[cfg(target_arch = "aarch64")]
168        const ARM64_FEATURE_ISA_SVEF32MM = sys::ZX_ARM64_FEATURE_ISA_SVEF32MM;
169        #[cfg(target_arch = "aarch64")]
170        const ARM64_FEATURE_ISA_SVEF64MM = sys::ZX_ARM64_FEATURE_ISA_SVEF64MM;
171        #[cfg(target_arch = "aarch64")]
172        const ARM64_FEATURE_ISA_SVEBF16 = sys::ZX_ARM64_FEATURE_ISA_SVEBF16;
173        #[cfg(target_arch = "aarch64")]
174        const ARM64_FEATURE_ISA_SVE2 = sys::ZX_ARM64_FEATURE_ISA_SVE2;
175        #[cfg(target_arch = "aarch64")]
176        const ARM64_FEATURE_ISA_SVEAES = sys::ZX_ARM64_FEATURE_ISA_SVEAES;
177        #[cfg(target_arch = "aarch64")]
178        const ARM64_FEATURE_ISA_SVEPMULL = sys::ZX_ARM64_FEATURE_ISA_SVEPMULL;
179        #[cfg(target_arch = "aarch64")]
180        const ARM64_FEATURE_ISA_SVEBITPERM = sys::ZX_ARM64_FEATURE_ISA_SVEBITPERM;
181        #[cfg(target_arch = "aarch64")]
182        const ARM64_FEATURE_ISA_SVESHA3 = sys::ZX_ARM64_FEATURE_ISA_SVESHA3;
183        #[cfg(target_arch = "aarch64")]
184        const ARM64_FEATURE_ISA_SVESM4 = sys::ZX_ARM64_FEATURE_ISA_SVESM4;
185
186        // Allow the source to set any bits.
187        const _ = !0;
188    }
189}
190
191impl FeatureFlags for CpuSveFeatureFlags {
192    fn kind(_: private::Internal) -> u32 {
193        sys::ZX_FEATURE_KIND_CPU_SVE
194    }
195}
196
197bitflags! {
198    #[repr(transparent)]
199    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
200    pub struct AddressTaggingFeatureFlags: u32 {
201        // arm64 address-tagging features
202        #[cfg(target_arch = "aarch64")]
203        const ARM64_FEATURE_ADDRESS_TAGGING_TBI = sys::ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI;
204
205        // Allow the source to set any bits.
206        const _ = !0;
207    }
208}
209
210impl FeatureFlags for AddressTaggingFeatureFlags {
211    fn kind(_: private::Internal) -> u32 {
212        sys::ZX_FEATURE_KIND_ADDRESS_TAGGING
213    }
214}
215
216/// Get supported hardware capabilities bitflags.
217///
218/// Wraps the
219/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
220/// syscall.
221pub fn system_get_feature_flags<F: FeatureFlags>() -> Result<F, Status>
222where
223    F: bitflags::Flags<Bits = u32>,
224{
225    let mut raw_features: u32 = 0;
226    let access = private::Internal;
227    Status::ok(unsafe {
228        sys::zx_system_get_features(F::kind(access), &mut raw_features as *mut u32)
229    })
230    .and_then(|_status| Ok(F::from_bits_retain(raw_features)))
231}
232
233/// Get supported hardware capabilities counts.
234///
235/// Wraps the
236/// [zx_system_get_features](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features)
237/// syscall.
238pub fn system_get_feature_count(kind: FeatureKind) -> Result<u32, Status> {
239    let mut raw_features: u32 = 0;
240    Status::ok(unsafe { sys::zx_system_get_features(kind as u32, &mut raw_features as *mut u32) })
241        .and_then(|_status| Ok(raw_features))
242}
243
244/// The types of system events that may be requested via `system_get_event`.
245#[derive(Debug, Copy, Clone, Eq, PartialEq)]
246#[repr(u32)]
247pub enum SystemEventKind {
248    OutOfMemory = sys::ZX_SYSTEM_EVENT_OUT_OF_MEMORY,
249    MemoryPressureCritical = sys::ZX_SYSTEM_EVENT_MEMORY_PRESSURE_CRITICAL,
250    MemoryPressureWarning = sys::ZX_SYSTEM_EVENT_MEMORY_PRESSURE_WARNING,
251    MemoryPressureNormal = sys::ZX_SYSTEM_EVENT_MEMORY_PRESSURE_NORMAL,
252    ImminentOutOfMemory = sys::ZX_SYSTEM_EVENT_IMMINENT_OUT_OF_MEMORY,
253}
254
255/// Retrieve a system event handle from the kernel.
256///
257/// Wraps the
258/// [zx_system_get_event](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_event)
259/// syscall.
260pub fn system_get_event(
261    root_job: &crate::Job,
262    kind: SystemEventKind,
263) -> Result<crate::Event, Status> {
264    let mut event_handle = sys::ZX_HANDLE_INVALID;
265    // SAFETY: `root_job` is a valid job handle, and `event_handle` is a valid out-pointer.
266    Status::ok(unsafe {
267        sys::zx_system_get_event(root_job.raw_handle(), kind as u32, &mut event_handle)
268    })?;
269    // SAFETY: `event_handle` is a valid event handle returned by `zx_system_get_event` on success.
270    Ok(unsafe { crate::Event::from(crate::NullableHandle::from_raw(event_handle)) })
271}
272
273#[cfg(test)]
274mod tests {
275    use super::*;
276
277    #[test]
278    fn system_get_features_cpu_kind() {
279        // Clear extra CPU feature flags
280        let result = system_get_feature_flags()
281            .map(|flags: CpuFeatureFlags| flags & CpuFeatureFlags::HAS_CPU_FEATURES);
282
283        // Only aarch64 should return Ok.
284        #[cfg(target_arch = "aarch64")]
285        assert_eq!(result, Ok(CpuFeatureFlags::HAS_CPU_FEATURES));
286
287        #[cfg(not(target_arch = "aarch64"))]
288        assert_eq!(result, Err(Status::NOT_SUPPORTED));
289    }
290
291    #[test]
292    fn system_get_features_other_kinds() {
293        assert!(system_get_feature_flags::<VirtualMemoryFeatureFlags>().is_ok());
294        assert!(system_get_feature_flags::<AddressTaggingFeatureFlags>().is_ok());
295        assert!(system_get_feature_flags::<CpuSveFeatureFlags>().is_ok());
296        assert!(system_get_feature_count(FeatureKind::HardwareBreakpointCount).is_ok());
297        assert!(system_get_feature_count(FeatureKind::HardwareWatchpointCount).is_ok());
298    }
299
300    #[test]
301    fn system_get_event_access_denied() {
302        let job = fuchsia_runtime::job_default();
303        assert_eq!(
304            zx::system_get_event(&job, zx::SystemEventKind::MemoryPressureNormal),
305            Err(zx::Status::ACCESS_DENIED)
306        );
307    }
308}