stack movement in JamesM tutorial
Posted: Mon Apr 23, 2012 4:39 am
Hi,
I am going though the Multitasking section of JamesM tutorial in which
a method is added to move stack from lower address to some higher address.
This method is called as - move_stack((void*)0xE0000000, 0x2000) while creating the first task.
What I am not able to understand is the calculation of offset (line marked by <<< above).
According to my understanding initial_esp should be the physical address of base of initial stack. However new_stack_start is the
virtual address of the base of new stack which might not be equal to its physical address. So adding the
offset to the current stack pointer might not give the virtual address of the base of the new stack.
Am I correct ?
I am going though the Multitasking section of JamesM tutorial in which
a method is added to move stack from lower address to some higher address.
Code: Select all
void move_stack(void *new_stack_start, u32int size)
{
u32int i;
// Allocate some space for the new stack.
for( i = (u32int)new_stack_start;
i >= ((u32int)new_stack_start-size);
i -= 0x1000)
{
// General-purpose stack is in user-mode.
alloc_frame( get_page(i, 1, current_directory), 0 /* User mode */, 1 /* Is writable */ );
}
// Flush the TLB by reading and writing the page directory address again.
u32int pd_addr;
asm volatile("mov %%cr3, %0" : "=r" (pd_addr));
asm volatile("mov %0, %%cr3" : : "r" (pd_addr));
// Old ESP and EBP, read from registers.
u32int old_stack_pointer; asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer));
u32int old_base_pointer; asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer));
// Offset to add to old stack addresses to get a new stack address.
u32int offset = (u32int)new_stack_start - initial_esp; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// New ESP and EBP.
u32int new_stack_pointer = old_stack_pointer + offset;
u32int new_base_pointer = old_base_pointer + offset;
// Copy the stack.
memcpy((void*)new_stack_pointer, (void*)old_stack_pointer, initial_esp-old_stack_pointer);
// Backtrace through the original stack, copying new values into
// the new stack.
for(i = (u32int)new_stack_start; i > (u32int)new_stack_start-size; i -= 4)
{
u32int tmp = * (u32int*)i;
// If the value of tmp is inside the range of the old stack, assume it is a base pointer
// and remap it. This will unfortunately remap ANY value in this range, whether they are
// base pointers or not.
if (( old_stack_pointer < tmp) && (tmp < initial_esp))
{
tmp = tmp + offset;
u32int *tmp2 = (u32int*)i;
*tmp2 = tmp;
}
}
// Change stacks.
asm volatile("mov %0, %%esp" : : "r" (new_stack_pointer));
asm volatile("mov %0, %%ebp" : : "r" (new_base_pointer));
}
What I am not able to understand is the calculation of offset (line marked by <<< above).
According to my understanding initial_esp should be the physical address of base of initial stack. However new_stack_start is the
virtual address of the base of new stack which might not be equal to its physical address. So adding the
offset to the current stack pointer might not give the virtual address of the base of the new stack.
Am I correct ?