From dab5c3935704e7ca84c6ca62b40c57ab5d3810b7 Mon Sep 17 00:00:00 2001 From: Berkus Date: Wed, 2 Sep 2009 08:45:46 +0300 Subject: [PATCH] Eliminate unnecessary stack copying. Add fake memmap entry. --- src/vesper/x86/kickstart/kickstart.cpp | 58 +++++--------------------- src/vesper/x86/kickstart/loader.s | 5 +-- src/vesper/x86/lib/bootinfo.h | 30 ++++++++++++- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/src/vesper/x86/kickstart/kickstart.cpp b/src/vesper/x86/kickstart/kickstart.cpp index 659641e8..69ccce84 100644 --- a/src/vesper/x86/kickstart/kickstart.cpp +++ b/src/vesper/x86/kickstart/kickstart.cpp @@ -62,48 +62,6 @@ interrupt_descriptor_table_t interrupts_table; extern "C" void kickstart(multiboot_t::header_t* mbh); extern "C" address_t placement_address; extern "C" address_t KICKSTART_BASE; -extern "C" address_t initial_esp; // in loader.s - - -//! Remap stack for paging mode. -/*! -* Allocate enough pages to fit existing stack frame, copy data from old stack -* and switch over to a new stack. -* @todo Allocated stack pages are 1-1 mapped currently, but probably should be mapped -* to some reserved stack area? -* Changes the original stack given by the bootloader to one at -* a virtual memory location defined at compile time. -*/ -static void remap_stack() -{ - address_t old_stack_pointer = read_stack_pointer(); - address_t old_base_pointer = read_base_pointer(); - - size_t stack_size = initial_esp - old_stack_pointer; - size_t stack_npages = page_align_up(stack_size) / PAGE_SIZE; - address_t stack_page = init_memmgr.alloc_next_page(); - init_memmgr.mapping_enter(stack_page, stack_page); - for (size_t i = 1; i < stack_npages; i++) - { - address_t p = init_memmgr.alloc_next_page(); - init_memmgr.mapping_enter(p, p); - } - - ia32_mmu_t::flush_page_directory(); - - int offset = stack_page + stack_npages * PAGE_SIZE - initial_esp; - address_t new_stack_pointer = old_stack_pointer + offset; - address_t new_base_pointer = old_base_pointer + offset; - - kconsole.print("Copying stack from %p-%p to %p-%p (%d bytes)..", old_stack_pointer, initial_esp, new_stack_pointer, new_stack_pointer + stack_size, stack_size); - - memutils::copy_memory((void*)new_stack_pointer, (const void*)old_stack_pointer, stack_size); - - write_stack_pointer(new_stack_pointer); - write_base_pointer(new_base_pointer); - - kconsole << "done. Activated new stack." << endl; -} //! Prepare and boot system. /*! @@ -139,7 +97,7 @@ void kickstart(multiboot_t::header_t* mbh) << "bootcp module at " << bootcp->mod_start << ", end " << bootcp->mod_end << endl << "Alloctn start at " << init_memmgr.get_alloced_start() << endl; - // fake_mmap_entry->start = init_memmgr.get_alloced_start(); + uint32_t fake_mmap_entry_start = init_memmgr.get_alloced_start(); init_memmgr.setup_pagetables(); @@ -147,8 +105,6 @@ void kickstart(multiboot_t::header_t* mbh) init_memmgr.mapping_enter(bootinfo_page, bootinfo_page); mb.copy(bootinfo_page); bootinfo_t bootinfo(bootinfo_page); - debugger_t::dump_memory(bootinfo_page, bootinfo.size()); - mb.set_header(bootinfo.multiboot_header()); uint32_t k; @@ -185,15 +141,23 @@ void kickstart(multiboot_t::header_t* mbh) interrupts_table.set_isr_handler(14, &page_fault_handler); interrupts_table.install(); - remap_stack(); + // Map stack page + address_t old_stack_pointer = read_stack_pointer(); + init_memmgr.mapping_enter(old_stack_pointer, old_stack_pointer); // Get kernel entry before enabling paging, as this area won't be mapped. typedef void (*kernel_entry)(bootinfo_t bi_page); kernel_entry init_nucleus = (kernel_entry)elf.get_entry_point(); - // TODO: We've allocated memory from a contiguous region, mark it and modify + // We've allocated memory from a contiguous region, mark it and modify // boot info page to exclude this region as occupied. + uint32_t fake_mmap_entry_end = init_memmgr.get_alloced_start(); + multiboot_t::mmap_entry_t fake_mmap_entry; + + fake_mmap_entry.set_region(fake_mmap_entry_start, fake_mmap_entry_end - fake_mmap_entry_start, multiboot_t::mmap_entry_t::bootinfo); + bootinfo.append_mmap_entry(&fake_mmap_entry); + init_memmgr.start_paging(); /// here we have paging enabled and can call kernel functions diff --git a/src/vesper/x86/kickstart/loader.s b/src/vesper/x86/kickstart/loader.s index 475a638a..5598a62a 100644 --- a/src/vesper/x86/kickstart/loader.s +++ b/src/vesper/x86/kickstart/loader.s @@ -8,7 +8,6 @@ ; jump to kickstart() in kickstart.cpp to do all the dirty job. ; global loader ; making entry point visible to linker -global initial_esp extern kickstart extern KICKSTART_BASE extern data_end @@ -25,6 +24,7 @@ CHECKSUM equ -(MAGIC + FLAGS) ; checksum required bits 32 ; 32 bit PM section .bss +align 0x1000 resb 0x1000 initial_stack: ; reserve one page for startup stack @@ -40,13 +40,10 @@ multiboot_header: dd bss_end dd loader -initial_esp: dd 0 ; referencing initial_stack from C doesn't work :( - section .text loader: cli mov esp, initial_stack - mov [initial_esp], esp push ebx ; pass Multiboot info structure mov ebp, 0 ; make base pointer NULL here so we know diff --git a/src/vesper/x86/lib/bootinfo.h b/src/vesper/x86/lib/bootinfo.h index 057aa1ea..3fa119ce 100644 --- a/src/vesper/x86/lib/bootinfo.h +++ b/src/vesper/x86/lib/bootinfo.h @@ -7,6 +7,7 @@ #pragma once #include "multiboot.h" +#include "memory.h" /*! * Provide access to boot info page structures. @@ -16,19 +17,44 @@ class bootinfo_t public: bootinfo_t(address_t bootinfo_page) : boot_info(bootinfo_page) {} size_t size(); + void increase_size(size_t addend); multiboot_t::header_t* multiboot_header(); + bool append_mmap_entry(multiboot_t::mmap_entry_t* entry); private: address_t boot_info; }; inline size_t bootinfo_t::size() { - return *reinterpret_cast(boot_info); + return *reinterpret_cast(boot_info); +} + +inline void bootinfo_t::increase_size(size_t addend) +{ + (*reinterpret_cast(boot_info)) += addend; } inline multiboot_t::header_t* bootinfo_t::multiboot_header() { - return reinterpret_cast(boot_info + 4); + return reinterpret_cast(boot_info + sizeof(size_t)); +} + +//TODO: move to bootinfo.cpp +inline bool bootinfo_t::append_mmap_entry(multiboot_t::mmap_entry_t* entry) +{ + if (size() + sizeof(multiboot_t::mmap_entry_t) > PAGE_SIZE) + return false; + + multiboot_t::header_t* header = multiboot_header(); + uint32_t end = boot_info + size(); + size_t entry_size = sizeof(multiboot_t::mmap_entry_t); + + memutils::copy_memory(reinterpret_cast(end), entry, entry_size); + reinterpret_cast(end)->set_entry_size(entry_size); // ignore any extra fields + header->mmap.set_size(header->mmap.size() + entry_size); + increase_size(entry_size); + + return true; } // kate: indent-width 4; replace-tabs on;