Compare commits

..

No commits in common. "d7557d84f704c16d724f9def05a5a2bf8b883489" and "09fb2b65541d4a6a510f090cf120d8c35d8e4c32" have entirely different histories.

13 changed files with 13 additions and 189 deletions

View File

@ -3,7 +3,6 @@ const target = @import("builtin").target;
const thread = @import("../thread.zig");
const pmm = @import("../pmm.zig");
const vmm = @import("vmm.zig").arch;
const platform = @import("platform.zig").arch;
pub const arch = switch (target.cpu.arch) {
.x86_64 => @import("x86_64/cpu.zig"),
@ -27,15 +26,11 @@ pub fn setupCore(allocator: *pmm.FrameAllocator) !void {
idle_thread.id = 0;
idle_thread.directory = null;
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
idle_thread.state = .Running;
thread.arch.initKernelRegisters(&idle_thread.regs);
thread.arch.setAddress(&idle_thread.regs, @intFromPtr(&thread.arch.idleLoop));
core.thread_list.append(&core.idle_thread);
const stack = try pmm.allocFrame(allocator);
thread.arch.setStack(&idle_thread.regs, stack.virtualAddress(vmm.PHYSICAL_MAPPING_BASE) + (platform.PAGE_SIZE - 16));
this_core = core;
}

View File

@ -139,16 +139,7 @@ fn pageFault(frame: *InterruptStackFrame) void {
}
export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
if (frame.isr >= 32 and frame.isr < 48) {
// IRQ
const irq_handler = irq_handlers[frame.error_or_irq];
if (irq_handler) |handler| {
handler(@intCast(frame.error_or_irq), frame);
}
pic.picEOI(@intCast(frame.error_or_irq));
return;
}
debug.print("Caught interrupt {d}\n", .{frame.isr});
switch (frame.isr) {
@intFromEnum(Exceptions.PageFault) => {
pageFault(frame);
@ -158,7 +149,7 @@ export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
},
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, @ptrCast(&frame.rax));
sys.invokeSyscall(frame.rax, frame, &args, @ptrFromInt(@as(usize, @intFromPtr(&frame.rax))));
},
else => {},
}

View File

@ -1,28 +0,0 @@
const io = @import("ioports.zig");
const interrupts = @import("interrupts.zig");
const pic = @import("pic.zig");
const thread = @import("../../thread.zig");
// Every timer tick is equivalent to 1 millisecond.
const TIMER_RESOLUTION = 1;
const PIT_CHANNEL_0 = 0x40;
const base_frequency: u64 = 1193182;
pub fn initializePIT() void {
const divisor: u16 = @intCast(base_frequency / (TIMER_RESOLUTION * 1000));
if (divisor < 100) {
@compileError("Timer resolution is too low");
}
io.outb(PIT_CHANNEL_0, @as(u8, @intCast(divisor & 0xFF)));
io.outb(0x80, 0); // short delay
io.outb(PIT_CHANNEL_0, @as(u8, @intCast((divisor & 0xFF00) >> 8)));
_ = interrupts.registerIRQ(0, &pitTimerHandler);
}
pub fn pitTimerHandler(_: u32, regs: *interrupts.InterruptStackFrame) void {
thread.preempt(regs);
}

View File

@ -1,7 +1,6 @@
const gdt = @import("gdt.zig");
const idt = @import("idt.zig");
const pic = @import("pic.zig");
const pit = @import("pit.zig");
const interrupts = @import("interrupts.zig");
pub const PAGE_SIZE = 4096;
@ -27,5 +26,5 @@ pub fn platformInit() void {
pub fn platformEndInit() void {
pic.remapPIC();
interrupts.syncInterrupts();
pit.initializePIT();
interrupts.enableInterrupts();
}

View File

@ -1,24 +0,0 @@
const std = @import("std");
const debug = @import("../arch/debug.zig");
pub const SpinLock = struct {
lock_value: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
pub fn lock(self: *SpinLock) void {
while (self.lock_value.cmpxchgWeak(0, 1, .seq_cst, .seq_cst) != null) {}
}
pub fn unlock(self: *SpinLock) void {
if (self.lock_value.cmpxchgStrong(1, 0, .seq_cst, .seq_cst) != null) {
debug.print("Error: SpinLock.unlock() called on an unlocked lock!\n", .{});
}
}
pub fn tryLock(self: *SpinLock) bool {
return self.lock_value.cmpxchgStrong(0, 1, .seq_cst, .seq_cst) == null;
}
pub fn isLocked(self: *SpinLock) bool {
return self.lock_value.load() != 0;
}
};

View File

@ -99,14 +99,8 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
};
thread.arch.setStack(&init.regs, stack);
pmm.setGlobalAllocator(&allocator) catch |err| {
debug.print("Error while setting up global frame allocator: {}\n", .{err});
while (true) {}
};
platform.platformEndInit();
init.state = .Running;
thread.enterTask(init);
}

View File

@ -1,10 +1,8 @@
const std = @import("std");
const easyboot = @cImport(@cInclude("easyboot.h"));
const platform = @import("arch/platform.zig").arch;
const vmm = @import("arch/vmm.zig").arch;
const mmap = @import("mmap.zig");
const bmap = @import("lib/bitmap.zig");
const locking = @import("lib/spinlock.zig");
const FrameAllocatorError = error{
InvalidMemoryMap,
@ -106,28 +104,3 @@ pub fn initializeFrameAllocator(tag: *easyboot.multiboot_tag_mmap_t) !FrameAlloc
return allocator;
}
var lock: locking.SpinLock = .{};
var global_allocator: *FrameAllocator = undefined;
pub fn setGlobalAllocator(allocator: *FrameAllocator) !void {
const frame = try allocFrame(allocator);
const virt = frame.virtualAddress(vmm.PHYSICAL_MAPPING_BASE);
global_allocator = @ptrFromInt(virt);
global_allocator.* = allocator.*;
}
pub fn lockGlobalAllocator() *FrameAllocator {
lock.lock();
return global_allocator;
}
pub fn tryLockGlobalAllocator() ?*FrameAllocator {
if (!lock.tryLock()) return null;
return global_allocator;
}
pub fn unlockGlobalAllocator() void {
lock.unlock();
}

View File

@ -1,26 +0,0 @@
const interrupts = @import("../arch/interrupts.zig").arch;
const sys = @import("syscall.zig");
const pmm = @import("../pmm.zig");
pub fn allocFrame(_: *interrupts.InterruptStackFrame, _: *sys.Arguments, retval: *isize) anyerror!void {
const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator();
const frame = try pmm.allocFrame(allocator);
retval.* = @bitCast(frame.address);
}
pub fn freeFrame(_: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void {
const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator();
try pmm.freeFrame(allocator, args.arg0);
}
pub fn lockFrame(_: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void {
const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator();
try pmm.lockFrame(allocator, args.arg0);
}

View File

@ -1,7 +0,0 @@
const interrupts = @import("../arch/interrupts.zig").arch;
const sys = @import("syscall.zig");
const thread = @import("../thread.zig");
pub fn yield(regs: *interrupts.InterruptStackFrame, _: *sys.Arguments, _: *isize) anyerror!void {
thread.scheduleNewTask(regs);
}

View File

@ -1,8 +1,6 @@
const std = @import("std");
const interrupts = @import("../arch/interrupts.zig").arch;
const print = @import("print.zig").print;
const mem = @import("mem.zig");
const sched = @import("sched.zig");
pub const Arguments = struct {
arg0: usize,
@ -15,7 +13,7 @@ pub const Arguments = struct {
const SystemCall = *const fn (frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) anyerror!void;
const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield };
const syscalls = [_]SystemCall{print};
pub fn invokeSyscall(number: usize, frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) void {
if (number >= syscalls.len) {

View File

@ -6,16 +6,13 @@ const pmm = @import("pmm.zig");
const cpu = @import("arch/cpu.zig");
pub const ThreadState = enum {
Inactive,
Running,
Blocked,
};
pub const ThreadControlBlock = struct {
id: u64,
directory: ?*vmm.PageDirectory,
regs: interrupts.InterruptStackFrame,
state: ThreadState,
ticks: u64,
};
@ -85,7 +82,6 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB
thread.id = next_id.fetchAdd(1, .seq_cst);
thread.directory = null;
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
thread.state = .Inactive;
return thread;
}

View File

@ -1,41 +0,0 @@
const SystemCall = enum(u64) {
Print,
AllocFrame,
LockFrame,
FreeFrame,
Yield,
};
const SystemError = error{
OutOfMemory,
};
fn syscall(num: SystemCall, arg: u64) i64 {
return asm volatile ("int $66"
: [result] "=r" (-> i64),
: [num] "{rax}" (@intFromEnum(num)),
[arg] "{rdi}" (arg),
);
}
pub fn print(arg: u64) void {
_ = syscall(.Print, arg);
}
pub fn allocFrame() !usize {
const retval = syscall(.AllocFrame, 0);
if (retval < 0) return error.OutOfMemory;
return @bitCast(retval);
}
pub fn lockFrame(address: u64) void {
_ = syscall(.LockFrame, address);
}
pub fn freeFrame(address: u64) void {
_ = syscall(.FreeFrame, address);
}
pub fn yield() void {
_ = syscall(.Yield, 0);
}

View File

@ -1,9 +1,13 @@
const kernel = @import("kernel.zig");
fn syscall(num: u64, arg: u64) void {
asm volatile ("int $66"
:
: [num] "{rax}" (num),
[arg] "{rdi}" (arg),
);
}
export fn _start(base: u64) callconv(.C) noreturn {
kernel.print(base);
syscall(0, base);
while (true) {
kernel.yield();
}
while (true) {}
}