Page faulting when it really shouldn't

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Page faulting when it really shouldn't

Post by alethiophile »

Having just fixed my last issue with move_stack, I now find myself with another. The code is below:

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) {
    alloc_frame(get_page(i, 1, current_directory), 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 it faults
  /* 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));
}
Despite having allocated space (and made it world-readable and -writable) in the first loop, I get a page fault on the memcpy instruction, which indicates that I'm trying to write read-only memory. Huh? Details: The parameter new_stack_start is passed as 0xe0000000, the page fault occurs at 0xdfffff74. This should be well within the memory mapped for it.
If I had an OS, there would be a link here.
User avatar
gzaloprgm
Member
Member
Posts: 141
Joined: Sun Sep 23, 2007 4:53 pm
Location: Buenos Aires, Argentina
Contact:

Re: Page faulting when it really shouldn't

Post by gzaloprgm »

The parameter new_stack_start is passed as 0xe0000000, the page fault occurs at 0xdfffff74. This should be well within the memory mapped for it.
The stack (at least in x86 architecture) grows downward, so writes to 0xDFFF.... are expected.

I think your memory mapper isn't working fine.
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.
Post Reply