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> {}