Page 1 of 1

paging code - crazy bug (again)

Posted: Thu Nov 24, 2005 1:45 pm
by 0Scoder
Ok, I'm re-writing my paging set-up code, and it gives me a page fault every time I run it. Well, chances are I'm missing something obvious, but I really am stumped on this one!

Here's the current code (I'm not posting other functions and header files just yet - it might needlessly clutter up the post if they aren't needed):

Code: Select all

/* Copyright (c) 2005 Tim Saunders - see license.txt file for the license
 * SCIOX - Basic Page Handler: Sets up address spaces and provides functions for managing them
 */
#include "..\..\include\config.h"
#include "..\..\include\defs.h"
#include "..\include\system\paging.h"
#include "..\include\asm.h"

void paging_init()
{
   unsigned long counter;
   unsigned long temp;

   unsigned long (*page_directory)      [PAGE_TABLE_SIZE-1];   /*First Page Directory (4096 bytes)*/
   unsigned long (*page_table_kernel)   [PAGE_TABLE_SIZE-1];   /*Maps in the kernel*/

/*Set up our page tables and directories to their physical addresses: - warning - incompatible assignment types*/
   page_directory=      (long *)0x00110000;
   page_table_kernel=   (long *)0x00111000;

/*Fill up all tables and directories:*/
   for(counter=0; counter<1024; counter++)
   {*page_directory[counter]=0 | 2;
    *page_table_kernel[counter]=((counter*4096) | 3);}

   *page_directory[0]=0x00111000 | 3;
   *page_directory[512]=0x00110000 | 3;

/*Enable paging:*/
   write_cr3(0x00110000);
   get_cr0(temp);
   write_cr0((temp | 0x80000000));
   asm("hlt");
}
Thanks in advance for your help,
OScoder

Re:paging code - crazy bug (again)

Posted: Thu Nov 24, 2005 2:32 pm
by Cjmovie
Gee, I'm no expert on mixing pointers with arrays (as in, precedence), but I'd take a wild guess and say the problem is that your making an array of pointers instead of a pointer to the start of an array. I'd say try this:

Code: Select all

/* Copyright (c) 2005 Tim Saunders - see license.txt file for the license
* SCIOX - Basic Page Handler: Sets up address spaces and provides functions for managing them
*/
#include "..\..\include\config.h"
#include "..\..\include\defs.h"
#include "..\include\system\paging.h"
#include "..\include\asm.h"

void paging_init()
{
   unsigned long counter;
   unsigned long temp;

   unsigned long *page_directory;     /*First Page Directory (4096 bytes)*/
   unsigned long *page_table_kernel;  /*Maps in the kernel*/

/*Set up our page tables and directories to their physical addresses: - warning - incompatible assignment types*/
   page_directory=      (long *)0x00110000;
   page_table_kernel=   (long *)0x00111000;

/*Fill up all tables and directories:*/
   for(counter=0; counter<1024; counter++)
   {page_directory[counter]=0 | 2;
    page_table_kernel[counter]=((counter*4096) | 3);}

   page_directory[0]=0x00111000 | 3;
   page_directory[512]=0x00111000 | 3;
/*NOTE! It seems you were trying to use the page directory as a page table also, I made it use the page table for the kernel twice...not sure but this might confuse the CPU */


/*Enable paging:*/
   write_cr3(0x00110000);
   get_cr0(temp);
   write_cr0((temp | 0x80000000));
   asm("hlt");
}


Re:paging code - crazy bug (again)

Posted: Thu Nov 24, 2005 2:56 pm
by 0Scoder
Ok, changed code to this, and I still get the same error:

Code: Select all

   unsigned long counter;
   unsigned long temp;

   unsigned long *page_directory;      //[PAGE_TABLE_SIZE-1];   /*First Page Directory (4096 bytes)*/
   unsigned long *page_table_kernel;   //[PAGE_TABLE_SIZE-1];   /*Maps in the kernel*/

/*Set up our page tables and directories to their physical addresses: - warning - incompatible assignment types*/
   *page_directory=   (long *)0x00110000;
   *page_table_kernel=   (long *)0x00111000;

/*Fill up all tables and directories:*/
   for(counter=0; counter<1024; counter++)
   {page_directory[counter]=0 | 2;
    page_table_kernel[counter]=(counter * 4096) | 3;
     }

   page_directory[0]=      0x00111000 | 3;
   page_directory[512]=   0x00110000 | 3;

/*Enable paging:*/
   write_cr3(0x00110000);
   get_cr0(temp);
   write_cr0((temp | 0x80000000));
   asm("hlt");
However, last time I had a porblem like this there where like, 3 main errors, so I'd fix one, then change the code back to normal when it still failed to work!

Also, yes, I do use a kind of memory saving trick to map the page directory into itself. This is so as to map all of the (potential) page tables into one place. A page table that did this would be EXACTLY the same as the page directory, so why not use the page directory as a table at the same time instead? Makes adding page tables alot simpler in the long run...

Perhaps I should have explained the code better before...

Thanks for your help so far,
OScoder

Re:paging code - crazy bug (again)

Posted: Thu Nov 24, 2005 6:44 pm
by Cjmovie
Hmm...Just out of intuition, I feel the need to ask....

Try changing the asm 'hlt' line to this:

Code: Select all

__asm__ __volatile__ ("cli" \
                              "hlt");
NOTE! When you run this code in bochs, it will say "Warning! Halt with IF == 0.", basically it's saying the inturrept enable flag is set to false and it's halting, so nothing else can run PERIOD. With just the halt command you still continue to get IRQ's and whatnot.

If it works, remove the hlt and cli instructions (or just comment them out). Let us know please, also, that it works if it does then (I don't see any chance of still getting a page fault, even though CLI doesn't mask internal software-generated interrupts and exceptions).
Then, in your exception handler, add some code to read CR2 and print it out -> This is the address that was trying to be accessed when the error occured, and will help out a lot with debugging.

Re:paging code - crazy bug (again)

Posted: Thu Nov 24, 2005 7:28 pm
by AR
That ASM statement doesn't look like it works. IIRC, GCC will run both lines together yielding an assembler error ("Unknown instruction clihlt"), you need a \n at the end of the first line:

Code: Select all

__asm__ volatile ("cli\n\t"
              "hlt");
This does not work on newer versions of Bochs though, they panic on contact with a HLT while interrupts are off, you would be better off with an infinite halt loop:

Code: Select all

#define BochsBreakpoint   __asm__ volatile ("mov $0, %%ecx\n1:\thlt\n\tjecxz 1b" : : : "ecx" )
With this problem, I can't see anything wrong with the latest code (although I may not be looking hard enough), the only thing that currently comes to mind is to check where your stack is.

Re:paging code - crazy bug (again)

Posted: Fri Nov 25, 2005 11:16 am
by 0Scoder

Code: Select all

void paging_init()
{
   unsigned long counter;
   unsigned long temp;

   unsigned long *page_directory;      //[PAGE_TABLE_SIZE-1];   /*First Page Directory (4096 bytes)*/
   unsigned long *page_table_kernel;   //[PAGE_TABLE_SIZE-1];   /*Maps in the kernel*/

/*Set up our page tables and directories to their physical addresses: - warning - incompatible assignment types*/
   *page_directory=   (long *)0x00110000;
   *page_table_kernel=   (long *)0x00111000;

/*Fill up all tables and directories:*/
   for(counter=0; counter<1024; counter++)
   {page_directory[counter]=0 | 2;
    page_table_kernel[counter]=(counter * 4096) | 3;
     }

   page_directory[0]=      0x00111000 | 3;
   page_directory[512]=   0x00110000 | 3;

/*Enable paging:*/
   write_cr3(0x00110000);
   get_cr0(temp);
   temp=temp | 0x80000000;
   write_cr0(temp);
   asm("cli");
   asm("hlt");
}
Ok, this is what my code looks like now, there is STILL the bug there was before (i.e page fault resulting in triple fault) I suppose I ought to post some of my debugging info so far:

registers are all as they should be as far as I can see:

Code: Select all

00000850940i[CPU  ] protected mode
00000850940i[CPU  ] CS.d_b = 32 bit
00000850940i[CPU  ] SS.d_b = 32 bit
00000850940i[CPU  ] | EAX=00100baa  EBX=000000ab  ECX=000ab000  EDX=0000ffe4
00000850940i[CPU  ] | ESP=0000ffcc  EBP=0000ffe4  ESI=e0000011  EDI=00000005
00000850940i[CPU  ] | IOPL=0 NV UP DI NG NZ NA PO NC
00000850940i[CPU  ] | SEG selector     base    limit G D
00000850940i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00000850940i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00000850940i[CPU  ] | EIP=001006cb (001006cb)
00000850940i[CPU  ] | CR0=0xe0000011 CR1=0x00000000 CR2=0x0010195c
00000850940i[CPU  ] | CR3=0x00110000 CR4=0x00000000
Inserting a 'NOP' opcode before the 'hlt' and 'cli' does NOT change the faulting address in CR2 (so there can't be a problem with those instructions).

Stack is at 0xFFFC

Entire OS is EXACTLY 4.00 kb (no overlap there)

-Changing other bits of code around:-
I've tried changing the order I do things in around (load paging before PIC, IDT and GDT (before it was after)), some of the registers change, but the same error still occurs:

Code: Select all

00000854267i[CPU  ] protected mode
00000854267i[CPU  ] CS.d_b = 32 bit
00000854267i[CPU  ] SS.d_b = 32 bit
00000854267i[CPU  ] | EAX=db6f0802  EBX=000003ff  ECX=003ff000  EDX=0ee0ffe0
00000854267i[CPU  ] | ESP=0000ffcc  EBP=0000ffe4  ESI=e0000011  EDI=00000005
00000854267i[CPU  ] | IOPL=0 NV UP DI NG NZ NA PO NC
00000854267i[CPU  ] | SEG selector     base    limit G D
00000854267i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00000854267i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00000854267i[CPU  ] | EIP=001006cb (001006cb)
00000854267i[CPU  ] | CR0=0xe0000011 CR1=0x00000000 CR2=0x00000040
00000854267i[CPU  ] | CR3=0x00110000 CR4=0x00000000
So - I can see no reason why there should be a problem here. If anyone spots anything in the above code, please reply!

I'll post an attachment containing my OS'es source so far (makefiles included), along with my bochsrc and bochsout (included in the 'bin' directory). It may be hard to find your way around, so I'll tell you: the main kernel sources are located in '/src/core/kernel/'

Thanks so much to everyone who's helped so far, an also to those who can see what's wrong with this crazy thing,

OScoder

Re:paging code - crazy bug (again)

Posted: Fri Nov 25, 2005 11:31 am
by bluecode
hi,

You might want to change:

Code: Select all

*page_directory=   (long *)0x00110000;
*page_table_kernel=   (long *)0x00111000;
into:

Code: Select all

page_directory=   (long *)0x00110000;
page_table_kernel=   (long *)0x00111000;
And you should begin thinking about compiler warnings... They're not there to make someones life harder...

Re:paging code - crazy bug (again)

Posted: Fri Nov 25, 2005 3:55 pm
by 0Scoder
Lol, well, I kinda forgot to put the attachment on before, so here it is now. (couldn't put in bochsout.txt - too big) [edit - deleted attachment - now the codes fixed it is outdated]

[edit]
Well, I've managed to fix this at last. The first reply here WAS actually right, the only problem was the way the address of the pointer was assigned. Being rather stupid I copied his code incorrectly - I used a * to assign the pointer address, (because why would you assign the address and the values in the same way?), although it turns out the compiler automatically notices it's a pointer, and assigns it properly anyway. Thanks for the help give (although, btw, I was safe to ignore the warnings mentioned above, I've had those kinda things before).