mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Loading processes from within their memory space
The scheduler's create_process now sets up the stack to iretq into a load_process function, which will load the process image into memory from within the process' own virtual memory space. Currently this loading is just copying the old 'taskA' function from kernel space.
This commit is contained in:
@@ -12,10 +12,16 @@ scheduler scheduler::s_instance(nullptr);
|
||||
static const uint32_t quantum = 20000000;
|
||||
|
||||
const int stack_size = 0x1000;
|
||||
const uint64_t rflags_noint = 0x002;
|
||||
const uint64_t rflags_int = 0x202;
|
||||
|
||||
extern "C" void taskA();
|
||||
extern "C" void taskB();
|
||||
extern "C" {
|
||||
void taskA();
|
||||
void taskAend();
|
||||
void ramdisk_process_loader();
|
||||
|
||||
void load_process(void *copy_start, size_t butes, cpu_state state);
|
||||
};
|
||||
|
||||
scheduler::scheduler(lapic *apic) :
|
||||
m_apic(apic),
|
||||
@@ -24,8 +30,30 @@ scheduler::scheduler(lapic *apic) :
|
||||
m_processes.ensure_capacity(50);
|
||||
}
|
||||
|
||||
void
|
||||
load_process(void *copy_start, size_t bytes, cpu_state state)
|
||||
{
|
||||
log::debug(logs::task, "Loading task! Start: %016lx [%d]", copy_start, bytes);
|
||||
log::debug(logs::task, "New process state:");
|
||||
log::debug(logs::task, " CS: %d [%d]", state.cs >> 3, state.cs & 0x07);
|
||||
log::debug(logs::task, " SS: %d [%d]", state.ss >> 3, state.ss & 0x07);
|
||||
log::debug(logs::task, " RFLAGS: %08x", state.rflags);
|
||||
log::debug(logs::task, " RIP: %016lx", state.rip);
|
||||
log::debug(logs::task, " uRSP: %016lx", state.user_rsp);
|
||||
|
||||
// We're now in the process space for this process, allocate memory for the
|
||||
// process code and load it
|
||||
page_manager *pager = page_manager::get();
|
||||
|
||||
size_t count = ((bytes - 1) / page_manager::page_size) + 1;
|
||||
void *loading = pager->map_pages(0x200000, count, true);
|
||||
|
||||
kutil::memcpy(loading, copy_start, bytes);
|
||||
state.rip = reinterpret_cast<uint64_t>(loading);
|
||||
}
|
||||
|
||||
static process
|
||||
create_process(uint16_t pid, void (*rip)())
|
||||
create_process(uint16_t pid)
|
||||
{
|
||||
uint64_t flags;
|
||||
__asm__ __volatile__ ( "pushf; pop %0" : "=r" (flags) );
|
||||
@@ -36,25 +64,47 @@ create_process(uint16_t pid, void (*rip)())
|
||||
uint16_t kss = (2 << 3) | 0; // Kernel SS is GDT entry 2, ring 0
|
||||
uint16_t ss = (4 << 3) | 3; // User SS is GDT entry 4, ring 3
|
||||
|
||||
void *stack0 = kutil::malloc(stack_size);
|
||||
void *sp0 = kutil::offset_pointer(stack0, stack_size);
|
||||
cpu_state *state = reinterpret_cast<cpu_state *>(sp0) - 1;
|
||||
kutil::memset(state, 0, sizeof(cpu_state));
|
||||
// Set up the page tables - this also allocates an initial user stack
|
||||
page_table *pml4 = page_manager::get()->create_process_map();
|
||||
|
||||
// Create a one-page kernel stack space
|
||||
void *stack0 = kutil::malloc(stack_size);
|
||||
kutil::memset(stack0, 0, stack_size);
|
||||
|
||||
// Stack grows down, point to the end
|
||||
void *sp0 = kutil::offset_pointer(stack0, stack_size);
|
||||
|
||||
cpu_state *state = reinterpret_cast<cpu_state *>(sp0) - 1;
|
||||
|
||||
// Highest state in the stack is the process' kernel stack for the loader
|
||||
// to iret to:
|
||||
state->ds = state->ss = ss;
|
||||
state->cs = cs;
|
||||
state->rflags = 0x202;
|
||||
state->rip = reinterpret_cast<uint64_t>(rip);
|
||||
|
||||
page_table *pml4 = page_manager::get()->create_process_map();
|
||||
state->rflags = rflags_int;
|
||||
state->rip = 0; // to be filled by the loader
|
||||
state->user_rsp = page_manager::initial_stack;
|
||||
|
||||
log::debug(logs::task, "Creating PID %d:", pid);
|
||||
log::debug(logs::task, " RSP0 %016lx", state);
|
||||
log::debug(logs::task, " RSP3 %016lx", state->user_rsp);
|
||||
log::debug(logs::task, " PML4 %016lx", pml4);
|
||||
// Next state in the stack is the loader's kernel stack. The scheduler will
|
||||
// iret to this which will kick off the loading:
|
||||
cpu_state *loader_state = reinterpret_cast<cpu_state *>(sp0) - 2;
|
||||
|
||||
return {pid, reinterpret_cast<addr_t>(state), pml4};
|
||||
loader_state->ds = loader_state->ss = kss;
|
||||
loader_state->cs = kcs;
|
||||
loader_state->rflags = rflags_noint;
|
||||
loader_state->rip = reinterpret_cast<uint64_t>(ramdisk_process_loader);
|
||||
loader_state->user_rsp = reinterpret_cast<uint64_t>(state);
|
||||
|
||||
// TODO: replace with an actual ELF location in memory
|
||||
loader_state->rax = reinterpret_cast<uint64_t>(taskA);
|
||||
loader_state->rbx = reinterpret_cast<uint64_t>(taskAend) - reinterpret_cast<uint64_t>(taskA);
|
||||
|
||||
log::debug(logs::task, "Creating PID %d:", pid);
|
||||
log::debug(logs::task, " RSP0 %016lx", state);
|
||||
log::debug(logs::task, " RSP3 %016lx", state->user_rsp);
|
||||
log::debug(logs::task, " PML4 %016lx", pml4);
|
||||
log::debug(logs::task, " Loading %016lx [%d]", loader_state->rax, loader_state->rbx);
|
||||
|
||||
return {pid, reinterpret_cast<addr_t>(loader_state), pml4};
|
||||
}
|
||||
|
||||
void
|
||||
@@ -65,8 +115,8 @@ scheduler::start()
|
||||
m_apic->enable_timer(isr::isrTimer, 128, quantum, false);
|
||||
|
||||
m_processes.append({0, 0, page_manager::get_pml4()}); // The kernel idle task, also the thread we're in now
|
||||
m_processes.append(create_process(1, &taskA));
|
||||
m_processes.append(create_process(2, &taskB));
|
||||
m_processes.append(create_process(1));
|
||||
//m_processes.append(create_process(2, &taskB));
|
||||
}
|
||||
|
||||
addr_t
|
||||
|
||||
Reference in New Issue
Block a user