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:
parent
b06c76e477
commit
23895b5c6c
26 changed files with 403 additions and 94 deletions
|
|
@ -1,5 +1,6 @@
|
|||
add_library(mammoth_lib STATIC
|
||||
src/debug.cpp
|
||||
src/process.cpp
|
||||
src/thread.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void dbgln(const char*);
|
||||
|
||||
// Checks that the code is ok.
|
||||
// if not exits the process.
|
||||
void check(uint64_t);
|
||||
|
|
|
|||
5
lib/mammoth/include/mammoth/process.h
Normal file
5
lib/mammoth/include/mammoth/process.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t SpawnProcessFromElfRegion(uint64_t program);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
97
lib/mammoth/src/process.cpp
Normal file
97
lib/mammoth/src/process.cpp
Normal 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));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue