OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 12:02 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 2:42 am 
Offline

Joined: Tue May 11, 2010 8:05 pm
Posts: 12
Hello,

I've been creeping on these forums since last summer. I've been reading all the tutorials I could find, mainly Bran's and JamesM's. I've gotten to the point where I'm looking to enable paging. I completely understand the very high level theory, but I'm not 100% on the nitty gritty implementation details. I'm a little hung up on some of the locations JamesM, out of the blue, decides to use for storing certain things with no explanation. I've read that his code on his personal website isn't maintained and might be buggy, so I've also been following the code he has on code.google.com. I've spent the past few days reading every thread that even mentions the word "paging" on this forum. I've been pouring over the wiki to no avail.

Now to the problem.

I successfully set up a GDT (with 3 values, null, a code, and a data segment; 0- 4GB limit, 4KB granularity), and IDT with working interrupt service routines and IRQs, the timer is set up.
I'm reading the multiboot memory map, but I'm not using it yet. I've been printing out all the addresses floating around and you may find them of use.

My kernel ends at address 0x00106CC8, so I allocate the first page directory at 0x00108000. The first page table follows at 0x00109000. The read/write and present flags are correctly set on those pages.

This is the paging enable code:
Code:
int i;
unsigned int cr0;

install_interrupt_handler(14, &page_fault);

// Allocate a new frame for the page directory to sit in
unsigned int *pd = (unsigned int*)AllocateFrame();  // AllocateFrame() returns the next page aligned address that is free

// Clear it
memset_dw(pd, 0, 0x1000);

// Create the first page table entry to go in the new page directory
unsigned int *pt = (unsigned int*)AllocateFrame();

// Assign it to the page directory and set its flags
pd[0] = (unsigned int)pt | PAGE_PRESENT | PAGE_WRITE;

// Identity map the first 4MB of physical memory to it
for (i = 0; i < 1024; i++)
   pt[i] = (i*0x1000) | PAGE_PRESENT | PAGE_WRITE;

SwitchPageDirectory(pd);  // simply does - asm volatile("mov %0, %%cr3" : : "r" (pd));

// Enable paging
asm volatile ("mov %%cr0, %0" : "=r" (cr0));
cr0 |= 0x80000000;
asm volatile ("mov %0, %%cr0" : : "r" (cr0));

pagingActive = 1;


All pretty straightforward. Now, though, if I try to force a page fault with
Code:
// quick test of page fault handler
unsigned int *ptr = (unsigned int*)0xC0000000;
*ptr = 500;


It throws a General Protection fault.

Shouldn't it be throwing a page fault?

Furthermore even if I do this
Code:
// quick test of page fault handler
unsigned int *ptr = (unsigned int*)0xC0000000;
unsigned int doPageFault = *ptr;
doPageFault++;


where I would expect a page fault, I get nothing and execution continues...

I am out of my league on this problem so far. I could imagine that maybe the page_fault handler is somehow not paged in, so when it tries to execute that code it throws the GPF, but my IDT is identity mapped in, and also if I simply change the int from 14 to 13 in the install_interrupt_handler routine, it runs my page_fault handler just fine for the GPF.

Please, someone just tell me I'm doing something obviously retarded so I can facepalm and keep going.

Thanks.


Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 5:27 am 
Offline
Member
Member
User avatar

Joined: Tue Dec 25, 2007 6:03 am
Posts: 734
Location: Perth, Western Australia
I'm either thinking an error in the INT14 IDT entry, or there's an off-by-one error in your interrupt register code.

@berkus - That would cause an overrun, no real issue here (but still a bug)

_________________
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc


Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 5:37 am 
Offline
Member
Member
User avatar

Joined: Sat Jul 17, 2010 12:45 am
Posts: 487
I would recommend Bochs in this case. First off, uninstall the 'Page Fault' handler and see if your code still fires the 'General Protection Fault'. If it does, you may throw out all the exception handlers from your code and run your code under Bochs. Examine the Bochs debug window to see what fault it reports. If it is again the same GPF, then, you may want to examine the contents of CR0 and CR3 register to figure out if paging is actually enabled and if page directory is where you want it to be. If it reports page fault, then there might be some problem with your interrupt handlers. Check them.

Regards,
Chandra

Edit: Can we have the code for interrupt handlers?

_________________
Programming is not about using a language to solve a problem, it's about using logic to find a solution !


Last edited by Chandra on Sat Feb 19, 2011 7:19 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 6:19 am 
Offline
Member
Member

Joined: Tue Jun 15, 2010 9:27 am
Posts: 255
Location: Flyover State, United States
Also, for a good description of every kind of paging structure imaginable and all the other assorted features, I would recommend the Intel manuals. Check with those and make sure you are setting the structures up correctly.

_________________
Getting_Started on the wiki
x86 technical information
Interrupt Jump Table
Real Programmers Don't Use Pascal
My open-source projects


Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 11:37 am 
Offline

Joined: Tue May 11, 2010 8:05 pm
Posts: 12
berkus wrote:
Does memset_dw take number of dwords to clear?

Yes it does. I was coding late last night and this morning when I woke up I realized the problem you point out. Then I just now realized that I'm retarded and apparently I forgot how pointers work for about an hour last night. Thank you, and I fixed that. No longer using dwords.

Chandra wrote:
I would recommend Bochs in this case. First off, uninstall the 'Page Fault' handler and see if your code still fires the 'General Protection Fault'.

It does.
Chandra wrote:
If it is again the same GPF, then, you may want to examine the contents of CR0 and CR3 register to figure out if paging is actually enabled and if page directory is where you want it to be.

CR0=0xe0000011
CR3=0x00108000
The paging bit is enabled and the page directory is where I told it to be.

Chandra wrote:
Edit: Can we have the code for interrupt handlers?

Ask and ye shall recieve.

I will admit I'm lost in all the Intel assembly code. I learned assembly for MIPS once, so I know *basically* whats happening, but I'm don't know very much about the specifics of the x86 processor. I really just want to get into portable C code since I intend on running this on ARM someday (I like RISC).

My interrupt handlers are pretty basic.
Code:
isr13:
  cli
  ; this exception already pushes an error code
  push byte 13
  jmp isr_common_stub

and
Code:
isr_common_stub:
  pusha

  mov ax, ds
  push eax

  mov ax, 0x10   ; Load the Kernel Data Segment Descriptor
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax

  push esp
  call fault_handler
  add esp, 4

  pop ebx
  mov ds, bx
  mov es, bx
  mov fs, bx
  mov gs, bx

  popa
  add esp, 8   ; Cleans up the pushed error code and pushed ISR number
  iret      ; Pop 5 things at once: CS, EIP, EFLAGS, SS, and ESP

and then finally
Code:
void fault_handler(struct regs *r)
{
  void (*handler)(struct regs *r);

  handler = isrs[r->int_no];

  if (handler)
    handler(r);

  /* Is this a fault whose number is from 0 to 31? */
  if (r->int_no < 32)
  {
    /* Display the description for the exception that occurred */
    /* For now, deal with the exception by entering an infinite loop */
    puts (exception_messages[r->int_no]);
    puts (" System Halted!\n");
    for (;;);
  }
}


Thank you for responding!

I've noticed that when I try to write to the ptr to force a page fault, bochs says "write_virtual_dword_32() segment limit violation".
I set the limit in my GDT to 0xFFFFFFFF which is 4 GB and way higher than 0xC0000000...
Code:
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);

Code:
// The null descriptor
gdt_set_gate(0, 0, 0, 0, 0);
 
// The second entry is the Code Segment.  The base address is 0, the limit is 4 GB, it uses 4 KB granularity, uses 32 bit opcodes
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
 
// The third entry is the Data Segment.  Its the same as the Code Segment, but the descriptor type is that of a Data Segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);

and yes, the GDT is properly installed.

Confusing...


Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Sat Feb 19, 2011 4:50 pm 
Offline

Joined: Tue May 11, 2010 8:05 pm
Posts: 12
Well I appear to have fixed it.

The problem was in my GDT. It was twofold, I think. For starters in the set_gate function I had left out
Code:
gdt[num].granularity = (limit >> 16) & 0x0F;


The other problem could have been that my limit was set at 0xFFFFFFFF instead of 0xFFFFF. I don't think this would have been a problem since it would have just set the limit to a value higher than could be addressed anyway, but its fixed now.

Thanks for the help.


Top
 Profile  
 
 Post subject: Re: Enabling Paging - GPF
PostPosted: Tue Feb 21, 2012 5:13 pm 
Offline

Joined: Tue May 11, 2010 8:05 pm
Posts: 12
Well, I solved this problem, and quickly ran into another one that I never solved.

I backed up my project just before I fixed this error apparently, and just recently wiped my hard drive thinking I had a backup of my most recent work.

Nope, I'm now back to a version of my code just before I fixed this problem. Except the fix I posted above doesn't seem to work. Damnit, what else did I do?!

Just though I'd share my stupid experience.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 82 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group