1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
const std = @import("std");
const Console = @import("Console.zig");
const TrapFrame = @import("TrapFrame.zig");
const mem = @import("mem.zig");
const paging = @import("paging.zig");
const process = @import("process.zig");
const riscv = @import("riscv.zig");
pub const Error = error{
ZeroAddressSupplied,
};
pub const HandleError = error{
UnknownSyscall,
};
pub fn handler(proc: *process.Info, trap_frame: *TrapFrame) !void {
switch (trap_frame.general_purpose_registers[17]) {
100000 => trap_frame.setReturnValue(errorName(trap_frame)),
100001 => trap_frame.setReturnValue(consoleWrite(trap_frame)),
100002 => trap_frame.setReturnValue(launch(trap_frame)),
100003 => trap_frame.setReturnValue(end(proc)),
100004 => trap_frame.setReturnValue(terminate(proc, trap_frame)),
100005 => trap_frame.setReturnValue(processId(proc)),
100006 => trap_frame.setReturnValue(threadId(proc)),
else => return HandleError.UnknownSyscall,
}
}
pub const ErrorNameError = error{ErrorCodeOutOfRange};
// errorName(code: u16, buffer: [*]u8, len: usize) !usize
fn errorName(trap_frame: *const TrapFrame) !usize {
const code_wide = trap_frame.general_purpose_registers[10];
const buffer_opt: ?[*]u8 = @ptrFromInt(trap_frame.general_purpose_registers[11]);
const buffer_ptr = buffer_opt orelse return Error.ZeroAddressSupplied;
const len = trap_frame.general_purpose_registers[12];
const code = std.math.cast(u16, code_wide) orelse {
return ErrorNameError.ErrorCodeOutOfRange;
};
const buffer = buffer_ptr[0..len];
if (code == 0) return 0;
const error_name = @errorName(@errorFromInt(code));
const n = @min(buffer.len, error_name.len);
paging.setUserMemoryAccess(true);
defer paging.setUserMemoryAccess(false);
@memcpy(buffer[0..n], error_name[0..n]);
return n;
}
// consoleWrite(bytes: [*]const u8, len: usize) !usize
fn consoleWrite(trap_frame: *const TrapFrame) !usize {
const vaddr = trap_frame.general_purpose_registers[10];
const len = trap_frame.general_purpose_registers[11];
const procmem: *paging.Table = @ptrFromInt(riscv.satp.read().ppn << 12);
const flags = paging.EntryFlags.userReadOnly;
const paddr = procmem.translate(vaddr, flags) orelse {
const faulter: *volatile u8 = @ptrFromInt(vaddr);
_ = faulter.*;
unreachable;
};
const bytes_ptr: [*]const u8 = @ptrFromInt(paddr);
const bytes = bytes_ptr[0..len];
const w = Console.autoChoose().?.writer();
return w.write(bytes);
}
// launch(bytes: [*]align(@alignOf(std.elf.Elf64_Ehdr)) const u8, len: usize) !usize
fn launch(trap_frame: *const TrapFrame) !usize {
const alignment = @alignOf(std.elf.Elf64_Ehdr);
const bytes_addr = trap_frame.general_purpose_registers[10];
const bytes_opt: ?[*]align(alignment) const u8 = @ptrFromInt(bytes_addr);
const bytes_ptr = bytes_opt orelse return Error.ZeroAddressSupplied;
const len = trap_frame.general_purpose_registers[11];
const bytes = bytes_ptr[0..len];
paging.setUserMemoryAccess(true);
defer paging.setUserMemoryAccess(false);
const new_proc = try process.create(mem.page_allocator, bytes);
return new_proc.id;
}
// end() noreturn
fn end(proc: *process.Info) noreturn {
proc.terminate();
process.schedule() catch |err| {
std.debug.panic("schedule error: {}", .{err});
};
}
pub const TerminateError = error{
PidOutOfRange,
ProcessNotFound,
};
// terminate(pid: u16, tid: usize) !void
fn terminate(proc: *const process.Info, trap_frame: *const TrapFrame) !void {
const pid_wide = trap_frame.general_purpose_registers[10];
const pid = std.math.cast(u16, pid_wide) orelse {
return TerminateError.PidOutOfRange;
};
const tid = trap_frame.general_purpose_registers[11];
const target = process.findThread(pid, tid) orelse {
return TerminateError.ProcessNotFound;
};
target.terminate();
if (target.shouldTerminate(proc)) {
process.schedule() catch |err| {
std.debug.panic("schedule error: {}", .{err});
};
}
}
// processId() usize
fn processId(proc: *const process.Info) usize {
return proc.id;
}
// threadId() usize
fn threadId(proc: *const process.Info) usize {
return proc.thread_id;
}
|