Restructuring paging into an object that carries its page cache with it and makes for simpler code. Program loading is also changed to not copy the pages loaded from the file into new pages - we can impose a new constraint that anything loaded by boot have a simple, page-aligned layout so that we can just map the existing pages into the right addresses. Also included are some linker script changes to help accommodate this.
116 lines
3.1 KiB
C++
116 lines
3.1 KiB
C++
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include <bootproto/kernel.h>
|
|
#include <util/vector.h>
|
|
|
|
#include "assert.h"
|
|
#include "capabilities.h"
|
|
#include "cpu.h"
|
|
#include "device_manager.h"
|
|
#include "interrupts.h"
|
|
#include "logger.h"
|
|
#include "memory.h"
|
|
#include "objects/process.h"
|
|
#include "objects/system.h"
|
|
#include "objects/thread.h"
|
|
#include "objects/vm_area.h"
|
|
#include "scheduler.h"
|
|
#include "smp.h"
|
|
#include "syscall.h"
|
|
#include "sysconf.h"
|
|
|
|
extern "C" {
|
|
void kernel_main(bootproto::args *args);
|
|
}
|
|
|
|
/// Bootstrap the memory managers.
|
|
void load_init_server(bootproto::program &program, uintptr_t modules_address);
|
|
|
|
|
|
void
|
|
kernel_main(bootproto::args *args)
|
|
{
|
|
if (args->panic_handler) {
|
|
panic::install(args->panic_handler, args->symbol_table);
|
|
}
|
|
|
|
logger_init();
|
|
|
|
cpu_data *cpu = bsp_early_init();
|
|
|
|
kassert(args->magic == bootproto::args_magic,
|
|
"Bad kernel args magic number");
|
|
|
|
log::verbose(logs::boot, "jsix init args are at: %016lx", args);
|
|
log::verbose(logs::boot, " Memory map is at: %016lx", args->mem_map);
|
|
log::verbose(logs::boot, "ACPI root table is at: %016lx", args->acpi_table);
|
|
log::verbose(logs::boot, "Runtime service is at: %016lx", args->runtime_services);
|
|
log::verbose(logs::boot, " Kernel PML4 is at: %016lx", args->pml4);
|
|
|
|
disable_legacy_pic();
|
|
|
|
mem::initialize(*args);
|
|
|
|
bsp_late_init();
|
|
|
|
using bootproto::boot_flags;
|
|
bool enable_test = util::bits::has(args->flags, boot_flags::test);
|
|
syscall_initialize(enable_test);
|
|
|
|
device_manager &devices = device_manager::get();
|
|
devices.parse_acpi(args->acpi_table);
|
|
|
|
devices.init_drivers();
|
|
cpu_init(cpu, true);
|
|
|
|
g_num_cpus = smp::start(*cpu, args->pml4);
|
|
|
|
sysconf_create();
|
|
interrupts_enable();
|
|
|
|
scheduler *sched = new scheduler {g_num_cpus};
|
|
smp::ready();
|
|
|
|
// Load the init server
|
|
load_init_server(args->init, args->init_modules);
|
|
|
|
sched->start();
|
|
}
|
|
|
|
void
|
|
load_init_server(bootproto::program &program, uintptr_t modules_address)
|
|
{
|
|
using bootproto::section_flags;
|
|
using obj::vm_flags;
|
|
|
|
obj::process *p = new obj::process;
|
|
|
|
j6_handle_t sys_handle =
|
|
g_cap_table.create(&obj::system::get(), obj::system::init_caps);
|
|
p->add_handle(sys_handle);
|
|
|
|
vm_space &space = p->space();
|
|
for (const auto § : program.sections) {
|
|
vm_flags flags =
|
|
((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) |
|
|
((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none);
|
|
|
|
obj::vm_area *vma = new obj::vm_area_fixed(sect.phys_addr, sect.size, flags);
|
|
space.add(sect.virt_addr, vma);
|
|
}
|
|
|
|
uint64_t iopl = (3ull << 12);
|
|
|
|
obj::thread *main = p->create_thread();
|
|
main->add_thunk_user(program.entrypoint, 0, iopl);
|
|
main->set_state(obj::thread::state::ready);
|
|
|
|
// Hacky: No process exists to have created a stack for init; it needs to create
|
|
// its own stack. We take advantage of that to use rsp to pass it the init modules
|
|
// address.
|
|
auto *tcb = main->tcb();
|
|
tcb->rsp3 = modules_address;
|
|
}
|