diff options
-rw-r--r-- | static/md/srvre/kernel/wiki.md | 2 | ||||
-rw-r--r-- | static/md/srvre/kernel/wiki/startup.md | 3 | ||||
-rw-r--r-- | static/md/srvre/kernel/wiki/syscalls.md | 267 | ||||
-rw-r--r-- | static/md/srvre/kernel/wiki/userinit.md | 3 | ||||
-rw-r--r-- | static/md/srvre/kernel/wiki/vfs.md | 128 |
5 files changed, 72 insertions, 331 deletions
diff --git a/static/md/srvre/kernel/wiki.md b/static/md/srvre/kernel/wiki.md index 2480cd3..44309e8 100644 --- a/static/md/srvre/kernel/wiki.md +++ b/static/md/srvre/kernel/wiki.md @@ -15,7 +15,7 @@ List * [Startup](/md/srvre/kernel/wiki/startup.md) * [userinit](/md/srvre/kernel/wiki/userinit.md) * [Syscalls](/md/srvre/kernel/wiki/syscalls.md) -* [VFS](/md/srvre/kernel/wiki/vfs.md) and [builtin resources](/md/srvre/kernel/wiki/vfs.md#builtin-resources) +* [Message passing](/md/srvre/kernel/wiki/msgpass.md) * [Errors](/md/srvre/kernel/wiki/errors.md) [Project Page](/md/srvre/kernel.md) diff --git a/static/md/srvre/kernel/wiki/startup.md b/static/md/srvre/kernel/wiki/startup.md index 8cf05aa..58d52a1 100644 --- a/static/md/srvre/kernel/wiki/startup.md +++ b/static/md/srvre/kernel/wiki/startup.md @@ -7,9 +7,8 @@ When the kernel starts up on the boot hart it performs the following steps: 1. Initialize the SBI console 2. Enable all interrupts -3. Configure Sv39 identity paging +3. Configure Sv39 paging 4. Configure the PLIC (Platform-Level Interrupt Controller) if present -5. Enumerate PCI(e) devices if present 6. Start `/init` from the embedded [userinit](/md/srvre/kernel/wiki/userinit.md) It is legal for the init process to terminate, but only if there is at least diff --git a/static/md/srvre/kernel/wiki/syscalls.md b/static/md/srvre/kernel/wiki/syscalls.md index 28b9d50..0f44f98 100644 --- a/static/md/srvre/kernel/wiki/syscalls.md +++ b/static/md/srvre/kernel/wiki/syscalls.md @@ -4,8 +4,8 @@ date: "Wed Jun 19 2024" --- System calls are the most fundamental interface between processes -and the kernel. They provide access to kernel APIs such as the -[VFS](/md/srvre/kernel/wiki/vfs.md). +and the kernel. They provide access to kernel APIs such as +[message passing](/md/srvre/kernel/wiki/msgpass.md). Calling convention ================== @@ -29,8 +29,14 @@ registers: | Register | Friendly name | Meaning | | :------: | :-----------: | :-------------- | -| x10 | a0 | Return value #0 | -| x11 | a1 | Return value #1 | +| x10 | a0 | Return value | +| x11 | a1 | Error code | + +The operation was successful if and only if the error code is zero. +Any other value indicates an [error](/md/srvre/kernel/wiki/errors.md). +Error codes are not stable across source code changes due to the use of Zig's +`@intFromError` cast. You may however pass such an error code to +[errorName](#errorname-100000) to retrieve its name. List ==== @@ -38,253 +44,118 @@ List The following syscalls are currently available. Detailed descriptions follow after the summary table. -| Number | Name | -| :----: | :--------------------------------------- | -| 100000 | [uprint](#uprint-100000) | -| 100001 | [open](#open-100001) | -| 100002 | [close](#close-100002) | -| 100003 | [provideStream](#providestream-100003) | -| 100004 | [provideFile](#providefile-100004) | -| 100005 | [provideHook](#providehook-100005) | -| 100006 | [mkdir](#mkdir-100006) | -| 100007 | [provideDirHook](#providedirhook-100007) | -| 100008 | [remove](#remove-100008) | -| 100009 | [read](#read-100009) | -| 100010 | [write](#write-100010) | - -uprint (#100000) ----------------- - -Signature: -``` -uprint(str_addr: usize, len: usize) void -``` - -**WARNING:** This system call will be removed in a future version. - -Prints the string at `str_addr` to the debug console, -preceeded by "User message: " and succeeded by "\n". - -* `str_addr` is the memory address of the first character of the string -* `len` is the length of the string in bytes +| Number | Name | +| :----: | :----------------------------------- | +| 100000 | [errorName](#errorname-100000) | +| 100001 | [consoleWrite](#consoleWrite-100001) | +| 100002 | [launch](#launch-100002) | +| 100003 | [end](#end-100003) | +| 100004 | [terminate](#terminate-100004) | +| 100005 | [processId](#processid-100005) | +| 100006 | [threadId](#threadid-100006) | -open (#100001) --------------- +errorName (#100000) +------------------- Signature: ``` -open(path_c: [*:0]const u8, data: usize) Result(usize) +errorName(code: usize, buffer: [*]u8, len: usize) !usize ``` -Opens the resource at `path_c`, returning a handle to a descriptor -(or a driver-specific return value) or an error. -All but the last component of the path must already exist -and support holding sub-resources. - -* `path_c` is a null-terminated POSIX path -* `data` is either passed to the driver or used to decide -how to open the resource (i.e. read-only, read-write, append etc.) - -close (#100002) ---------------- - -Signature: +Possible errors: ``` -close(handle: usize) void +ZeroAddressSupplied +ErrorCodeOutOfRange ``` -Closes the resource descriptor identified by `handle`. -This system call cannot fail, invalid handles are silently ignored. +Writes the name matching an error code to a buffer. +If the name exceeds the length of the buffer the remaining bytes are truncated. -* `handle` is a handle to a resource descriptor +* `code` is the error code to get the name of +* `buffer` is a pointer to the output buffer +* `len` is the length of the buffer in bytes -provideStream (#100003) ------------------------ +consoleWrite (#100001) +---------------- Signature: ``` -provideStream( - path_c: [*:0]const u8, - readFn: ?*const fn (buffer: []u8) Result(usize), - writefn: ?*const fn (bytes: []const u8) Result(usize), -) Result(void) +consoleWrite(bytes: [*]const u8, len: usize) void ``` -Provides a [stream resource](/md/srvre/kernel/wiki/vfs.md#stream) -at `path_c`. This system call can fail. The callbacks are optional, -omitting them causes their respective operations to raise a -"\*NotSupported" error. -All but the last component of the path must already exist -and support holding sub-resources. +Writes the string at `bytes` directly to the debug console. -* `path_c` is a null-terminated POSIX path -* `readFn` is the callback to invoke when a process tries to read from the resource -* `writeFn` is the callback to invoke when a process tries to write to the resource +* `bytes` is a pointer to the string +* `len` is the length of the string in bytes -provideFile (#100004) ---------------------- +launch (#100002) +---------------- Signature: ``` -provideFile( - path_c: [*:0]const u8, - readFn: ?*const fn (context: *vfs.FileContext, buffer: []u8) Result(usize), - writeFn: ?*const fn (context: *vfs.FileContext, bytes: []const u8) Result(usize), - closeFn: ?*const fn (context: *vfs.FileContext) void, - initializer: ?*anyopaque, -) Result(void) -``` - -Provides a [file resource](/md/srvre/kernel/wiki/vfs.md#file) -at `path_c`. This system call can fail. All callbacks are optional, -omitting them causes their respective operations to raise a "\*NotSupported" -error with the exception of `close` which will still work without invoking a -custom callback. -All but the last component of the path must already exist -and support holding sub-resources. - -* `path_c` is a null-terminated POSIX path -returning a pointer to a driver-specific context data structure which is passed -to the other callbacks but never exposed to any other processes by the kernel, -or an error; You may store the process ID in this context object if required -* `readFn` is the callback to invoke when a process tries to read from the resource -* `writeFn` is the callback to invoke when a process tries to write to the resource -* `closeFn` is the callback to invoke when a process closes the resource -* `initializer` is an optional pointer to an initial context object passed to the callback functions. - -The `vfs.FileContext` struct is defined as follows: - -``` -pub const FileContext = extern struct { - inner: ?*anyopaque, -}; +launch(bytes: [*]align(@alignOf(std.elf.Elf64_Ehdr)) const u8, len: usize) !usize ``` -Callbacks, particularly `readFn` and `writeFn`, may initialize this value -if unset or modify it later and it will be preserved across calls from the -same process. +Maps the provided ELF into memory and starts its entry point in a new process, +returning its ID. -The `inner` field is set to `null` by default. Most callback implementations -will want to check for this and initialize it using the `initializer` field -if necessary. +The bytes need to have the same alignment as the ELF header (currently 8). -The `initializer` field is set to the `initializer` parameter of this -system call. Changing it will not affect its value for later -[open](#open-100001) operations. +* `bytes` is a pointer to the ELF data +* `len` is the length of the ELF data in bytes -provideHook (#100005) ---------------------- +end (#100003) +------------- Signature: ``` -provideHook( - path_c: [*:0]const u8, - callback: *allowzero const fn (pid: u16, data: usize) Result(usize), -) Result(void) +end() noreturn ``` -Provides a [hook resource](/md/srvre/kernel/wiki/vfs.md#hook) -at `path_c`. This system call can fail. -All but the last component of the path must already exist -and support holding sub-resources. - -* `path_c` is a null-terminated POSIX path -* `callback` is the callback to invoke when a process tries to open the resource, -returning a driver-specific integer value or an error; This callback gets access -to the `data` parameter passed to the [open](#open) syscall by the process +Terminates the calling thread. If the calling thread is the main thread (ID 0) +of the calling process, the entire process is terminated. +This may change in the future. -mkdir (#100006) ---------------- +terminate (#100004) +------------------- Signature: ``` -mkdir(path_c: [*:0]const u8, options: usize) Result(void) +terminate(pid: u16, tid: usize) !void ``` -**WARNING:** This system call is currently not implemented and will cause a kernel panic. -**WARNING:** The options will be removed before this version is released. - -Creates a [directory](/md/srvre/kernel/wiki/vfs.md#directory) -at `path_c`. This system call can fail. -All but the last component of the path must already exist -and support holding sub-resources, unless the `full` option is set -which creates missing components as directories unless they already exist -as non-directory resources (which raises an error). - -* `path_c` is a null-terminated POSIX path -* `options` is a bit field holding any combination of the following flags: - * `full` (1): Create all required components as directories if possible (comparable to `mkdir -p` on Linux) - -provideDirHook (#100007) ------------------------- - -Signature: +Possible errors: ``` -provideDirHook( - path_c: [*:0]const u8, - provideFn: *allowzero const fn (inode: Inode) Result(void), - findFn: *allowzero const fn (name: []const u8) ?Inode, - removeFn: *allowzero const fn (name: []const u8) Result(void), -) Result(void) +PidOutOfRange +ProcessNotFound ``` -Creates a [directory hook](/md/srvre/kernel/wiki/vfs.md#directory-hook) -at `path_c`. This system call can fail. -All but the last component of the path must already exist -and support holding sub-resources. +Terminates the specified thread. If the thread is the main thread (ID 0) +of the process, the entire process is terminated. +This may change in the future. -* `path_c` is a null-terminated POSIX path -* `provideFn` is the callback to invoke when any "provide\*" syscall provides a direct sub-resource of this resource -* `findFn` is the callback to invoke to get a sub-resource by name if it exists -* `removeFn` is the callback to invoke when the [remove](#remove-100008) syscall removes a direct sub-resource of this resource +* `pid` is the ID of the process to apply the termination to +* `tid` is the ID of the thread to terminate within the process -remove (#100008) ----------------- +processId (#100005) +------------------- Signature: ``` -remove(path_c: [*:0]const u8) Result(void) +processId() usize ``` -**WARNING:** This system call is currently not implemented and will cause a kernel panic. - -Removes a [resource](/md/srvre/kernel/wiki/vfs.md#resources) -from the [VFS](/md/srvre/kernel/wiki/vfs.md). +Returns the ID of the calling process. -* `path_c` is a null-terminated POSIX path - -read (#100009) --------------- +threadId (#100006) +------------------ Signature: ``` -read(handle: usize, buffer: [*]u8, len: usize) Result(usize) +threadId() usize ``` -Reads up to `len` bytes from the resource referenced by `handle` into `buffer`, -returning how many bytes were read or an error. -A return value of zero indicates that there is no more data to be read -or that `len` is zero. - -* `handle` is a handle to a resource descriptor -* `buffer` is the buffer to read into -* `len` is the maximum number of bytes to read and **must not be larger than the length of the buffer to prevent buffer overflows** - -write (#100010) ---------------- - -Signature: -``` -write(handle: usize, bytes: [*]const u8, len: usize) Result(usize) -``` - -Writes up to `len` bytes from `bytes` to the resource referenced by `handle`, -returning how many bytes were written or an error. -A return value of zero indicates that `len` is zero. - -* `handle` is a handle to a resource descriptor -* `bytes` is the buffer to write from -* `len` is the maximum number of bytes to write and **must not be larger than the length of the buffer to prevent buffer underflows** +Returns the ID of the calling thread within the calling process. [Return to Wiki Main Page](/md/srvre/kernel/wiki.md) diff --git a/static/md/srvre/kernel/wiki/userinit.md b/static/md/srvre/kernel/wiki/userinit.md index 67d6100..a835002 100644 --- a/static/md/srvre/kernel/wiki/userinit.md +++ b/static/md/srvre/kernel/wiki/userinit.md @@ -13,8 +13,7 @@ The kernel cannot be built if a userinit cannot be accessed at a predefined path. This is because it is embedded into the kernel binary so that it can be accessed without requiring any in-kernel drivers. -A userinit is simply an uncompressed `tar(1)` blob containing a directory tree -that is made available via the [VFS](/md/srvre/kernel/wiki/vfs.md). +A userinit is an uncompressed `tar(1)` blob. The kernel searches for an `init` executable at its root (ignoring file permissions). This file is executed to hand over control to userspace and is typically responsible for starting essential drivers, diff --git a/static/md/srvre/kernel/wiki/vfs.md b/static/md/srvre/kernel/wiki/vfs.md deleted file mode 100644 index 377095e..0000000 --- a/static/md/srvre/kernel/wiki/vfs.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: "VFS - SRVRE Kernel Wiki" -date: "Wed Jun 19 2024" ---- - -The VFS (Virtual File System) is the universal interface between processes -and resources. It is protected by the permission system. - -Authorized processes have the ability to access or provide resources. - -Resources -========= - -A resource is a control or data interface in the file system. -Examples include process metadata and termination, files on storage media -and network protocols. They are uniquely identified by unique POSIX paths, -though it is possible to reuse the same implementation with multiple paths. -There are several different kinds of resources. - -Stream ------- - -A stream is a shared byte stream that can be readable, writable, -both or none. The data will be distributed across all readers -in an unpredictable (but cryptographically insecure) fashion. -Writes can be interleaved. The combination of process authorization -and provider-side implementation decides which directions are available. - -Example use cases: Random byte stream, infinite zeroes, null/void - -File ----- - -A file is similar to a stream in that it provides a byte stream -that can be readable, writable, both or none. The main difference -is that the provider can tell the handles to it apart. - -Example use cases: Stored files, network sockets, runtime configuration -and control options - -Hook ----- - -A hook performs an action when opened. Resources of this kind -don't allocate a resource descriptor when opened, meaning that they can't -and never need to be closed. The provider can return any `usize` value instead. - -Example use cases: Process termination, system shutdown, UNIX time retrieval - -Directory ---------- - -A directory is a collection of resources and managed by the kernel. -Nesting is supported. - -Example use cases: Grouping of runtime configuration and control options, -hardware devices, network protocols etc. - -Directory hook --------------- - -A directory hook functions like a regular directory, but is managed by -a U-mode provider instead of the kernel keeping track of the items -contained within. - -Example use cases: Filesystem drivers, network protocols - -Builtin resources -================= - -The kernel provides the following builtin resources for providers -and other programs to build upon: - -`/io` ------ - -The `/io` directory provides interfaces for byte-grained, often text-based -communication with the environment the program is running in. - -* `/io/debug`: Write-only access to the debug console, usually provided by the SBI (firmware) - -`/userinit` ------------ - -The `/userinit` directory provides read-only access to the -[userinit](/md/srvre/kernel/wiki/userinit.md) tree. -Its purpose is to make essential drivers and the data required to run them -to the init process. - -* `/userinit/init`: The executable started as the init process. There is nothing special about it internally but it's noteworthy enough to be listed here explicitly. - -`/process` ----------- - -The `/process` directory provides information about as well as control -interfaces to processes and threads, including the caller. - -* `/process/create`: A [hook](#hook) that adds a new process to the scheduler, returning its ID. The extra data is the null-terminated path of the program to start. - -### `/process/self` - -The `/process/self` subdirectory provides information about as well as control -interfaces to the calling process and thread. - -* `/process/self/terminate`: A [hook](#hook) that terminates the current thread. The extra data is ignored. This is likely to be made more powerful in the future. -* `/process/self/id`: A [hook](#hook) that returns the ID of the current process. The extra data is ignored. -* `/process/self/thread_id`: A [hook](#hook) that returns the ID of the current thread within the current process. The extra data is ignored. - -Interaction from U-mode -======================= - -VFS resources are provided or accessed using -[system calls](/md/srvre/kernel/wiki/syscalls.md): - -* [open](/md/srvre/kernel/wiki/syscalls.md#open-100001): Opens a resource, obtaining a resource descriptor handle. -* [close](/md/srvre/kernel/wiki/syscalls.md#close-100002): Closes a resource descriptor handle. -* [provideStream](/md/srvre/kernel/wiki/syscalls.md#providestream-100003): Provides a stream resource. -* [provideFile](/md/srvre/kernel/wiki/syscalls.md#providefile-100004): Provides a file resource. -* [provideHook](/md/srvre/kernel/wiki/syscalls.md#providehook-100005): Provides a hook resource. -* [mkdir](/md/srvre/kernel/wiki/syscalls.md#mkdir-100006): Creates a kernel-managed directory. -* [provideDirHook](/md/srvre/kernel/wiki/syscalls.md#providedirhook-100007): Provides a directory hook. -* [remove](/md/srvre/kernel/wiki/syscalls.md#remove-100008): Removes a resource from the VFS. -* [read](/md/srvre/kernel/wiki/syscalls.md#read-100009): Reads from a resource descriptor handle into a buffer. -* [write](/md/srvre/kernel/wiki/syscalls.md#write-100010): Writes to a resource descriptor handle from a buffer. - -[Return to Wiki Main Page](/md/srvre/kernel/wiki.md) - -[Return to Index Page](/md/index.md) |