@@ -89,7 +89,24 @@ impl MmioDriver {
8989 }
9090}
9191
92- unsafe fn check_ptr ( ptr : * mut u8 ) -> Option < VolatileRef < ' static , DeviceRegisters > > {
92+ unsafe fn check_ptr (
93+ virtual_address : VirtAddr ,
94+ current_address : usize ,
95+ ) -> Option < VolatileRef < ' static , DeviceRegisters > > {
96+ trace ! ( "try to detect MMIO device at physical address {current_address:#X}" ) ;
97+
98+ let mut flags = PageTableEntryFlags :: empty ( ) ;
99+ flags. normal ( ) . writable ( ) ;
100+ paging:: map :: < BasePageSize > (
101+ virtual_address,
102+ PhysAddr :: from ( current_address. align_down ( BasePageSize :: SIZE as usize ) ) ,
103+ 1 ,
104+ flags,
105+ ) ;
106+
107+ let addr = virtual_address. as_usize ( ) | ( current_address & ( BasePageSize :: SIZE as usize - 1 ) ) ;
108+ let ptr = ptr:: with_exposed_provenance_mut :: < u8 > ( addr) ;
109+
93110 // Verify the first register value to find out if this is really an MMIO magic-value.
94111 let mmio = unsafe { VolatileRef :: new ( NonNull :: new ( ptr. cast :: < DeviceRegisters > ( ) ) . unwrap ( ) ) } ;
95112
@@ -114,16 +131,21 @@ unsafe fn check_ptr(ptr: *mut u8) -> Option<VolatileRef<'static, DeviceRegisters
114131
115132 info ! ( "Found Virtio {id:?} device: {mmio:p}" ) ;
116133
134+ if cfg ! ( debug_assertions) {
135+ let len = usize:: try_from ( BasePageSize :: SIZE ) . unwrap ( ) ;
136+ let start = current_address. align_down ( len) ;
137+ let frame_range = PageRange :: from_start_len ( start, len) . unwrap ( ) ;
138+
139+ FrameAlloc :: allocate_at ( frame_range) . unwrap_err ( ) ;
140+ }
141+
117142 Some ( mmio)
118143}
119144
120145fn check_linux_args (
121146 linux_mmio : & ' static [ String ] ,
147+ virtual_address : VirtAddr ,
122148) -> Vec < ( VolatileRef < ' static , DeviceRegisters > , u8 ) > {
123- let layout = PageLayout :: from_size ( BasePageSize :: SIZE as usize ) . unwrap ( ) ;
124- let page_range = PageBox :: new ( layout) . unwrap ( ) ;
125- let virtual_address = VirtAddr :: from ( page_range. start ( ) ) ;
126-
127149 let mut devices = vec ! [ ] ;
128150 for arg in linux_mmio {
129151 trace ! ( "check linux parameter: {arg}" ) ;
@@ -135,32 +157,10 @@ fn check_linux_args(
135157 let current_address = usize:: from_str_radix ( without_prefix, 16 ) . unwrap ( ) ;
136158 let irq: u8 = v[ 1 ] . parse :: < u8 > ( ) . unwrap ( ) ;
137159
138- trace ! ( "try to detect MMIO device at physical address {current_address:#X}" ) ;
139-
140- let mut flags = PageTableEntryFlags :: empty ( ) ;
141- flags. normal ( ) . writable ( ) ;
142- paging:: map :: < BasePageSize > (
143- virtual_address,
144- PhysAddr :: from ( current_address. align_down ( BasePageSize :: SIZE as usize ) ) ,
145- 1 ,
146- flags,
147- ) ;
148-
149- let addr = virtual_address. as_usize ( )
150- | ( current_address & ( BasePageSize :: SIZE as usize - 1 ) ) ;
151- let ptr = ptr:: with_exposed_provenance_mut ( addr) ;
152- let Some ( mmio) = ( unsafe { check_ptr ( ptr) } ) else {
160+ let Some ( mmio) = ( unsafe { check_ptr ( virtual_address, current_address) } ) else {
153161 continue ;
154162 } ;
155163
156- if cfg ! ( debug_assertions) {
157- let len = usize:: try_from ( BasePageSize :: SIZE ) . unwrap ( ) ;
158- let start = current_address. align_down ( len) ;
159- let frame_range = PageRange :: from_start_len ( start, len) . unwrap ( ) ;
160-
161- FrameAlloc :: allocate_at ( frame_range) . unwrap_err ( ) ;
162- }
163-
164164 devices. push ( ( mmio, irq) ) ;
165165 }
166166 _ => {
@@ -172,64 +172,44 @@ fn check_linux_args(
172172 devices
173173}
174174
175- fn guess_device ( ) -> Vec < ( VolatileRef < ' static , DeviceRegisters > , u8 ) > {
175+ fn guess_device ( virtual_address : VirtAddr ) -> Vec < ( VolatileRef < ' static , DeviceRegisters > , u8 ) > {
176176 // Trigger page mapping in the first iteration!
177177 let mut current_page = 0 ;
178- let layout = PageLayout :: from_size ( BasePageSize :: SIZE as usize ) . unwrap ( ) ;
179- let page_range = PageBox :: new ( layout) . unwrap ( ) ;
180- let virtual_address = VirtAddr :: from ( page_range. start ( ) ) ;
181178
182179 // Look for the device-ID in all possible 64-byte aligned addresses within this range.
183180 let mut devices = vec ! [ ] ;
184181 for current_address in ( MMIO_START ..MMIO_END ) . step_by ( 512 ) {
185- trace ! ( "try to detect MMIO device at physical address {current_address:#X}" ) ;
186182 // Have we crossed a page boundary in the last iteration?
187183 // info!("before the {}. paging", current_page);
188184 if current_address / BasePageSize :: SIZE as usize > current_page {
189185 if !devices. is_empty ( ) {
190186 return devices;
191187 }
192188
193- let mut flags = PageTableEntryFlags :: empty ( ) ;
194- flags. normal ( ) . writable ( ) ;
195- paging:: map :: < BasePageSize > (
196- virtual_address,
197- PhysAddr :: from ( current_address. align_down ( BasePageSize :: SIZE as usize ) ) ,
198- 1 ,
199- flags,
200- ) ;
201-
202189 current_page = current_address / BasePageSize :: SIZE as usize ;
203190 }
204191
205- let addr =
206- virtual_address. as_usize ( ) | ( current_address & ( BasePageSize :: SIZE as usize - 1 ) ) ;
207- let ptr = ptr:: with_exposed_provenance_mut ( addr) ;
208- let Some ( mmio) = ( unsafe { check_ptr ( ptr) } ) else {
192+ let Some ( mmio) = ( unsafe { check_ptr ( virtual_address, current_address) } ) else {
209193 continue ;
210194 } ;
211195
212- if cfg ! ( debug_assertions) {
213- let len = usize:: try_from ( BasePageSize :: SIZE ) . unwrap ( ) ;
214- let start = current_address. align_down ( len) ;
215- let frame_range = PageRange :: from_start_len ( start, len) . unwrap ( ) ;
216-
217- FrameAlloc :: allocate_at ( frame_range) . unwrap_err ( ) ;
218- }
219-
220196 devices. push ( ( mmio, IRQ_NUMBER ) ) ;
221197 }
222198
223199 devices
224200}
225201
226202fn detect_devices ( ) -> Vec < ( VolatileRef < ' static , DeviceRegisters > , u8 ) > {
203+ let layout = PageLayout :: from_size ( BasePageSize :: SIZE as usize ) . unwrap ( ) ;
204+ let page_range = PageBox :: new ( layout) . unwrap ( ) ;
205+ let virtual_address = VirtAddr :: from ( page_range. start ( ) ) ;
206+
227207 let linux_mmio = env:: mmio ( ) ;
228208
229209 if linux_mmio. is_empty ( ) {
230- guess_device ( )
210+ guess_device ( virtual_address )
231211 } else {
232- check_linux_args ( linux_mmio)
212+ check_linux_args ( linux_mmio, virtual_address )
233213 }
234214}
235215
0 commit comments