Skip to content

Commit c0a96f7

Browse files
committed
refactor(mmio): deduplicate device mapping code
1 parent 5127c77 commit c0a96f7

1 file changed

Lines changed: 36 additions & 56 deletions

File tree

src/arch/x86_64/kernel/mmio.rs

Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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

120145
fn 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

226202
fn 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

Comments
 (0)