@@ -17,6 +17,7 @@ use kernel::{
1717 } ,
1818 new_mutex,
1919 prelude:: * ,
20+ ptr,
2021 sync:: {
2122 aref:: ARef ,
2223 Mutex , //
@@ -255,37 +256,46 @@ impl DmaGspMem {
255256 /// As the message queue is a circular buffer, the region may be discontiguous in memory. In
256257 /// that case the second slice will have a non-zero length.
257258 fn driver_write_area ( & mut self ) -> ( & mut [ [ u8 ; GSP_PAGE_SIZE ] ] , & mut [ [ u8 ; GSP_PAGE_SIZE ] ] ) {
258- let tx = self . cpu_write_ptr ( ) as usize ;
259- let rx = self . gsp_read_ptr ( ) as usize ;
259+ let tx = self . cpu_write_ptr ( ) ;
260+ let rx = self . gsp_read_ptr ( ) ;
260261
261- // SAFETY:
262- // - We will only access the driver-owned part of the shared memory.
263- // - Per the safety statement of the function, no concurrent access will be performed.
264- let gsp_mem = unsafe { & mut * self . 0 . as_mut ( ) } ;
265- // PANIC: per the invariant of `cpu_write_ptr`, `tx` is `< MSGQ_NUM_PAGES`.
266- let ( before_tx, after_tx) = gsp_mem. cpuq . msgq . data . split_at_mut ( tx) ;
267-
268- // The area starting at `tx` and ending at `rx - 2` modulo MSGQ_NUM_PAGES, inclusive,
269- // belongs to the driver for writing.
270-
271- if rx == 0 {
272- // Since `rx` is zero, leave an empty slot at end of the buffer.
273- let last = after_tx. len ( ) - 1 ;
274- ( & mut after_tx[ ..last] , & mut [ ] )
262+ // Pointer to the first entry of the CPU message queue.
263+ let data = ptr:: project!( mut self . 0 . as_mut_ptr( ) , . cpuq. msgq. data[ 0 ] ) ;
264+
265+ let ( tail_end, wrap_end) = if rx == 0 {
266+ // The write area is non-wrapping, and stops at the second-to-last entry of the command
267+ // queue (to leave the last one empty).
268+ ( MSGQ_NUM_PAGES - 1 , 0 )
275269 } else if rx <= tx {
276- // The area is discontiguous and we leave an empty slot before `rx`.
277- // PANIC:
278- // - The index `rx - 1` is non-negative because `rx != 0` in this branch.
279- // - The index does not exceed `before_tx.len()` (which equals `tx`) because
280- // `rx <= tx` in this branch.
281- ( after_tx, & mut before_tx[ ..( rx - 1 ) ] )
270+ // The write area wraps and continues until `rx - 1`.
271+ ( MSGQ_NUM_PAGES , rx - 1 )
282272 } else {
283- // The area is contiguous and we leave an empty slot before `rx`.
284- // PANIC:
285- // - The index `rx - tx - 1` is non-negative because `rx > tx` in this branch.
286- // - The index does not exceed `after_tx.len()` (which is `MSGQ_NUM_PAGES - tx`)
287- // because `rx < MSGQ_NUM_PAGES` by the `gsp_read_ptr` invariant.
288- ( & mut after_tx[ ..( rx - tx - 1 ) ] , & mut [ ] )
273+ // The write area doesn't wrap and stops at `rx - 1`.
274+ ( rx - 1 , 0 )
275+ } ;
276+
277+ // SAFETY:
278+ // - `data` was created from a valid pointer, and `rx` and `tx` are in the
279+ // `0..MSGQ_NUM_PAGES` range per the invariants of `cpu_write_ptr` and `gsp_read_ptr`,
280+ // thus the created slices are valid.
281+ // - The area starting at `tx` and ending at `rx - 2` modulo `MSGQ_NUM_PAGES`,
282+ // inclusive, belongs to the driver for writing and is not accessed concurrently by
283+ // the GSP.
284+ // - The caller holds a reference to `self` for as long as the returned slices are live,
285+ // meaning the CPU write pointer cannot be advanced and thus that the returned area
286+ // remains exclusive to the CPU for the duration of the slices.
287+ // - The created slices point to non-overlapping sub-ranges of `data` in all
288+ // branches (in the `rx <= tx` case, the second slice ends at `rx - 1` which is strictly
289+ // less than `tx` where the first slice starts; in the other cases the second slice is
290+ // empty), so creating two `&mut` references from them does not violate aliasing rules.
291+ unsafe {
292+ (
293+ core:: slice:: from_raw_parts_mut (
294+ data. add ( num:: u32_as_usize ( tx) ) ,
295+ num:: u32_as_usize ( tail_end - tx) ,
296+ ) ,
297+ core:: slice:: from_raw_parts_mut ( data, num:: u32_as_usize ( wrap_end) ) ,
298+ )
289299 }
290300 }
291301
@@ -308,26 +318,38 @@ impl DmaGspMem {
308318 /// As the message queue is a circular buffer, the region may be discontiguous in memory. In
309319 /// that case the second slice will have a non-zero length.
310320 fn driver_read_area ( & self ) -> ( & [ [ u8 ; GSP_PAGE_SIZE ] ] , & [ [ u8 ; GSP_PAGE_SIZE ] ] ) {
311- let tx = self . gsp_write_ptr ( ) as usize ;
312- let rx = self . cpu_read_ptr ( ) as usize ;
321+ let tx = self . gsp_write_ptr ( ) ;
322+ let rx = self . cpu_read_ptr ( ) ;
313323
314- // SAFETY:
315- // - We will only access the driver-owned part of the shared memory.
316- // - Per the safety statement of the function, no concurrent access will be performed.
317- let gsp_mem = unsafe { & * self . 0 . as_ptr ( ) } ;
318- let data = & gsp_mem. gspq . msgq . data ;
319-
320- // The area starting at `rx` and ending at `tx - 1` modulo MSGQ_NUM_PAGES, inclusive,
321- // belongs to the driver for reading.
322- // PANIC:
323- // - per the invariant of `cpu_read_ptr`, `rx < MSGQ_NUM_PAGES`
324- // - per the invariant of `gsp_write_ptr`, `tx < MSGQ_NUM_PAGES`
325- if rx <= tx {
326- // The area is contiguous.
327- ( & data[ rx..tx] , & [ ] )
324+ // Pointer to the first entry of the GSP message queue.
325+ let data = ptr:: project!( self . 0 . as_ptr( ) , . gspq. msgq. data[ 0 ] ) ;
326+
327+ let ( tail_end, wrap_end) = if rx <= tx {
328+ // Read area is non-wrapping and stops right before `tx`.
329+ ( tx, 0 )
328330 } else {
329- // The area is discontiguous.
330- ( & data[ rx..] , & data[ ..tx] )
331+ // Read area is wrapping and stops right before `tx`.
332+ ( MSGQ_NUM_PAGES , tx)
333+ } ;
334+
335+ // SAFETY:
336+ // - `data` was created from a valid pointer, and `rx` and `tx` are in the
337+ // `0..MSGQ_NUM_PAGES` range per the invariants of `gsp_write_ptr` and `cpu_read_ptr`,
338+ // thus the created slices are valid.
339+ // - The area starting at `rx` and ending at `tx - 1` modulo `MSGQ_NUM_PAGES`,
340+ // inclusive, belongs to the driver for reading and is not accessed concurrently by
341+ // the GSP.
342+ // - The caller holds a reference to `self` for as long as the returned slices are live,
343+ // meaning the CPU read pointer cannot be advanced and thus that the returned area
344+ // remains exclusive to the CPU for the duration of the slices.
345+ unsafe {
346+ (
347+ core:: slice:: from_raw_parts (
348+ data. add ( num:: u32_as_usize ( rx) ) ,
349+ num:: u32_as_usize ( tail_end - rx) ,
350+ ) ,
351+ core:: slice:: from_raw_parts ( data, num:: u32_as_usize ( wrap_end) ) ,
352+ )
331353 }
332354 }
333355
0 commit comments