Page 1 of 1

[solved]Triple fault on enabling paging-phys. addr. not avai

Posted: Mon Jul 19, 2010 5:22 pm
by dukedevon
I am following James Molloys Tutorial.

When I try to initialize paging Bochs outputs the following error:

Code: Select all

(0).[22947675] ??? (physical address not available)
My switch_directory function:

Code: Select all

void Paging::switch_directory(page_directory_t *dir) {
	extern Video video;

	Paging::current_directory = dir;
	asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));

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

	asm volatile("xchg %bx, %bx");
	asm volatile("mov %0, %%cr0":: "r"(cr0));   <<<-------- Triple fault here
}
Does anyone have an idea or should I post more info?
Thanks in advance
dukedevon

Re: Triple fault on enabling paging - phys. address not avai

Posted: Mon Jul 19, 2010 5:27 pm
by gerryg400

Code: Select all

asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
cr3 must contain the physical address of the top-level page directory. Does this line really achieve that ?

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 2:00 am
by Kevin
The code to switch paging on looks fine.

How is page_directory_t defined and how do you initialize dir? You seem to end up with an invalid page directory, either because cr3 points at the wrong place or it points at the right place, but the PD (or the page table) contains the wrong values. You may want to manually resolve a virtual address by looking at cr3 and the memory that contains the page directory and the page table. Usually you find the problem quickly this way.

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 2:21 am
by dukedevon
Kevin wrote:How is page_directory_t defined and how do you initialize dir?

Code: Select all

typedef struct page {
   unsigned int present    : 1;   // Page present in memory
   unsigned int rw         : 1;   // Read-only if clear, readwrite if set
   unsigned int user       : 1;   // Supervisor level only if clear
   unsigned int accessed   : 1;   // Has the page been accessed since last refresh?
   unsigned int dirty      : 1;   // Has the page been written to since last refresh?
   unsigned int unused     : 7;   // Amalgamation of unused and reserved bits
   unsigned int frame      : 20;  // Frame address (shifted right 12 bits)
} page_t;

typedef struct page_table {
   page_t pages[1024];
} page_table_t;

typedef struct page_directory {
   page_table_t *tables[1024];
   unsigned int tablesPhysical[1024];
   unsigned int physicalAddr;
} page_directory_t;
Kevin wrote:You seem to end up with an invalid page directory, either because cr3 points at the wrong place or it points at the right place, but the PD (or the page table) contains the wrong values. You may want to manually resolve a virtual address by looking at cr3 and the memory that contains the page directory and the page table. Usually you find the problem quickly this way.
I must admit that I'm still missing a decent overview of the whole paging thing. Up until now, learning by doing did suffice. What actually should be in there?
After bochs has passed the following command

Code: Select all

mov cr3, eax
creg displays

Code: Select all

CR0=0x60000011: pg CD NW ac wp ne ET ts em mp PE
CR2=page fault laddr=0x0000000000000000
CR3=0x00001080
    PCD=page-level cache disable=0
    PWT=page-level write-through=0
CR4=0x00000000: osxsave pcid smx vmx osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme
EFER=0x00000000: ffxsr nxe lma lme sce
Is 1080 a possible physical address?

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 2:27 am
by Combuster
0x1080 is not page aligned, so its not a valid address for CR3, or for any page table/directory.

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 2:34 am
by Artlav
dukedevon wrote:

Code: Select all

typedef struct page {
   unsigned int present    : 1;   // Page present in memory
   unsigned int rw         : 1;   // Read-only if clear, readwrite if set
   unsigned int user       : 1;   // Supervisor level only if clear
   unsigned int accessed   : 1;   // Has the page been accessed since last refresh?
   unsigned int dirty      : 1;   // Has the page been written to since last refresh?
   unsigned int unused     : 7;   // Amalgamation of unused and reserved bits
   unsigned int frame      : 20;  // Frame address (shifted right 12 bits)
} page_t;
Curious. Are you sure the bit fields struct page are honestly mapped and all the sizes are right?
I've never seen things that low made in HLL, might be worth chacking if something like struct padding or packing got in the way. try using Bochs I/O debugger to look at what is being constructed at the address you give into cr3. (If you don't know how, learning that is a must).
dukedevon wrote:

Code: Select all

typedef struct page_table {
   page_t pages[1024];
} page_table_t;

typedef struct page_directory {
   page_table_t *tables[1024];
   unsigned int tablesPhysical[1024];
   unsigned int physicalAddr;
} page_directory_t;
struct page_directory looks like you're doing something quite wrong, if a pointer to it is what goes to cr3.
cr3 should point on an array of 1024 page directory descriptors, similar and slightly different from struct page, each of which points to some page table.

Then, i think the cr3 address should be page-aligned. If all else fails, try putting page directory on a $1000-aligned address.
dukedevon wrote:I must admit that I'm still missing a decent overview of the whole paging thing. Up until now, learning by doing did suffice. What actually should be in there?
The wiki here seems descriptive enough:
http://wiki.osdev.org/Paging

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 2:40 am
by dukedevon
Combuster wrote:0x1080 is not page aligned, so its not a valid address for CR3, or for any page table/directory.
Thanks a lot. That eased it a lot for me. I figured out that my kmalloc function was completely messed up.
Thanks again, this forum is just great =D>

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 3:26 am
by Kevin
dukedevon wrote:I must admit that I'm still missing a decent overview of the whole paging thing. Up until now, learning by doing did suffice.

Maybe as an additional source (in German): http://www.lowlevel.eu/wiki/Paging
Kevin wrote:You seem to end up with an invalid page directory, either because cr3 points at the wrong place or it points at the right place, but the PD (or the page table) contains the wrong values. You may want to manually resolve a virtual address by looking at cr3 and the memory that contains the page directory and the page table. Usually you find the problem quickly this way.
What actually should be in there?
cr3 should point to the physical address of a PD. And that PD should contain, well, Page Directory Entries. Basically the address of a (4k-aligned) PT with some flags. The PT contains the addresses of pages within a 4 MB block, again with some flags.
Is 1080 a possible physical address?
It surely is, but not a valid one for a PD, as was pointed out. Also, you seem to use the same variable for accessing the PD in the kernel (which will use virtual addresses) and for cr3 (which must be a physical address, obviously). I doubt that it's going to work very well this way.

Re: Triple fault on enabling paging - phys. address not avai

Posted: Tue Jul 20, 2010 4:12 am
by Creature
Artlav wrote:
dukedevon wrote:

Code: Select all

typedef struct page {
   unsigned int present    : 1;   // Page present in memory
   unsigned int rw         : 1;   // Read-only if clear, readwrite if set
   unsigned int user       : 1;   // Supervisor level only if clear
   unsigned int accessed   : 1;   // Has the page been accessed since last refresh?
   unsigned int dirty      : 1;   // Has the page been written to since last refresh?
   unsigned int unused     : 7;   // Amalgamation of unused and reserved bits
   unsigned int frame      : 20;  // Frame address (shifted right 12 bits)
} page_t;
Curious. Are you sure the bit fields struct page are honestly mapped and all the sizes are right?
I've never seen things that low made in HLL, might be worth chacking if something like struct padding or packing got in the way. try using Bochs I/O debugger to look at what is being constructed at the address you give into cr3. (If you don't know how, learning that is a must).
This has been reported as an issue some time ago. Well, as long as you don't actually use those bits, I don't really see it as an issue, but it's always nice to have the correct bits in your structure. I believe only 3 bits of the structure are actually "unused". The other 4 bits are used for other flags (which you can find in the Intel manual).