move_stack problem (I think)

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

move_stack problem (I think)

Post by alethiophile »

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:

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));
}
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:

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;
}
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).
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: move_stack problem (I think)

Post by gzaloprgm »

If you are sure that you have single/double-checked the multitasking code and compared it with the downloaded, then the problem must come from another file.
I have successfully compiled and run the downloaded tutorial code, and it works.
Well, if you are sure then you can use a tool such as diff to find diferences between the two files.

Cheers,
gzaloprgm
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: move_stack problem (I think)

Post by yemista »

If you are running the downloaded code, and not the copy and paste code from the site, it should work fine, so it thats a case, and its freezes when you are allocating space for a new table, maybe your emulator does not think it has enough ram?
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: move_stack problem (I think)

Post by Creature »

I think you've run into the same problem I have when I started learning more about the heap. The problem is not that there isn't sufficient RAM, but your get_page function wants to allocate space for the tables, goes to the heap, then the heap sees it has to expand in order to get more space, when expanding it needs to allocate more frames and calls get_page with make = true, which will then try to create page tables again, ... resulting in an infinite loop. Eventually it just freezes or triple faults.

I'm not sure this is the case, but if it is, you're pretty much stuck with a few options:
  • Before creating the heap, allocate space for the tables and create everything before using the heap.
  • Before creating the heap, allocate space for some kind of stack where you can allocate whenever you want. This 'stack' is not on the heap so it won't go through there either.
  • Use the first approach, but only for the kernel directory. Other page tables will get created by page_get just like they would normally. This way the heap won't have trouble with the page tables because the kernel directory's page tables are already there.
  • ...
The best solution seemed the first to me at that time, and I still have that solution. The good thing is that the heap works perfectly fine now and I can allocate every bit of RAM in the computer. The downside is the fact that I can't seem to get multitasking working either, I've tried different approaches but no success. I've also tried the exact same code, but no positive results. I'm not sure if this is a drawback of my approach or I'm just messing it up. You'll also find that others on this forum think it's not such a good idea, as we discussed it here.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
gzaloprgm
Member
Member
Posts: 141
Joined: Sun Sep 23, 2007 4:53 pm
Location: Buenos Aires, Argentina
Contact:

Re: move_stack problem (I think)

Post by gzaloprgm »

You can also use is the recursive page directory method, in which you map PDE #1023 to the physical address of the page dir, and you can access every PT without needing to map them somewhere.

That method wastes 4MB of virtual memory (and 0 bytes of physical), so its almost nothing.

You can find more info of it here.

Cheers,
Gzaloprgm
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: move_stack problem (I think)

Post by alethiophile »

All right, this specific issue is fixed. I had a loop in the get_smallest_hole function that wasn't incrementing its counter. I suppose the reason that it worked so far was that the smallest hole was always the first. :?
If I had an OS, there would be a link here.
Post Reply