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
apps/src
kernel

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

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

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

@ -70,3 +70,61 @@ void AddressSpace::destroy()
kdbgln("Reclaimed %ld pages from address space!", pages_freed); 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);
}

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

@ -12,9 +12,12 @@
#include "sys/elf/ELFLoader.h" #include "sys/elf/ELFLoader.h"
#include "thread/Scheduler.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) if (!kpathname)
{ {
context->rax = -EFAULT; context->rax = -EFAULT;
@ -73,13 +76,11 @@ void sys_exec(Context* context, const char* pathname)
// At this point, pretty much nothing can fail. // At this point, pretty much nothing can fail.
VMM::switch_back_to_kernel_address_space(); 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::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); 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 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); kfree(kpathname);
return; return;*/
} }