Pass argv to processes on a SysV entry stack; grow the user stack to 32 KiB
Processes now start with C-compatible arguments: the kernel builds the System V AMD64 entry block (argc, argv, empty envp, auxiliary vector) at the top of the stack, argv[0] is the path or initial-ramdisk name the process was spawned as, and system_spawn carries an optional NUL-separated blob that becomes argv[1..]. The runtime parses the block (runtime.argumentCount/argument) and its spawn wrappers pass arguments through. The name is also recorded on the task, so a fault report says which binary died, not just its id. The user stack grows from one page to eight (32 KiB, parameters.user_stack_pages), with the page below left unmapped as a guard so an overflow faults into a clean process kill rather than corrupting the image. Task.name_buffer is zero-initialised, not undefined: an undefined default is materialised as a 0xAA fill that moved the static task pool out of .bss and made the whole kernel ~7x slower under QEMU TCG (caught by the affinity test). Proven end to end by the new args test: args-echo respawns itself with arguments via the syscall blob, burns more stack than one page could hold, and echoes its argv intact. Full suite: 44/44.
This commit is contained in:
@@ -44,11 +44,31 @@ pub fn exit(code: usize) noreturn {
|
||||
}
|
||||
|
||||
/// Start the binary bundled in the initial-ramdisk under `name` as a new ring-3
|
||||
/// process, returning true on success. This is how a supervisor (the device manager)
|
||||
/// launches a driver it matched — danos-native, not POSIX (a spawn/exec family comes
|
||||
/// with the process work later).
|
||||
/// process, returning true on success. The child's argv[0] is `name`. This is how
|
||||
/// a supervisor (the device manager) launches a driver it matched — danos-native,
|
||||
/// not POSIX (a spawn/exec family comes with the process work later).
|
||||
pub fn spawn(name: []const u8) bool {
|
||||
return sc.systemCall2(.system_spawn, @intFromPtr(name.ptr), name.len) == 0;
|
||||
return sc.systemCall4(.system_spawn, @intFromPtr(name.ptr), name.len, 0, 0) == 0;
|
||||
}
|
||||
|
||||
/// Like `spawn`, but hands the child command-line arguments: they arrive as
|
||||
/// argv[1..] on its System V entry stack (argv[0] is still `name`). Marshalled to
|
||||
/// the kernel as one NUL-separated blob; the combined arguments must fit
|
||||
/// `blob` (the kernel caps the blob at 256 bytes and argc at 8 anyway).
|
||||
pub fn spawnWithArguments(name: []const u8, arguments: []const []const u8) bool {
|
||||
var blob: [256]u8 = undefined;
|
||||
var len: usize = 0;
|
||||
for (arguments, 0..) |argument, i| {
|
||||
if (i != 0) {
|
||||
if (len >= blob.len) return false;
|
||||
blob[len] = 0;
|
||||
len += 1;
|
||||
}
|
||||
if (len + argument.len > blob.len) return false;
|
||||
@memcpy(blob[len..][0..argument.len], argument);
|
||||
len += argument.len;
|
||||
}
|
||||
return sc.systemCall4(.system_spawn, @intFromPtr(name.ptr), name.len, @intFromPtr(&blob), len) == 0;
|
||||
}
|
||||
|
||||
/// Grant `len` bytes (rounded up to whole pages) of fresh, zeroed, writable
|
||||
|
||||
Reference in New Issue
Block a user