[kernel] Improve process init

Move process init from each process needing a main.s with _start to
crt0.s in libc. Also change to a sysv-like initial stack with a
j6-specific array of initialization values after the program arguments.
This commit is contained in:
2020-12-31 00:57:51 -08:00
parent db8a14720b
commit 0e6b27e741
8 changed files with 148 additions and 71 deletions

View File

@@ -1,25 +1,16 @@
#include <stdint.h>
#include <stdlib.h>
#include "j6/types.h"
#include "j6/init.h"
#include "j6/errors.h"
#include "j6/signals.h"
#include "j6/types.h"
#include <j6libc/syscalls.h>
extern "C" {
void _init_libc(j6_process_init *);
int main(int, const char **);
}
j6_handle_t sys = j6_handle_invalid;
size_t size = 0;
void
_init_libc(j6_process_init *init)
{
sys = init->handles[0];
size = reinterpret_cast<size_t>(init->handles[1]);
void _get_init(size_t *initc, struct j6_init_value **initv);
}
int
@@ -27,12 +18,25 @@ main(int argc, const char **argv)
{
_syscall_system_log("fb driver starting");
if (size == 0)
size_t initc = 0;
j6_init_value *initv = nullptr;
_get_init(&initc, &initv);
j6_init_framebuffer *fb = nullptr;
for (unsigned i = 0; i < initc; ++i) {
if (initv[i].type == j6_init_desc_framebuffer) {
fb = reinterpret_cast<j6_init_framebuffer*>(initv[i].value);
break;
}
}
if (!fb)
return 1;
uint32_t *fb = reinterpret_cast<uint32_t*>(0x100000000);
uint32_t *fbp = reinterpret_cast<uint32_t*>(fb->addr);
size_t size = fb->size;
for (size_t i=0; i < size/4; ++i) {
fb[i] = 0xff;
fbp[i] = 0xff;
}
_syscall_system_log("fb driver done, exiting");

View File

@@ -11,7 +11,7 @@
#include "serial.h"
char inbuf[1024];
j6_handle_t sys = j6_handle_invalid;
extern j6_handle_t __handle_sys;
j6_handle_t endp = j6_handle_invalid;
extern "C" {
@@ -51,12 +51,6 @@ thread_proc()
_syscall_thread_exit(0);
}
void
_init_libc(j6_process_init *init)
{
sys = init->handles[0];
}
int
main(int argc, const char **argv)
{
@@ -65,6 +59,9 @@ main(int argc, const char **argv)
_syscall_system_log("main thread starting");
for (int i = 0; i < argc; ++i)
_syscall_system_log(argv[i]);
void *base = malloc(0x1000);
if (!base)
return 1;
@@ -97,7 +94,7 @@ main(int argc, const char **argv)
if (tag != 17)
_syscall_system_log("GOT WRONG TAG FROM SENDRECV");
result = _syscall_system_bind_irq(sys, endp, 3);
result = _syscall_system_bind_irq(__handle_sys, endp, 3);
if (result != j6_status_ok)
return result;

View File

@@ -1,24 +0,0 @@
section .bss
mymessage:
resq 1024
extern main
extern _init_libc
extern exit
section .text
global _start
_start:
mov rbp, rsp
mov rdi, rsp
call _init_libc
mov rdi, 0
mov rsi, 0
call main
mov rdi, rax
call exit

30
src/include/j6/init.h Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
/// \file init.h
/// Types used in process and thread initialization
#include <stdint.h>
enum j6_init_type { // `value` is a:
j6_init_handle_system, // Handle to the system
j6_init_handle_process, // Handle to this process
j6_init_handle_thread, // Handle to this thread
j6_init_handle_space, // Handle to this process' address space
j6_init_desc_framebuffer // Pointer to a j6_init_framebuffer descriptor
};
struct j6_init_value {
enum j6_init_type type;
uint64_t value;
};
/// Structure defining a framebuffer.
/// `flags` has the following bits:
/// 0-3: Pixel layout. 0000: bgr8, 0001: rgb8
struct j6_init_framebuffer {
void* addr;
size_t size;
uint32_t vertical;
uint32_t horizontal;
uint32_t scanline;
uint32_t flags;
};

View File

@@ -1,5 +1,7 @@
#include <stddef.h>
#include <j6/init.h>
#include "apic.h"
#include "clock.h"
#include "console.h"
@@ -63,6 +65,14 @@ scheduler::scheduler(lapic *apic) :
bsp_cpu_data.t = idle;
}
template <typename T>
inline T * push(uintptr_t &rsp, size_t size = sizeof(T)) {
rsp -= size;
T *p = reinterpret_cast<T*>(rsp);
rsp &= ~(sizeof(uint64_t)-1); // Align the stack
return p;
}
uintptr_t
load_process_image(uintptr_t phys, uintptr_t virt, size_t bytes, TCB *tcb)
{
@@ -72,31 +82,60 @@ load_process_image(uintptr_t phys, uintptr_t virt, size_t bytes, TCB *tcb)
// We're now in the process space for this process, allocate memory for the
// process code and load it
process &proc = process::current();
thread &th = thread::current();
vm_space &space = proc.space();
vm_area *vma = new vm_area_open(bytes, space, vm_flags::zero|vm_flags::write);
space.add(virt, vma);
vma->commit(phys, 0, memory::page_count(bytes));
tcb->rsp3 -= 2 * sizeof(uint64_t);
uint64_t *sentinel = reinterpret_cast<uint64_t*>(tcb->rsp3);
sentinel[0] = sentinel[1] = 0;
// double zero stack sentinel
*push<uint64_t>(tcb->rsp3) = 0;
*push<uint64_t>(tcb->rsp3) = 0;
tcb->rsp3 -= sizeof(j6_process_init);
j6_process_init *init = reinterpret_cast<j6_process_init*>(tcb->rsp3);
const char message[] = "Hello from the kernel!";
char *message_arg = push<char>(tcb->rsp3, sizeof(message));
kutil::memcpy(message_arg, message, sizeof(message));
init->process = proc.add_handle(&proc);
init->handles[0] = proc.add_handle(system::get());
init->handles[1] = j6_handle_invalid;
init->handles[2] = j6_handle_invalid;
j6_init_framebuffer *fb_desc = push<j6_init_framebuffer>(tcb->rsp3);
fb_desc->addr = reinterpret_cast<void*>(0x100000000);
fb_desc->size = fb_size;
j6_init_value *initv = push<j6_init_value>(tcb->rsp3);
initv->type = j6_init_handle_system;
initv->value = static_cast<uint64_t>(proc.add_handle(system::get()));
initv = push<j6_init_value>(tcb->rsp3);
initv->type = j6_init_handle_process;
initv->value = static_cast<uint64_t>(proc.add_handle(&proc));
initv = push<j6_init_value>(tcb->rsp3);
initv->type = j6_init_handle_thread;
initv->value = static_cast<uint64_t>(proc.add_handle(&th));
initv = push<j6_init_value>(tcb->rsp3);
initv->type = j6_init_handle_space;
//initv->value = static_cast<uint64_t>(proc.add_handle(&space));
initv = push<j6_init_value>(tcb->rsp3);
initv->type = j6_init_desc_framebuffer;
initv->value = reinterpret_cast<uint64_t>(fb_desc);
uint64_t *initc = push<uint64_t>(tcb->rsp3);
*initc = 5;
char **argv0 = push<char*>(tcb->rsp3);
*argv0 = message_arg;
uint64_t *argc = push<uint64_t>(tcb->rsp3);
*argc = 1;
// Crazypants framebuffer part
init->handles[1] = reinterpret_cast<j6_handle_t>(fb_size);
vma = new vm_area_open(fb_size, space, vm_flags::write|vm_flags::mmio);
space.add(0x100000000, vma);
vma->commit(fb_loc, 0, memory::page_count(fb_size));
thread::current().clear_state(thread::state::loading);
th.clear_state(thread::state::loading);
return tcb->rsp3;
}

View File

@@ -1,24 +1,19 @@
section .bss
mymessage:
resq 1024
extern main
extern _init_libc
extern exit
extern _init_libc
section .text
global _start
global _start:function (_start.end - _start)
_start:
mov rbp, rsp
mov rdi, rsp
call _init_libc
mov rdi, 0
mov rsi, 0
pop rdi
mov rsi, rsp
call main
mov rdi, rax
call exit
.end:

View File

@@ -0,0 +1,36 @@
#include <stdint.h>
#include <j6/init.h>
#include <j6/types.h>
static size_t __initc = 0;
static struct j6_init_value *__initv = 0;
j6_handle_t __handle_sys = j6_handle_invalid;
void
_get_init(size_t *initc, struct j6_init_value **initv)
{
if (!initc)
return;
*initc = __initc;
if (initv)
*initv = __initv;
}
void
_init_libc(uint64_t *rsp)
{
uint64_t argc = *rsp++;
rsp += argc;
__initc = *rsp++;
__initv = (struct j6_init_value *)rsp;
for (unsigned i = 0; i < __initc; ++i) {
if (__initv[i].type == j6_init_handle_system) {
__handle_sys = __initv[i].value;
break;
}
}
}