Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.12 KB | None | 0 0
  1. /// Sound MMIO requires **indirection**
  2. #[macro_use]
  3. mod mmio {
  4. use ::core::marker::PhantomData;
  5.  
  6. pub
  7. struct VolatileRef<'a, T : Copy + 'a> {
  8. ptr: *const T,
  9. lifetime: PhantomData<&'a T>,
  10. }
  11.  
  12. pub
  13. struct VolatileRefMut<'a, T : Copy + 'a> {
  14. ptr: *mut T,
  15. lifetime: PhantomData<&'a mut T>,
  16. }
  17.  
  18. impl<T : Copy> VolatileRef<'_, T> {
  19. #[inline]
  20. pub
  21. unsafe
  22. fn new (ptr: *const T) -> Self
  23. {
  24. Self { ptr, lifetime: PhantomData }
  25. }
  26.  
  27. #[inline]
  28. pub
  29. fn read (self: &'_ Self) -> T
  30. {
  31. unsafe { ::core::ptr::read_volatile(self.ptr) }
  32. }
  33. }
  34.  
  35. impl<T : Copy> VolatileRefMut<'_, T> {
  36. #[inline]
  37. pub
  38. unsafe
  39. fn new (ptr: *mut T) -> Self
  40. {
  41. Self { ptr, lifetime: PhantomData }
  42. }
  43.  
  44. #[inline]
  45. pub
  46. fn read (self: &'_ Self) -> T
  47. {
  48. unsafe { ::core::ptr::read_volatile(self.ptr) }
  49. }
  50.  
  51. #[inline]
  52. pub
  53. fn write (self: &'_ Self, value: T)
  54. {
  55. unsafe { ::core::ptr::write_volatile(self.ptr, value) }
  56. }
  57. }
  58.  
  59. macro_rules! mmio_struct {(
  60. #[repr(C)]
  61. $(#[$struct_meta:meta])*
  62. $struct_vis:vis
  63. struct $StructName:ident {
  64. $(
  65. $(#[doc = $docstring:tt])*
  66. $field_vis:vis
  67. $field_name:ident : $field_ty:ty
  68. ),* $(,)?
  69. }
  70. ) => (
  71. #[repr(C)]
  72. $(#[$struct_meta])*
  73. $struct_vis
  74. struct $StructName {
  75. _private: [u8; 0],
  76. }
  77.  
  78. mod offset_of {
  79. use super::*;
  80.  
  81. #[repr(C)]
  82. struct OffsetComputer {
  83. $(
  84. pub(in super)
  85. $field_name : $field_ty ,
  86. )*
  87. }
  88.  
  89. const OFFSET_COMPUTER: OffsetComputer = OffsetComputer {
  90. $(
  91. $field_name: 0,
  92. )*
  93. };
  94.  
  95. $(
  96. #[allow(bad_style)]
  97. pub(in super)
  98. const $field_name: usize = {
  99. let base = &OFFSET_COMPUTER;
  100. (
  101. &base.$field_name as *const $field_ty as usize
  102. ) - (
  103. base as *const OffsetComputer as usize
  104. )
  105. };
  106. )*
  107. }
  108.  
  109. impl $StructName {
  110. $(
  111. $(#[doc = $docstring])*
  112. $field_vis
  113. fn $field_name (self: &'_ mut Self)
  114. -> $crate::mmio::VolatileRefMut<'_, $field_ty>
  115. {
  116. unsafe {
  117. $crate::mmio::VolatileRefMut::<$field_ty>::new(
  118. (
  119. self
  120. as *mut Self
  121. as usize
  122. +
  123. offset_of::$field_name
  124. ) as *mut $field_ty
  125. )
  126. }
  127. }
  128. )*
  129. }
  130. )}
  131. }
  132.  
  133. /// SAFETY BOUNDARY
  134. /// It must not be possible to trigger UB with safe code outside this
  135. /// module
  136. mod library {
  137. #[repr(u32)]
  138. pub
  139. enum AuxPeripheral {
  140. MiniUART = 1,
  141. SPI1 = 2,
  142. SPI2 = 4
  143. }
  144.  
  145. mmio_struct! {
  146. #[repr(C)]
  147. struct Registers {
  148. /// read-only memory-mapped register
  149. pub aux_irq: u32,
  150.  
  151. /// read-write memory-mapped register
  152. pub aux_enb: u32,
  153. }
  154. }
  155.  
  156. const AUX_BASE_ADDR: *mut Registers = 0xfe000000 as _;
  157.  
  158. // struct invariant: singleton type, _i.e._, at most one instance of Aux at any
  159. // given time.
  160. pub
  161. struct Aux {
  162. registers: *mut Registers,
  163. }
  164.  
  165. /// # Safety
  166. ///
  167. /// - Given the invariant, there is no way in the public API to get aliasing
  168. /// &mut on AUX_BASE_ADDR registers.
  169. unsafe impl Sync for Aux {}
  170.  
  171. impl Aux {
  172. /// # Safety
  173. ///
  174. /// - must be called at most once
  175. const
  176. unsafe
  177. fn new_unchecked () -> Aux
  178. {
  179. Aux {
  180. registers: AUX_BASE_ADDR,
  181. }
  182. }
  183.  
  184. #[inline]
  185. fn registers (self: &'_ mut Self)
  186. -> &'_ mut Registers
  187. {
  188. unsafe {
  189. // # Safety
  190. //
  191. // - Singleton pattern guarantees unaliasing of the pointee
  192. &mut* self.registers
  193. }
  194. }
  195.  
  196. pub
  197. fn enable (self: &'_ mut Self, p: AuxPeripheral)
  198. {
  199. let aux_enb = self.registers().aux_enb();
  200. aux_enb.write(aux_enb.read() | p as u32);
  201. }
  202. }
  203.  
  204. pub
  205. static AUX: Aux = unsafe {
  206. Aux::new_unchecked()
  207. };
  208. }
  209.  
  210. use library::{
  211. AUX,
  212. AuxPeripheral,
  213. };
  214.  
  215. fn main ()
  216. {
  217. AUX.enable(AuxPeripheral::MiniUART);
  218. // UB attempt
  219. // let _ = library::Aux::new_unchecked();
  220. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement