Compare commits
6 Commits
fce8a58cf6
...
da5335410d
Author | SHA1 | Date | |
---|---|---|---|
da5335410d | |||
c4bb857c4e | |||
baf3d39e98 | |||
d8236bc8f7 | |||
18ec598394 | |||
1ec239147a |
@ -73,11 +73,80 @@ export fn asmInterruptEntry() callconv(.Naked) void {
|
||||
);
|
||||
}
|
||||
|
||||
const Exceptions = enum(u64) {
|
||||
GeneralProtectionFault = 0xd,
|
||||
PageFault = 0xe,
|
||||
};
|
||||
|
||||
const PageFaultCodes = enum(u64) {
|
||||
Present = 1 << 0,
|
||||
Write = 1 << 1,
|
||||
User = 1 << 2,
|
||||
Reserved = 1 << 3,
|
||||
NoExecuteViolation = 1 << 4,
|
||||
};
|
||||
|
||||
const SYSCALL_INTERRUPT = 66;
|
||||
|
||||
fn generalProtectionFault(frame: *InterruptStackFrame) void {
|
||||
debug.print("General protection fault!\n", .{});
|
||||
debug.print("Faulting instruction: {x}\n", .{frame.rip});
|
||||
|
||||
const code = frame.error_or_irq;
|
||||
|
||||
debug.print("Error code: {d}\n", .{code});
|
||||
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
fn pageFault(frame: *InterruptStackFrame) void {
|
||||
var fault_address: u64 = undefined;
|
||||
asm volatile ("mov %%cr2, %[cr2]"
|
||||
: [cr2] "=r" (fault_address),
|
||||
);
|
||||
|
||||
debug.print("Page fault while accessing {x}!\n", .{fault_address});
|
||||
debug.print("Faulting instruction: {x}\n", .{frame.rip});
|
||||
|
||||
const code = frame.error_or_irq;
|
||||
|
||||
debug.print("Fault details: {s} | ", .{switch ((code & @intFromEnum(PageFaultCodes.Present)) > 0) {
|
||||
true => "Present",
|
||||
false => "Not present",
|
||||
}});
|
||||
|
||||
debug.print("{s} | ", .{switch ((code & @intFromEnum(PageFaultCodes.Write)) > 0) {
|
||||
true => "Write access",
|
||||
false => "Read access",
|
||||
}});
|
||||
|
||||
debug.print("{s}", .{switch ((code & @intFromEnum(PageFaultCodes.User)) > 0) {
|
||||
true => "User mode",
|
||||
false => "Kernel mode",
|
||||
}});
|
||||
|
||||
debug.print("{s}", .{switch ((code & @intFromEnum(PageFaultCodes.Reserved)) > 0) {
|
||||
true => " | Reserved bits set",
|
||||
false => "",
|
||||
}});
|
||||
|
||||
debug.print("{s}\n", .{switch ((code & @intFromEnum(PageFaultCodes.NoExecuteViolation)) > 0) {
|
||||
true => " | NX Violation",
|
||||
false => "",
|
||||
}});
|
||||
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
|
||||
debug.print("Caught interrupt {d}\n", .{frame.isr});
|
||||
switch (frame.isr) {
|
||||
@intFromEnum(Exceptions.PageFault) => {
|
||||
pageFault(frame);
|
||||
},
|
||||
@intFromEnum(Exceptions.GeneralProtectionFault) => {
|
||||
generalProtectionFault(frame);
|
||||
},
|
||||
SYSCALL_INTERRUPT => {
|
||||
var args = sys.Arguments{ .arg0 = frame.rdi, .arg1 = frame.rsi, .arg2 = frame.rdx, .arg3 = frame.r10, .arg4 = frame.r8, .arg5 = frame.r9 };
|
||||
sys.invokeSyscall(frame.rax, frame, &args, @ptrFromInt(@as(usize, @intFromPtr(&frame.rax))));
|
||||
|
@ -15,4 +15,5 @@ pub fn platformInit() void {
|
||||
pub fn platformEndInit() void {
|
||||
pic.remapPIC();
|
||||
interrupts.syncInterrupts();
|
||||
interrupts.enableInterrupts();
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ const pmm = @import("pmm.zig");
|
||||
const MultibootInfo = [*c]u8;
|
||||
|
||||
export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
interrupts.disableInterrupts();
|
||||
|
||||
if (magic != easyboot.MULTIBOOT2_BOOTLOADER_MAGIC) {
|
||||
debug.print("Invalid magic number: {x}\n", .{magic});
|
||||
while (true) {}
|
||||
@ -19,14 +21,10 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
|
||||
multiboot.parseMultibootTags(@ptrCast(info));
|
||||
|
||||
interrupts.disableInterrupts();
|
||||
platform.platformInit();
|
||||
|
||||
debug.print("GDT initialized\n", .{});
|
||||
|
||||
platform.platformEndInit();
|
||||
interrupts.enableInterrupts();
|
||||
|
||||
if (multiboot.findMultibootTag(easyboot.multiboot_tag_mmap_t, @ptrCast(info))) |tag| {
|
||||
var allocator = pmm.initializeFrameAllocator(tag) catch |err| {
|
||||
debug.print("Error while initializing frame allocator: {}\n", .{err});
|
||||
@ -44,6 +42,8 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
||||
debug.print("No memory map multiboot tag found!\n", .{});
|
||||
}
|
||||
|
||||
platform.platformEndInit();
|
||||
|
||||
asm volatile ("int3");
|
||||
|
||||
while (true) {}
|
||||
|
@ -1,4 +1,5 @@
|
||||
const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||
const target = @import("builtin").target;
|
||||
|
||||
const MemoryMapIterator = struct {
|
||||
tag: *easyboot.multiboot_tag_mmap_t,
|
||||
@ -15,6 +16,16 @@ const MemoryMapIterator = struct {
|
||||
|
||||
if (@intFromPtr(self.entry) >= self.end) self.entry = null;
|
||||
|
||||
if (target.cpu.arch == .x86_64) {
|
||||
// Workaround for https://gitlab.com/qemu-project/qemu/-/commit/8504f129450b909c88e199ca44facd35d38ba4de
|
||||
// This invalid 12GiB reserved entry is made up by QEMU (doesn't appear on any real hardware), so we can simply
|
||||
// ignore it and move on to the next entry.
|
||||
if (current_entry) |entry| {
|
||||
if (entry.base_addr == 0x000000fd00000000 and entry.length == (0x000000ffffffffff - 0x000000fd00000000) + 1)
|
||||
return self.next();
|
||||
}
|
||||
}
|
||||
|
||||
return current_entry;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ pub fn findMultibootTag(comptime Type: type, info: MultibootInfo) ?*Type {
|
||||
}
|
||||
|
||||
/// Find every multiboot tag of the given type.
|
||||
pub fn findMultibootTags(comptime Type: type, info: MultibootInfo, callback: *const fn (tag: *Type) void) void {
|
||||
pub fn findMultibootTags(comptime Type: type, info: MultibootInfo, callback: *const fn (tag: *Type, ctx: *const anyopaque) void, ctx: *const anyopaque) void {
|
||||
const mb_tag: *easyboot.multiboot_info_t = @alignCast(@ptrCast(info));
|
||||
const mb_size = mb_tag.total_size;
|
||||
|
||||
@ -77,43 +77,43 @@ pub fn findMultibootTags(comptime Type: type, info: MultibootInfo, callback: *co
|
||||
while ((@intFromPtr(tag) < last) and (tag.type != easyboot.MULTIBOOT_TAG_TYPE_END)) {
|
||||
switch (tag.type) {
|
||||
easyboot.MULTIBOOT_TAG_TYPE_CMDLINE => {
|
||||
if (Type == easyboot.multiboot_tag_cmdline_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_cmdline_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME => {
|
||||
if (Type == easyboot.multiboot_tag_loader_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_loader_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_MODULE => {
|
||||
if (Type == easyboot.multiboot_tag_module_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_module_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_MMAP => {
|
||||
if (Type == easyboot.multiboot_tag_mmap_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_mmap_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_FRAMEBUFFER => {
|
||||
if (Type == easyboot.multiboot_tag_framebuffer_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_framebuffer_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_EFI64 => {
|
||||
if (Type == easyboot.multiboot_tag_efi64_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_efi64_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_EFI64_IH => {
|
||||
if (Type == easyboot.multiboot_tag_efi64_ih_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_efi64_ih_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_SMBIOS => {
|
||||
if (Type == easyboot.multiboot_tag_smbios_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_smbios_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_ACPI_OLD => {
|
||||
if (Type == easyboot.multiboot_tag_old_acpi_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_old_acpi_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_ACPI_NEW => {
|
||||
if (Type == easyboot.multiboot_tag_new_acpi_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_new_acpi_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_SMP => {
|
||||
if (Type == easyboot.multiboot_tag_smp_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_smp_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_PARTUUID => {
|
||||
if (Type == easyboot.multiboot_tag_partuuid_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_partuuid_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
easyboot.MULTIBOOT_TAG_TYPE_EDID => {
|
||||
if (Type == easyboot.multiboot_tag_edid_t) callback(@alignCast(@ptrCast(tag)));
|
||||
if (Type == easyboot.multiboot_tag_edid_t) callback(@alignCast(@ptrCast(tag)), ctx);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
@ -99,5 +99,8 @@ pub fn initializeFrameAllocator(tag: *easyboot.multiboot_tag_mmap_t) !FrameAlloc
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user