Skip to content

Commit

Permalink
Eliminate unnecessary stack copying. Add fake memmap entry.
Browse files Browse the repository at this point in the history
  • Loading branch information
berkus committed Sep 2, 2009
1 parent f453a12 commit dab5c39
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 53 deletions.
58 changes: 11 additions & 47 deletions src/vesper/x86/kickstart/kickstart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<address_t>(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.
/*!
Expand Down Expand Up @@ -139,16 +97,14 @@ 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();

address_t bootinfo_page = init_memmgr.alloc_next_page();
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;
Expand Down Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions src/vesper/x86/kickstart/loader.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down
30 changes: 28 additions & 2 deletions src/vesper/x86/lib/bootinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include "multiboot.h"
#include "memory.h"

/*!
* Provide access to boot info page structures.
Expand All @@ -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<uint32_t*>(boot_info);
return *reinterpret_cast<size_t*>(boot_info);
}

inline void bootinfo_t::increase_size(size_t addend)
{
(*reinterpret_cast<size_t*>(boot_info)) += addend;
}

inline multiboot_t::header_t* bootinfo_t::multiboot_header()
{
return reinterpret_cast<multiboot_t::header_t*>(boot_info + 4);
return reinterpret_cast<multiboot_t::header_t*>(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<void*>(end), entry, entry_size);
reinterpret_cast<multiboot_t::mmap_entry_t*>(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;
Expand Down

0 comments on commit dab5c39

Please sign in to comment.