Skip to main content

sbi_spec/binary/
shared_physical_ptr.rs

1use core::marker::PhantomData;
2
3/// Shared memory physical address raw pointer with type annotation.
4///
5/// This is a structure wrapping a raw pointer to the value of the type `T` without
6/// a pointer metadata. `SharedPtr`'s are _thin_; they won't include metadata
7/// as RISC-V SBI does not provide an approach to pass them via SBI calls,
8/// thus the length of type `T` should be decided independently of raw
9/// pointer structure.
10///
11/// `SharedPtr` can be used as a parameter to pass the shared memory physical pointer
12///  with a given base address in RISC-V SBI calls. For example, a `SharedPtr<[u8; 64]>`
13/// would represent a fixed-size 64 byte array on a RISC-V SBI function argument
14/// type.
15///
16/// This structure cannot be dereferenced directly with physical addresses,
17/// because on RISC-V systems the physical address space could be larger than the
18/// virtual ones. Hence, this structure describes the physical memory range by
19/// two `usize` values: the upper `phys_addr_hi` and lower `phys_addr_lo`.
20///
21/// RISC-V SBI extensions may declare special pointer values for shared memory
22/// raw pointers. For example, SBI STA declares that steal-time information
23/// should stop from reporting when the SBI call is invoked using all-ones
24/// bitwise shared pointer, i.e. `phys_addr_hi` and `phys_addr_lo` both equals
25/// `usize::MAX`. `SharedPtr` can be constructed using such special values
26/// by providing them to the `SharedPtr::new` function.
27///
28/// # Requirements
29///
30/// If an SBI function needs to pass a shared memory physical address range to
31/// the SBI implementation (or higher privilege mode), then this physical memory
32/// address range MUST satisfy the following requirements:
33///
34/// * The SBI implementation MUST check that the supervisor-mode software is
35///   allowed to access the specified physical memory range with the access
36///   type requested (read and/or write).
37/// * The SBI implementation MUST access the specified physical memory range
38///   using the PMA attributes.
39/// * The data in the shared memory MUST follow little-endian byte ordering.
40///
41/// *NOTE:* If the supervisor-mode software accesses the same physical memory
42/// range using a memory type different from the PMA, then a loss of coherence
43/// or unexpected memory ordering may occur. The invoking software should
44/// follow the rules and sequences defined in the RISC-V Svpbmt specification
45/// to prevent the loss of coherence and memory ordering.
46///
47/// It is recommended that a memory physical address passed to an SBI function
48/// should use at least two `usize` parameters to support platforms
49/// which have memory physical addresses wider than `XLEN` bits.
50// FIXME: should constrain with `T: Thin` once ptr_metadata feature is stabled;
51// RISC-V SBI does not provide an approach to pass pointer metadata by SBI calls.
52pub struct SharedPtr<T> {
53    phys_addr_lo: usize,
54    phys_addr_hi: usize,
55    _marker: PhantomData<*mut T>,
56}
57
58// FIXME: we should consider strict provenance rules for this pointer-like structure
59// once feature strict_provenance is stabled.
60impl<T> SharedPtr<T> {
61    /// Create a shared physical memory pointer by physical address.
62    #[inline]
63    pub const fn new(phys_addr_lo: usize, phys_addr_hi: usize) -> Self {
64        Self {
65            phys_addr_lo,
66            phys_addr_hi,
67            _marker: PhantomData,
68        }
69    }
70
71    /// Returns low-part physical address of the shared physical memory pointer.
72    #[inline]
73    pub const fn phys_addr_lo(self) -> usize {
74        self.phys_addr_lo
75    }
76
77    /// Returns high-part physical address of the shared physical memory pointer.
78    #[inline]
79    pub const fn phys_addr_hi(self) -> usize {
80        self.phys_addr_hi
81    }
82}
83
84impl<T> Clone for SharedPtr<T> {
85    #[inline(always)]
86    fn clone(&self) -> Self {
87        *self
88    }
89}
90
91impl<T> Copy for SharedPtr<T> {}