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 <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)
{ {

View File

@ -7,6 +7,8 @@ struct AddressSpace
void destroy(); void destroy();
void reset();
PageTable* get_pml4() PageTable* get_pml4()
{ {
return m_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/init");
Scheduler::load_user_task("/bin/sym");
kinfoln("Prepared scheduler tasks"); kinfoln("Prepared scheduler tasks");

View File

@ -68,5 +68,63 @@ void AddressSpace::destroy()
pages_freed++; pages_freed++;
PMM::free_page(m_pml4); PMM::free_page(m_pml4);
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); kdbgln("Reclaimed %ld pages from address space!", pages_freed);
} }

View File

@ -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");

View File

@ -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;*/
} }