64 bit paging 4 level pages (4kb)

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
gabe
Posts: 6
Joined: Fri Jul 06, 2012 12:20 pm

64 bit paging 4 level pages (4kb)

Post by gabe »

I'm hitting a brick wall setting up paging in 64bit with 4kb pages. Using 2MB pages...I have absolutely no problem. I've oversimplified my code to show what works and what doesn't...hopefully someone can point me in the right direction.

This code sets up 2MB pages and it works fine

Code: Select all

	u64 *pml, *pdp, *pd, *pt;

	pml = (u64 *)physmem_getpage();
	pdp = (u64 *)physmem_getpage();
	pd = (u64 *)physmem_getpage();

	memset((void*)pml, 0x0, PAGE_SIZE);
	memset((void*)pdp, 0x0, PAGE_SIZE);
	memset((void*)pd, 0x0, PAGE_SIZE);

// +3 = present & write
	pml[0] = ((u64)pdp) + 0x3;
	pdp[0] = ((u64)pd) + 0x3;
	pd[0] = ((u64)pt) + 0x3;


	for (int i = 0;i < 512;i++) {
		pd[i] = ((u64)i << 21) + 0x83;
	}

	asm volatile ("movq %0,%%cr3\n\t"
			"jmp 1f\n\t"
			"1:\n\t"
			"movq $2f, %%rax\n\t"
			"jmp *%%rax\n\t"
			"2:\n\t" ::"r"(pml):"memory","rax");
This code sets up 4kb pages (4 levels) and IMO should work...but does not, crashes the second I load CR3

Code: Select all

	u64 *pml, *pdp, *pd, *pt;

	pml = (u64 *)physmem_getpage();
	pdp = (u64 *)physmem_getpage();
	pd = (u64 *)physmem_getpage();
	pt = (u64 *)physmem_getpage();

	memset((void*)pml, 0x0, PAGE_SIZE);
	memset((void*)pdp, 0x0, PAGE_SIZE);
	memset((void*)pd, 0x0, PAGE_SIZE);
	memset((void*)pt, 0x0, PAGE_SIZE);

// +3 = present & write
	pml[0] = ((u64)pdp) + 0x3;
	pdp[0] = ((u64)pd) + 0x3;
	pd[0] = ((u64)pt) + 0x3;


	for (int i = 0;i < 512;i++) {
		pt[i] = ((u64)i << 12) + 0x3;
	}

	asm volatile ("movq %0,%%cr3\n\t"
			"jmp 1f\n\t"
			"1:\n\t"
			"movq $2f, %%rax\n\t"
			"jmp *%%rax\n\t"
			"2:\n\t" ::"r"(pml):"memory","rax");
Thanks.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: 64 bit paging 4 level pages (4kb)

Post by bluemoon »

Code: Select all

   memset((void*)pml, 0x0, PAGE_SIZE);
   memset((void*)pdp, 0x0, PAGE_SIZE);
   memset((void*)pd, 0x0, PAGE_SIZE);

// +3 = present & write
   pml[0] = ((u64)pdp) + 0x3;
   pdp[0] = ((u64)pd) + 0x3;
   pd[0] = ((u64)pt) + 0x3;

Note the above code uses pml/pdp/pd for both logical address(when accessing array) and physical address(filling page structures)
It only work if the memory is identity mapped.

And then, how does it crash? When dealing with paging I strongly recommend all sort of debug tool, including bochs-debugger or qemu+gdb(not quite work well with 64bit). bochs will tell you exactly what's wrong most of the time.
gabe
Posts: 6
Joined: Fri Jul 06, 2012 12:20 pm

Re: 64 bit paging 4 level pages (4kb)

Post by gabe »

yes, this is identity mapping, I understand that. Like I said, I just wrote that to oversimplify my code to find what's wrong.
jbemmel
Member
Member
Posts: 53
Joined: Fri May 11, 2012 11:54 am

Re: 64 bit paging 4 level pages (4kb)

Post by jbemmel »

Which register does gcc choose for loading CR3 in both cases? IIRC only eax can be used?
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: 64 bit paging 4 level pages (4kb)

Post by jnc100 »

Your first example identity maps the first 1 GiB, your second example only identity maps the first 2 MiB. Are you sure the mov to cr3 code is located within the first 2 MiB?

Regards,
John.
gabe
Posts: 6
Joined: Fri Jul 06, 2012 12:20 pm

Re: 64 bit paging 4 level pages (4kb)

Post by gabe »

Thanks for the help.

Turns out my stack was outside the first 2mb that is identity mapped (compared to 1gig) which caused it to crash.

duhhhhhhhh... (always a stupid problem)
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: 64 bit paging 4 level pages (4kb)

Post by xenos »

jbemmel wrote:Which register does gcc choose for loading CR3 in both cases? IIRC only eax can be used?
Nope, you can use any 64 bit register from RAX to R15 in 64 bit mode (and any 32 bit register in 32 bit mode).
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply