Cloning page directory not working

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

Cloning page directory not working

Post by alethiophile »

I am following James Molloy's kernel-development tutorial, working on multitasking. When I try to switch page directories to a directory that I made using the clone_directory call, I get a triple fault. I have isolated the fault to the switch_page_directory function, below.

Code: Select all

/* Set the page directory. */
void switch_page_directory(page_directory_t *dir) {
  current_directory = dir;
  /* Tell the CPU where the pagedir is. */
  asm volatile ("mov %0, %%cr3" : : "r" (dir->tablesPhysical));
  u32int cr0;
  /* Make sure paging is enabled. */
  asm volatile ("mov %%cr0, %0" : "=r" (cr0));
  cr0 |= 0x80000000; // enable paging bit                                                                                                                    
  asm volatile ("mov %0, %%cr0" : : "r" (cr0));
}
This is line-for-line like the one in the tutorial. When I put an infinite loop in the init_paging function, just after this call, it still triple faults, but when I put the loop immediately after the last inline asm in this function, it does not. My conjecture is that the new directory does not map the original stack (though it should), and hence when I try to return, it page faults, and the page fault code accesses the stack, so it double faults, et cetera. My clone_directory code is below:

Code: Select all

/* Clones a page directory, linking those tables that are used by the kernel and copying those
   not.
*/
page_directory_t *clone_directory(page_directory_t *src) {
  u32int phys;
  page_directory_t *new_dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
  memset(new_dir, 0, sizeof(page_directory_t));

  u32int off = (u32int) new_dir->tablesPhysical - (u32int) new_dir;

  new_dir->physicalAddr = phys + off;

  u32int i;
  for (i = 0; i < 1024; i++) {
    if (!src->tables[i])
      continue;
    if (kernel_directory->tables[i] == src->tables[i]) { // If it's kernel, then link it.
      new_dir->tables[i] = src->tables[i];
      new_dir->tablesPhysical[i] = src->tablesPhysical[i];
    }
    else { // Else, copy it.
      u32int np;
      new_dir->tables[i] = clone_table(src->tables[i], &np);
      new_dir->tablesPhysical[i] = np | 0x07;
    }
  }
  return new_dir;
}

/* Clones a page table. */
page_table_t *clone_table(page_table_t *src, u32int *phys) {
  page_table_t *new_table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), phys);
  memset(new_table, 0, sizeof(page_table_t));
  u32int i;
  for (i = 0; i < 1024; i++) {
    // If it's not allocated, than don't bother
    if (src->pages[i].frame) {
      // Allocate space for page
      alloc_frame(&new_table->pages[i], 0, 0);
      // Copy attributes of page
      if (src->pages[i].present) new_table->pages[i].present = 1;
      if (src->pages[i].rw) new_table->pages[i].rw = 1;
      if (src->pages[i].user) new_table->pages[i].user = 1;
      if (src->pages[i].accessed) new_table->pages[i].accessed = 1;
      if (src->pages[i].dirty) new_table->pages[i].dirty = 1;
      // Copy page data
      copy_frame(src->pages[i].frame * 0x1000, new_table->pages[i].frame * 0x1000);
    }
  }
  return new_table;
}
This is pretty much line-for-line like the tutorial. However, I have successfully built and run the tutorial, and it works fine. Does anyone have any insight into why there is this difference?
If I had an OS, there would be a link here.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Re: Cloning page directory not working

Post by frank »

There are some differences between the code in the tutorial and the downloadable code. The downloads get updated more often, so you should rely on the code in those.
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: Cloning page directory not working

Post by alethiophile »

I am comparing with the downloaded code.
If I had an OS, there would be a link here.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Cloning page directory not working

Post by JamesM »

Frank is correct - there are minor typographical errors on the website sample code that are rectified in the downloadable code.

I keep them there to deter copy-pasters.
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: Cloning page directory not working

Post by Creature »

If it still won't work after that, it's most likely a problem with either:
  • Your paging setup.
  • Your heap or memory allocator (which is being used to create the cloned directory in) not correctly page-aligning the data.
I've had this problem too and it was always one of the above cases. It can also be something different, but I suggest you especially look out for mistakes in heap page-aligning code and wrong page-alignments and such.
Last edited by Creature on Wed Jul 29, 2009 3:44 am, edited 1 time in total.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
steve23
Posts: 1
Joined: Tue Jul 21, 2009 10:55 pm

Re: Cloning page directory not working

Post by steve23 »

I'm having problems with chapter 9. Multitasking too.
Using the tar files from the end of each chapter, all the chapters up to chapter 8 compile and run fine on my PC. But the chapter 9 multitasking code gives a kernel panic:

Page fault! ( present ) at 0x0x106d7815 - EIP: 0x106d7815
PANIC(Page fault) at paging.c:230

So I think there is a bug in the tutorial.
Part of the code moves the stack, and modifies some values on the new stack.
That sounds dangerous to me.
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: Cloning page directory not working

Post by alethiophile »

The downloaded code works fine for me; I just have bugs in my version.
If I had an OS, there would be a link here.
Dominator
Member
Member
Posts: 25
Joined: Fri Jul 06, 2012 10:52 am

Re: Cloning page directory not working

Post by Dominator »

steve23 wrote:I'm having problems with chapter 9. Multitasking too.
Using the tar files from the end of each chapter, all the chapters up to chapter 8 compile and run fine on my PC. But the chapter 9 multitasking code gives a kernel panic:

Page fault! ( present ) at 0x0x106d7815 - EIP: 0x106d7815
PANIC(Page fault) at paging.c:230

So I think there is a bug in the tutorial.
Part of the code moves the stack, and modifies some values on the new stack.
That sounds dangerous to me.
I had the same problem. Then I added

Code: Select all

 __asm__ volatile("cli")
and

Code: Select all

 __asm__ volatile("sti")
around switch_task(), which makes sense. The kernel now runs fine when compiled with gcc at -O0, however any optimization seems to screw it up.

Update: Seems like a stable fix even with gcc -O2/O3. I guess I was having issues with bochs. Also tried some mutex/spinlock which worked as well.
Last edited by Dominator on Tue Jul 10, 2012 11:52 pm, edited 3 times in total.
Dominator
Member
Member
Posts: 25
Joined: Fri Jul 06, 2012 10:52 am

Re: Cloning page directory not working

Post by Dominator »

alethiophile wrote:The downloaded code works fine for me; I just have bugs in my version.
The downloaded binary works, but the one recompiled with gcc 4.6.3 has kernel panics.
Dominator
Member
Member
Posts: 25
Joined: Fri Jul 06, 2012 10:52 am

Re: Cloning page directory not working

Post by Dominator »

JamesM wrote:Frank is correct - there are minor typographical errors on the website sample code that are rectified in the downloadable code.

I keep them there to deter copy-pasters.
Hi James, thanks for those awesome tutorials! While I'm not sure if my fix was correct, should the entire switch_task() function be made atomic?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Cloning page directory not working

Post by JamesM »

Yeah the code's generally a bit ****. I'm working on new versions (actively, and will full intent to release by September for the doubters among you)...
jbemmel
Member
Member
Posts: 53
Joined: Fri May 11, 2012 11:54 am

Re: Cloning page directory not working

Post by jbemmel »

alethiophile wrote: My clone_directory code is below:

Code: Select all

/* Clones a page directory, linking those tables that are used by the kernel and copying those
   not.
*/
page_directory_t *clone_directory(page_directory_t *src) {
  u32int phys;
  page_directory_t *new_dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
  memset(new_dir, 0, sizeof(page_directory_t));

  u32int off = (u32int) new_dir->tablesPhysical - (u32int) new_dir;

  new_dir->physicalAddr = phys + off;
After the memset, new_dir->tablesPhysical should be 0 right? so new_dir->physicalAddr = phys - (u32int) new_dir. I don't follow what's going on here, seem to be mixing physical and linear addresses?
Post Reply