core: Reserve kernel physical pages + provide our own stack
This solves a very weird bug that occurred when we allocated a page that was already used for the stack.
This commit is contained in:
parent
d3231f1362
commit
c5876768c5
@ -1,3 +1,4 @@
|
||||
const std = @import("std");
|
||||
const gdt = @import("gdt.zig");
|
||||
const idt = @import("idt.zig");
|
||||
const pic = @import("pic.zig");
|
||||
@ -18,6 +19,21 @@ fn enableNX() void {
|
||||
);
|
||||
}
|
||||
|
||||
var stack: [PAGE_SIZE * 8]u8 = std.mem.zeroes([PAGE_SIZE * 8]u8);
|
||||
const top: usize = (PAGE_SIZE * 8) - 16;
|
||||
|
||||
pub inline fn _start() noreturn {
|
||||
asm volatile (
|
||||
\\ mov %[stack], %rsp
|
||||
\\ addq %[top], %rsp
|
||||
\\ call main
|
||||
:
|
||||
: [stack] "i" (&stack),
|
||||
[top] "i" (top),
|
||||
);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// Initialize platform-specific components.
|
||||
pub fn platformInit() void {
|
||||
gdt.setupGDT();
|
||||
|
@ -3,6 +3,7 @@ const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||
const mmap = @import("../../mmap.zig");
|
||||
const pmm = @import("../../pmm.zig");
|
||||
const platform = @import("platform.zig");
|
||||
const debug = @import("../debug.zig");
|
||||
|
||||
const USER_ADDRESS_RANGE_END = 0x0000_7fff_ffff_ffff;
|
||||
pub const PHYSICAL_MAPPING_BASE = 0xffff_8000_0000_0000;
|
||||
@ -151,6 +152,11 @@ pub fn getEntry(space: AddressSpace, base: usize, virt_address: u64) ?*PageTable
|
||||
return pt_entry;
|
||||
}
|
||||
|
||||
pub fn getAddress(space: AddressSpace, base: usize, virt_address: u64) ?usize {
|
||||
const entry = getEntry(space, base, virt_address) orelse return null;
|
||||
return entry.getAddress();
|
||||
}
|
||||
|
||||
pub fn copyToUser(space: AddressSpace, base: usize, user: usize, kernel: [*]const u8, size: usize) !void {
|
||||
const remainder: usize = @rem(user, platform.PAGE_SIZE);
|
||||
const user_page = user - remainder;
|
||||
@ -277,22 +283,20 @@ fn setUpKernelPageDirectory(allocator: *pmm.FrameAllocator, tag: *easyboot.multi
|
||||
return table;
|
||||
}
|
||||
|
||||
pub fn setUpInitialUserPageDirectory(allocator: *pmm.FrameAllocator, tag: *easyboot.multiboot_tag_mmap_t, user_table: *PageTable) !usize {
|
||||
pub fn setUpInitialUserPageDirectory(allocator: *pmm.FrameAllocator, tag: *easyboot.multiboot_tag_mmap_t, space: AddressSpace) !usize {
|
||||
const kernel_space = AddressSpace.create(readPageTable(), PHYSICAL_MAPPING_BASE);
|
||||
const kernel_table = kernel_space.table;
|
||||
|
||||
const physical_address_space_size = mmap.getAddressSpaceSize(tag) orelse return error.InvalidMemoryMap;
|
||||
|
||||
user_table.* = std.mem.zeroes(PageTable);
|
||||
space.table.* = std.mem.zeroes(PageTable);
|
||||
|
||||
const directory_upper_half: *[256]PageTableEntry = kernel_table.entries[256..];
|
||||
const user_directory_upper_half: *[256]PageTableEntry = user_table.entries[256..];
|
||||
const user_directory_upper_half: *[256]PageTableEntry = space.table.entries[256..];
|
||||
@memcpy(user_directory_upper_half, directory_upper_half);
|
||||
|
||||
const user_physical_address_base = (USER_ADDRESS_RANGE_END + 1) - physical_address_space_size;
|
||||
|
||||
const space = AddressSpace.create(.{ .address = @intFromPtr(user_table) }, 0);
|
||||
|
||||
try mapPhysicalMemory(allocator, tag, space, PHYSICAL_MAPPING_BASE, user_physical_address_base, @intFromEnum(Flags.ReadWrite) | @intFromEnum(Flags.NoExecute) | @intFromEnum(Flags.User));
|
||||
|
||||
return user_physical_address_base;
|
||||
|
@ -13,51 +13,11 @@ const elf = @import("elf.zig");
|
||||
|
||||
const MultibootInfo = [*c]u8;
|
||||
|
||||
fn adjustAddressToPageBoundary(address: *usize, size: *usize) void {
|
||||
const diff = address.* % platform.PAGE_SIZE;
|
||||
|
||||
address.* -= diff;
|
||||
size.* += diff;
|
||||
export fn _start(_: u32, _: MultibootInfo) callconv(.C) noreturn {
|
||||
platform._start();
|
||||
}
|
||||
|
||||
fn reserveMultibootMemory(allocator: *pmm.FrameAllocator, info: MultibootInfo) !void {
|
||||
const info_tag: *easyboot.multiboot_info_t = @alignCast(@ptrCast(info));
|
||||
|
||||
var address: usize = @intFromPtr(info);
|
||||
var size: usize = info_tag.total_size;
|
||||
adjustAddressToPageBoundary(&address, &size);
|
||||
|
||||
debug.print("Locking multiboot memory at {x}, {d} bytes\n", .{ address, size });
|
||||
|
||||
try pmm.lockFrames(allocator, address, try std.math.divCeil(usize, size, platform.PAGE_SIZE));
|
||||
|
||||
const Context = struct {
|
||||
allocator: *pmm.FrameAllocator,
|
||||
};
|
||||
|
||||
var ctx = Context{ .allocator = allocator };
|
||||
|
||||
multiboot.findMultibootTags(easyboot.multiboot_tag_module_t, @ptrCast(info), struct {
|
||||
fn reserveMemory(mod: *easyboot.multiboot_tag_module_t, context: *const Context) !void {
|
||||
var mod_address: usize = mod.mod_start;
|
||||
var mod_size: usize = mod.mod_end - mod.mod_start;
|
||||
adjustAddressToPageBoundary(&mod_address, &mod_size);
|
||||
|
||||
debug.print("Locking memory for module {s} at address {x}, {d} bytes\n", .{ mod.string(), mod_address, mod_size });
|
||||
|
||||
try pmm.lockFrames(context.allocator, mod_address, try std.math.divCeil(usize, mod_size, platform.PAGE_SIZE));
|
||||
}
|
||||
|
||||
fn handler(mod: *easyboot.multiboot_tag_module_t, context: *const anyopaque) void {
|
||||
reserveMemory(mod, @alignCast(@ptrCast(context))) catch |err| {
|
||||
debug.print("Error while reserving multiboot memory {s}: {}\n", .{ mod.string(), err });
|
||||
while (true) {}
|
||||
};
|
||||
}
|
||||
}.handler, &ctx);
|
||||
}
|
||||
|
||||
export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
export fn main(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
interrupts.disableInterrupts();
|
||||
|
||||
if (magic != easyboot.MULTIBOOT2_BOOTLOADER_MAGIC) {
|
||||
@ -80,7 +40,7 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
while (true) {}
|
||||
};
|
||||
|
||||
reserveMultibootMemory(&allocator, info) catch |err| {
|
||||
pmm.reserveMultibootMemory(&allocator, info) catch |err| {
|
||||
debug.print("Error while reserving multiboot memory: {}\n", .{err});
|
||||
while (true) {}
|
||||
};
|
||||
@ -108,7 +68,7 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
const frame = try pmm.allocFrame(context.allocator);
|
||||
const space = vmm.AddressSpace.create(frame, vmm.PHYSICAL_MAPPING_BASE);
|
||||
|
||||
const base = try vmm.setUpInitialUserPageDirectory(context.allocator, context.mmap, space.table);
|
||||
const base = try vmm.setUpInitialUserPageDirectory(context.allocator, context.mmap, space);
|
||||
|
||||
const module = try thread.createThreadControlBlock(context.allocator);
|
||||
|
||||
|
@ -5,6 +5,8 @@ const vmm = @import("arch/vmm.zig");
|
||||
const mmap = @import("mmap.zig");
|
||||
const bmap = @import("lib/bitmap.zig");
|
||||
const locking = @import("lib/spinlock.zig");
|
||||
const debug = @import("arch/debug.zig");
|
||||
const multiboot = @import("multiboot.zig");
|
||||
|
||||
const FrameAllocatorError = error{
|
||||
InvalidMemoryMap,
|
||||
@ -104,9 +106,74 @@ pub fn initializeFrameAllocator(tag: *easyboot.multiboot_tag_mmap_t) !FrameAlloc
|
||||
// Avoid causing trouble.
|
||||
try lockFrame(&allocator, 0);
|
||||
|
||||
try reserveKernelMemory(&allocator);
|
||||
|
||||
return allocator;
|
||||
}
|
||||
|
||||
fn adjustAddressToPageBoundary(address: *usize, size: *usize) void {
|
||||
const diff = address.* % platform.PAGE_SIZE;
|
||||
|
||||
address.* -= diff;
|
||||
size.* += diff;
|
||||
}
|
||||
|
||||
extern const kernel_start: [*]u8;
|
||||
extern const kernel_end: [*]u8;
|
||||
|
||||
fn reserveKernelMemory(allocator: *FrameAllocator) !void {
|
||||
debug.print("Kernel begins at {*} and ends at {*}\n", .{ &kernel_start, &kernel_end });
|
||||
|
||||
const start: usize = @intFromPtr(&kernel_start);
|
||||
const end: usize = @intFromPtr(&kernel_end);
|
||||
const pages = try std.math.divCeil(usize, end - start, platform.PAGE_SIZE);
|
||||
|
||||
const page_table = vmm.readPageTable();
|
||||
const space = vmm.AddressSpace.create(page_table, 0);
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < pages) : (i += 1) {
|
||||
try lockFrame(allocator, vmm.getAddress(space, 0, start + (i * platform.PAGE_SIZE)).?);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reserveMultibootMemory(allocator: *FrameAllocator, info: [*c]u8) !void {
|
||||
const info_tag: *easyboot.multiboot_info_t = @alignCast(@ptrCast(info));
|
||||
|
||||
var address: usize = @intFromPtr(info);
|
||||
var size: usize = info_tag.total_size;
|
||||
adjustAddressToPageBoundary(&address, &size);
|
||||
|
||||
debug.print("Locking multiboot memory at {x}, {d} bytes\n", .{ address, size });
|
||||
|
||||
try lockFrames(allocator, address, try std.math.divCeil(usize, size, platform.PAGE_SIZE));
|
||||
|
||||
const Context = struct {
|
||||
allocator: *FrameAllocator,
|
||||
};
|
||||
|
||||
var ctx = Context{ .allocator = allocator };
|
||||
|
||||
multiboot.findMultibootTags(easyboot.multiboot_tag_module_t, @ptrCast(info), struct {
|
||||
fn reserveMemory(mod: *easyboot.multiboot_tag_module_t, context: *const Context) !void {
|
||||
var mod_address: usize = mod.mod_start;
|
||||
var mod_size: usize = mod.mod_end - mod.mod_start;
|
||||
adjustAddressToPageBoundary(&mod_address, &mod_size);
|
||||
|
||||
debug.print("Locking memory for module {s} at address {x}, {d} bytes\n", .{ mod.string(), mod_address, mod_size });
|
||||
|
||||
try lockFrames(context.allocator, mod_address, try std.math.divCeil(usize, mod_size, platform.PAGE_SIZE));
|
||||
}
|
||||
|
||||
fn handler(mod: *easyboot.multiboot_tag_module_t, context: *const anyopaque) void {
|
||||
reserveMemory(mod, @alignCast(@ptrCast(context))) catch |err| {
|
||||
debug.print("Error while reserving multiboot memory {s}: {}\n", .{ mod.string(), err });
|
||||
while (true) {}
|
||||
};
|
||||
}
|
||||
}.handler, &ctx);
|
||||
}
|
||||
|
||||
var lock: locking.SpinLock = .{};
|
||||
var global_allocator: *FrameAllocator = undefined;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user