Confirmation of my Maths Requested

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
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Confirmation of my Maths Requested

Post by AJ »

Hello,

Many of you are probably familiar with the scheme where you set the last PDE to the physical address of the page directory itself, thus enabling easier page-ins. The range where the page tables lives, starts at 0xFFC00000.

I am now attempting the same in 64 bit (really 48 bit) space, but keep getting page faults. I wonder if someone could kindly confirm my maths, as I keep getting page not present PFE's, so I must be wrong somewhere!

Here are my 'table entry' variables:

Code: Select all

u16 pml4e = ((uptr)vptr >> 39) & 0x1FF;
u16 pdpte = ((uptr)vptr >> 30) & 0x1FF;
u16 pde = ((uptr)vptr >> 21) & 0x1FF;
u16 pte = ((uptr)vptr >> 12) & 0x1FF;
This should be fairly self-explanatory to anyone who can help me! VPTR is the address of the pointer I want to page in (in Canonical form) and the variables are ones I have declared for PML4 entry, PDPT entry and so on... (uptr) has been typedef'd to be the same width as the pointer size of the processor (in this case, a 64 bit unsigned integer). u16 should be self explanatory.

Next, my 'table base' variables:

Code: Select all

uptr *pdpt = (uptr*)((uptr)ptbase + (pdpte * 0x40000000) + (pdpte * 0x200000) + (pdpte * 0x1000));
uptr *pd = (uptr*)((uptr)ptbase + (pdpte * 0x40000000) + (pde * 0x200000) + (pde * 0x1000));
uptr *pt = (uptr*)((uptr)ptbase + (pdpte * 0x40000000) + (pde * 0x200000) + (pte * 0x1000));		
So, ptbase here is the start of the range of page tables (because pml4[0x1ff] = itself | flags;, this is 0xFFFF FF80 0000 0000, the last area represented by a PML4 entry in the 48 bit paging scheme - made canonical, of course).

Let me explain. uptr *pdpt here should point to the appropriate Page Directory Pointer Table in virtual RAM. *pd should point to the appropriate Page Directory and *pt should point to the page table. This means that I can then go through checking pml4[pml4e], then pdpt[pdpte], pd[pde] and pt[pde] for the page present flag, adding in the tables as necessary.

My page in function does not cause any PFE's itself - rather, the PFE I have does not seem to resolve after running the function. If I identity map the paging structures individually and page-in that way, it works nicely, but when I have a user process running in low RAM, I don't want to be doing that!

Can anyone spot a mistake / make a suggestion?

Cheers,
Adam
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

OK - I think I was missing something really obvious and can really simplify this. If I just worry about paging in the actual page table, with a little work on my PFE handler, the PML4E, PDPT and PD can take care of themselves. In other words:

Code: Select all

u64 *pt = (uptr*)(((uptr)vptr & 0xFFFFFFFFFFFF) / 0x1000);
u64 pte = ((uptr)vptr >> 12) & 0x1FF;
		
flags &= 0xFFF;
		
if(!(pt[pte] & PAGE_PRESENT))
{
  pt[pte] = (uptr)pmalloc() | flags;
}
This function will recurse until all page-mapping structures are filled. I'm looking in to it now...

Cheers,
Adam
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Confirmation of my Maths Requested [solved]

Post by AJ »

OK - just a bad day. In the end, for all my unnecessary complexity, all that was needed was:

Code: Select all

void page_in48(void *vptr, u16 flags)
{
	uptr pte = ((uptr)vptr & 0xFFFFFFFFFFFF) / 0x1000;
		
	flags &= 0xFFF;
	if(!(ptbase[pte] & PAGE_PRESENT))
		ptbase[pte] = (uptr)pmalloc() | flags;
}
That's it! If the PT, PD and PDPT do not exist, they just recurse the PFE handler. I'm going to make use of a variable which will check whether or not I am actually paging in at the moment or not. This will stop just any application randomly trying to access my PML4e and getting that range paged in.

Thanks to anyone who read this.

Cheers,
Adam
Post Reply