Skip to main content

arch_rs/
lib.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#![no_std]
8
9#[cfg(target_arch = "aarch64")]
10pub use arch_arm64::{self as arm64, ArchSavedNormalState};
11
12#[cfg(target_arch = "riscv64")]
13pub use arch_riscv64::{self as riscv64, ArchSavedNormalState};
14
15#[cfg(target_arch = "x86_64")]
16pub use arch_x86::{self as x86, ArchSavedNormalState};
17
18use zx_status::Status;
19
20unsafe extern "C" {
21    fn cpp_arch_ints_disabled() -> bool;
22    fn cpp_arch_disable_ints();
23    fn cpp_arch_enable_ints();
24    fn cpp_arch_interrupt_save() -> InterruptSavedState;
25    fn cpp_arch_interrupt_restore(state: InterruptSavedState);
26    fn cpp_arch_curr_cpu_num() -> u32;
27    fn cpp_arch_max_num_cpus() -> u32;
28    fn cpp_arch_copy_from_user(
29        dst: *mut core::ffi::c_void,
30        src: *const core::ffi::c_void,
31        len: usize,
32    ) -> i32;
33    fn cpp_arch_copy_to_user(
34        dst: *mut core::ffi::c_void,
35        src: *const core::ffi::c_void,
36        len: usize,
37    ) -> i32;
38}
39
40/// Returns true if interrupts are disabled on the current CPU.
41#[inline(always)]
42pub fn ints_disabled() -> bool {
43    unsafe { cpp_arch_ints_disabled() }
44}
45
46/// Disable interrupts on the current CPU.
47#[inline(always)]
48pub fn disable_ints() {
49    unsafe { cpp_arch_disable_ints() }
50}
51
52/// Enable interrupts on the current CPU.
53#[inline(always)]
54pub fn enable_ints() {
55    unsafe { cpp_arch_enable_ints() }
56}
57
58/// The saved interrupt state, representing architecture-specific interrupt flags.
59#[cfg(target_arch = "x86_64")]
60#[repr(transparent)]
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62pub struct InterruptSavedState(usize);
63
64/// The saved interrupt state, representing architecture-specific interrupt flags.
65#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
66#[repr(transparent)]
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68pub struct InterruptSavedState(bool);
69
70/// Save the current interrupt state (specifically, whether interrupts are enabled)
71/// and disable interrupts on the current CPU.
72#[inline(always)]
73pub fn arch_interrupt_save() -> InterruptSavedState {
74    unsafe { cpp_arch_interrupt_save() }
75}
76
77/// Restore the interrupt state on the current CPU to a previously saved state.
78#[inline(always)]
79pub fn arch_interrupt_restore(state: InterruptSavedState) {
80    unsafe { cpp_arch_interrupt_restore(state) }
81}
82
83/// A guard that disables interrupts on the current CPU when created,
84/// and restores the previous interrupt state when dropped.
85pub struct InterruptDisableGuard {
86    state: InterruptSavedState,
87}
88
89impl InterruptDisableGuard {
90    #[inline(always)]
91    pub fn new() -> Self {
92        Self { state: arch_interrupt_save() }
93    }
94}
95
96impl Drop for InterruptDisableGuard {
97    #[inline(always)]
98    fn drop(&mut self) {
99        arch_interrupt_restore(self.state);
100    }
101}
102
103/// Returns the CPU number of the calling CPU.
104#[inline(always)]
105pub fn curr_cpu_num() -> u32 {
106    unsafe { cpp_arch_curr_cpu_num() }
107}
108
109/// Returns the maximum number of CPUs in the system.
110#[inline(always)]
111pub fn max_num_cpus() -> u32 {
112    unsafe { cpp_arch_max_num_cpus() }
113}
114
115/// Copies `len` bytes from user memory at `src` into kernel memory at `dst`.
116///
117/// # Safety
118/// Caller must ensure `dst` points to at least `len` bytes of valid memory
119/// and `src` is a user pointer.
120#[inline(always)]
121pub unsafe fn arch_copy_from_user(
122    dst: *mut core::ffi::c_void,
123    src: *const core::ffi::c_void,
124    len: usize,
125) -> Result<(), Status> {
126    Status::ok(unsafe { cpp_arch_copy_from_user(dst, src, len) })
127}
128
129/// Copies `len` bytes from kernel memory at `src` into user memory at `dst`.
130///
131/// # Safety
132/// Caller must ensure `src` points to at least `len` bytes of valid memory
133/// and `dst` is a user pointer.
134#[inline(always)]
135pub unsafe fn arch_copy_to_user(
136    dst: *mut core::ffi::c_void,
137    src: *const core::ffi::c_void,
138    len: usize,
139) -> Result<(), Status> {
140    Status::ok(unsafe { cpp_arch_copy_to_user(dst, src, len) })
141}