Userspace exec()

This commit is contained in:
Mark
2020-01-30 15:16:13 +02:00
parent 3b4c461c85
commit df4eeefc8f
3 changed files with 85 additions and 29 deletions
+36 -4
View File
@@ -1,10 +1,6 @@
#include "sys/amd64/asm/asm_cpu.h"
.section .text
.global context_enter
.global context_enter_forked
context_enter_forked:
nop
nop
context_enter:
popq %rax
popq %rdi
@@ -18,6 +14,42 @@ context_enter:
iretq
.global context_exec_enter
context_exec_enter:
// %rdi - arg
// %rsi - thread
// %rdx - stack
// %rcx - entry
movq (%rsi), %rsp
pushq $0x1B
pushq %rdx
pushq $0x200
pushq $0x23
pushq %rcx
// Zero registers before entry
xorq %rax, %rax
xorq %rcx, %rcx
xorq %rdx, %rdx
xorq %rbx, %rbx
xorq %rsi, %rsi
xorq %rbp, %rbp
xorq %r8, %r8
xorq %r9, %r9
xorq %r10, %r10
xorq %r11, %r11
xorq %r12, %r12
xorq %r13, %r13
xorq %r14, %r14
xorq %r15, %r15
iretq
.global context_switch_first
.global context_switch_to
.type context_switch_to, %function
+2 -2
View File
@@ -6,11 +6,11 @@
#define MSR_IA32_SFMASK 0xC0000084
extern void syscall_entry(void);
extern void sys_fork(void);
extern int sys_exec(void *(*)(void *), void *arg);
void *syscall_table[256] = {
NULL,
[123] = sys_fork,
[124] = sys_exec,
};
void syscall_undefined(uint64_t rax) {
+47 -23
View File
@@ -11,6 +11,8 @@
// Enter a newly-created task
extern void context_enter(struct thread *thr);
// Enter a task from exec
extern void context_exec_enter(void *arg, struct thread *thr, uintptr_t stack3, uintptr_t entry);
// Stores current task context, loads new one's
extern void context_switch_to(struct thread *thr, struct thread *from);
// No current task, only load the first task to begin execution
@@ -218,6 +220,17 @@ struct sys_fork_frame {
uint64_t rip;
};
int sys_exec(void *(*func)(void *), void *arg) {
_assert(func);
struct thread *thr = thread_current;
thr->data.rsp0 = thr->data.rsp0_top;
uintptr_t rsp3 = thr->data.rsp3_base + thr->data.rsp3_size;
context_exec_enter(arg, thr, rsp3, (uintptr_t) func);
panic("No\n");
}
int sys_fork(struct sys_fork_frame *frame) {
static int nfork = 0;
static struct thread forkt[3] = {0};
@@ -235,6 +248,9 @@ int sys_fork(struct sys_fork_frame *frame) {
mm_space_t space = amd64_mm_pool_alloc();
mm_space_fork(space, (mm_space_t) MM_VIRTUALIZE(src->data.cr3), MM_CLONE_FLG_KERNEL | MM_CLONE_FLG_USER);
dst->data.rsp3_base = src->data.rsp3_base;
dst->data.rsp3_size = src->data.rsp3_size;
space[AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 39] |= MM_PAGE_USER;
uint64_t *pdpt = (uint64_t *) MM_VIRTUALIZE(space[AMD64_MM_STRIPSX(KERNEL_VIRT_BASE) >> 39] & ~0xFFF);
for (uint64_t i = 0; i < 4; ++i) {
@@ -317,28 +333,42 @@ int sys_fork(struct sys_fork_frame *frame) {
return dst->pid;
}
static void *u1(void *arg) {
uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(arg);
*ptr = 0;
while (1) {
*ptr ^= '1' | 0xC00;
for (size_t i = 0; i < 1000000; ++i);
}
return 0;
}
static void *u0(void *arg) {
int r;
asm volatile ("syscall":"=a"(r):"a"(123));
if (r == 0) {
arg = (void *) ((uint64_t) arg + 5);
uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8000 + (uint64_t) arg * 2);
*ptr = 0;
while (1) {
for (size_t i = 0; i < 10000000; ++i);
*ptr ^= 'A' | 0x1200;
}
(void) u1;
asm volatile ("leaq u1(%rip), %rdi; movq $0xB8040, %rsi; movq $124, %rax; syscall");
}
uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8000 + (uint64_t) arg * 2);
asm volatile ("syscall":"=a"(r):"a"(123));
if (r == 0) {
(void) u1;
asm volatile ("leaq u1(%rip), %rdi; movq $0xB8050, %rsi; movq $124, %rax; syscall");
}
uint16_t *ptr = (uint16_t *) MM_VIRTUALIZE(0xB8030);
*ptr = 0;
while (1) {
for (size_t i = 0; i < 10000000; ++i);
*ptr ^= 'A' | 0x1200;
*ptr ^= '0' | 0xD00;
for (size_t i = 0; i < 1000000; ++i);
}
return 0;
}
@@ -362,31 +392,25 @@ static struct thread t_n[3] = {0};
static struct thread t_u[3] = {0};
void sched_init(void) {
init_thread(&thread_idle, idle, 0, 0);
thread_idle.pid = -1;
init_thread(&t_n[0], t0, (void *) 0, 0);
init_thread(&t_n[1], t0, (void *) 1, 0);
init_thread(&t_n[2], t0, (void *) 2, 0);
init_thread(&t_u[0], u0, (void *) 5, 1);
init_thread(&t_u[1], u0, (void *) 6, 1);
init_thread(&t_u[2], u0, (void *) 7, 1);
init_thread(&thread_idle, idle, 0, 0);
thread_idle.pid = -1;
t_n[0].pid = 1;
t_n[1].pid = 2;
t_n[2].pid = 3;
init_thread(&t_u[0], u0, (void *) 0, 1);
t_u[0].pid = 10;
t_u[1].pid = 11;
t_u[2].pid = 12;
sched_queue(&t_n[0]);
sched_queue(&t_n[1]);
sched_queue(&t_n[2]);
sched_queue(&t_u[0]);
sched_queue(&t_u[1]);
sched_queue(&t_u[2]);
}
void sched_enter(void) {