Nothing to see here, move along
1use x86_64::PhysAddr;
2use x86_64::VirtAddr;
3use x86_64::structures::paging::{
4 Mapper, OffsetPageTable, Page, PageTableFlags, PhysFrame, Size4KiB,
5};
6
7use super::phys::BitmapFrameAllocator;
8
9pub fn map_mmio(
10 mapper: &mut OffsetPageTable,
11 allocator: &mut BitmapFrameAllocator,
12 phys: u64,
13 hhdm_offset: u64,
14) -> Result<(), crate::error::KernelError> {
15 let virt = VirtAddr::new(phys + hhdm_offset);
16 let page: Page<Size4KiB> = Page::containing_address(virt);
17 let frame = PhysFrame::containing_address(PhysAddr::new(phys));
18 let flags = PageTableFlags::PRESENT
19 | PageTableFlags::WRITABLE
20 | PageTableFlags::NO_CACHE
21 | PageTableFlags::WRITE_THROUGH
22 | PageTableFlags::NO_EXECUTE;
23
24 match unsafe { mapper.map_to(page, frame, flags, allocator) } {
25 Ok(flush) => {
26 flush.flush();
27 Ok(())
28 }
29 Err(x86_64::structures::paging::mapper::MapToError::PageAlreadyMapped(existing)) => {
30 if existing == frame {
31 Ok(())
32 } else {
33 Err(crate::error::KernelError::InvalidAddress)
34 }
35 }
36 Err(_) => Err(crate::error::KernelError::ResourceExhausted),
37 }
38}
39
40pub fn test_mapping(mapper: &mut OffsetPageTable, allocator: &mut BitmapFrameAllocator) {
41 let test_addr = VirtAddr::new(0xFFFF_FFFF_F000_0000);
42 let test_page: Page<Size4KiB> = Page::containing_address(test_addr);
43
44 let frame = allocator.allocate().expect("Failed to allocate test frame");
45
46 let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
47 let phys_frame = frame.inner();
48
49 unsafe {
50 mapper
51 .map_to(test_page, phys_frame, flags, allocator)
52 .expect("Failed to map test page")
53 .flush();
54 }
55
56 let ptr: *mut u64 = test_addr.as_mut_ptr();
57 unsafe { ptr.write_volatile(0xDEAD_BEEF_CAFE_BABE) };
58 let readback = unsafe { ptr.read_volatile() };
59 assert_eq!(
60 readback, 0xDEAD_BEEF_CAFE_BABE,
61 "Virtual memory test failed"
62 );
63
64 let (returned_frame, flush) = mapper.unmap(test_page).expect("Failed to unmap test page");
65 flush.flush();
66 allocator.deallocate_frame(returned_frame);
67
68 crate::kprintln!(" Virtual memory mapping test passed");
69}