In the kernel's early stages we access physical memory identity-mapped, so it's not very good for us to allocate that frame and then try to use it.
107 lines
3.7 KiB
Zig
107 lines
3.7 KiB
Zig
const std = @import("std");
|
|
const easyboot = @cImport(@cInclude("easyboot.h"));
|
|
const platform = @import("arch/platform.zig").arch;
|
|
const mmap = @import("mmap.zig");
|
|
const bmap = @import("lib/bitmap.zig");
|
|
|
|
const FrameAllocatorError = error{
|
|
InvalidMemoryMap,
|
|
MemoryAlreadyInUse,
|
|
MemoryNotInUse,
|
|
OutOfMemory,
|
|
};
|
|
|
|
pub const FrameAllocator = struct {
|
|
bitmap: bmap.Bitmap,
|
|
free_memory: u64,
|
|
used_memory: u64,
|
|
reserved_memory: u64,
|
|
start_index: usize,
|
|
};
|
|
|
|
pub const PhysFrame = struct {
|
|
address: usize,
|
|
|
|
pub fn virtualAddress(self: *const PhysFrame, base: usize) usize {
|
|
return base + self.address;
|
|
}
|
|
};
|
|
|
|
pub fn lockFrame(allocator: *FrameAllocator, address: usize) !void {
|
|
const index = address / platform.PAGE_SIZE;
|
|
if (try allocator.bitmap.get(index) == 1) return error.MemoryAlreadyInUse;
|
|
try allocator.bitmap.set(index, 1);
|
|
allocator.used_memory += platform.PAGE_SIZE;
|
|
allocator.free_memory -= platform.PAGE_SIZE;
|
|
}
|
|
|
|
pub fn lockFrames(allocator: *FrameAllocator, address: usize, pages: usize) !void {
|
|
var index: usize = 0;
|
|
while (index < pages) : (index += 1) {
|
|
try lockFrame(allocator, address + (index * platform.PAGE_SIZE));
|
|
}
|
|
}
|
|
|
|
pub fn freeFrame(allocator: *FrameAllocator, address: usize) !void {
|
|
const index = address / platform.PAGE_SIZE;
|
|
if (try allocator.bitmap.get(index) == 0) return error.MemoryNotInUse;
|
|
try allocator.bitmap.set(index, 0);
|
|
allocator.used_memory -= platform.PAGE_SIZE;
|
|
allocator.free_memory += platform.PAGE_SIZE;
|
|
|
|
if (allocator.start_index > index) allocator.start_index = index;
|
|
}
|
|
|
|
pub fn freeFrames(allocator: *FrameAllocator, address: usize, pages: usize) !void {
|
|
const index: usize = 0;
|
|
while (index < pages) : (index += 1) {
|
|
try freeFrame(allocator, address + (index * platform.PAGE_SIZE));
|
|
}
|
|
}
|
|
|
|
pub fn allocFrame(allocator: *FrameAllocator) !PhysFrame {
|
|
const index: usize = try bmap.findInBitmap(&allocator.bitmap, 0, allocator.start_index) orelse return error.OutOfMemory;
|
|
const address = index * platform.PAGE_SIZE;
|
|
try lockFrame(allocator, address);
|
|
|
|
allocator.start_index = index + 1;
|
|
|
|
return PhysFrame{ .address = address };
|
|
}
|
|
|
|
pub fn initializeFrameAllocator(tag: *easyboot.multiboot_tag_mmap_t) !FrameAllocator {
|
|
const largest_free = mmap.findLargestFreeEntry(tag) orelse return error.InvalidMemoryMap;
|
|
const physical_address_space_size = mmap.getAddressSpaceSize(tag) orelse return error.InvalidMemoryMap;
|
|
|
|
const bitmap_base_address: [*]u8 = @ptrFromInt(largest_free.base_addr);
|
|
|
|
const bitmap_bit_size = physical_address_space_size / @as(usize, platform.PAGE_SIZE);
|
|
const bitmap_size: usize = try std.math.divCeil(usize, bitmap_bit_size, 8);
|
|
|
|
var allocator: FrameAllocator = FrameAllocator{ .bitmap = bmap.createBitmap(bitmap_base_address, bitmap_size), .free_memory = 0, .used_memory = 0, .reserved_memory = 0, .start_index = 0 };
|
|
|
|
allocator.bitmap.clear(1); // Set all pages to used/reserved by default, then clear out the free ones
|
|
|
|
var iter = mmap.createMemoryMapIterator(tag);
|
|
while (iter.next()) |entry| {
|
|
const index = entry.base_addr / platform.PAGE_SIZE;
|
|
const pages = entry.length / platform.PAGE_SIZE;
|
|
|
|
if (entry.type != easyboot.MULTIBOOT_MEMORY_AVAILABLE) {
|
|
allocator.reserved_memory += entry.length;
|
|
continue;
|
|
}
|
|
|
|
allocator.free_memory += entry.length;
|
|
try bmap.updateBitmapRegion(&allocator.bitmap, index, pages, 0);
|
|
}
|
|
|
|
const frames_to_lock = try std.math.divCeil(usize, bitmap_size, platform.PAGE_SIZE);
|
|
try lockFrames(&allocator, @intFromPtr(bitmap_base_address), frames_to_lock);
|
|
|
|
// Avoid causing trouble.
|
|
try lockFrame(&allocator, 0);
|
|
|
|
return allocator;
|
|
}
|