@@ -233,15 +233,123 @@ impl SvsmPlatform for NativePlatform {
233233 Ok ( ( ) )
234234 }
235235
236- unsafe fn mmio_write ( & self , _paddr : PhysAddr , _data : & [ u8 ] ) -> Result < ( ) , SvsmError > {
237- unimplemented ! ( )
236+ /// Perform a write to a memory-mapped IO area
237+ ///
238+ /// This function expects data to be 1, 2, 4 or 8 bytes long.
239+ ///
240+ /// It is not possible to loop and write one byte at a time because mmio devices (e.g., those emulated by QEMU)
241+ /// expect certain registers to be written with a single operation. Using a generic on SvsmPlatform is
242+ /// not possible because it uses the dyn trait.
243+ ///
244+ /// # Safety
245+ ///
246+ /// Caller must ensure that `vaddr` points to a properly aligned memory location and the
247+ /// memory accessed is part of a valid MMIO range.
248+ unsafe fn mmio_write ( & self , vaddr : VirtAddr , data : & [ u8 ] ) -> Result < ( ) , SvsmError > {
249+ match data. len ( ) {
250+ 1 => {
251+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
252+ unsafe {
253+ mmio_write_type :: < u8 > ( vaddr, data) ;
254+ }
255+ }
256+ 2 => {
257+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
258+ unsafe {
259+ mmio_write_type :: < u16 > ( vaddr, data) ;
260+ }
261+ }
262+ 4 => {
263+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
264+ unsafe {
265+ mmio_write_type :: < u32 > ( vaddr, data) ;
266+ }
267+ }
268+ 8 => {
269+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
270+ unsafe {
271+ mmio_write_type :: < u64 > ( vaddr, data) ;
272+ }
273+ }
274+ _ => return Err ( SvsmError :: InvalidBytes ) ,
275+ } ;
276+
277+ Ok ( ( ) )
238278 }
239279
280+ /// Perform a read from a memory-mapped IO area
281+ ///
282+ /// This function expects reads to be 1, 2, 4 or 8 bytes long.
283+ ///
284+ /// It is not possible to loop and read one byte at a time because mmio devices (e.g., those emulated by QEMU)
285+ /// expect certain registers to be read with a single operation. Using a generic on SvsmPlatform is
286+ /// not possible because it uses the dyn trait.
287+ ///
288+ /// # Safety
289+ ///
290+ /// Caller must ensure that `vaddr` points to a properly aligned memory location and the
291+ /// memory accessed is part of a valid MMIO range.
240292 unsafe fn mmio_read (
241293 & self ,
242- _paddr : PhysAddr ,
243- _data : & mut [ MaybeUninit < u8 > ] ,
294+ vaddr : VirtAddr ,
295+ data : & mut [ MaybeUninit < u8 > ] ,
244296 ) -> Result < ( ) , SvsmError > {
245- unimplemented ! ( )
297+ match data. len ( ) {
298+ 1 => {
299+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
300+ unsafe {
301+ mmio_read_type :: < u8 > ( vaddr, data) ;
302+ }
303+ }
304+ 2 => {
305+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
306+ unsafe {
307+ mmio_read_type :: < u16 > ( vaddr, data) ;
308+ }
309+ }
310+ 4 => {
311+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
312+ unsafe {
313+ mmio_read_type :: < u32 > ( vaddr, data) ;
314+ }
315+ }
316+ 8 => {
317+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
318+ unsafe {
319+ mmio_read_type :: < u64 > ( vaddr, data) ;
320+ }
321+ }
322+ _ => return Err ( SvsmError :: InvalidBytes ) ,
323+ } ;
324+
325+ Ok ( ( ) )
246326 }
247327}
328+
329+ unsafe fn mmio_write_type < T : Copy > ( vaddr : VirtAddr , data : & [ u8 ] ) {
330+ let data_ptr = data. as_ptr ( ) . cast :: < T > ( ) ;
331+ let ptr = vaddr. as_mut_ptr :: < T > ( ) ;
332+
333+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
334+ unsafe {
335+ if data_ptr. is_aligned ( ) {
336+ ptr. write_volatile ( data_ptr. read ( ) ) ;
337+ } else {
338+ ptr. write_volatile ( data_ptr. read_unaligned ( ) ) ;
339+ }
340+ } ;
341+ }
342+
343+ unsafe fn mmio_read_type < T > ( vaddr : VirtAddr , data : & mut [ MaybeUninit < u8 > ] ) {
344+ let data_ptr = data. as_mut_ptr ( ) . cast :: < T > ( ) ;
345+ let ptr = vaddr. as_mut_ptr :: < T > ( ) ;
346+
347+ // SAFETY: We are trusting the caller to ensure validity of `vaddr`.
348+ unsafe {
349+ if data_ptr. is_aligned ( ) {
350+ data_ptr. write ( ptr. read_volatile ( ) ) ;
351+ } else {
352+ data_ptr. write_unaligned ( ptr. read_volatile ( ) ) ;
353+ }
354+ } ;
355+ }
0 commit comments