move_stack problem (I think)
Posted: Fri Jul 10, 2009 9:12 pm
I am following JamesM's tutorial, working on section Multitasking. I wrote a move_stack function line-for-line like the one in the code (and yes, I am using the downloaded code here), and call it in the init_multitasking function, again as in the tutorial. Here's the move_stack:
When I run this, it freezes. Tracing it, it freezes in the call to get_page that is marked above. When I traced it into that function, it turned out to freeze during allocation of space for creating page tables in the routine for doing that. get_page is below:
The call in which it freezes is marked above. Does anyone know why this is happening? I have successfully compiled and run the downloaded tutorial code, and it works.
EDIT: It should be noted that when it freezes interrupts do not run (i.e. my keyboard sort-of-driver doesn't print scancodes).
Code: Select all
void move_stack(void *new_stack_start, u32int size) {
u32int i;
// Allocate space
for (i = (u32int) new_stack_start; i >= ((u32int) new_stack_start - size); i -= 0x1000) {
printf("%x %x %x\n", (u32int) new_stack_start, size, i);
page_t *pgtmp = get_page(i, 1, current_directory); // Freezes in this call
alloc_frame(pgtmp, 0, 1);
}
// Flush TLB (?)
u32int pd_addr;
asm volatile ("mov %%cr3, %0" : "=r" (pd_addr));
asm volatile ("mov %0, %%cr3" : : "r" (pd_addr));
// Get the old stack/base pointers
u32int old_esp, old_ebp;
asm volatile ("mov %%esp, %0" : "=r" (old_esp));
asm volatile ("mov %%ebp, %0" : "=r" (old_ebp));
// Get stack offset
u32int off = (u32int) new_stack_start - initial_esp;
// New stack/base pointers
u32int new_esp = old_esp + off;
u32int new_ebp = old_ebp + off;
memcpy((void *) new_esp, (void *) old_esp, initial_esp - old_esp);
/* Here we have to look for pushed EBP values to change them to point to the new stack.
This algorithm assumes that any value that points into the old stack is a pushed EBP,
meaning that it'll mess up any local variables or function parameters that are in
that range.
*/
for (i = (u32int) new_stack_start; i > ((u32int) new_stack_start - size); i -= 4) {
u32int tmp = *(u32int*)i;
if ((old_esp < tmp) && (tmp < initial_esp)) {
tmp += off;
u32int *tmp2 = (u32int *)i;
*tmp2 = tmp;
}
}
asm volatile ("mov %0, %%esp" : : "r" (new_esp));
asm volatile ("mov %0, %%ebp" : : "r" (new_ebp));
}
Code: Select all
page_t *get_page(u32int addr, int make, page_directory_t *dir) {
addr /= 0x1000; // make into an index
u32int table_idx = addr / 0x400;
if (dir->tables[table_idx]) {
return &dir->tables[table_idx]->pages[addr%0x400];
}
if (make) {
u32int tmp;
dir->tables[table_idx] = (page_table_t *) kmalloc_a(sizeof(page_table_t)); // Freezes here
tmp = (u32int) dir->tables[table_idx];
memset(dir->tables[table_idx], 0, 0x1000);
dir->tablesPhysical[table_idx] = tmp | 0x07; // present, read/write, kernel
return &dir->tables[table_idx]->pages[addr%0x400];
}
return 0;
}
EDIT: It should be noted that when it freezes interrupts do not run (i.e. my keyboard sort-of-driver doesn't print scancodes).