core: Add a struct named "platform.Registers" to cover different architectures

This replaces the architecture-independent usage of InterruptStackFrame, which is an x86_64 implementation thing.
This commit is contained in:
Gabriel 2025-02-21 19:40:46 +01:00
parent 52cb29dbca
commit d858700da4
9 changed files with 35 additions and 32 deletions

View File

@ -1,4 +1,5 @@
const io = @import("ioports.zig"); const io = @import("ioports.zig");
const platform = @import("platform.zig");
const interrupts = @import("interrupts.zig"); const interrupts = @import("interrupts.zig");
const pic = @import("pic.zig"); const pic = @import("pic.zig");
const thread = @import("../../thread.zig"); const thread = @import("../../thread.zig");
@ -23,6 +24,6 @@ pub fn initializePIT() void {
_ = interrupts.registerIRQ(0, &pitTimerHandler); _ = interrupts.registerIRQ(0, &pitTimerHandler);
} }
pub fn pitTimerHandler(_: u32, regs: *interrupts.InterruptStackFrame) void { pub fn pitTimerHandler(_: u32, regs: *platform.Registers) void {
thread.preempt(regs); thread.preempt(regs);
} }

View File

@ -6,6 +6,8 @@ const interrupts = @import("interrupts.zig");
pub const PAGE_SIZE = 4096; pub const PAGE_SIZE = 4096;
pub const Registers = interrupts.InterruptStackFrame;
// FIXME: Check if it's supported first. // FIXME: Check if it's supported first.
fn enableNX() void { fn enableNX() void {
asm volatile ( asm volatile (

View File

@ -1,7 +1,7 @@
const std = @import("std"); const std = @import("std");
const interrupts = @import("interrupts.zig"); const platform = @import("platform.zig");
pub inline fn enterThread(regs: *interrupts.InterruptStackFrame, base: u64, directory: u64) noreturn { pub inline fn enterThread(regs: *platform.Registers, base: u64, directory: u64) noreturn {
asm volatile ( asm volatile (
\\ addq %[base], %rsp \\ addq %[base], %rsp
\\ push %[ss] \\ push %[ss]
@ -54,28 +54,28 @@ pub inline fn readStackPointer() usize {
); );
} }
pub fn setAddress(regs: *interrupts.InterruptStackFrame, address: u64) void { pub fn setAddress(regs: *platform.Registers, address: u64) void {
regs.rip = address; regs.rip = address;
} }
pub fn setArguments(regs: *interrupts.InterruptStackFrame, arg0: u64, arg1: u64) void { pub fn setArguments(regs: *platform.Registers, arg0: u64, arg1: u64) void {
regs.rdi = arg0; regs.rdi = arg0;
regs.rsi = arg1; regs.rsi = arg1;
} }
pub fn setStack(regs: *interrupts.InterruptStackFrame, stack: u64) void { pub fn setStack(regs: *platform.Registers, stack: u64) void {
regs.rsp = stack; regs.rsp = stack;
} }
pub fn initKernelRegisters(regs: *interrupts.InterruptStackFrame) void { pub fn initKernelRegisters(regs: *platform.Registers) void {
regs.* = std.mem.zeroes(interrupts.InterruptStackFrame); regs.* = std.mem.zeroes(platform.Registers);
regs.cs = 0x08; regs.cs = 0x08;
regs.ss = 0x10; regs.ss = 0x10;
regs.rflags = 1 << 9; // IF (Interrupt enable flag) regs.rflags = 1 << 9; // IF (Interrupt enable flag)
} }
pub fn initUserRegisters(regs: *interrupts.InterruptStackFrame) void { pub fn initUserRegisters(regs: *platform.Registers) void {
regs.* = std.mem.zeroes(interrupts.InterruptStackFrame); regs.* = std.mem.zeroes(platform.Registers);
regs.cs = 0x18 | 3; regs.cs = 0x18 | 3;
regs.ss = 0x20 | 3; regs.ss = 0x20 | 3;
regs.rflags = 1 << 9; // IF (Interrupt enable flag) regs.rflags = 1 << 9; // IF (Interrupt enable flag)

View File

@ -15,7 +15,7 @@ const MultibootInfo = [*c]u8;
const Context = struct { const Context = struct {
allocator: *pmm.FrameAllocator, allocator: *pmm.FrameAllocator,
space: vmm.AddressSpace, space: vmm.AddressSpace,
regs: *interrupts.InterruptStackFrame, regs: *platform.Registers,
}; };
export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn { export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {

View File

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

View File

@ -1,7 +1,7 @@
const interrupts = @import("../arch/interrupts.zig").arch; const platform = @import("../arch/platform.zig").arch;
const sys = @import("syscall.zig"); const sys = @import("syscall.zig");
const debug = @import("../arch/debug.zig"); const debug = @import("../arch/debug.zig");
pub fn print(_: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void { pub fn print(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
debug.print("The userspace program gave us the number {x}\n", .{args.arg0}); debug.print("The userspace program gave us the number {x}\n", .{args.arg0});
} }

View File

@ -1,25 +1,25 @@
const interrupts = @import("../arch/interrupts.zig").arch; const platform = @import("../arch/platform.zig").arch;
const sys = @import("syscall.zig"); const sys = @import("syscall.zig");
const thread = @import("../thread.zig"); const thread = @import("../thread.zig");
const cpu = @import("../arch/cpu.zig"); const cpu = @import("../arch/cpu.zig");
pub fn yield(regs: *interrupts.InterruptStackFrame, _: *sys.Arguments, _: *isize) anyerror!void { pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore(); const core = cpu.thisCore();
const new_thread = thread.fetchNewThread(core, false) orelse return; const new_thread = thread.fetchNewThread(core, false) orelse return;
const current_thread = thread.scheduleNewThread(core, regs, new_thread); const current_thread = thread.scheduleNewThread(core, regs, new_thread);
thread.addThreadToPriorityQueue(core, current_thread); thread.addThreadToPriorityQueue(core, current_thread);
} }
pub fn setPriority(_: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void { pub fn setPriority(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore(); const core = cpu.thisCore();
core.current_thread.user_priority = @truncate(args.arg0); core.current_thread.user_priority = @truncate(args.arg0);
} }
pub fn getPriority(_: *interrupts.InterruptStackFrame, _: *sys.Arguments, retval: *isize) anyerror!void { pub fn getPriority(_: *platform.Registers, _: *sys.Arguments, retval: *isize) anyerror!void {
const core = cpu.thisCore(); const core = cpu.thisCore();
retval.* = core.current_thread.user_priority; retval.* = core.current_thread.user_priority;
} }
pub fn sleep(regs: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void { pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
_ = thread.startSleep(regs, args.arg0); _ = thread.startSleep(regs, args.arg0);
} }

View File

@ -1,5 +1,5 @@
const std = @import("std"); const std = @import("std");
const interrupts = @import("../arch/interrupts.zig").arch; const platform = @import("../arch/platform.zig").arch;
const print = @import("print.zig").print; const print = @import("print.zig").print;
const mem = @import("mem.zig"); const mem = @import("mem.zig");
const sched = @import("sched.zig"); const sched = @import("sched.zig");
@ -13,11 +13,11 @@ pub const Arguments = struct {
arg5: usize, arg5: usize,
}; };
const SystemCall = *const fn (frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) anyerror!void; const SystemCall = *const fn (frame: *platform.Registers, args: *Arguments, retval: *isize) anyerror!void;
const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep }; const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep };
pub fn invokeSyscall(number: usize, frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) void { pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void {
if (number >= syscalls.len) { if (number >= syscalls.len) {
retval.* = -1; retval.* = -1;
return; return;

View File

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const vmm = @import("arch/vmm.zig").arch; const vmm = @import("arch/vmm.zig").arch;
const interrupts = @import("arch/interrupts.zig").arch; const platform = @import("arch/platform.zig").arch;
pub const arch = @import("arch/thread.zig").arch; pub const arch = @import("arch/thread.zig").arch;
const pmm = @import("pmm.zig"); const pmm = @import("pmm.zig");
const cpu = @import("arch/cpu.zig"); const cpu = @import("arch/cpu.zig");
@ -16,7 +16,7 @@ pub const ThreadState = enum {
pub const ThreadControlBlock = struct { pub const ThreadControlBlock = struct {
id: u64, id: u64,
address_space: ?vmm.AddressSpace, address_space: ?vmm.AddressSpace,
regs: interrupts.InterruptStackFrame, regs: platform.Registers,
state: ThreadState, state: ThreadState,
user_priority: u8, user_priority: u8,
@ -58,7 +58,7 @@ pub fn enterThread(thread: *ThreadControlBlock) noreturn {
} }
/// Updates the processor state to run a new thread. /// Updates the processor state to run a new thread.
fn switchThread(regs: *interrupts.InterruptStackFrame, new_thread: *ThreadControlBlock) void { fn switchThread(regs: *platform.Registers, new_thread: *ThreadControlBlock) void {
const core = cpu.thisCore(); const core = cpu.thisCore();
core.current_thread.regs = regs.*; core.current_thread.regs = regs.*;
@ -74,7 +74,7 @@ fn switchThread(regs: *interrupts.InterruptStackFrame, new_thread: *ThreadContro
} }
/// Changes the running thread to a new one and returns the previous one. /// Changes the running thread to a new one and returns the previous one.
pub fn scheduleNewThread(core: *cpu.arch.Core, regs: *interrupts.InterruptStackFrame, new_thread: *ThreadControlBlock) *ThreadControlBlock { pub fn scheduleNewThread(core: *cpu.arch.Core, regs: *platform.Registers, new_thread: *ThreadControlBlock) *ThreadControlBlock {
if (core.active_thread_list.first) |first| { if (core.active_thread_list.first) |first| {
first.data.current_priority +|= 4; first.data.current_priority +|= 4;
} }
@ -90,7 +90,7 @@ pub fn scheduleNewThread(core: *cpu.arch.Core, regs: *interrupts.InterruptStackF
/// ///
/// Updates the core's sleep queue, checks if the running thread's time /// Updates the core's sleep queue, checks if the running thread's time
/// is up, and if it is, schedules a new one. /// is up, and if it is, schedules a new one.
pub fn preempt(regs: *interrupts.InterruptStackFrame) void { pub fn preempt(regs: *platform.Registers) void {
const core = cpu.thisCore(); const core = cpu.thisCore();
updateSleepQueue(core); updateSleepQueue(core);
@ -107,7 +107,7 @@ pub fn preempt(regs: *interrupts.InterruptStackFrame) void {
} }
/// Sets the current thread's state to "Blocked" and schedules a new one to replace it. /// Sets the current thread's state to "Blocked" and schedules a new one to replace it.
pub fn block(regs: *interrupts.InterruptStackFrame) *ThreadControlBlock { pub fn block(regs: *platform.Registers) *ThreadControlBlock {
const core = cpu.thisCore(); const core = cpu.thisCore();
// fetchNewThread() always returns a thread if should_idle_if_not_found is set to true. // fetchNewThread() always returns a thread if should_idle_if_not_found is set to true.
@ -119,7 +119,7 @@ pub fn block(regs: *interrupts.InterruptStackFrame) *ThreadControlBlock {
} }
/// Puts the current thread to sleep, adding it to the sleep queue, and schedules a new one to replace it. /// Puts the current thread to sleep, adding it to the sleep queue, and schedules a new one to replace it.
pub fn startSleep(regs: *interrupts.InterruptStackFrame, ticks: u64) *ThreadControlBlock { pub fn startSleep(regs: *platform.Registers, ticks: u64) *ThreadControlBlock {
const core = cpu.thisCore(); const core = cpu.thisCore();
// fetchNewThread() always returns a thread if should_idle_if_not_found is set to true. // fetchNewThread() always returns a thread if should_idle_if_not_found is set to true.