33//! AMI driver is used to issue gcq command to the RPU
44//! Those command are used for configuration and register R/W
55use lazy_static:: lazy_static;
6- use libc;
76use std:: error:: Error ;
87use std:: fs:: { File , OpenOptions } ;
98use std:: io:: { BufRead , BufReader , Read } ;
109use std:: os:: fd:: AsRawFd ;
1110use std:: ptr:: NonNull ;
1211use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
1312use std:: time:: Duration ;
13+ use nix:: sys:: mman:: { mmap, munmap, MapFlags , ProtFlags } ;
14+ use std:: num:: NonZero ;
15+ use std:: os:: unix:: fs:: OpenOptionsExt ;
1416
1517const AMI_VERSION_FILE : & str = "/sys/module/ami/version" ;
1618const AMI_VERSION_PATTERN : & str = r"3\.2\.\d+-zama" ;
@@ -81,6 +83,7 @@ impl AmiInfo {
8183
8284pub struct AmiDriver {
8385 ami_dev : File ,
86+ bar_reg_ptr : Option < NonNull < u8 > > ,
8487 iop_ack_atomic_ptr : NonNull < AtomicU32 > ,
8588 retry_rate : Duration ,
8689}
@@ -100,6 +103,7 @@ impl AmiDriver {
100103 . read ( true )
101104 . write ( true )
102105 . create ( false )
106+ . custom_flags ( libc:: O_SYNC )
103107 . open ( ami_path) ?;
104108
105109 let ami_proc_path = format ! ( "/proc/ami_iop_ack_{}" , ami_info. devn) ;
@@ -109,43 +113,56 @@ impl AmiDriver {
109113 . create ( false )
110114 . open ( & ami_proc_path)
111115 . unwrap ( ) ;
112- unsafe {
113- let addr = libc:: mmap (
114- std:: ptr:: null_mut ( ) ,
115- 4096 ,
116- libc:: PROT_READ | libc:: PROT_WRITE ,
117- libc:: MAP_SHARED ,
118- ami_proc. as_raw_fd ( ) ,
116+
117+ let addr = unsafe {
118+ mmap (
119+ None ,
120+ NonZero :: new ( 4096 as usize ) . unwrap ( ) ,
121+ ProtFlags :: PROT_READ | ProtFlags :: PROT_WRITE ,
122+ MapFlags :: MAP_SHARED ,
123+ & ami_proc,
119124 0 ,
120- ) ;
125+ ) ?
126+ } ;
121127
122- if addr == libc:: MAP_FAILED {
123- return Err ( format ! ( "mmap on ami_iop_ack_{} failed" , ami_info. devn) . into ( ) ) ;
124- }
128+ let iop_ack_atomic_ptr: NonNull < AtomicU32 > = addr. cast ( ) ;
125129
126- Ok ( Self {
127- ami_dev,
128- iop_ack_atomic_ptr : NonNull :: new_unchecked ( addr as * mut AtomicU32 ) ,
129- retry_rate,
130- } )
131- }
130+ Ok ( Self {
131+ ami_dev,
132+ bar_reg_ptr : None ,
133+ iop_ack_atomic_ptr,
134+ retry_rate,
135+ } )
136+ }
137+
138+ pub fn map_bar_reg ( & mut self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
139+ let length: usize = 0x140000 ;
140+
141+ let map_addr = unsafe {
142+ mmap (
143+ None ,
144+ NonZero :: new ( length) . unwrap ( ) ,
145+ ProtFlags :: PROT_READ | ProtFlags :: PROT_WRITE , // Read & Write
146+ MapFlags :: MAP_SHARED ,
147+ & self . ami_dev ,
148+ 0 , // Offset in BAR0
149+ ) ?
150+ } ;
151+ tracing:: info!( "mapping HPU BAR0 at address -> {:p}" , map_addr) ;
152+
153+ let bar_addr: NonNull < u8 > = map_addr. cast ( ) ;
154+ self . bar_reg_ptr = Some ( bar_addr) ;
155+
156+ Ok ( ( ) )
132157 }
133158
159+
134160 pub fn munmap_cnt ( & self ) -> Result < ( ) , Box < dyn Error > > {
135- let cnt_addr = self . iop_ack_atomic_ptr . as_ptr ( ) as * mut libc :: c_void ;
161+ let cnt_addr = self . iop_ack_atomic_ptr . cast ( ) ;
136162 unsafe {
137- let retc = libc:: munmap ( cnt_addr, 4096 ) ;
138-
139- if retc == 0 {
140- Ok ( ( ) )
141- } else {
142- Err ( format ! (
143- "Could not unmap the atomic shared cnt (mumap returned {})" ,
144- retc
145- )
146- . into ( ) )
147- }
163+ munmap ( cnt_addr, 4096 ) ?;
148164 }
165+ Ok ( ( ) )
149166 }
150167
151168 /// Read currently loaded UUID in BAR
@@ -276,24 +293,32 @@ impl AmiDriver {
276293 let data = Box :: < u32 > :: new ( 0xdeadc0de ) ;
277294 let data_ptr = Box :: into_raw ( data) ;
278295
279- // Populate payload
280- let payload = AmiPeakPokePayload {
281- data_ptr,
282- len : 0x1 ,
283- offset : addr as u32 ,
284- } ;
285-
286- tracing:: trace!( "AMI: Read request with following payload {payload:x?}" ) ;
287- loop {
288- let ret = unsafe { ami_peak ( ami_fd, & payload) } ;
289- match ret {
290- Err ( err) => {
291- tracing:: debug!( "AMI: Read failed -> {err:?}" ) ;
292- std:: thread:: sleep ( self . retry_rate ) ;
293- }
294- Ok ( val) => {
295- tracing:: trace!( "AMI: Read ack received {payload:x?} -> {val:?}" ) ;
296- break ;
296+ if let Some ( base) = self . bar_reg_ptr {
297+ unsafe {
298+ let raw_base = base. as_ptr ( ) ;
299+ let reg_ptr = raw_base. add ( ( addr + 0x100000 ) . try_into ( ) . unwrap ( ) ) as * const u32 ;
300+ * data_ptr = std:: ptr:: read_volatile ( reg_ptr) ;
301+ }
302+ } else {
303+ // Populate payload
304+ let payload = AmiPeakPokePayload {
305+ data_ptr,
306+ len : 0x1 ,
307+ offset : addr as u32 ,
308+ } ;
309+
310+ tracing:: trace!( "AMI: Read request with following payload {payload:x?}" ) ;
311+ loop {
312+ let ret = unsafe { ami_peak ( ami_fd, & payload) } ;
313+ match ret {
314+ Err ( err) => {
315+ tracing:: debug!( "AMI: Read failed -> {err:?}" ) ;
316+ std:: thread:: sleep ( self . retry_rate ) ;
317+ }
318+ Ok ( val) => {
319+ tracing:: trace!( "AMI: Read ack received {payload:x?} -> {val:?}" ) ;
320+ break ;
321+ }
297322 }
298323 }
299324 }
@@ -307,24 +332,32 @@ impl AmiDriver {
307332 let data = Box :: < u32 > :: new ( value) ;
308333 let data_ptr = Box :: into_raw ( data) ;
309334
310- // Populate payload
311- let payload = AmiPeakPokePayload {
312- data_ptr,
313- len : 0x1 ,
314- offset : addr as u32 ,
315- } ;
316-
317- tracing:: trace!( "AMI: Write request with following payload {payload:x?}" ) ;
318- loop {
319- let ret = unsafe { ami_poke ( ami_fd, & payload) } ;
320- match ret {
321- Err ( err) => {
322- tracing:: debug!( "AMI: Write failed -> {err:?}" ) ;
323- std:: thread:: sleep ( self . retry_rate ) ;
324- }
325- Ok ( val) => {
326- tracing:: trace!( "AMI: Write ack received {payload:x?} -> {val:?}" ) ;
327- break ;
335+ if let Some ( base) = self . bar_reg_ptr {
336+ unsafe {
337+ let raw_base = base. as_ptr ( ) ;
338+ let reg_ptr = raw_base. add ( ( addr + 0x100000 ) . try_into ( ) . unwrap ( ) ) as * mut u32 ;
339+ std:: ptr:: write_volatile ( reg_ptr, value) ;
340+ }
341+ } else {
342+ // Populate payload
343+ let payload = AmiPeakPokePayload {
344+ data_ptr,
345+ len : 0x1 ,
346+ offset : addr as u32 ,
347+ } ;
348+
349+ tracing:: trace!( "AMI: Write request with following payload {payload:x?}" ) ;
350+ loop {
351+ let ret = unsafe { ami_poke ( ami_fd, & payload) } ;
352+ match ret {
353+ Err ( err) => {
354+ tracing:: debug!( "AMI: Write failed -> {err:?}" ) ;
355+ std:: thread:: sleep ( self . retry_rate ) ;
356+ }
357+ Ok ( val) => {
358+ tracing:: trace!( "AMI: Write ack received {payload:x?} -> {val:?}" ) ;
359+ break ;
360+ }
328361 }
329362 }
330363 }
0 commit comments