core+init: Move syscall code from init to the system library + add a setEventQueue() syscall
This commit is contained in:
parent
fb8de7b83b
commit
6acf83692f
@ -1,7 +1,18 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const system = @import("system");
|
||||||
const platform = @import("../arch/platform.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");
|
||||||
|
const pmm = @import("../pmm.zig");
|
||||||
|
const vmm = @import("../arch/vmm.zig").arch;
|
||||||
|
|
||||||
|
const RingBuffer = system.ring_buffer.RingBuffer;
|
||||||
|
|
||||||
|
const SyscallError = error{
|
||||||
|
NoSuchThread,
|
||||||
|
ThreadQueueAlreadySet,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void {
|
pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
const core = cpu.thisCore();
|
const core = cpu.thisCore();
|
||||||
@ -23,3 +34,17 @@ pub fn getPriority(_: *platform.Registers, _: *sys.Arguments, retval: *isize) an
|
|||||||
pub fn sleep(regs: *platform.Registers, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
if (target.event_queue) |_| return error.ThreadQueueAlreadySet;
|
||||||
|
|
||||||
|
const phys = pmm.PhysFrame{ .address = args.arg1 };
|
||||||
|
|
||||||
|
const virt = phys.virtualAddress(vmm.PHYSICAL_MAPPING_BASE);
|
||||||
|
|
||||||
|
const data: [*]u8 = @ptrFromInt(virt);
|
||||||
|
|
||||||
|
target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true);
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ pub const Arguments = struct {
|
|||||||
|
|
||||||
const SystemCall = *const fn (frame: *platform.Registers, 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, sched.setEventQueue };
|
||||||
|
|
||||||
pub fn invokeSyscall(number: usize, frame: *platform.Registers, 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) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const kernel = @import("../../kernel.zig");
|
const system = @import("system");
|
||||||
|
|
||||||
|
const syscalls = system.syscalls;
|
||||||
|
|
||||||
const MapError = error{
|
const MapError = error{
|
||||||
MemoryAlreadyInUse,
|
MemoryAlreadyInUse,
|
||||||
@ -7,7 +9,7 @@ const MapError = error{
|
|||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
};
|
};
|
||||||
|
|
||||||
const PhysFrame = struct {
|
pub const PhysFrame = struct {
|
||||||
address: u64,
|
address: u64,
|
||||||
|
|
||||||
pub fn virtualAddress(self: *const PhysFrame, base: usize) usize {
|
pub fn virtualAddress(self: *const PhysFrame, base: usize) usize {
|
||||||
@ -105,7 +107,7 @@ fn updatePageTableEntry(entry: *PageTableEntry, phys: PhysFrame, flags: u32) voi
|
|||||||
fn setUpParentPageTableEntry(mapper: *const MemoryMapper, pte: *PageTableEntry, flags: u32) !void {
|
fn setUpParentPageTableEntry(mapper: *const MemoryMapper, pte: *PageTableEntry, flags: u32) !void {
|
||||||
if (pte.present == 0) {
|
if (pte.present == 0) {
|
||||||
pte.clear();
|
pte.clear();
|
||||||
const frame = PhysFrame{ .address = try kernel.allocFrame() };
|
const frame = PhysFrame{ .address = try syscalls.allocFrame() };
|
||||||
pte.present = 1;
|
pte.present = 1;
|
||||||
pte.setAddress(frame.address);
|
pte.setAddress(frame.address);
|
||||||
getTable(mapper, pte).* = std.mem.zeroes(PageDirectory);
|
getTable(mapper, pte).* = std.mem.zeroes(PageDirectory);
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
const SystemCall = enum(u64) {
|
|
||||||
Print,
|
|
||||||
AllocFrame,
|
|
||||||
LockFrame,
|
|
||||||
FreeFrame,
|
|
||||||
Yield,
|
|
||||||
SetPriority,
|
|
||||||
GetPriority,
|
|
||||||
Sleep,
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setPriority(priority: u8) void {
|
|
||||||
_ = syscall(.SetPriority, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getPriority() u8 {
|
|
||||||
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0))));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sleep(ms: u64) void {
|
|
||||||
_ = syscall(.Sleep, ms);
|
|
||||||
}
|
|
@ -1,14 +1,30 @@
|
|||||||
const kernel = @import("kernel.zig");
|
const system = @import("system");
|
||||||
const vm = @import("arch/vm.zig").arch;
|
const vm = @import("arch/vm.zig").arch;
|
||||||
|
|
||||||
|
const syscalls = system.syscalls;
|
||||||
|
const buffer = system.ring_buffer;
|
||||||
|
|
||||||
|
// FIXME: Make arch-specific.
|
||||||
|
const PAGE_SIZE = 4096;
|
||||||
|
|
||||||
|
fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer {
|
||||||
|
const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() };
|
||||||
|
|
||||||
|
const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base));
|
||||||
|
|
||||||
|
try syscalls.setEventQueue(1, phys.address);
|
||||||
|
|
||||||
|
return buffer.RingBuffer.init(data, PAGE_SIZE, true);
|
||||||
|
}
|
||||||
|
|
||||||
export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
||||||
const mapper = vm.MemoryMapper.create(.{ .address = address }, base);
|
const mapper = vm.MemoryMapper.create(.{ .address = address }, base);
|
||||||
|
|
||||||
kernel.print(base);
|
syscalls.print(base);
|
||||||
kernel.print(address);
|
syscalls.print(address);
|
||||||
kernel.print(@intFromPtr(mapper.directory));
|
syscalls.print(@intFromPtr(mapper.directory));
|
||||||
|
|
||||||
const phys = kernel.allocFrame() catch {
|
const phys = syscalls.allocFrame() catch {
|
||||||
while (true) {}
|
while (true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,10 +32,17 @@ export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
|||||||
while (true) {}
|
while (true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var event_queue = setupKernelRingBuffer(base) catch {
|
||||||
|
while (true) {}
|
||||||
|
};
|
||||||
|
|
||||||
var counter: u64 = 0;
|
var counter: u64 = 0;
|
||||||
|
|
||||||
while (true) : (counter += 4) {
|
while (true) : (counter += 4) {
|
||||||
kernel.sleep(1000);
|
syscalls.sleep(1000);
|
||||||
kernel.print(counter);
|
|
||||||
|
// Reading a random number from the ring buffer we share with the kernel :D
|
||||||
|
var data: [1]u8 = .{0};
|
||||||
|
if (event_queue.read(@ptrCast(&data), 1)) syscalls.print(data[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
system/lib/kernel.zig
Normal file
16
system/lib/kernel.zig
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pub const SystemCall = enum(u64) {
|
||||||
|
Print,
|
||||||
|
AllocFrame,
|
||||||
|
LockFrame,
|
||||||
|
FreeFrame,
|
||||||
|
Yield,
|
||||||
|
SetPriority,
|
||||||
|
GetPriority,
|
||||||
|
Sleep,
|
||||||
|
SetEventQueue,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SystemError = error{
|
||||||
|
OutOfMemory,
|
||||||
|
NoSuchThread,
|
||||||
|
};
|
53
system/lib/syscalls.zig
Normal file
53
system/lib/syscalls.zig
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
const kernel = @import("kernel.zig");
|
||||||
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
|
fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64) i64 {
|
||||||
|
return switch (target.cpu.arch) {
|
||||||
|
.x86_64 => asm volatile ("int $66"
|
||||||
|
: [result] "=r" (-> i64),
|
||||||
|
: [num] "{rax}" (@intFromEnum(num)),
|
||||||
|
[arg0] "{rdi}" (arg0),
|
||||||
|
[arg1] "{rsi}" (arg1),
|
||||||
|
),
|
||||||
|
else => @compileError("unsupported architecture"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(arg: u64) void {
|
||||||
|
_ = syscall(.Print, arg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocFrame() !usize {
|
||||||
|
const retval = syscall(.AllocFrame, 0, 0);
|
||||||
|
if (retval < 0) return error.OutOfMemory;
|
||||||
|
return @bitCast(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lockFrame(address: u64) void {
|
||||||
|
_ = syscall(.LockFrame, address, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn freeFrame(address: u64) void {
|
||||||
|
_ = syscall(.FreeFrame, address, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yield() void {
|
||||||
|
_ = syscall(.Yield, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setPriority(priority: u8) void {
|
||||||
|
_ = syscall(.SetPriority, priority, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPriority() u8 {
|
||||||
|
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sleep(ms: u64) void {
|
||||||
|
_ = syscall(.Sleep, ms, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setEventQueue(pid: u64, address: u64) !void {
|
||||||
|
const retval = syscall(.SetEventQueue, pid, address);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
@ -1 +1,3 @@
|
|||||||
|
pub const kernel = @import("kernel.zig");
|
||||||
pub const ring_buffer = @import("ring_buffer.zig");
|
pub const ring_buffer = @import("ring_buffer.zig");
|
||||||
|
pub const syscalls = @import("syscalls.zig");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user