Spawn Processes using memory primitives rather than and elf loader.

This allows us to remove the temporary syscall for that style of process
spawn.
This commit is contained in:
Drew Galbraith 2023-06-07 00:04:53 -07:00
parent b06c76e477
commit 23895b5c6c
26 changed files with 403 additions and 94 deletions

View file

@ -1,5 +1,31 @@
#include "include/mammoth/debug.h"
#include <zcall.h>
#include <zerrors.h>
void dbgln(const char* str) { ZDebug(str); }
void dbgln(const char* str) {
// Safe to ignore the result since right now this doesn't throw.
uint64_t _ = ZDebug(str);
}
void check(uint64_t code) {
switch (code) {
case Z_OK:
return;
case ZE_NOT_FOUND:
dbgln("crash: NOT_FOUND");
break;
case ZE_INVALID:
dbgln("crash: INVALID");
break;
case ZE_DENIED:
dbgln("crash: DENIED");
break;
case ZE_UNIMPLEMENTED:
dbgln("crash: UNIMPLEMENTED");
default:
dbgln("Unhandled code");
break;
}
ZProcessExit(code);
}

View file

@ -0,0 +1,97 @@
#include "include/mammoth/process.h"
#include <zcall.h>
#include "include/mammoth/debug.h"
namespace {
typedef struct {
char ident[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t phoff;
uint64_t shoff;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum;
uint16_t shentsize;
uint16_t shnum;
uint16_t shstrndx;
} Elf64Header;
typedef struct {
uint32_t name;
uint32_t type;
uint64_t flags;
uint64_t addr;
uint64_t offset;
uint64_t size;
uint32_t link;
uint32_t info;
uint64_t addralign;
uint64_t entsize;
} Elf64SectionHeader;
typedef struct {
uint32_t type;
uint32_t flags;
uint64_t offset;
uint64_t vaddr;
uint64_t paddr;
uint64_t filesz;
uint64_t memsz;
uint64_t align;
} Elf64ProgramHeader;
void memcpy(uint64_t base, uint64_t len, uint64_t dest) {
uint8_t* srcptr = reinterpret_cast<uint8_t*>(base);
uint8_t* destptr = reinterpret_cast<uint8_t*>(dest);
for (uint64_t i = 0; i < len; i++) {
destptr[i] = srcptr[i];
}
}
uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
Elf64Header* header = reinterpret_cast<Elf64Header*>(base);
Elf64ProgramHeader* programs =
reinterpret_cast<Elf64ProgramHeader*>(base + header->phoff);
for (uint64_t i = 0; i < header->phnum; i++) {
Elf64ProgramHeader& program = programs[i];
dbgln("Create mem object");
uint64_t mem_cap;
uint64_t size = program.filesz;
check(ZMemoryObjectCreate(size, &mem_cap));
dbgln("Map Local");
uint64_t vaddr;
check(ZAddressSpaceMap(Z_INIT_AS_SELF, 0, mem_cap, &vaddr));
dbgln("Copy");
memcpy(base + program.offset, program.filesz, vaddr);
dbgln("Map Foreign");
check(ZAddressSpaceMap(as_cap, program.vaddr, mem_cap, &vaddr));
}
return header->entry;
}
} // namespace
uint64_t SpawnProcessFromElfRegion(uint64_t program) {
dbgln("Spawn");
uint64_t proc_cap;
uint64_t as_cap;
check(ZProcessSpawn(Z_INIT_PROC_SELF, &proc_cap, &as_cap));
uint64_t entry_point = LoadElfProgram(program, as_cap);
dbgln("Thread Create");
uint64_t thread_cap;
check(ZThreadCreate(proc_cap, &thread_cap));
dbgln("Thread start");
check(ZThreadStart(thread_cap, entry_point, 0, 0));
}