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