diff --git a/kobold/hal/hal.zig b/kobold/hal/hal.zig index e826d71..4bf44bf 100644 --- a/kobold/hal/hal.zig +++ b/kobold/hal/hal.zig @@ -15,6 +15,7 @@ pub const debug = @import("debug/debug.zig"); pub const Writer = std.io.Writer(@TypeOf(.{}), error{}, arch.write); pub const writer = Writer{ .context = .{} }; const team = @import("root").team; +const thread = @import("root").thread; pub var hiList: ?[]*HartInfo = null; @@ -37,6 +38,7 @@ pub export fn HALInitialize(stackTop: usize, dtb: *allowzero anyopaque) callconv if (arch.memModel.layout == .Flat) @panic("MMUless setups are not supported!"); team.Init(); + thread.Init(); root.KoboldInit(); @panic("No Command"); } diff --git a/kobold/hal/x86_64/hart.zig b/kobold/hal/x86_64/hart.zig index 48036c2..e1e0f97 100644 --- a/kobold/hal/x86_64/hart.zig +++ b/kobold/hal/x86_64/hart.zig @@ -25,7 +25,7 @@ pub fn startSMP() void { cycles += 1; if (cycles >= 50000000) { std.log.err("Hart #{} took too long (potential triple fault on hart!)", .{hartCount}); - hal.HALOops("X86_64 HAL Initialization Failure"); + hal.HALOops("X86-64 HAL Initialization Failure"); } std.atomic.spinLoopHint(); } diff --git a/kobold/hal/x86_64/main.zig b/kobold/hal/x86_64/main.zig index 5934889..a030623 100644 --- a/kobold/hal/x86_64/main.zig +++ b/kobold/hal/x86_64/main.zig @@ -177,14 +177,15 @@ pub export fn HartStart(stackTop: usize) callconv(.C) noreturn { } fn ArchWriteString(_: @TypeOf(.{}), string: []const u8) error{}!usize { - var i: isize = 0; - while (i < string.len) : (i += 1) { - while ((io.inb(0x3F8 + 5) & 0x20) == 0) - std.atomic.spinLoopHint(); - io.outb(0x3f8, string[@bitCast(i)]); - } if (termCtx) |ctx| { flanterm.flanterm_write(ctx, string.ptr, string.len); + } else { + var i: isize = 0; + while (i < string.len) : (i += 1) { + while ((io.inb(0x3F8 + 5) & 0x20) == 0) + std.atomic.spinLoopHint(); + io.outb(0x3f8, string[@bitCast(i)]); + } } return string.len; } @@ -234,6 +235,65 @@ const Context = packed struct { rsp: u64 = 0, ss: u64 = 0, + pub fn SetMode(self: *Context, kern: bool) void { + if (kern) { + self.cs = 0x28; + self.ss = 0x30; + } else { + self.cs = 0x43; + self.ss = 0x3b; + } + self.rflags = 0x202; + } + + pub fn SetReg(self: *Context, reg: u8, val: usize) void { + switch (reg) { + 0 => { + self.rax = val; + }, + 1 => { + self.rdi = val; + }, + 2 => { + self.rsi = val; + }, + 3 => { + self.rdx = val; + }, + 4 => { + self.r10 = val; + }, + 5 => { + self.r8 = val; + }, + 6 => { + self.r9 = val; + }, + 128 => { + self.rip = val; + }, + 129 => { + self.rsp = val; + }, + else => {}, + } + } + + pub fn GetReg(self: *Context, reg: u8) usize { + return switch (reg) { + 0 => self.rax, + 1 => self.rdi, + 2 => self.rsi, + 3 => self.rdx, + 4 => self.r10, + 5 => self.r8, + 6 => self.r9, + 128 => self.rip, + 129 => self.rsp, + else => 0, + }; + } + pub fn Dump(self: *Context) void { std.log.debug(" rax 0x{x: <16} rbx 0x{x: <16} rcx 0x{x: <16}\n", .{ self.rax, self.rbx, self.rcx }); std.log.debug(" rdx 0x{x: <16} rsi 0x{x: <16} rdi 0x{x: <16}\n", .{ self.rdx, self.rsi, self.rdi }); diff --git a/kobold/hal/x86_64/timer.zig b/kobold/hal/x86_64/timer.zig index dfb6a28..54d704a 100644 --- a/kobold/hal/x86_64/timer.zig +++ b/kobold/hal/x86_64/timer.zig @@ -81,6 +81,6 @@ pub fn setDeadline(microsecs: u64) void { } pub fn getRemainingUs() u64 { - const count = 0xffffffff - apic.read(0x390); + const count = apic.read(0x390); return @intFromFloat(@as(f64, @floatFromInt(count)) * (@as(f64, @floatFromInt(ticksPerSecond)) / 1000000.0)); } diff --git a/kobold/kernel/main.zig b/kobold/kernel/main.zig index dae1ddb..24c977d 100644 --- a/kobold/kernel/main.zig +++ b/kobold/kernel/main.zig @@ -6,6 +6,7 @@ pub const Spinlock = @import("perlib").Spinlock; pub const elf = @import("elf.zig"); pub const pfn = @import("pfn.zig"); pub const team = @import("team.zig"); +pub const thread = @import("thread.zig"); pub const kmain_log = std.log.scoped(.KernelMain); diff --git a/kobold/kernel/team.zig b/kobold/kernel/team.zig index 5d87cfc..9cdee6a 100644 --- a/kobold/kernel/team.zig +++ b/kobold/kernel/team.zig @@ -43,7 +43,44 @@ pub fn NewTeam(parent: ?*Team, name: []const u8) *Team { return team; } +pub fn GetTeamByID(id: i64) ?*Team { + const old = hal.arch.intControl(false); + teamLock.acquire(); + if (teams.root != null) { + var x = teams.root; + while (x) |node| { + if (id < node.key.teamID) { + x = node.children[0]; + } else if (id > node.key.teamID) { + x = node.children[1]; + } else { + return node.key; + } + } + } + teamLock.release(); + _ = hal.arch.intControl(old); + return null; +} + +fn mttreeCommand(cmd: []const u8, iter: *std.mem.SplitIterator(u8, .sequence)) void { + _ = iter; + _ = cmd; + var ind = teams.inorderIterator(); + while (ind.next()) |node| { + const team = node.key; + std.log.debug("Team {}: {s}\n", .{ team.teamID, team.name }); + var tInd = team.threads.first; + while (tInd) |tNode| { + const thr: *thread.Thread = tNode.data; + std.log.debug(" |-- Thread {}: {s}\n", .{ thr.threadID, thr.name }); + tInd = tNode.next; + } + } +} + pub fn Init() void { std.log.info("Creating Kernel Team", .{}); kteam = NewTeam(null, "Kernel Team"); + hal.debug.NewDebugCommand("mtTree", "Prints a tree of all of the threads and teams available", &mttreeCommand); } diff --git a/kobold/kernel/thread.zig b/kobold/kernel/thread.zig index 68b58a4..346000b 100644 --- a/kobold/kernel/thread.zig +++ b/kobold/kernel/thread.zig @@ -3,9 +3,9 @@ const hal = @import("root").hal; const Spinlock = @import("root").Spinlock; const team = @import("team.zig"); const RedBlackTree = @import("perlib").RedBlackTree; +const physmem = @import("physmem.zig"); pub const ThreadState = enum { - Embryo, Runnable, Running, Waiting, @@ -34,3 +34,61 @@ const ThreadTreeType = RedBlackTree(*Thread, struct { return std.math.order(a.threadID, b.threadID); } }.compare); + +pub var threads: ThreadTreeType = ThreadTreeType{}; +var threadLock: Spinlock = .unaquired; +pub var nextThreadID: i64 = 1; + +pub fn NewThread( + t: *team.Team, + name: []u8, + ip: usize, + sp: ?usize, + prior: usize, +) *Thread { // If SP is null then this is a kernel thread + const old = hal.arch.intControl(false); + threadLock.acquire(); + var thread = @as(*Thread, @ptrCast(@alignCast(physmem.Allocate(@sizeOf(Thread), @alignOf(Thread)).?))); + @memset(@as([*]u8, @ptrFromInt(@intFromPtr(&thread.name)))[0..32], 0); + @memcpy(@as([*]u8, @ptrFromInt(@intFromPtr(&thread.name))), name); + thread.queueNode.data = thread; + thread.semaphoreNode.data = thread; + thread.teamListNode.data = thread; + thread.team = t; + thread.threadID = nextThreadID; + nextThreadID += 1; + thread.state = .Runnable; + thread.priority = prior; + const stack = @as([*]u8, @ptrFromInt(@intFromPtr(physmem.Allocate(8192, 4096).?)))[0..8192]; + thread.kstack = stack; + if (sp == null) { + thread.gpContext.SetMode(true); + thread.gpContext.SetReg(129, @intFromPtr(stack.ptr) + stack.len); + } else { + thread.gpContext.SetMode(false); + thread.gpContext.SetReg(129, sp.?); + } + thread.gpContext.SetReg(128, ip); + t.threads.append(&thread.teamListNode); + threadLock.release(); + _ = hal.arch.intControl(old); + return thread; +} + +pub fn Init() void { + const kteam = team.GetTeamByID(1).?; + var i: i32 = 0; + var buf: [32]u8 = [_]u8{0} ** 32; + while (i < hal.hiList.?.len) : (i += 1) { + const name = std.fmt.bufPrint(buf[0..32], "Idle Thread #{}", .{i + 1}) catch { + @panic("Unable to parse string!"); + }; + _ = NewThread(kteam, name, @intFromPtr(&IdleThread), null, 0); + } +} + +fn IdleThread() callconv(.C) void { + while (true) { + hal.arch.waitForInt(); + } +}