diff --git a/kernel/include/kernel/Memory/VirtualRange.h b/kernel/include/kernel/Memory/VirtualRange.h index c096ba8d..f8f404bb 100644 --- a/kernel/include/kernel/Memory/VirtualRange.h +++ b/kernel/include/kernel/Memory/VirtualRange.h @@ -20,8 +20,6 @@ namespace Kernel static BAN::ErrorOr> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages); ~VirtualRange(); - BAN::ErrorOr> clone(PageTable&); - vaddr_t vaddr() const { return m_vaddr + (m_has_guard_pages ? PAGE_SIZE : 0); } size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); } PageTable::flags_t flags() const { return m_flags; } diff --git a/kernel/kernel/Memory/VirtualRange.cpp b/kernel/kernel/Memory/VirtualRange.cpp index 32ec4ec7..62ca878b 100644 --- a/kernel/kernel/Memory/VirtualRange.cpp +++ b/kernel/kernel/Memory/VirtualRange.cpp @@ -110,36 +110,6 @@ namespace Kernel return {}; } - BAN::ErrorOr> VirtualRange::clone(PageTable& page_table) - { - ASSERT(&PageTable::current() == &m_page_table); - ASSERT(&m_page_table != &page_table); - - SpinLockGuard _(m_lock); - - auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), m_flags, m_preallocated, m_has_guard_pages)); - - const size_t page_count = size() / PAGE_SIZE; - for (size_t i = 0; i < page_count; i++) - { - if (m_paddrs[i] == 0) - continue; - if (!result->m_preallocated) - { - result->m_paddrs[i] = Heap::get().take_free_page(); - if (result->m_paddrs[i] == 0) - return BAN::Error::from_errno(ENOMEM); - result->m_page_table.map_page_at(result->m_paddrs[i], vaddr() + i * PAGE_SIZE, m_flags); - } - - PageTable::with_fast_page(result->m_paddrs[i], [&] { - memcpy(PageTable::fast_page_as_ptr(), reinterpret_cast(vaddr() + i * PAGE_SIZE), PAGE_SIZE); - }); - } - - return result; - } - BAN::ErrorOr VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr) { ASSERT(contains(vaddr)); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 3e8fd163..2eafc640 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -13,6 +13,12 @@ namespace Kernel { +#if ARCH(x86_64) + static constexpr vaddr_t s_user_stack_addr_start = 0x0000700000000000; +#elif ARCH(i686) + static constexpr vaddr_t s_user_stack_addr_start = 0xB0000000; +#endif + extern "C" [[noreturn]] void start_kernel_thread(); extern "C" [[noreturn]] void start_userspace_thread(); @@ -200,15 +206,9 @@ namespace Kernel thread->m_is_userspace = true; -#if ARCH(x86_64) - static constexpr vaddr_t stack_addr_start = 0x0000700000000000; -#elif ARCH(i686) - static constexpr vaddr_t stack_addr_start = 0xB0000000; -#endif - thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range( page_table, - stack_addr_start, USERSPACE_END, + s_user_stack_addr_start, USERSPACE_END, kernel_stack_size, PageTable::Flags::ReadWrite | PageTable::Flags::Present, true, true @@ -217,7 +217,7 @@ namespace Kernel auto userspace_stack = TRY(MemoryBackedRegion::create( page_table, userspace_stack_size, - { stack_addr_start, USERSPACE_END }, + { s_user_stack_addr_start, USERSPACE_END }, MemoryRegion::Type::PRIVATE, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present, O_RDWR @@ -346,7 +346,24 @@ namespace Kernel thread->m_is_userspace = true; - thread->m_kernel_stack = TRY(m_kernel_stack->clone(new_process->page_table())); + thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range( + new_process->page_table(), + s_user_stack_addr_start, USERSPACE_END, + kernel_stack_size, + PageTable::Flags::ReadWrite | PageTable::Flags::Present, + true, true + )); + + // NOTE: copy [sp, stack_end] so fork return works + PageTable::with_fast_page(thread->m_kernel_stack->paddr_of(thread->kernel_stack_top() - PAGE_SIZE), [&] { + const size_t ncopy = kernel_stack_top() - sp; + ASSERT(ncopy <= PAGE_SIZE); + memcpy( + PageTable::fast_page_as_ptr(PAGE_SIZE - ncopy), + reinterpret_cast(sp), + ncopy + ); + }); const auto stack_index = new_process->find_mapped_region(m_userspace_stack->vaddr()); thread->m_userspace_stack = static_cast(new_process->m_mapped_regions[stack_index].ptr());