Compare commits
No commits in common. "d7557d84f704c16d724f9def05a5a2bf8b883489" and "09fb2b65541d4a6a510f090cf120d8c35d8e4c32" have entirely different histories.
d7557d84f7
...
09fb2b6554
@ -3,7 +3,6 @@ const target = @import("builtin").target;
|
|||||||
const thread = @import("../thread.zig");
|
const thread = @import("../thread.zig");
|
||||||
const pmm = @import("../pmm.zig");
|
const pmm = @import("../pmm.zig");
|
||||||
const vmm = @import("vmm.zig").arch;
|
const vmm = @import("vmm.zig").arch;
|
||||||
const platform = @import("platform.zig").arch;
|
|
||||||
|
|
||||||
pub const arch = switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/cpu.zig"),
|
.x86_64 => @import("x86_64/cpu.zig"),
|
||||||
@ -27,15 +26,11 @@ pub fn setupCore(allocator: *pmm.FrameAllocator) !void {
|
|||||||
idle_thread.id = 0;
|
idle_thread.id = 0;
|
||||||
idle_thread.directory = null;
|
idle_thread.directory = null;
|
||||||
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
|
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
|
||||||
idle_thread.state = .Running;
|
|
||||||
thread.arch.initKernelRegisters(&idle_thread.regs);
|
thread.arch.initKernelRegisters(&idle_thread.regs);
|
||||||
thread.arch.setAddress(&idle_thread.regs, @intFromPtr(&thread.arch.idleLoop));
|
thread.arch.setAddress(&idle_thread.regs, @intFromPtr(&thread.arch.idleLoop));
|
||||||
|
|
||||||
core.thread_list.append(&core.idle_thread);
|
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;
|
this_core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,16 +139,7 @@ fn pageFault(frame: *InterruptStackFrame) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
|
export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
|
||||||
if (frame.isr >= 32 and frame.isr < 48) {
|
debug.print("Caught interrupt {d}\n", .{frame.isr});
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (frame.isr) {
|
switch (frame.isr) {
|
||||||
@intFromEnum(Exceptions.PageFault) => {
|
@intFromEnum(Exceptions.PageFault) => {
|
||||||
pageFault(frame);
|
pageFault(frame);
|
||||||
@ -158,7 +149,7 @@ export fn interruptEntry(frame: *InterruptStackFrame) callconv(.C) void {
|
|||||||
},
|
},
|
||||||
SYSCALL_INTERRUPT => {
|
SYSCALL_INTERRUPT => {
|
||||||
var args = sys.Arguments{ .arg0 = frame.rdi, .arg1 = frame.rsi, .arg2 = frame.rdx, .arg3 = frame.r10, .arg4 = frame.r8, .arg5 = frame.r9 };
|
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 => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
const gdt = @import("gdt.zig");
|
const gdt = @import("gdt.zig");
|
||||||
const idt = @import("idt.zig");
|
const idt = @import("idt.zig");
|
||||||
const pic = @import("pic.zig");
|
const pic = @import("pic.zig");
|
||||||
const pit = @import("pit.zig");
|
|
||||||
const interrupts = @import("interrupts.zig");
|
const interrupts = @import("interrupts.zig");
|
||||||
|
|
||||||
pub const PAGE_SIZE = 4096;
|
pub const PAGE_SIZE = 4096;
|
||||||
@ -27,5 +26,5 @@ pub fn platformInit() void {
|
|||||||
pub fn platformEndInit() void {
|
pub fn platformEndInit() void {
|
||||||
pic.remapPIC();
|
pic.remapPIC();
|
||||||
interrupts.syncInterrupts();
|
interrupts.syncInterrupts();
|
||||||
pit.initializePIT();
|
interrupts.enableInterrupts();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
@ -99,14 +99,8 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
|
|||||||
};
|
};
|
||||||
thread.arch.setStack(&init.regs, stack);
|
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();
|
platform.platformEndInit();
|
||||||
|
|
||||||
init.state = .Running;
|
|
||||||
thread.enterTask(init);
|
thread.enterTask(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const easyboot = @cImport(@cInclude("easyboot.h"));
|
const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||||
const platform = @import("arch/platform.zig").arch;
|
const platform = @import("arch/platform.zig").arch;
|
||||||
const vmm = @import("arch/vmm.zig").arch;
|
|
||||||
const mmap = @import("mmap.zig");
|
const mmap = @import("mmap.zig");
|
||||||
const bmap = @import("lib/bitmap.zig");
|
const bmap = @import("lib/bitmap.zig");
|
||||||
const locking = @import("lib/spinlock.zig");
|
|
||||||
|
|
||||||
const FrameAllocatorError = error{
|
const FrameAllocatorError = error{
|
||||||
InvalidMemoryMap,
|
InvalidMemoryMap,
|
||||||
@ -106,28 +104,3 @@ pub fn initializeFrameAllocator(tag: *easyboot.multiboot_tag_mmap_t) !FrameAlloc
|
|||||||
|
|
||||||
return allocator;
|
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();
|
|
||||||
}
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -1,8 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const interrupts = @import("../arch/interrupts.zig").arch;
|
const interrupts = @import("../arch/interrupts.zig").arch;
|
||||||
const print = @import("print.zig").print;
|
const print = @import("print.zig").print;
|
||||||
const mem = @import("mem.zig");
|
|
||||||
const sched = @import("sched.zig");
|
|
||||||
|
|
||||||
pub const Arguments = struct {
|
pub const Arguments = struct {
|
||||||
arg0: usize,
|
arg0: usize,
|
||||||
@ -15,7 +13,7 @@ pub const Arguments = struct {
|
|||||||
|
|
||||||
const SystemCall = *const fn (frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) anyerror!void;
|
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 {
|
pub fn invokeSyscall(number: usize, frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) void {
|
||||||
if (number >= syscalls.len) {
|
if (number >= syscalls.len) {
|
||||||
|
@ -6,16 +6,13 @@ const pmm = @import("pmm.zig");
|
|||||||
const cpu = @import("arch/cpu.zig");
|
const cpu = @import("arch/cpu.zig");
|
||||||
|
|
||||||
pub const ThreadState = enum {
|
pub const ThreadState = enum {
|
||||||
Inactive,
|
|
||||||
Running,
|
Running,
|
||||||
Blocked,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ThreadControlBlock = struct {
|
pub const ThreadControlBlock = struct {
|
||||||
id: u64,
|
id: u64,
|
||||||
directory: ?*vmm.PageDirectory,
|
directory: ?*vmm.PageDirectory,
|
||||||
regs: interrupts.InterruptStackFrame,
|
regs: interrupts.InterruptStackFrame,
|
||||||
state: ThreadState,
|
|
||||||
|
|
||||||
ticks: u64,
|
ticks: u64,
|
||||||
};
|
};
|
||||||
@ -85,7 +82,6 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB
|
|||||||
thread.id = next_id.fetchAdd(1, .seq_cst);
|
thread.id = next_id.fetchAdd(1, .seq_cst);
|
||||||
thread.directory = null;
|
thread.directory = null;
|
||||||
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
|
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
|
||||||
thread.state = .Inactive;
|
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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 {
|
export fn _start(base: u64) callconv(.C) noreturn {
|
||||||
kernel.print(base);
|
syscall(0, base);
|
||||||
|
|
||||||
while (true) {
|
while (true) {}
|
||||||
kernel.yield();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user