Compare commits
No commits in common. "c80c7bbc6ed8f663ee4d8391c04d28074abdbba9" and "32ecd325e3d1ca1d134a1245e72a42692bd64cde" have entirely different histories.
c80c7bbc6e
...
32ecd325e3
@ -7,12 +7,8 @@ pub fn build(b: *std.Build) void {
|
|||||||
|
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const system_module = b.addModule("system", .{
|
core.build(b, build_step, optimize);
|
||||||
.root_source_file = b.path("system/lib/system.zig"),
|
system.build(b, build_step, optimize);
|
||||||
});
|
|
||||||
|
|
||||||
core.buildAsSubmodule(b, build_step, optimize, system_module);
|
|
||||||
system.buildAsSubmodule(b, build_step, optimize, system_module);
|
|
||||||
|
|
||||||
b.default_step = build_step;
|
b.default_step = build_step;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("std");
|
|||||||
|
|
||||||
const here = "core";
|
const here = "core";
|
||||||
|
|
||||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||||
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||||
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||||
|
|
||||||
@ -38,8 +38,6 @@ pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: st
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
core.root_module.addImport("system", system_module);
|
|
||||||
|
|
||||||
var kernel_step = b.step("core", "Build the core microkernel");
|
var kernel_step = b.step("core", "Build the core microkernel");
|
||||||
kernel_step.dependOn(&core.step);
|
kernel_step.dependOn(&core.step);
|
||||||
kernel_step.dependOn(&install.step);
|
kernel_step.dependOn(&install.step);
|
||||||
|
@ -2,8 +2,8 @@ const std = @import("std");
|
|||||||
const target = @import("builtin").target;
|
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");
|
const vmm = @import("vmm.zig").arch;
|
||||||
const platform = @import("platform.zig");
|
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"),
|
||||||
@ -30,7 +30,6 @@ pub fn setupCore(allocator: *pmm.FrameAllocator) !void {
|
|||||||
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
|
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
|
||||||
idle_thread.state = .Running;
|
idle_thread.state = .Running;
|
||||||
idle_thread.user_priority = 0;
|
idle_thread.user_priority = 0;
|
||||||
idle_thread.event_queue = null;
|
|
||||||
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));
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
pub usingnamespace switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/interrupts.zig"),
|
.x86_64 => @import("x86_64/interrupts.zig"),
|
||||||
else => {
|
else => {
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
pub usingnamespace switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/platform.zig"),
|
.x86_64 => @import("x86_64/platform.zig"),
|
||||||
else => {
|
else => {
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
pub usingnamespace switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/thread.zig"),
|
.x86_64 => @import("x86_64/thread.zig"),
|
||||||
else => {
|
else => {
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
pub usingnamespace switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/vmm.zig"),
|
.x86_64 => @import("x86_64/vmm.zig"),
|
||||||
else => {
|
else => {
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
const vmm = @import("arch/vmm.zig");
|
const vmm = @import("arch/vmm.zig").arch;
|
||||||
const platform = @import("arch/platform.zig");
|
const platform = @import("arch/platform.zig").arch;
|
||||||
const pmm = @import("pmm.zig");
|
const pmm = @import("pmm.zig");
|
||||||
const debug = @import("arch/debug.zig");
|
const debug = @import("arch/debug.zig");
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ const std = @import("std");
|
|||||||
const easyboot = @cImport(@cInclude("easyboot.h"));
|
const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||||
const debug = @import("arch/debug.zig");
|
const debug = @import("arch/debug.zig");
|
||||||
const cpu = @import("arch/cpu.zig");
|
const cpu = @import("arch/cpu.zig");
|
||||||
const platform = @import("arch/platform.zig");
|
const platform = @import("arch/platform.zig").arch;
|
||||||
const interrupts = @import("arch/interrupts.zig");
|
const interrupts = @import("arch/interrupts.zig").arch;
|
||||||
const vmm = @import("arch/vmm.zig");
|
const vmm = @import("arch/vmm.zig").arch;
|
||||||
const multiboot = @import("multiboot.zig");
|
const multiboot = @import("multiboot.zig");
|
||||||
const pmm = @import("pmm.zig");
|
const pmm = @import("pmm.zig");
|
||||||
const thread = @import("thread.zig");
|
const thread = @import("thread.zig");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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");
|
const platform = @import("arch/platform.zig").arch;
|
||||||
const vmm = @import("arch/vmm.zig");
|
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 locking = @import("lib/spinlock.zig");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const platform = @import("../arch/platform.zig");
|
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");
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const platform = @import("../arch/platform.zig");
|
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");
|
||||||
|
|
||||||
|
@ -1,18 +1,7 @@
|
|||||||
const std = @import("std");
|
const platform = @import("../arch/platform.zig").arch;
|
||||||
const system = @import("system");
|
|
||||||
const platform = @import("../arch/platform.zig");
|
|
||||||
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");
|
|
||||||
|
|
||||||
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();
|
||||||
@ -34,17 +23,3 @@ 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);
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const platform = @import("../arch/platform.zig");
|
const platform = @import("../arch/platform.zig").arch;
|
||||||
const print = @import("print.zig");
|
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");
|
||||||
|
|
||||||
@ -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.print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep, sched.setEventQueue };
|
const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep };
|
||||||
|
|
||||||
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,14 +1,11 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const system = @import("system");
|
const vmm = @import("arch/vmm.zig").arch;
|
||||||
const vmm = @import("arch/vmm.zig");
|
const platform = @import("arch/platform.zig").arch;
|
||||||
const platform = @import("arch/platform.zig");
|
|
||||||
const pmm = @import("pmm.zig");
|
const pmm = @import("pmm.zig");
|
||||||
const cpu = @import("arch/cpu.zig");
|
const cpu = @import("arch/cpu.zig");
|
||||||
const locking = @import("lib/spinlock.zig");
|
const locking = @import("lib/spinlock.zig");
|
||||||
|
|
||||||
const RingBuffer = system.ring_buffer.RingBuffer;
|
pub const arch = @import("arch/thread.zig").arch;
|
||||||
|
|
||||||
pub const arch = @import("arch/thread.zig");
|
|
||||||
|
|
||||||
pub const ThreadState = enum {
|
pub const ThreadState = enum {
|
||||||
Inactive,
|
Inactive,
|
||||||
@ -23,7 +20,6 @@ pub const ThreadControlBlock = struct {
|
|||||||
regs: platform.Registers,
|
regs: platform.Registers,
|
||||||
state: ThreadState,
|
state: ThreadState,
|
||||||
user_priority: u8,
|
user_priority: u8,
|
||||||
event_queue: ?RingBuffer,
|
|
||||||
|
|
||||||
// Managed by addThreadToGlobalList(), no need to set manually.
|
// Managed by addThreadToGlobalList(), no need to set manually.
|
||||||
tag: GlobalThreadList.Node,
|
tag: GlobalThreadList.Node,
|
||||||
@ -150,7 +146,6 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB
|
|||||||
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
|
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
|
||||||
thread.state = .Inactive;
|
thread.state = .Inactive;
|
||||||
thread.user_priority = 127;
|
thread.user_priority = 127;
|
||||||
thread.event_queue = null;
|
|
||||||
|
|
||||||
addThreadToGlobalList(thread);
|
addThreadToGlobalList(thread);
|
||||||
|
|
||||||
@ -319,7 +314,7 @@ pub fn lookupThreadById(id: u64) ?*ThreadControlBlock {
|
|||||||
|
|
||||||
var it: ?*GlobalThreadList.Node = global_thread_list.first;
|
var it: ?*GlobalThreadList.Node = global_thread_list.first;
|
||||||
while (it) |n| : (it = n.next) {
|
while (it) |n| : (it = n.next) {
|
||||||
const thread: *ThreadControlBlock = @alignCast(@fieldParentPtr("tag", n));
|
const thread: *ThreadControlBlock = @fieldParentPtr("tag", n);
|
||||||
if (thread.id == id) return thread;
|
if (thread.id == id) return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const init = @import("init/build.zig");
|
const init = @import("init/build.zig");
|
||||||
|
|
||||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||||
const system_step = b.step("system", "Build core system services");
|
const system_step = b.step("system", "Build core system services");
|
||||||
init.buildAsSubmodule(b, system_step, optimize, system_module);
|
init.build(b, system_step, optimize);
|
||||||
|
|
||||||
build_step.dependOn(system_step);
|
build_step.dependOn(system_step);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
pub usingnamespace switch (target.cpu.arch) {
|
pub const arch = switch (target.cpu.arch) {
|
||||||
.x86_64 => @import("x86_64/vm.zig"),
|
.x86_64 => @import("x86_64/vm.zig"),
|
||||||
else => {
|
else => {
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const system = @import("system");
|
const kernel = @import("../../kernel.zig");
|
||||||
|
|
||||||
const syscalls = system.syscalls;
|
|
||||||
|
|
||||||
const MapError = error{
|
const MapError = error{
|
||||||
MemoryAlreadyInUse,
|
MemoryAlreadyInUse,
|
||||||
@ -9,7 +7,7 @@ const MapError = error{
|
|||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PhysFrame = struct {
|
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 {
|
||||||
@ -107,7 +105,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 syscalls.allocFrame() };
|
const frame = PhysFrame{ .address = try kernel.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);
|
||||||
|
@ -2,7 +2,7 @@ const std = @import("std");
|
|||||||
|
|
||||||
const here = "system/init";
|
const here = "system/init";
|
||||||
|
|
||||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||||
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||||
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||||
|
|
||||||
@ -29,8 +29,6 @@ pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: st
|
|||||||
.code_model = .default,
|
.code_model = .default,
|
||||||
});
|
});
|
||||||
|
|
||||||
init.root_module.addImport("system", system_module);
|
|
||||||
|
|
||||||
const install = b.addInstallArtifact(init, .{
|
const install = b.addInstallArtifact(init, .{
|
||||||
.dest_dir = .{
|
.dest_dir = .{
|
||||||
.override = .{ .custom = "boot/" },
|
.override = .{ .custom = "boot/" },
|
||||||
|
56
system/init/kernel.zig
Normal file
56
system/init/kernel.zig
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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,30 +1,14 @@
|
|||||||
const system = @import("system");
|
const kernel = @import("kernel.zig");
|
||||||
const vm = @import("arch/vm.zig");
|
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);
|
||||||
|
|
||||||
syscalls.print(base);
|
kernel.print(base);
|
||||||
syscalls.print(address);
|
kernel.print(address);
|
||||||
syscalls.print(@intFromPtr(mapper.directory));
|
kernel.print(@intFromPtr(mapper.directory));
|
||||||
|
|
||||||
const phys = syscalls.allocFrame() catch {
|
const phys = kernel.allocFrame() catch {
|
||||||
while (true) {}
|
while (true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,16 +16,10 @@ export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
|||||||
while (true) {}
|
while (true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const event_queue = setupKernelRingBuffer(base) catch {
|
|
||||||
while (true) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
_ = event_queue;
|
|
||||||
|
|
||||||
var counter: u64 = 0;
|
var counter: u64 = 0;
|
||||||
|
|
||||||
while (true) : (counter += 4) {
|
while (true) : (counter += 4) {
|
||||||
syscalls.sleep(1000);
|
kernel.sleep(1000);
|
||||||
syscalls.print(counter);
|
kernel.print(counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
pub const SystemCall = enum(u64) {
|
|
||||||
Print,
|
|
||||||
AllocFrame,
|
|
||||||
LockFrame,
|
|
||||||
FreeFrame,
|
|
||||||
Yield,
|
|
||||||
SetPriority,
|
|
||||||
GetPriority,
|
|
||||||
Sleep,
|
|
||||||
SetEventQueue,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const SystemError = error{
|
|
||||||
OutOfMemory,
|
|
||||||
NoSuchThread,
|
|
||||||
};
|
|
@ -1,130 +0,0 @@
|
|||||||
//! Single-producer single-consumer lockfree ring buffer, which supports reading and storing arbitrary amounts of bytes,
|
|
||||||
//! and which supports being stored in shared memory, for usage in IPC.
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub const RingBuffer = struct {
|
|
||||||
const Data = packed struct {
|
|
||||||
read_index: u16,
|
|
||||||
write_index: u16,
|
|
||||||
data_start: u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
capacity: u16,
|
|
||||||
data: *Data,
|
|
||||||
|
|
||||||
pub fn init(buffer: [*]u8, length: u16, initialize: bool) RingBuffer {
|
|
||||||
const data: *Data = @alignCast(@ptrCast(buffer));
|
|
||||||
|
|
||||||
if (initialize) {
|
|
||||||
data.read_index = 0;
|
|
||||||
data.write_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const capacity = length - (@sizeOf(@TypeOf(data.read_index)) + @sizeOf(@TypeOf(data.write_index)));
|
|
||||||
|
|
||||||
return .{ .capacity = capacity, .data = data };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: *RingBuffer, data: [*]const u8, length: usize) bool {
|
|
||||||
const available = self.bytesAvailableToWrite();
|
|
||||||
var tail = @atomicLoad(u16, &self.data.write_index, .monotonic);
|
|
||||||
|
|
||||||
const buffer = self.dataPointer();
|
|
||||||
|
|
||||||
const bytes_to_write = length;
|
|
||||||
if (bytes_to_write == 0) return false;
|
|
||||||
if (bytes_to_write > available) return false;
|
|
||||||
if (self.capacity <= tail) return false;
|
|
||||||
|
|
||||||
var written: usize = 0;
|
|
||||||
|
|
||||||
// Write first segment: from tail up to the end of the buffer.
|
|
||||||
const first_chunk = @min(bytes_to_write, self.capacity - tail);
|
|
||||||
@memcpy(buffer[tail .. tail + first_chunk], data[0..first_chunk]);
|
|
||||||
written += first_chunk;
|
|
||||||
tail = (tail + first_chunk) % self.capacity;
|
|
||||||
|
|
||||||
// Write second segment if needed (wrap-around).
|
|
||||||
if (written < bytes_to_write) {
|
|
||||||
const second_chunk = bytes_to_write - written;
|
|
||||||
@memcpy(buffer[0..second_chunk], data[first_chunk .. first_chunk + second_chunk]);
|
|
||||||
tail = @intCast(second_chunk);
|
|
||||||
written += second_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
@atomicStore(u16, &self.data.write_index, tail, .release);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_impl(self: *RingBuffer, data: [*]u8, length: usize) ?u16 {
|
|
||||||
const available = self.bytesAvailableToRead();
|
|
||||||
var head = @atomicLoad(u16, &self.data.read_index, .monotonic);
|
|
||||||
|
|
||||||
const buffer = self.dataPointer();
|
|
||||||
|
|
||||||
const bytes_to_read = length;
|
|
||||||
if (bytes_to_read == 0) return null;
|
|
||||||
if (bytes_to_read > available) return null;
|
|
||||||
if (self.capacity <= head) return null;
|
|
||||||
|
|
||||||
var bytes_read: usize = 0;
|
|
||||||
|
|
||||||
// Read first segment: from head up to the end of the buffer.
|
|
||||||
const first_chunk = @min(bytes_to_read, self.capacity - head);
|
|
||||||
@memcpy(data[0..first_chunk], buffer[head .. head + first_chunk]);
|
|
||||||
bytes_read += first_chunk;
|
|
||||||
head = (head + first_chunk) % self.capacity;
|
|
||||||
|
|
||||||
// Read second segment if needed (wrap-around).
|
|
||||||
if (bytes_read < bytes_to_read) {
|
|
||||||
const second_chunk = bytes_to_read - bytes_read;
|
|
||||||
@memcpy(data[first_chunk .. first_chunk + second_chunk], buffer[0..second_chunk]);
|
|
||||||
head = @intCast(second_chunk);
|
|
||||||
bytes_read += second_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek(self: *RingBuffer, data: [*]u8, length: usize) bool {
|
|
||||||
return switch (self.read_impl(data, length)) {
|
|
||||||
null => false,
|
|
||||||
else => true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: *RingBuffer, data: [*]u8, length: usize) bool {
|
|
||||||
const result = self.read_impl(data, length) orelse return false;
|
|
||||||
|
|
||||||
@atomicStore(u16, &self.data.read_index, result, .release);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dataPointer(self: *RingBuffer) [*]u8 {
|
|
||||||
return @ptrCast(&self.data.data_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bytesAvailableToWrite(self: *RingBuffer) u16 {
|
|
||||||
const head = @atomicLoad(u16, &self.data.read_index, .acquire);
|
|
||||||
const tail = @atomicLoad(u16, &self.data.write_index, .monotonic);
|
|
||||||
if (head >= self.capacity or tail >= self.capacity) return 0; // Who tampered with the indices??
|
|
||||||
if (tail >= head) {
|
|
||||||
return self.capacity - (tail - head) - 1;
|
|
||||||
} else {
|
|
||||||
return head - tail - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bytesAvailableToRead(self: *RingBuffer) u16 {
|
|
||||||
const head = @atomicLoad(u16, &self.data.read_index, .monotonic);
|
|
||||||
const tail = @atomicLoad(u16, &self.data.write_index, .acquire);
|
|
||||||
if (head >= self.capacity or tail >= self.capacity) return 0; // Who tampered with the indices??
|
|
||||||
if (tail >= head) {
|
|
||||||
return tail - head;
|
|
||||||
} else {
|
|
||||||
return self.capacity - (head - tail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
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,3 +0,0 @@
|
|||||||
pub const kernel = @import("kernel.zig");
|
|
||||||
pub const ring_buffer = @import("ring_buffer.zig");
|
|
||||||
pub const syscalls = @import("syscalls.zig");
|
|
Loading…
x
Reference in New Issue
Block a user