Allocate and clear buddy maps

This commit is contained in:
Jeremy Soller
2020-09-07 21:44:23 -06:00
parent d752c5c91e
commit 21d7f28fdc
+50 -8
View File
@@ -195,8 +195,7 @@ impl<A: Arch> SlabAllocator<A> {
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<A> {
table_phys: PhysicalAddress,
table_virt: VirtualAddress,
@@ -217,6 +222,9 @@ pub struct BuddyAllocator<A> {
}
impl<A: Arch> BuddyAllocator<A> {
const MAP_PAGE_BYTES: usize = (A::PAGE_SIZE - mem::size_of::<BuddyMapFooter>());
const MAP_PAGE_BITS: usize = Self::MAP_PAGE_BYTES * 8;
pub unsafe fn new(areas: &'static [MemoryArea], offset: usize) -> Option<Self> {
// 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<A: Arch> BuddyAllocator<A> {
//TODO: sort areas?
//TODO: Allocate buddy maps
// Allocate buddy maps
for i in 0 .. (A::PAGE_SIZE / mem::size_of::<BuddyEntry>()) {
let virt = table_virt.add(i * mem::size_of::<BuddyEntry>());
let mut entry = A::read::<BuddyEntry>(virt);
@@ -276,16 +284,50 @@ impl<A: Arch> BuddyAllocator<A> {
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::<BuddyEntry>()) {
let virt = self.table_virt.add(i * mem::size_of::<BuddyEntry>());
let entry = A::read::<BuddyEntry>(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<A> {