Userspace exec()
This commit is contained in:
+36
-4
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user