It (almost) works now

The only thing doing weird stuff is exec(), so that's commented out and throws ENOSYS right now.

But we have two user tasks running in parallel, isolated from each other!
This commit is contained in:
apio 2022-10-14 16:46:00 +02:00
parent 0c7c249935
commit 26211bd49f
6 changed files with 80 additions and 9 deletions

View File

@ -1,8 +1,11 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
sleep(6);
FILE* syms = fopen("/sys/moon.sym", "r");
if (!syms)
{

View File

@ -7,6 +7,8 @@ struct AddressSpace
void destroy();
void reset();
PageTable* get_pml4()
{
return m_pml4;

View File

@ -74,6 +74,7 @@ extern "C" void _start()
});
Scheduler::load_user_task("/bin/init");
Scheduler::load_user_task("/bin/sym");
kinfoln("Prepared scheduler tasks");

View File

@ -70,3 +70,61 @@ void AddressSpace::destroy()
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
}
void AddressSpace::reset()
{
uint64_t pages_freed = 0;
for (int i = 0; i < 512; i++)
{
PageDirectoryEntry& pdp_pde = m_pml4->entries[i];
if (!pdp_pde.present) continue;
if (pdp_pde.larger_pages)
{
pages_freed++;
PMM::free_page((void*)pdp_pde.get_address());
continue;
}
PageTable* pdp = (PageTable*)pdp_pde.get_address();
for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one
{
PageDirectoryEntry& pd_pde = pdp->entries[j];
if (!pd_pde.present) continue;
if (pd_pde.larger_pages)
{
pages_freed++;
PMM::free_page((void*)pd_pde.get_address());
continue;
}
PageTable* pd = (PageTable*)pd_pde.get_address();
for (int k = 0; k < 512; k++)
{
PageDirectoryEntry& pt_pde = pd->entries[k];
if (!pt_pde.present) continue;
if (pt_pde.larger_pages)
{
pages_freed++;
PMM::free_page((void*)pt_pde.get_address());
continue;
}
PageTable* pt = (PageTable*)pt_pde.get_address();
for (int l = 0; l < 512; l++)
{
PageDirectoryEntry& pde = pt->entries[l];
if (!pde.present) continue;
pages_freed++;
PMM::free_page((void*)pde.get_address());
}
pages_freed++;
PMM::free_page(pt);
}
pages_freed++;
PMM::free_page(pd);
}
pages_freed++;
PMM::free_page(pdp);
}
VMM::install_kernel_page_directory_into_address_space(*this);
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
}

View File

@ -8,6 +8,7 @@
#include "interrupts/Interrupts.h"
#include "io/IO.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "misc/hang.h"
#include "std/string.h"
@ -85,6 +86,11 @@ static void try_idt_triple_fault()
[[noreturn]] void reboot()
{
Interrupts::disable();
if (!VMM::is_using_kernel_address_space())
{
VMM::switch_back_to_kernel_address_space();
VMM::apply_address_space();
}
kinfoln("Attempting reboot using ACPI");
try_acpi_reboot();
kinfoln("Attempting reboot using keyboard RESET pulsing");

View File

@ -12,9 +12,12 @@
#include "sys/elf/ELFLoader.h"
#include "thread/Scheduler.h"
void sys_exec(Context* context, const char* pathname)
void sys_exec(Context* context, const char*)
{
char* kpathname = Syscall::strdup_from_user(pathname);
context->rax = -ENOSYS; // FIXME: Make exec() work under separate address spaces.
return;
/*char* kpathname = Syscall::strdup_from_user(pathname);
if (!kpathname)
{
context->rax = -EFAULT;
@ -73,13 +76,11 @@ void sys_exec(Context* context, const char* pathname)
// At this point, pretty much nothing can fail.
VMM::switch_back_to_kernel_address_space();
task->address_space.destroy();
task->address_space = AddressSpace::create();
VMM::switch_to_user_address_space(task->address_space);
VMM::apply_address_space();
VMM::enter_syscall_context();
task->address_space.reset();
// VMM::switch_to_user_address_space(task->address_space);
ELFImage* image = ELFLoader::load_elf_from_vfs(program);
ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly
@ -98,5 +99,5 @@ void sys_exec(Context* context, const char* pathname)
kfree(kpathname);
return;
return;*/
}