page-table-arm 0.0.1

A library of arm page table
Documentation
#[cfg(test)]
mod test {
    extern crate std;

    use arch::PTE;
    use log::{info, LevelFilter};
    use page_table_interface::*;

    use super::*;

    fn init() {
        let _ = env_logger::builder()
            .filter_level(LevelFilter::Trace)
            .is_test(true)
            .try_init();
    }

    struct AcImpl;

    impl Access for AcImpl {
        unsafe fn alloc(&mut self, layout: core::alloc::Layout) -> Option<usize> {
            Some((std::alloc::alloc(layout) as usize).into())
        }

        unsafe fn dealloc(&mut self, ptr: usize, layout: core::alloc::Layout) {
            std::alloc::dealloc(ptr as _, layout)
        }

        fn va_offset(&self) -> usize {
            0
        }
    }

    #[test]
    fn test_l1() {
        unsafe {
            let mut access = AcImpl;
            let mut table =
                PageTableRef::<'_, PTE, 512, 4>::new_with_level(4, &mut access).unwrap();
            let vaddr = (0xffff_ffff_0000_0000usize + 50 * 0x1000) as _;
            let paddr = 0x1000;

            table
                .map(
                    &MapConfig {
                        vaddr,
                        paddr,
                        attrs: PageAttribute::Read | PageAttribute::Write,
                    },
                    1,
                    &mut access,
                )
                .unwrap();

            let pte = table.get_pte_mut(vaddr, &mut access);

            assert!(pte.is_some());

            assert!(pte.unwrap().paddr() == paddr)
        }
    }
    #[test]
    fn test_l2() {
        unsafe {
            let mut access = AcImpl;
            let mut table =
                PageTableRef::<'_, PTE, 512, 4>::new_with_level(4, &mut access).unwrap();
            let vaddr = (0xffff_ffff_0000_0000usize + 50 * 2 * 1024 * 1024) as _;
            let paddr = 0x1000;

            table
                .map(
                    &MapConfig {
                        vaddr,
                        paddr,
                        attrs: PageAttribute::Read | PageAttribute::Write,
                    },
                    2,
                    &mut access,
                )
                .unwrap();

            let pte = table.get_pte_mut(vaddr, &mut access);

            assert!(pte.is_some());

            assert!(pte.unwrap().paddr() == paddr)
        }
    }

    #[test]
    fn test_l3() {
        unsafe {
            let mut access = AcImpl;
            let mut table =
                PageTableRef::<'_, PTE, 512, 4>::new_with_level(4, &mut access).unwrap();
            let vaddr = (0xffff_ff00_0000_0000usize + 50 * 1024 * 1024 * 1024) as _;
            let paddr = 0x1000;

            table
                .map(
                    &MapConfig {
                        vaddr,
                        paddr,
                        attrs: PageAttribute::Read | PageAttribute::Write,
                    },
                    3,
                    &mut access,
                )
                .unwrap();

            let pte = table.get_pte_mut(vaddr, &mut access);

            assert!(pte.is_some());

            assert!(pte.unwrap().paddr() == paddr)
        }
    }

    #[test]
    fn test_table() {
        init();
        unsafe {
            let mut access = AcImpl;

            let table_l1 = PageTableRef::<'_, PTE, 512, 4>::new_with_level(1, &mut access).unwrap();
            info!("L1 entry_size = {:#X}", table_l1.entry_size());

            let mut table =
                PageTableRef::<'_, PTE, 512, 4>::new_with_level(4, &mut access).unwrap();

            let virt = (0xffff_ffff_0000_0000usize + 1024 * 1024 * 1024) as _;
            let phys = 0x1000;

            table
                .map(
                    &MapConfig {
                        vaddr: virt,
                        paddr: phys,
                        attrs: PageAttribute::Read | PageAttribute::Write,
                    },
                    2,
                    &mut access,
                )
                .unwrap();

            info!("created table");

            table.walk(
                |info| {
                    info!("L{} {:#X} {:?}", info.level, info.vaddr, info.pte);
                },
                &access,
            );

            info!("walk finish");

            let pte = table.get_pte_mut(virt, &mut access);

            info!("pte: {:?}", pte);

            assert!(pte.is_some());

            assert!(pte.unwrap().paddr() == phys.into())
        }
    }

    const BYTES_1G: usize = 1024 * 1024 * 1024;

    #[test]
    fn test_table_map_region() {
        init();
        unsafe {
            let mut access = AcImpl;
            let mut table =
                PageTableRef::<'_, PTE, 512, 4>::new_with_level(4, &mut access).unwrap();
            let va_offset = 0xffff_ff00_0000_0000;

            let phys_down = 0x4000_0000;
            let vphys_down = phys_down as *mut u8;
            let virt_down = vphys_down.add(va_offset);

            table
                .map_region(
                    MapConfig {
                        vaddr: vphys_down,
                        paddr: phys_down,
                        attrs: PageAttribute::Read | PageAttribute::Write | PageAttribute::Execute,
                    },
                    BYTES_1G,
                    true,
                    &mut access,
                )
                .unwrap();

            table
                .map_region(
                    MapConfig {
                        vaddr: virt_down,
                        paddr: phys_down,
                        attrs: PageAttribute::Read | PageAttribute::Write | PageAttribute::Execute,
                    },
                    BYTES_1G,
                    true,
                    &mut access,
                )
                .unwrap();

            info!("created table");

            table.walk(
                |info| {
                    info!("L{} {:#X} {:?}", info.level, info.vaddr, info.entry);
                },
                &access,
            );

            info!("walk finish");
        }
    }
}