help: unable to enter long mode, problem in page hierarchy?

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
hippykin
Posts: 11
Joined: Mon Feb 11, 2008 3:44 pm
Location: UK

help: unable to enter long mode, problem in page hierarchy?

Post by hippykin »

Hello, this is my first 'help me' post, thanks in advance.

I am trying to enter long mode, from 32 bit protected mode and am constantly encountering an interrupt 14 (page exception [which is not handled because there is no IDT yet]) the moment i enable paging, even though the linear address accessed after paging is enabled should be paged in.

Code: Select all

switchTo64Bitmode(void *Eentry)
 {
	unsigned long *PeHigh;
	unsigned long *PeLow;
	unsigned int i;
	 
	// pt
	PeLow = (unsigned long*) 4194304;
	for(i = 0; i < 512; i++)
	 {
	
		*PeLow = i * 4 * 1024;
		SetAtributes(PeLow, 0, 1, 0, 0);
		PeHigh = PeLow + 4;
		*PeHigh = 0;
		PeLow = PeLow + 8;
	 }
	 
	 // pd
	 
	PeLow = PeLow + 8;
	*PeLow = 4194304;
	SetAtributes(PeLow, 0, 1, 0, 0);
	PeHigh = PeLow + 4;
	*PeHigh = 0;
	PeLow = PeLow + 8;
	for(i = 1; i < 512; i++)
	 {
		*PeLow = 1;
		PeHigh = PeLow + 4;
		*PeHigh = 0;
		PeLow = PeLow + 8;
	 }
	 
	 // pdt
	PeLow = PeLow + 8;
	*PeLow = 4194304 + (4 * 1024);
	SetAtributes(PeLow, 0, 1, 0, 0);
	PeHigh = PeLow + 4;
	*PeHigh = 0;
	PeLow = PeLow + 8;
	for(i = 1; i < 512; i++)
	 {
	
		*PeLow = 1;
		PeHigh = PeLow + 4;
		*PeHigh = 0;
		PeLow = PeLow + 8;
	 }
	 
	 //pl4
	 
	PeLow =  PeLow + 8;
	*PeLow = 4194304 + (2 * 4 * 1024);
	SetAtributes(PeLow, 0, 1, 0, 0);
	PeHigh =  PeLow + 4;
	*PeHigh = 0;
	PeLow =  PeLow + 8;
	for(i = 1; i < 512; i++)
	 {
	
		*PeLow = 1;
		PeHigh = PeLow + 4;
		*PeHigh = 0;
		PeLow = PeLow + 8;
	 }
	 
	// page structure built enable long mode
	 
	enableLongMode();
	
	 
	return;
 }
here is the code for the the SetAtributes function (with many unused parameters i know)

Code: Select all

SetAtributes(unsigned long *at, char supervisor, char present, char read, char write)
{
	// pwd = 1
	// pcd = 0
	// pat = 0
	// global page
	/*
	1 present flag
	2 read write 
	3 user super user
	4 caching polciy (1 - for now)
	5 caching disable (0 dont disable)
	6 acsessed - proccessor (we dont touch)
	7 dirty bit (0) - set by prossesor when pages is written to
	8 pages acsess table (0)
	*/
	// first bit of adress low is globoal (0 for now all flushed), next three bits are avalible
	// for now there are no users...so ignore parameters
	if(present == 1)
	{
		// page is present
		*at = *at | 3;
		return;
	}
	//page is not present
	*at = *at | 2;
}
and finally the enableLongMode function (i am pretty sure that this is ok because i copied it from the AMD manual)

Code: Select all

global enableLongMode;

enableLongMode:

push eax
push edx
push ecx

; enable long mode
;set PAE enable bit in cr4 (bit 7)
cli;
mov eax, cr4
bts eax, 5
mov cr4, eax

; set cr3 load address of pageing structure  (first t 12 bits must be 0) remaiing 20 bits addr 
mov eax, 0x403000 
mov cr3, eax

; enable long mode
mov ecx, 0x0c0000080
rdmsr ; puts stuff in EDX:EAX from msr ecx
bts eax, 8
wrmsr;

; enable paging cr0 (bit 31)
mov eax, cr0
bts eax, 31
mov edx, 2
mov cr0, eax

; >>tripple fault here becuase of unhandled int 14<<

pop ecx
pop edx
pop eax

ret; return we are now in 32 bit compatability mode....
the bochs log file complains about a PDPE not being present - but as far as i can see the structures are all ok

if you don't have the time to find the problem i would greatly appreciate someone posting there long mode initialization code - just so that i can see what i am doing wrong.

as you can see from my code - i am still learning English literature (and it is my first language)

thanks again.
The BBC micro could have become the world standard - it was so ahead of its time
zerosum
Member
Member
Posts: 63
Joined: Wed Apr 09, 2008 6:57 pm

Post by zerosum »

Why are you using magic numbers for things like the address of your PML4 table? That could very easily be your problem, without even looking at anything else.

The other thing I noticed at first glance is that you're continuing without a branch, after enabling paging. According to the AMD manual at least the instruction following that which enables paging MUST be a branch instruction.

Stolen from the AMD64 Architecture Programmer's Manual, Volume 2: System Programming

14.6.1

3. Enable paging by setting CR0.PG to 1. This causes the processor to set the EFER.LMA bit to 1. The instruction following the MOV CR0 that enables paging must be a branch, and both the MOV CR0 and the following branch instruction must be located in an identity-mapped page.


Beyond that, I'm not going to attempt to decipher that code... my head hurt while I was trying to enable long mode and that code hurts my head even mode [no offence intended, but it does] ;-)

Cheers,
Lee
hippykin
Posts: 11
Joined: Mon Feb 11, 2008 3:44 pm
Location: UK

Post by hippykin »

thank you, lee

i have reread the AMD manual - looks like i missed that line about having to do a far jump - sorry

i know my code was very messy - but it was the result of 8 hours straight coding (with ever increasing frustration and tiredness).

i am currently looking at my GDT initialization code because i have a nasty feeling it is setting the compatibility mode bit to 1 enabling 64 bit mode when i want 32 bit mode

and the magic number nasty hacks are going

many thanks
The BBC micro could have become the world standard - it was so ahead of its time
Post Reply