mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-28 16:17:51 +01:00
Hacky execve
This commit is contained in:
@@ -13,13 +13,13 @@
|
||||
uint64_t _do_syscall(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
|
||||
register uint64_t res asm("rax");
|
||||
if (id_rdi != SYSCALL_FORK_ID)
|
||||
asm volatile("syscall; mov (0x10016), %%rsp;" // TASK_POINTER->ret_sp_val
|
||||
asm volatile("syscall; mov (0x10010), %%rsp;" // TASK_POINTER->ret_sp_val
|
||||
: "=ra"(res)
|
||||
: "D"(id_rdi), "S"(a1_rsi), "d"(a2_rdx), "a"(a3_rcx)
|
||||
: "cc", "rcx", "r8",
|
||||
"r9", "r10", "r11", "r15", "memory");
|
||||
else
|
||||
asm volatile("syscall; mov (0x10016), %%rsp;" // TASK_POINTER->ret_sp_val
|
||||
asm volatile("syscall; mov (0x10010), %%rsp;" // TASK_POINTER->ret_sp_val
|
||||
"pop %%r15;"
|
||||
"pop %%r14;"
|
||||
"pop %%r13;"
|
||||
|
||||
@@ -19,9 +19,9 @@ _syscall_entrypoint:
|
||||
push r15
|
||||
|
||||
.not_fork:
|
||||
mov [0x10016], rsp ; TASK_POINTER->ret_sp_val
|
||||
mov [0x10024], r11 ; TASK_POINTER->ret_flags
|
||||
mov [0x10032], rcx ; TASK_POINTER->ret_ip
|
||||
mov [0x10010], rsp ; TASK_POINTER->ret_sp_val
|
||||
mov [0x10018], r11 ; TASK_POINTER->ret_flags
|
||||
mov [0x10020], rcx ; TASK_POINTER->ret_ip
|
||||
mov rsp, [0x10008] ; TASK_POINTER->entry_ksp_val
|
||||
mov rcx, rax ; FIXME: Not needed anymore
|
||||
|
||||
@@ -32,7 +32,15 @@ _syscall_entrypoint:
|
||||
_syscall_ret:
|
||||
|
||||
cli
|
||||
mov r11, [0x10024] ; TASK_POINTER->ret_flags
|
||||
mov rcx, [0x10032] ; TASK_POINTER->ret_ip
|
||||
mov r11, [0x10018] ; TASK_POINTER->ret_flags
|
||||
mov rcx, [0x10020] ; TASK_POINTER->ret_ip
|
||||
o64 sysret
|
||||
.end:
|
||||
section .text
|
||||
|
||||
global _execve_entrypoint:function (_execve_entrypoint.end - _execve_entrypoint)
|
||||
_execve_entrypoint:
|
||||
mov rsp,[0x10010] ; TASK_POINTER->ret_sp_val
|
||||
mov rcx,[0x10028] ; TASK_POINTER->exec_ip
|
||||
jmp rcx
|
||||
.end:
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "task.hpp"
|
||||
#include "timer.hpp"
|
||||
|
||||
#include <globals.hpp>
|
||||
|
||||
// Don't forget the correct order
|
||||
// Shockingly, it doesn't immediately break and even something simple as putchar works
|
||||
// even with completely broken 16-bit segments somehow
|
||||
@@ -185,11 +187,22 @@ uint64_t syscall_execve(const char *pathname, char *const argv[], char *const en
|
||||
|
||||
ElfParser elfParser(read_data);
|
||||
|
||||
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), pathname);
|
||||
if (elfParser.copy_to(utask))
|
||||
utask->start();
|
||||
else
|
||||
return -1;
|
||||
uint64_t flags_bak = ((task_pointer *) (TASK_POINTER))->ret_flags;
|
||||
Scheduler::cur_task()->user_reset();
|
||||
|
||||
if (!elfParser.copy_to(Scheduler::cur_task()))
|
||||
assert(false);
|
||||
|
||||
// FIXME: that seems... hacky
|
||||
char *trampoline = (char *) Scheduler::cur_task()->_vma->mmap_mem((void *) 0x5000, 4096, 0, PAGE_USER | PAGE_RW);
|
||||
char *trampoline_w = (char *) HHDM_P2V(Scheduler::cur_task()->_addressSpace->virt2real(trampoline));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
*(trampoline_w + i) = *(((char *) &_execve_entrypoint) + i);
|
||||
}
|
||||
|
||||
((task_pointer *) (TASK_POINTER))->ret_ip = (uint64_t) trampoline;
|
||||
((task_pointer *) (TASK_POINTER))->exec_ip = elfParser.get_entrypoint();
|
||||
((task_pointer *) (TASK_POINTER))->ret_flags = flags_bak;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
void setup_syscalls();
|
||||
|
||||
extern "C" void _syscall_entrypoint();
|
||||
extern "C" void _execve_entrypoint();
|
||||
|
||||
extern "C" void _syscall_ret();
|
||||
|
||||
|
||||
@@ -187,6 +187,64 @@ static void trampoline(void *rdi, void (*rsi_entrypoint)()) {
|
||||
Scheduler::remove_self();
|
||||
}
|
||||
|
||||
void Task::user_setup() {
|
||||
assert(_mode == TaskMode::TASKMODE_USER);
|
||||
_frame.cs = Arch::GDT::gdt_code_user.selector() | 0x3;
|
||||
_frame.ss = Arch::GDT::gdt_data_user.selector() | 0x3;
|
||||
_ownAddressSpace = UniquePtr(new AddressSpace());
|
||||
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
||||
|
||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||
_vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER),
|
||||
sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe
|
||||
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||
|
||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
|
||||
|
||||
_entry_ksp_val = ((((uintptr_t) _kstack->_ptr) + (TASK_SS - 9) - 1) & (~0xFULL)); // Ensure 16byte alignment
|
||||
// It should be aligned before call, therefore it actually should be aligned here
|
||||
assert((_entry_ksp_val & 0xFULL) == 0);
|
||||
|
||||
taskptr_real->taskptr = this;
|
||||
taskptr_real->entry_ksp_val = _entry_ksp_val;
|
||||
taskptr_real->ret_sp = 0x0;
|
||||
|
||||
void *ustack = _vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
|
||||
_vma->map_kern();
|
||||
|
||||
// Ensure 16byte alignment
|
||||
_frame.sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8;
|
||||
}
|
||||
|
||||
void Task::user_reset() {
|
||||
assert(_mode == TaskMode::TASKMODE_USER);
|
||||
|
||||
// FIXME:
|
||||
// delete _ownAddressSpace.release();
|
||||
|
||||
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
||||
|
||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||
_vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER),
|
||||
sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe
|
||||
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||
|
||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_ownAddressSpace->virt2real(taskptr)));
|
||||
|
||||
_entry_ksp_val = ((((uintptr_t) _kstack->_ptr) + (TASK_SS - 9) - 1) & (~0xFULL)); // Ensure 16byte alignment
|
||||
// It should be aligned before call, therefore it actually should be aligned here
|
||||
assert((_entry_ksp_val & 0xFULL) == 0);
|
||||
|
||||
taskptr_real->taskptr = this;
|
||||
taskptr_real->entry_ksp_val = _entry_ksp_val;
|
||||
|
||||
void *ustack = _vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
|
||||
_vma->map_kern();
|
||||
|
||||
// Ensure 16byte alignment
|
||||
taskptr_real->ret_sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8;
|
||||
}
|
||||
|
||||
Task::Task(Task::TaskMode mode, void (*entrypoint)(), const char *name) {
|
||||
_name = name;
|
||||
|
||||
@@ -199,51 +257,23 @@ Task::Task(Task::TaskMode mode, void (*entrypoint)(), const char *name) {
|
||||
if (mode == TaskMode::TASKMODE_KERN) {
|
||||
_frame.cs = Arch::GDT::gdt_code.selector();
|
||||
_frame.ss = Arch::GDT::gdt_data.selector();
|
||||
} else if (mode == TaskMode::TASKMODE_USER) {
|
||||
_frame.cs = Arch::GDT::gdt_code_user.selector() | 0x3;
|
||||
_frame.ss = Arch::GDT::gdt_data_user.selector() | 0x3;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 512; i++) _fxsave->_fxsave[i] = 0;
|
||||
|
||||
_frame.flags = flags();
|
||||
_frame.guard = Arch::kIDT_GUARD;
|
||||
if (mode == TaskMode::TASKMODE_USER) {
|
||||
_ownAddressSpace = UniquePtr(new AddressSpace());
|
||||
_vma = UniquePtr<VMA>(new VMA(_ownAddressSpace.get()));
|
||||
}
|
||||
_state = TaskState::TS_BLOCKED;
|
||||
_mode = mode;
|
||||
_pid = max_pid.fetch_add(1);
|
||||
_used_time = 0;
|
||||
|
||||
if (mode == TaskMode::TASKMODE_USER)
|
||||
user_setup();
|
||||
|
||||
_addressSpace = mode == TaskMode::TASKMODE_KERN ? KERN_AddressSpace : _ownAddressSpace.get();
|
||||
_state = TaskState::TS_BLOCKED;
|
||||
_mode = mode;
|
||||
_pid = max_pid.fetch_add(1);
|
||||
_used_time = 0;
|
||||
|
||||
if (mode == TaskMode::TASKMODE_USER) {
|
||||
task_pointer *taskptr = static_cast<task_pointer *>(
|
||||
_vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER),
|
||||
sizeof(task_pointer), 0, PAGE_RW | PAGE_USER)); // FIXME: this is probably unsafe
|
||||
assert((uintptr_t) taskptr == TASK_POINTER);
|
||||
|
||||
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(_addressSpace->virt2real(taskptr)));
|
||||
|
||||
_entry_ksp_val = ((((uintptr_t) _kstack->_ptr) + (TASK_SS - 9) - 1) & (~0xFULL)); // Ensure 16byte alignment
|
||||
// It should be aligned before call, therefore it actually should be aligned here
|
||||
assert((_entry_ksp_val & 0xFULL) == 0);
|
||||
|
||||
taskptr_real->taskptr = this;
|
||||
taskptr_real->entry_ksp_val = _entry_ksp_val;
|
||||
taskptr_real->ret_sp = 0x0;
|
||||
}
|
||||
|
||||
if (mode == TaskMode::TASKMODE_USER) {
|
||||
void *ustack = _vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
|
||||
_vma->map_kern();
|
||||
|
||||
// Ensure 16byte alignment
|
||||
_frame.sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8;
|
||||
} else {
|
||||
if (mode == TaskMode::TASKMODE_KERN) {
|
||||
_frame.sp = ((((uintptr_t) _kstack->_ptr) + (TASK_SS - 9) - 1) & (~0xFULL)) + 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
~ Task();
|
||||
|
||||
Task *clone();
|
||||
void user_setup();
|
||||
void user_reset();
|
||||
|
||||
//private:
|
||||
struct KernStack {
|
||||
@@ -95,6 +97,7 @@ struct task_pointer {
|
||||
uint64_t ret_sp;
|
||||
uint64_t ret_flags;
|
||||
uint64_t ret_ip;
|
||||
uint64_t exec_ip;
|
||||
} __attribute__((packed));
|
||||
|
||||
namespace Scheduler {
|
||||
|
||||
@@ -33,7 +33,10 @@ int main() {
|
||||
printf("\n %s \n", buf);
|
||||
}
|
||||
while (1) {
|
||||
execve("hello2", 0, 0);
|
||||
if (fork() == 0)
|
||||
execve("hello2", 0, 0);
|
||||
else
|
||||
wait(NULL);
|
||||
print_mem();
|
||||
sleep(500);
|
||||
}
|
||||
@@ -49,8 +52,10 @@ int main() {
|
||||
} else if (strcmp(line, "tasks") == 0) {
|
||||
print_tasks();
|
||||
} else {
|
||||
execve(line, 0, 0);
|
||||
// sleep(10000);
|
||||
if (fork() == 0)
|
||||
execve(line, 0, 0);
|
||||
else
|
||||
wait(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user