From 21d7f28fdc7c8ce1b8a83029a76ff39ecfe1fd92 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 7 Sep 2020 21:44:23 -0600 Subject: [PATCH] Allocate and clear buddy maps --- src/main.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1a3a6ca68c..41a729ed9d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -195,8 +195,7 @@ impl SlabAllocator { pub struct BuddyEntry { pub base: PhysicalAddress, pub size: usize, - pub map_phys: PhysicalAddress, - pub map_virt: VirtualAddress, + pub map: PhysicalAddress, } impl BuddyEntry { @@ -204,12 +203,18 @@ impl BuddyEntry { Self { base: PhysicalAddress::new(0), size: 0, - map_phys: PhysicalAddress::new(0), - map_virt: VirtualAddress::new(0), + map: PhysicalAddress::new(0), } } } +#[derive(Clone, Copy, Debug)] +#[repr(packed)] +pub struct BuddyMapFooter { + pub next: PhysicalAddress, + //TODO: index of last known free bit +} + pub struct BuddyAllocator { table_phys: PhysicalAddress, table_virt: VirtualAddress, @@ -217,6 +222,9 @@ pub struct BuddyAllocator { } impl BuddyAllocator { + const MAP_PAGE_BYTES: usize = (A::PAGE_SIZE - mem::size_of::()); + const MAP_PAGE_BITS: usize = Self::MAP_PAGE_BYTES * 8; + pub unsafe fn new(areas: &'static [MemoryArea], offset: usize) -> Option { // First, we need an allocator, so we can allocate the buddy tables // Since the tables are static, we can use the bump allocator @@ -267,7 +275,7 @@ impl BuddyAllocator { //TODO: sort areas? - //TODO: Allocate buddy maps + // Allocate buddy maps for i in 0 .. (A::PAGE_SIZE / mem::size_of::()) { let virt = table_virt.add(i * mem::size_of::()); let mut entry = A::read::(virt); @@ -276,16 +284,50 @@ impl BuddyAllocator { let pages = entry.size / A::PAGE_SIZE; println!(" pages: {}", pages); - let map_size = (pages + 7) / 8; - println!(" map size: {}", format_size(map_size)); + let map_pages = (pages + (Self::MAP_PAGE_BITS - 1)) / Self::MAP_PAGE_BITS; + println!(" map pages: {}", map_pages); + + for _ in 0 .. map_pages { + let map_phys = bump_allocator.allocate()?; + let map_virt = A::phys_to_virt(map_phys); + for i in 0..Self::MAP_PAGE_BYTES { + A::write(map_virt.add(i), 0); + } + A::write(map_virt.add(Self::MAP_PAGE_BYTES), BuddyMapFooter { + next: entry.map, + }); + entry.map = map_phys; + } } } - //TODO: mark areas used for static tables as used + // Mark unused areas as free + let mut area_offset = bump_allocator.offset; + for area in areas.iter() { + if area_offset < area.size { + area_offset = 0; + let area_base = area.base.add(offset); + let area_size = area.size - offset; + allocator.free(area_base, area_size); + } else { + area_offset -= area.size; + } + } Some(allocator) } + pub unsafe fn free(&mut self, base: PhysicalAddress, size: usize) { + for i in 0 .. (A::PAGE_SIZE / mem::size_of::()) { + let virt = self.table_virt.add(i * mem::size_of::()); + let entry = A::read::(virt); + if base >= entry.base && base.add(size) <= entry.base.add(entry.size) { + println!("{:X}:{:X} inside of {:X}:{:X}", base.data(), size, entry.base.data(), entry.size); + + //TODO + } + } + } } pub struct Mapper {