kernel/utilities/machine_register.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2024.
//! Machine-specific register-sized type.
//!
//! This type holds exactly one machine register of data. This type should be
//! used when storing a value that is exactly the contents of a register with no
//! additional type information.
//!
//! Tock defines this as a custom type as there is currently (Nov 2024) no
//! suitable standard type for this purpose that is correct across all hardware
//! architectures Tock supports. The closest suitable type is `*mut ()`.
//! However, in hybrid CHERI `*mut ()` is smaller than a full register.
use core::fmt::{Formatter, LowerHex, UpperHex};
use super::capability_ptr::CapabilityPtr;
/// [`MachineRegister`] is a datatype that can hold exactly the contents of a
/// register with no additional semantic information.
///
/// [`MachineRegister`] is useful when you know data is the size of a register,
/// but not its true data type. In the future it may be possible, useful, or
/// necessary to change the implementation of [`MachineRegister`], however, the
/// semantics will remain. No use of [`MachineRegister`] should assume a
/// particular Rust implementation or any semantics other this description.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
#[repr(transparent)]
pub struct MachineRegister {
// We store the actual data as a CapabilityPtr as a convenient way to hold
// an architecture-specific register's worth of data. `value` may or may not
// really be a CapabilityPtr: it may instead contain an integer.
value: CapabilityPtr,
}
impl From<CapabilityPtr> for MachineRegister {
/// Creates a [`MachineRegister`] containing this [`CapabilityPtr`],
/// including its provenance.
fn from(from: CapabilityPtr) -> Self {
Self { value: from }
}
}
// Note: `From<usize> for MachineRegister` is implemented in the capability_ptr
// module.
impl UpperHex for MachineRegister {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
UpperHex::fmt(&self.value, f)
}
}
impl LowerHex for MachineRegister {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
LowerHex::fmt(&self.value, f)
}
}
impl MachineRegister {
/// Returns this [`MachineRegister`] as a [`CapabilityPtr`].
///
/// If this [`MachineRegister`] contains a pointer with provenance and/or
/// authority, the returned [`CapabilityPtr`] will have the same provenance
/// and/or authority.
pub fn as_capability_ptr(self) -> CapabilityPtr {
self.value
}
/// Returns this [`MachineRegister`] as a [`usize`].
///
/// This is intended for use on [`MachineRegister`]s created from a
/// [`usize`], in which case the original [`usize`] will be returned. If
/// this [`MachineRegister`] was created from a pointer, this returns the
/// pointer's address (without exposing provenance).
pub fn as_usize(self) -> usize {
self.value.addr()
}
}