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
|
// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
const std = @import("std");
const instructions = @import("instructions.zig");
const mem = @import("mem.zig");
const paging = @import("paging.zig");
const process = @import("process.zig");
const trap = @import("trap.zig");
pub const Error = error{
Unimplemented,
ZeroAddressSupplied,
};
pub const HandleError = error{
UnknownSyscall,
};
pub fn handler(proc: *process.Info, trap_frame: *trap.Frame) !void {
switch (trap_frame.general_purpose_registers[17]) {
100000 => trap_frame.setReturnValue(errorName(trap_frame)),
100001 => trap_frame.setReturnValue(uprint(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{ErrorOutOfRange};
// errorName(value: usize, buffer: [*]u8, len: usize) !usize
fn errorName(trap_frame: *const trap.Frame) !usize {
const value_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 value = std.math.cast(u16, value_wide) orelse {
return ErrorNameError.ErrorOutOfRange;
};
const buffer = buffer_ptr[0..len];
if (value == 0) return 0;
const error_name = @errorName(@errorFromInt(value));
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;
}
// uprint(str_addr: usize, len: usize) void
fn uprint(trap_frame: *const trap.Frame) void {
const procmem: *paging.Table = @ptrFromInt(instructions.satp.read().ppn << 12);
const paddr = procmem.translate(trap_frame.general_purpose_registers[10]).?;
const str_ptr: [*]const u8 = @ptrFromInt(paddr);
const str = str_ptr[0..trap_frame.general_purpose_registers[11]];
const w = @import("Console.zig").autoChoose().?.writer();
w.print("User message: {s}\r\n", .{str}) catch unreachable;
}
// launch(bytes: [*]align(@alignOf(std.elf.Elf64_Ehdr)) const u8, len: usize) !usize
fn launch(trap_frame: *const trap.Frame) !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() void
fn end(proc: *process.Info) void {
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 trap.Frame) !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;
}
|