WIP: test objects
This commit is contained in:
+19
-1
@@ -1,3 +1,21 @@
|
||||
pub const SyscallNumber = enum(usize) { SYS_debug_write = 1, SYS_exit = 2, _ };
|
||||
pub const SyscallNumber = enum(usize) {
|
||||
SYS_send = 1,
|
||||
SYS_recv = 2,
|
||||
SYS_sendrecv = 3,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const ProcessObjectAction = enum(usize) {
|
||||
ZO_process_exit = 1,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const PhysicalMemoryObjectAction = enum(usize) {
|
||||
ZO_physical_memory_allocate = 1,
|
||||
ZO_physical_memory_free = 2,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const MAX_SYSCALL: usize = 32;
|
||||
|
||||
pub const Handle = enum(u32) { _ };
|
||||
|
||||
@@ -92,10 +92,7 @@ export fn __aa64_el0_sync_handler(frame: *ExceptionFrame) callconv(.C) void {
|
||||
|
||||
switch (esr.as_enum()) {
|
||||
.svc => {
|
||||
const func = frame.xN[8];
|
||||
const args = frame.xN[0..6];
|
||||
const result = syscall.syscall_handler(func, args);
|
||||
frame.xN[0] = result;
|
||||
syscall.syscall_handler(frame.xN[8], frame.xN[0..6]);
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
const mem = @import("mem.zig");
|
||||
const kernel = @import("kernel.zig");
|
||||
const thread = @import("thread.zig");
|
||||
const abi = @import("abi");
|
||||
|
||||
const ProcessAddressSpace = mem.vmm.ProcessAddressSpace;
|
||||
const log = kernel.log;
|
||||
const Thread = thread.Thread;
|
||||
|
||||
pub const PhysicalMemoryObject = struct {
|
||||
fn send(self: *const PhysicalMemoryObject, caller: *Thread, message: *const [5]usize) usize {
|
||||
_ = self;
|
||||
_ = caller;
|
||||
_ = message;
|
||||
@panic("TODO: physical memory object messaging");
|
||||
}
|
||||
|
||||
fn sendrecv(self: *const PhysicalMemoryObject, caller: *Thread, message: *[5]usize) usize {
|
||||
switch (@as(abi.PhysicalMemoryObjectAction, @enumFromInt(message[0]))) {
|
||||
.ZO_physical_memory_allocate => {
|
||||
// TODO somehow track ownership of the memory by the process
|
||||
const pages = mem.phys.alloc_pages(message[1]) orelse {
|
||||
return 1;
|
||||
};
|
||||
log.info("{*}: allocated {} pages: 0x{x}", .{caller, message[1], pages.raw});
|
||||
message[0] = pages.raw;
|
||||
return 0;
|
||||
},
|
||||
.ZO_physical_memory_free => {
|
||||
@panic("TODO: ZO_physical_memory_free");
|
||||
},
|
||||
else => {
|
||||
@panic("TODO: invalid message to Physical Memory Object");
|
||||
}
|
||||
}
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
pub const ProcessObject = struct {
|
||||
inner: *Thread,
|
||||
|
||||
fn send(self: *const ProcessObject, caller: *Thread, message: *const [5]usize) usize {
|
||||
_ = self;
|
||||
// TODO define this in IDL/ABI
|
||||
switch (@as(abi.ProcessObjectAction, @enumFromInt(message[0]))) {
|
||||
.ZO_process_exit => {
|
||||
log.info("{*} exited with code 0x{x} ({})", .{caller, message[1], message[1]});
|
||||
Thread.exit_current();
|
||||
},
|
||||
else => {
|
||||
@panic("TODO: invalid message to Process Object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sendrecv(self: *const ProcessObject, caller: *Thread, message: *[5]usize) usize {
|
||||
_ = self;
|
||||
_ = caller;
|
||||
_ = message;
|
||||
@panic("TODO: ProcessObject sendrecv()");
|
||||
}
|
||||
};
|
||||
|
||||
pub const DebugObject = struct {
|
||||
fn send(self: *const DebugObject, caller: *Thread, message: *const [5]usize) usize {
|
||||
_ = self;
|
||||
// Debug has only one message
|
||||
const text = @as([*]u8, @ptrFromInt(message[0]))[0..message[1]];
|
||||
log.info("{*}: {s}", .{ caller, text });
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn sendrecv(self: *const DebugObject, caller: *Thread, message: *[5]usize) usize {
|
||||
_ = self;
|
||||
_ = caller;
|
||||
_ = message;
|
||||
@panic("TODO: DebugObject sendrecv()");
|
||||
}
|
||||
};
|
||||
|
||||
pub const Object = union(enum) {
|
||||
physical_memory: PhysicalMemoryObject,
|
||||
process: ProcessObject,
|
||||
debug: DebugObject,
|
||||
// TODO userspace "object" can be placed here
|
||||
|
||||
pub fn send(self: Object, caller: *Thread, message: *const [5]usize) usize {
|
||||
return switch (self) {
|
||||
.physical_memory => |physical_memory| physical_memory.send(caller, message),
|
||||
.process => |process| process.send(caller, message),
|
||||
.debug => |debug| debug.send(caller, message),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn sendrecv(self: Object, caller: *Thread, message: *[5]usize) usize {
|
||||
return switch (self) {
|
||||
.physical_memory => |physical_memory| physical_memory.sendrecv(caller, message),
|
||||
.process => |process| process.sendrecv(caller, message),
|
||||
.debug => |debug| debug.sendrecv(caller, message),
|
||||
};
|
||||
}
|
||||
};
|
||||
+26
-14
@@ -5,39 +5,51 @@ const thread = kernel.thread;
|
||||
const Thread = thread.Thread;
|
||||
const log = kernel.log;
|
||||
|
||||
pub const SyscallFn = *const fn (*Thread, []usize) usize;
|
||||
pub const SyscallFn = *const fn (*Thread, *[6]usize) void;
|
||||
|
||||
pub const syscall_table: [abi.MAX_SYSCALL]?SyscallFn = make_syscall_table();
|
||||
|
||||
fn make_syscall_table() [abi.MAX_SYSCALL]?SyscallFn {
|
||||
const SC = abi.SyscallNumber;
|
||||
var array = [_]?SyscallFn{undefined} ** abi.MAX_SYSCALL;
|
||||
array[@intFromEnum(SC.SYS_debug_write)] = sys_debug_write;
|
||||
array[@intFromEnum(SC.SYS_exit)] = sys_exit;
|
||||
array[@intFromEnum(SC.SYS_send)] = sys_send;
|
||||
array[@intFromEnum(SC.SYS_recv)] = sys_recv;
|
||||
array[@intFromEnum(SC.SYS_sendrecv)] = sys_sendrecv;
|
||||
return array;
|
||||
}
|
||||
|
||||
fn sys_exit(cthread: *Thread, args: []usize) usize {
|
||||
log.info("{*} exits with code {}", .{ cthread, args[0] });
|
||||
Thread.exit_current();
|
||||
fn sys_send(cthread: *Thread, frame: *[6]usize) void {
|
||||
const handle: abi.Handle = @enumFromInt(frame[0]);
|
||||
const object = cthread.handle(handle) orelse {
|
||||
@panic("TODO: userspace invoked non-existent handle");
|
||||
};
|
||||
frame[0] = object.send(cthread, frame[1..6]);
|
||||
}
|
||||
|
||||
fn sys_debug_write(cthread: *Thread, args: []usize) usize {
|
||||
const message = @as([*]const u8, @ptrFromInt(args[0]))[0..args[1]];
|
||||
log.debug("{*}: {s}", .{ cthread, message });
|
||||
return 0;
|
||||
fn sys_recv(cthread: *Thread, frame: *[6]usize) void {
|
||||
_ = cthread;
|
||||
_ = frame;
|
||||
@panic("TODO: SYS_recv()");
|
||||
}
|
||||
|
||||
fn sys_undefined_syscall(cthread: *Thread, args: []usize) usize {
|
||||
_ = args;
|
||||
fn sys_sendrecv(cthread: *Thread, frame: *[6]usize) void {
|
||||
const handle: abi.Handle = @enumFromInt(frame[0]);
|
||||
const object = cthread.handle(handle) orelse {
|
||||
@panic("TODO: userspace invoked non-existent handle");
|
||||
};
|
||||
frame[0] = object.sendrecv(cthread, frame[1..6]);
|
||||
}
|
||||
|
||||
fn sys_undefined_syscall(cthread: *Thread, frame: *[6]usize) void {
|
||||
_ = frame;
|
||||
log.warn("{*} invoked an undefined syscall", .{cthread});
|
||||
Thread.exit_current();
|
||||
}
|
||||
|
||||
pub fn syscall_handler(func: usize, args: []usize) usize {
|
||||
pub fn syscall_handler(func: usize, frame: *[6]usize) void {
|
||||
const cthread = thread.Thread.current();
|
||||
const handler = if (func >= abi.MAX_SYSCALL) sys_undefined_syscall //
|
||||
else syscall_table[func] //
|
||||
orelse sys_undefined_syscall;
|
||||
return handler(cthread, args);
|
||||
handler(cthread, frame);
|
||||
}
|
||||
|
||||
+117
-82
@@ -7,8 +7,12 @@ const arch = @import("kernel.zig").arch;
|
||||
const log = @import("debug.zig").log;
|
||||
const mem = @import("mem.zig");
|
||||
const sync = @import("sync.zig");
|
||||
const object = @import("object.zig");
|
||||
const abi = @import("abi");
|
||||
|
||||
const ProcessAddressSpace = mem.vmm.ProcessAddressSpace;
|
||||
const Object = object.Object;
|
||||
const Handle = abi.Handle;
|
||||
|
||||
// TODO: are kernel threads needed at all if we're doing a microkernel?
|
||||
|
||||
@@ -27,6 +31,113 @@ pub fn idle_function(arg: usize) callconv(.C) noreturn {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a single execution thread.
|
||||
pub const Thread = struct {
|
||||
const MAX_HANDLES: usize = 64;
|
||||
|
||||
/// Arena.
|
||||
allocator: *arena.Arena,
|
||||
/// Architecture-specific task context.
|
||||
arch_context: arch.Context,
|
||||
|
||||
/// Queue to which this thread belongs
|
||||
queue: ?*Queue = null,
|
||||
/// Next thread in the queue.
|
||||
next: ?*Thread = null,
|
||||
/// Previous thread in the queue.
|
||||
prev: ?*Thread = null,
|
||||
|
||||
// TODO move to process
|
||||
address_space: ?ProcessAddressSpace = null,
|
||||
// TODO move to process
|
||||
handle_table: [MAX_HANDLES]?Object = [_]?Object{null} ** MAX_HANDLES,
|
||||
|
||||
pub const Error = error{out_of_memory} || mem.vmm.AddressSpaceError;
|
||||
|
||||
/// Creates a new (kernel) thread with given `function` and `arg`ument.
|
||||
pub fn create_kernel(a: *arena.Arena, function: *const KernelThreadFn, arg: usize) *Thread {
|
||||
const thread = a.create(Thread);
|
||||
thread.* = .{
|
||||
.allocator = a,
|
||||
.arch_context = arch.Context.kernel(function, arg),
|
||||
};
|
||||
return thread;
|
||||
}
|
||||
|
||||
pub fn create_user(
|
||||
a: *arena.Arena,
|
||||
address_space: ProcessAddressSpace,
|
||||
pc: usize,
|
||||
sp: usize,
|
||||
arg: usize,
|
||||
) *Thread {
|
||||
const thread = a.create(Thread);
|
||||
thread.* = .{
|
||||
.allocator = a,
|
||||
.address_space = address_space,
|
||||
.arch_context = arch.Context.user(&address_space, pc, sp, arg),
|
||||
};
|
||||
// "self" process object is granted to all processes
|
||||
const process_object = Object{ .process = object.ProcessObject {
|
||||
.inner = thread,
|
||||
} };
|
||||
_ = thread.grant(process_object);
|
||||
return thread;
|
||||
}
|
||||
|
||||
/// Enters the thread, does not return.
|
||||
pub fn enter(self: *@This()) noreturn {
|
||||
self.arch_context.enter();
|
||||
}
|
||||
|
||||
/// Switches from `from` to `self` thread.
|
||||
pub fn switch_from(self: *@This(), from: *@This()) void {
|
||||
self.arch_context.switch_from(&from.arch_context);
|
||||
}
|
||||
|
||||
pub fn grant(self: *@This(), obj: Object) Handle {
|
||||
for (0..MAX_HANDLES) |i| {
|
||||
if (self.handle_table[i] == null) {
|
||||
self.handle_table[i] = obj;
|
||||
return @enumFromInt(i + 1);
|
||||
}
|
||||
}
|
||||
@panic("TODO: ran out of objects");
|
||||
}
|
||||
|
||||
pub fn handle(self: *@This(), h: Handle) ?Object {
|
||||
const index = @as(usize, @intFromEnum(h));
|
||||
if (index > MAX_HANDLES or index == 0) {
|
||||
return null;
|
||||
}
|
||||
return self.handle_table[index - 1];
|
||||
}
|
||||
|
||||
pub fn dequeue(self: *@This()) void {
|
||||
// TODO queueing information should be put under a lock for SMP to work properly
|
||||
if (self.queue) |q| {
|
||||
q.dequeue(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current() *@This() {
|
||||
return Queue.t_this_cpu.?.current.?;
|
||||
}
|
||||
|
||||
pub fn exit_current() noreturn {
|
||||
// Mask IRQs so they don't break current thread's state
|
||||
const mask = arch.IrqGuard.acquire();
|
||||
defer mask.release();
|
||||
|
||||
const curr = Thread.current();
|
||||
curr.dequeue();
|
||||
|
||||
yield();
|
||||
|
||||
@panic("This code should not be reachable");
|
||||
}
|
||||
};
|
||||
|
||||
/// Per-CPU thread queue structure.
|
||||
pub const Queue = struct {
|
||||
/// Idle task context. Used when there are no other tasks running.
|
||||
@@ -152,86 +263,6 @@ pub const Queue = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a single execution thread.
|
||||
pub const Thread = struct {
|
||||
/// Arena.
|
||||
allocator: *arena.Arena,
|
||||
/// Architecture-specific task context.
|
||||
arch_context: arch.Context,
|
||||
|
||||
/// Queue to which this thread belongs
|
||||
queue: ?*Queue = null,
|
||||
/// Next thread in the queue.
|
||||
next: ?*Thread = null,
|
||||
/// Previous thread in the queue.
|
||||
prev: ?*Thread = null,
|
||||
|
||||
// TODO move to process
|
||||
address_space: ?ProcessAddressSpace = null,
|
||||
|
||||
pub const Error = error{out_of_memory} || mem.vmm.AddressSpaceError;
|
||||
|
||||
/// Creates a new (kernel) thread with given `function` and `arg`ument.
|
||||
pub fn create_kernel(a: *arena.Arena, function: *const KernelThreadFn, arg: usize) *Thread {
|
||||
const thread = a.create(Thread);
|
||||
thread.* = .{
|
||||
.allocator = a,
|
||||
.arch_context = arch.Context.kernel(function, arg),
|
||||
};
|
||||
return thread;
|
||||
}
|
||||
|
||||
pub fn create_user(
|
||||
a: *arena.Arena,
|
||||
address_space: ProcessAddressSpace,
|
||||
pc: usize,
|
||||
sp: usize,
|
||||
arg: usize,
|
||||
) *Thread {
|
||||
const thread = a.create(Thread);
|
||||
thread.* = .{
|
||||
.allocator = a,
|
||||
.address_space = address_space,
|
||||
.arch_context = arch.Context.user(&address_space, pc, sp, arg),
|
||||
};
|
||||
return thread;
|
||||
}
|
||||
|
||||
/// Enters the thread, does not return.
|
||||
pub fn enter(self: *@This()) noreturn {
|
||||
self.arch_context.enter();
|
||||
}
|
||||
|
||||
/// Switches from `from` to `self` thread.
|
||||
pub fn switch_from(self: *@This(), from: *@This()) void {
|
||||
self.arch_context.switch_from(&from.arch_context);
|
||||
}
|
||||
|
||||
pub fn dequeue(self: *@This()) void {
|
||||
// TODO queueing information should be put under a lock for SMP to work properly
|
||||
if (self.queue) |q| {
|
||||
q.dequeue(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current() *@This() {
|
||||
return Queue.t_this_cpu.?.current.?;
|
||||
}
|
||||
|
||||
pub fn exit_current() noreturn {
|
||||
// Mask IRQs so they don't break current thread's state
|
||||
const mask = arch.IrqGuard.acquire();
|
||||
defer mask.release();
|
||||
|
||||
const curr = Thread.current();
|
||||
curr.dequeue();
|
||||
|
||||
yield();
|
||||
|
||||
@panic("This code should not be reachable");
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper data structure to represent kernel stacks in task contexts.
|
||||
pub fn KStack(comptime SIZE: usize) type {
|
||||
return extern struct {
|
||||
@@ -292,6 +323,7 @@ pub fn yield() void {
|
||||
|
||||
pub fn test_create_user_from_code(a: *arena.Arena, code: []const u8) Thread.Error!*Thread {
|
||||
const L3 = mem.vmm.L3;
|
||||
const CODE_BASE: usize = 0x200000;
|
||||
|
||||
var address_space = try ProcessAddressSpace.init(a);
|
||||
errdefer {
|
||||
@@ -302,7 +334,7 @@ pub fn test_create_user_from_code(a: *arena.Arena, code: []const u8) Thread.Erro
|
||||
const code_page_count = L3.page_count(code.len);
|
||||
log.info("Code is {} pages", .{code_page_count});
|
||||
var offset: usize = 0;
|
||||
var address: usize = 0x200000;
|
||||
var address: usize = CODE_BASE;
|
||||
while (offset < code.len) {
|
||||
const page_offset = address % L3.SIZE;
|
||||
const amount = @min(L3.SIZE - page_offset, code.len - offset);
|
||||
@@ -327,7 +359,10 @@ pub fn test_create_user_from_code(a: *arena.Arena, code: []const u8) Thread.Erro
|
||||
|
||||
log.info("Enter with sp = 0x{x}", .{sp});
|
||||
|
||||
const thread = Thread.create_user(a, address_space, 0x200000, sp, 1234);
|
||||
const thread = Thread.create_user(a, address_space, CODE_BASE, sp, 1234);
|
||||
|
||||
_ = thread.grant(Object { .physical_memory = object.PhysicalMemoryObject {} });
|
||||
_ = thread.grant(Object { .debug = object.DebugObject {} });
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,13 @@ SECTIONS {
|
||||
*(.rodata*)
|
||||
}
|
||||
|
||||
.eh_frame_hdr : {
|
||||
*(.eh_frame_hdr*)
|
||||
}
|
||||
.eh_frame : {
|
||||
*(.eh_frame*)
|
||||
}
|
||||
|
||||
.data : ALIGN(4K) {
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
+41
-8
@@ -1,22 +1,55 @@
|
||||
const abi = @import("abi");
|
||||
|
||||
pub const syscall = struct {
|
||||
pub fn syscall1(func: abi.SyscallNumber, arg0: usize) usize {
|
||||
pub fn send(handle: u32, msg: *const [5]usize) usize {
|
||||
return asm volatile ("svc #0"
|
||||
: [result] "={x0}" (-> usize),
|
||||
: [arg0] "{x0}" (arg0),
|
||||
[func] "{x8}" (@intFromEnum(func)),
|
||||
: [a0] "{x0}" (handle),
|
||||
[a1] "{x1}" (msg[0]),
|
||||
[a2] "{x2}" (msg[1]),
|
||||
[a3] "{x3}" (msg[2]),
|
||||
[a4] "{x4}" (msg[3]),
|
||||
[a5] "{x5}" (msg[4]),
|
||||
[func] "{x8}" (@intFromEnum(abi.SyscallNumber.SYS_send)),
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
pub fn syscall2(func: abi.SyscallNumber, arg0: usize, arg1: usize) usize {
|
||||
return asm volatile ("svc #0"
|
||||
pub fn sendrecv(handle: u32, msg: *const[5]usize, buffer: *[5]usize) usize {
|
||||
return asm volatile (
|
||||
\\ svc #0
|
||||
\\ stp x1, x2, [%[buf], #16 * 0]
|
||||
\\ stp x3, x4, [%[buf], #16 * 1]
|
||||
\\ str x5, [%[buf], #16 * 2]
|
||||
: [result] "={x0}" (-> usize),
|
||||
: [arg0] "{x0}" (arg0),
|
||||
[arg1] "{x1}" (arg1),
|
||||
[func] "{x8}" (@intFromEnum(func)),
|
||||
: [a0] "{x0}" (handle),
|
||||
[a1] "{x1}" (msg[0]),
|
||||
[a2] "{x2}" (msg[1]),
|
||||
[a3] "{x3}" (msg[2]),
|
||||
[a4] "{x4}" (msg[3]),
|
||||
[a5] "{x5}" (msg[4]),
|
||||
[func] "{x8}" (@intFromEnum(abi.SyscallNumber.SYS_sendrecv)),
|
||||
[buf] "r" (buffer),
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
// pub fn syscall1(func: abi.SyscallNumber, arg0: usize) usize {
|
||||
// return asm volatile ("svc #0"
|
||||
// : [result] "={x0}" (-> usize),
|
||||
// : [arg0] "{x0}" (arg0),
|
||||
// [func] "{x8}" (@intFromEnum(func)),
|
||||
// : "memory"
|
||||
// );
|
||||
// }
|
||||
|
||||
// pub fn syscall2(func: abi.SyscallNumber, arg0: usize, arg1: usize) usize {
|
||||
// return asm volatile ("svc #0"
|
||||
// : [result] "={x0}" (-> usize),
|
||||
// : [arg0] "{x0}" (arg0),
|
||||
// [arg1] "{x1}" (arg1),
|
||||
// [func] "{x8}" (@intFromEnum(func)),
|
||||
// : "memory"
|
||||
// );
|
||||
// }
|
||||
};
|
||||
|
||||
+52
-2
@@ -1,8 +1,58 @@
|
||||
pub const arch = @import("arch.zig");
|
||||
pub const syscall = @import("syscall.zig");
|
||||
pub const log = @import("log.zig");
|
||||
const abi = @import("abi");
|
||||
|
||||
const Handle = abi.Handle;
|
||||
|
||||
fn debug_write(handle: Handle, message: []const u8) void {
|
||||
_ = syscall.send(handle, &.{
|
||||
@intFromPtr(message.ptr),
|
||||
message.len,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
});
|
||||
}
|
||||
|
||||
fn exit_process(handle: Handle, code: u32) noreturn {
|
||||
_ = syscall.send(handle, &.{
|
||||
@intFromEnum(abi.ProcessObjectAction.ZO_process_exit),
|
||||
code,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn allocate_memory(handle: Handle, count: usize) u64 {
|
||||
var output: [5]usize = undefined;
|
||||
// TODO error code
|
||||
_ = syscall.sendrecv(
|
||||
handle,
|
||||
&.{
|
||||
@intFromEnum(abi.PhysicalMemoryObjectAction.ZO_physical_memory_allocate),
|
||||
count,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
&output,
|
||||
);
|
||||
return output[0];
|
||||
}
|
||||
|
||||
export fn _start(arg: usize) linksection(".text.entry") callconv(.C) noreturn {
|
||||
log.println("arg=0x{x} ({})", .{ arg, arg });
|
||||
syscall.exit(0);
|
||||
// TODO make the kernel provide those dynamically somehow
|
||||
const SELF_PROCESS_HANDLE: Handle = @enumFromInt(1);
|
||||
const PHYSICAL_MEMORY_HANDLE: Handle = @enumFromInt(2);
|
||||
const DEBUG_HANDLE: Handle = @enumFromInt(3);
|
||||
|
||||
_ = arg;
|
||||
const mem = allocate_memory(PHYSICAL_MEMORY_HANDLE, 8);
|
||||
_ = mem;
|
||||
|
||||
debug_write(DEBUG_HANDLE, "Hello!!!");
|
||||
exit_process(SELF_PROCESS_HANDLE, 4321);
|
||||
}
|
||||
|
||||
+17
-6
@@ -2,13 +2,24 @@ const arch = @import("arch.zig");
|
||||
const abi = @import("abi");
|
||||
|
||||
const sc = arch.syscall;
|
||||
const SC = abi.SyscallNumber;
|
||||
|
||||
pub fn exit(code: u32) noreturn {
|
||||
_ = sc.syscall1(SC.SYS_exit, code);
|
||||
unreachable;
|
||||
pub inline fn send(object: abi.Handle, msg: *const [5]usize) usize {
|
||||
return sc.send(@intFromEnum(object), msg);
|
||||
}
|
||||
|
||||
pub fn debug_write(text: []const u8) void {
|
||||
_ = sc.syscall2(SC.SYS_debug_write, @intFromPtr(text.ptr), text.len);
|
||||
pub inline fn recv(object: abi.Handle, buffer: *[5]usize) usize {
|
||||
return sc.recv(@intFromEnum(object), buffer);
|
||||
}
|
||||
|
||||
pub inline fn sendrecv(object: abi.Handle, msg: *const [5]usize, buffer: *[5]usize) usize {
|
||||
return sc.sendrecv(@intFromEnum(object), msg, buffer);
|
||||
}
|
||||
|
||||
// pub fn exit(code: u32) noreturn {
|
||||
// _ = sc.syscall1(SC.SYS_exit, code);
|
||||
// unreachable;
|
||||
// }
|
||||
//
|
||||
// pub fn debug_write(text: []const u8) void {
|
||||
// _ = sc.syscall2(SC.SYS_debug_write, @intFromPtr(text.ptr), text.len);
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user