From 5bdac6ae0b3de12bc2da9a0ea6faca51dd148c52 Mon Sep 17 00:00:00 2001 From: Ratakor Date: Thu, 30 Nov 2023 18:58:34 +0100 Subject: [PATCH] Small improvement for idt + remove errno --- kernel/TTY.zig | 2 +- kernel/arch/x86_64/gdt.zig | 14 ++---- kernel/arch/x86_64/idt.zig | 89 +++++++++++++++++++--------------- kernel/lib/lock.zig | 10 ++-- kernel/sched.zig | 8 +-- kernel/vfs.zig | 99 +++++++++++++++++++------------------- 6 files changed, 109 insertions(+), 113 deletions(-) diff --git a/kernel/TTY.zig b/kernel/TTY.zig index 66d6d81..af35f77 100644 --- a/kernel/TTY.zig +++ b/kernel/TTY.zig @@ -78,7 +78,7 @@ capslock_active: bool, callback: *const CallbackFn, -pub const Reader = std.io.Reader(*TTY, error{}, read); +pub const Reader = std.io.GenericReader(*TTY, error{}, read); // TODO: change to AnyReader? pub const Writer = std.io.Writer(*TTY, error{}, write); pub const CallbackFn = fn (*TTY, Callback, u64, u64, u64) void; diff --git a/kernel/arch/x86_64/gdt.zig b/kernel/arch/x86_64/gdt.zig index 49288f6..64b777d 100644 --- a/kernel/arch/x86_64/gdt.zig +++ b/kernel/arch/x86_64/gdt.zig @@ -1,5 +1,3 @@ -const std = @import("std"); -const log = std.log.scoped(.gdt); const SpinLock = @import("root").SpinLock; /// Global Descriptor Table @@ -21,15 +19,10 @@ const GDT = extern struct { base_high: u8 = 0, }; - const Descriptor = extern struct { - limit: u16 align(1) = @sizeOf(GDT) - 1, - base: u64 align(1) = undefined, + const Descriptor = packed struct(u80) { + limit: u16 = @sizeOf(GDT) - 1, + base: u64 = undefined, }; - - comptime { - std.debug.assert(@sizeOf(GDT) == 7 * @sizeOf(u64)); - std.debug.assert(@bitSizeOf(Descriptor) == 80); - } }; /// Task State Segment @@ -96,7 +89,6 @@ var tss_lock: SpinLock = .{}; pub fn init() void { gdtr.base = @intFromPtr(&gdt); reload(); - log.info("init: successfully reloaded GDT", .{}); } pub fn reload() void { diff --git a/kernel/arch/x86_64/idt.zig b/kernel/arch/x86_64/idt.zig index cedaa05..465675f 100644 --- a/kernel/arch/x86_64/idt.zig +++ b/kernel/arch/x86_64/idt.zig @@ -4,9 +4,6 @@ const gdt = @import("gdt.zig"); const vmm = @import("root").vmm; const log = std.log.scoped(.idt); -const interrupt_gate = 0b1000_1110; -const trap_gate = 0b1000_1111; - pub const InterruptHandler = *const fn (ctx: *Context) callconv(.SysV) void; pub const Context = extern struct { @@ -36,32 +33,45 @@ pub const Context = extern struct { ss: u64, }; -/// Interrupt Descriptor Table Entry -const IDTEntry = extern struct { - offset_low: u16 align(1), - selector: u16 align(1), - ist: u8 align(1), - type_attributes: u8 align(1), - offset_mid: u16 align(1), - offset_high: u32 align(1), - reserved: u32 align(1), +/// Interrupt Descriptor Table +const IDT = struct { + entries: [256]Entry = undefined, + descriptor: Descriptor = .{}, - fn init(handler: u64, ist: u8, gate: u8) IDTEntry { - return .{ - .offset_low = @truncate(handler), - .selector = gdt.kernel_code, - .ist = ist, - .type_attributes = gate, - .offset_mid = @truncate(handler >> 16), - .offset_high = @truncate(handler >> 32), - .reserved = 0, - }; - } -}; + const Entry = packed struct(u128) { + offset_low: u16, + selector: u16, + ist: u3, + reserved0: u5 = 0, + gate_type: u4, + zero: u1 = 0, + dpl: u2, // Descriptor Privilege Level + p: u1, // present flag + offset_mid: u16, + offset_high: u32, + reserved1: u32 = 0, + + const interrupt_gate = 0b1110; + const trap_gate = 0b1111; + + fn init(handler: u64, ist: u3) Entry { + return .{ + .offset_low = @truncate(handler), + .selector = gdt.kernel_code, + .ist = ist, + .gate_type = interrupt_gate, + .dpl = 0b00, + .p = 1, + .offset_mid = @truncate(handler >> 16), + .offset_high = @truncate(handler >> 32), + }; + } + }; -const IDTDescriptor = extern struct { - limit: u16 align(1) = @sizeOf(@TypeOf(idt)) - 1, - base: u64 align(1) = undefined, + const Descriptor = packed struct(u80) { + limit: u16 = @sizeOf([256]Entry) - 1, + base: u64 = undefined, + }; }; const exceptions = [_][]const u8{ @@ -99,36 +109,35 @@ const exceptions = [_][]const u8{ "Reserved", }; +pub var panic_ipi_vector: u8 = undefined; + // TODO: replace isr with a interrupt dispatcher func? // -> move all handlers to interrupt.zig? var isr = [_]InterruptHandler{defaultHandler} ** 256; -var next_vector: u8 = exceptions.len; -pub var panic_ipi_vector: u8 = undefined; +var idt: IDT = .{}; -var idtr: IDTDescriptor = .{}; -var idt: [256]IDTEntry = undefined; +var next_vector: u8 = exceptions.len; pub fn init() void { - idtr.base = @intFromPtr(&idt); + idt.descriptor.base = @intFromPtr(&idt.entries); - inline for (0..256) |i| { - const handler = makeHandler(i); - idt[i] = IDTEntry.init(@intFromPtr(handler), 0, interrupt_gate); + inline for (0..256) |vector| { + const handler = makeHandler(vector); + idt.entries[vector] = IDT.Entry.init(@intFromPtr(handler), 0); } setIST(0x0e, 2); // page fault uses IST 2 panic_ipi_vector = allocVector(); - idt[panic_ipi_vector] = IDTEntry.init(@intFromPtr(&panicHandler), 0, interrupt_gate); + idt.entries[panic_ipi_vector] = IDT.Entry.init(@intFromPtr(&panicHandler), 0); reload(); - log.info("init: successfully reloaded IDT", .{}); } pub fn reload() void { asm volatile ( \\lidt (%[idtr]) : - : [idtr] "r" (&idtr), + : [idtr] "r" (&idt.descriptor), : "memory" ); } @@ -142,8 +151,8 @@ pub fn allocVector() u8 { return vector; } -pub inline fn setIST(vector: u8, ist: u8) void { - idt[vector].ist = ist; +pub inline fn setIST(vector: u8, ist: u3) void { + idt.entries[vector].ist = ist; } pub inline fn registerHandler(vector: u8, handler: InterruptHandler) void { diff --git a/kernel/lib/lock.zig b/kernel/lib/lock.zig index 6962004..352131a 100644 --- a/kernel/lib/lock.zig +++ b/kernel/lib/lock.zig @@ -4,15 +4,15 @@ const atomic = @import("std").atomic; pub const SpinLock = struct { state: State = State.init(.unlocked), - const State = atomic.Atomic(enum(u32) { unlocked, locked }); + const State = atomic.Value(enum(u32) { unlocked, locked }); /// return true on success pub inline fn tryLock(self: *SpinLock) bool { - return if (self.isUnlocked()) self.lockImpl("compareAndSwap") else false; + return if (self.isUnlocked()) self.cmpxchg("Strong") else false; } pub fn lock(self: *SpinLock) void { - while (!self.lockImpl("tryCompareAndSwap")) { + while (!self.cmpxchg("Weak")) { while (!self.isUnlocked()) { atomic.spinLoopHint(); } @@ -27,8 +27,8 @@ pub const SpinLock = struct { return self.state.load(.Monotonic) == .unlocked; } - inline fn lockImpl(self: *SpinLock, comptime cas_fn_name: []const u8) bool { - const casFn = @field(@TypeOf(self.state), cas_fn_name); + inline fn cmpxchg(self: *SpinLock, comptime strength: []const u8) bool { + const casFn = @field(@TypeOf(self.state), "cmpxchg" ++ strength); return casFn(&self.state, .unlocked, .locked, .Acquire, .Monotonic) == null; } }; diff --git a/kernel/sched.zig b/kernel/sched.zig index bed7bcf..2bff2ef 100644 --- a/kernel/sched.zig +++ b/kernel/sched.zig @@ -38,7 +38,7 @@ pub const Process = struct { fds_lock: SpinLock, fds: std.ArrayListUnmanaged(*vfs.FileDescriptor), - var next_pid = std.atomic.Atomic(std.os.pid_t).init(0); + var next_pid = std.atomic.Value(std.os.pid_t).init(0); // TODO: more errdefer pub fn init(parent: ?*Process, addr_space: ?*vmm.AddressSpace) !*Process { @@ -88,7 +88,6 @@ pub const Process = struct { }; pub const Thread = struct { - errno: usize, tid: usize, lock: SpinLock = .{}, process: *Process, @@ -121,7 +120,6 @@ pub const Thread = struct { errdefer root.allocator.destroy(thread); thread.* = .{ - .errno = 0, .tid = undefined, .process = kernel_process, .ctx = undefined, // defined after @@ -323,10 +321,6 @@ pub inline fn currentProcess() *Process { return currentThread().process; } -pub inline fn setErrno(errno: std.os.E) void { - currentThread().errno = @intFromEnum(errno); -} - fn nextThread() ?*Thread { const ticket = pcg.random().uintLessThan(usize, total_tickets + 1); var sum: usize = 0; diff --git a/kernel/vfs.zig b/kernel/vfs.zig index da277d3..b61a0cf 100644 --- a/kernel/vfs.zig +++ b/kernel/vfs.zig @@ -154,54 +154,55 @@ pub const Node = struct { } }; - pub const Stream = struct { - node: *Node, - offset: u64 = 0, - - pub const SeekError = error{}; - pub const GetSeekPosError = error{}; - - pub const SeekableStream = std.io.SeekableStream( - *Stream, - SeekError, - GetSeekPosError, - Stream.seekTo, - Stream.seekBy, - Stream.getPosFn, - Stream.getEndPosFn, - ); - - pub const Reader = std.io.Reader(*Stream, ReadError, Stream.read); - - fn seekTo(self: *Stream, offset: u64) SeekError!void { - self.offset = offset; - } - - fn seekBy(self: *Stream, offset: i64) SeekError!void { - self.offset +%= @bitCast(offset); - } - - fn getPosFn(self: *Stream) GetSeekPosError!u64 { - return self.offset; - } - - fn getEndPosFn(self: *Stream) GetSeekPosError!u64 { - _ = self; - return 0; // TODO - } - - fn read(self: *Stream, buf: []u8) ReadError!usize { - return self.node.read(buf, self.offset); - } - - pub fn seekableStream(self: *Stream) SeekableStream { - return .{ .context = self }; - } - - pub fn reader(self: *Stream) Reader { - return .{ .context = self }; - } - }; + // TODO: useless? + // pub const Stream = struct { + // node: *Node, + // offset: u64 = 0, + + // pub const SeekError = error{}; + // pub const GetSeekPosError = error{}; + + // pub const SeekableStream = std.io.SeekableStream( + // *Stream, + // SeekError, + // GetSeekPosError, + // Stream.seekTo, + // Stream.seekBy, + // Stream.getPosFn, + // Stream.getEndPosFn, + // ); + + // pub const Reader = std.io.Reader(*Stream, ReadError, Stream.read); + + // fn seekTo(self: *Stream, offset: u64) SeekError!void { + // self.offset = offset; + // } + + // fn seekBy(self: *Stream, offset: i64) SeekError!void { + // self.offset +%= @bitCast(offset); + // } + + // fn getPosFn(self: *Stream) GetSeekPosError!u64 { + // return self.offset; + // } + + // fn getEndPosFn(self: *Stream) GetSeekPosError!u64 { + // _ = self; + // return 0; // TODO + // } + + // fn read(self: *Stream, buf: []u8) ReadError!usize { + // return self.node.read(buf, self.offset); + // } + + // pub fn seekableStream(self: *Stream) SeekableStream { + // return .{ .context = self }; + // } + + // pub fn reader(self: *Stream) Reader { + // return .{ .context = self }; + // } + // }; pub fn init( vtable: *const VTable, @@ -365,7 +366,7 @@ pub const FileDescriptor = struct { // pub const MountFn = *const fn (parent: *Node, name: []const u8, source: *Node) CreateError!*Node; -var filesystems: std.StringHashMapUnmanaged(MountFn) = .{}; +var filesystems: std.StringHashMapUnmanaged(MountFn) = .{}; // TODO: use ComptimeStringMap pub var root_node: *Node = undefined; var vfs_lock: SpinLock = .{}; var dev_id_counter: os.dev_t = 0;