1
- use core:: mem:: transmute;
2
-
3
- /// In order to work with Miri's `-Zmiri-track-raw-pointers` flag, we cannot
4
- /// pass pointers to the kernel through `usize` values (as casting to and from
5
- /// `usize` drops the pointer`s tag). Instead, `RawSyscalls` uses the `Register`
6
- /// type. `Register` wraps a raw pointer type that keeps that tags around. User
7
- /// code should not depend on the particular type of pointer that `Register`
8
- /// wraps, but instead use the conversion functions in this module.
1
+ /// `Register` represents the value of a register used in Tock's syscall ABI. It
2
+ /// can contain integer values as well as pointer values.
3
+ ///
4
+ /// `Register` currently wraps a raw pointer, but that is not a stable guarantee
5
+ /// and users should not rely on it. However, `Register` does guarantee that the
6
+ /// type it wraps is a valid operand type for inline assembly.
7
+ ///
8
+ /// If a pointer is converted to a `Register`, that `Register` has that
9
+ /// pointer's provenance. The provenance is not exposed. If an integer is
10
+ /// converted to a `Register`, that `Register` has no provenance. When a
11
+ /// `Register` with provenance is converted into a pointer, that pointer carries
12
+ /// the `Register`'s provenance. When a `Register` without provenance is
13
+ /// converted into a pointer, that pointer has no provenance.
9
14
// Register is repr(transparent) so that an upcall's application data can be
10
15
// soundly passed as a Register.
11
16
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
@@ -36,22 +41,28 @@ impl From<i32> for Register {
36
41
37
42
impl From < usize > for Register {
38
43
fn from ( value : usize ) -> Register {
39
- // Note: clippy is wrong here; transmute has different semantics than
40
- // `as` casts under strict provenance.
41
- #[ allow( clippy:: useless_transmute) ]
42
- // We want to convert using the same semantics as core::ptr::invalid:
43
- // convert the usize into a pointer with that address without attaching
44
- // provenance to it. However, core::ptr::invalid is a nightly-only
45
- // function. In order to build on stable, we copy its implementation.
46
- // Safety: Raw pointers do not have any validity invariants that usize
47
- // does not have; a raw pointer can point to any address.
48
- Register ( unsafe { transmute ( value) } )
44
+ // TODO(Rust 1.84): We want to convert using the same semantics as
45
+ // core::ptr::without_provenance. However, until our MSRV is >= 1.84, we
46
+ // have to use an `as` cast instead. This may result in this Register
47
+ // converting into a pointer with provenance later on, but that
48
+ // shouldn't break any users of Register in practice.
49
+ #[ cfg( not( miri) ) ]
50
+ {
51
+ Register ( value as * mut ( ) )
52
+ }
53
+ // However, on Miri, we cannot do the conversion using an `as` cast.
54
+ // Fortunately, since Miri runs on nightly Rust, we can use
55
+ // `without_provenance_mut`.
56
+ #[ cfg( miri) ]
57
+ {
58
+ Register ( core:: ptr:: without_provenance_mut ( value) )
59
+ }
49
60
}
50
61
}
51
62
52
63
impl < T > From < * mut T > for Register {
53
64
fn from ( value : * mut T ) -> Register {
54
- Register ( value as * mut ( ) )
65
+ Register ( value. cast ( ) )
55
66
}
56
67
}
57
68
@@ -89,13 +100,17 @@ impl Register {
89
100
90
101
impl From < Register > for usize {
91
102
fn from ( register : Register ) -> usize {
103
+ // TODO(Rust 1.84): We want to convert using the same semantics as
104
+ // .addr(). Until our MSRV is >= 1.84, we have to convert using an `as`
105
+ // cast instead. This exposes the provenance of the pointer, which is
106
+ // not correct but shouldn't break any users in practice.
92
107
register. 0 as usize
93
108
}
94
109
}
95
110
96
111
impl < T > From < Register > for * mut T {
97
112
fn from ( register : Register ) -> * mut T {
98
- register. 0 as * mut T
113
+ register. 0 . cast ( )
99
114
}
100
115
}
101
116
@@ -116,6 +131,6 @@ impl TryFrom<Register> for u32 {
116
131
type Error = core:: num:: TryFromIntError ;
117
132
118
133
fn try_from ( register : Register ) -> Result < u32 , core:: num:: TryFromIntError > {
119
- ( register. 0 as usize ) . try_into ( )
134
+ usize :: from ( register) . try_into ( )
120
135
}
121
136
}
0 commit comments