Page 1 of 1

error code of general protection fault

Posted: Tue May 22, 2012 9:20 pm
by vjain20
Hi,

I am following the JamesM tutorial to switch to user mode in my kernel. The tutorial
provides the following function to switch to user mode which uses iret to jump to user mode
by pushing appropriate values on stack.

Code: Select all

void switch_to_user_mode()
{
   // Set up a stack structure for switching to user mode.
   asm volatile("  \ 
     cli; \ 
     mov $0x23, %ax; \ 
     mov %ax, %ds; \ 
     mov %ax, %es; \ 
     mov %ax, %fs; \ 
     mov %ax, %gs; \ 
                   \ 
     mov %esp, %eax; \ 
     pushl $0x23; \ 
     pushl %eax; \ 
     pushf; \ 
     pushl $0x1B; \ 
     push $1f; \ 
     iret; \ 
   1: \ 
     ");
}
[/size]

I call this function directly from my main() function and as expected it fails as I did not make changes to the permissions in page-tables.
It throws a General Protection Exception. However I am unable to understand the error code pushed by the exception which is 0x87F0. According to intel manual
If the fault condition was detected while loading a segment descriptor, the error code contains a segment selector to or IDT
vector number for the descriptor; otherwise, the error code is 0.
But I have only 5 entries in my GDT (indices 0x0, 0x8, 0x10, 0x18, 0x20). Therefore 0x87F0 does not seem to be a valid selector neither does it seem to be a valid interrupt vector number. From the description of intel manual it doesn't seem that garbage error code can be pushed.
Is my understanding wrong somewhere ?

Re: error code of general protection fault

Posted: Tue May 22, 2012 10:10 pm
by LindusSystem
Is this code

mov $0x23, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs

supposed to be this

mov %ax,$0x23
mov %ds,%ax
mov %es,%ax
mov %fs,%ax
mov %gs,%ax

The mov instruction is written as "mov dest,source" then if you copy the segments into ax ,whats the use?

EDIT:From http://www.brokenthorn.com/Resources/OSDev23.html

Code: Select all

       cli
		mov ax, 0x23	
		mov ds, ax
		mov es, ax
		mov fs, ax
		mov gs, ax

		push 0x23		
		push esp		
		pushfd		
		push 0x1b		
		lea eax, [a]		
		push eax

		iretd
	a:
		add esp, 4

Re: error code of general protection fault

Posted: Tue May 22, 2012 10:25 pm
by gerryg400
LyndusSystem, the order of src and dst depends on the assembler. Vjain is using a different assembler than you.

Re: error code of general protection fault

Posted: Tue May 22, 2012 10:34 pm
by LindusSystem
K, but he is using inline assembly.

Re: error code of general protection fault

Posted: Wed May 23, 2012 12:22 am
by Nable
LindusSystem
inline asembly of GCC is in AT&T syntax by default.

vjain20
what about using bochs debugger?
Also, "If the fault condition was detected while loading a segment descriptor". Are you sure that exception was at this stage?

Re: error code of general protection fault

Posted: Wed May 23, 2012 12:25 am
by iansjack
Two thoghts:

1. Are you absolutely sure that it's a GPF, not a PF?

2. Are you sure you are looking at the error code? Are you looking at the right stack?

Re: error code of general protection fault

Posted: Wed May 23, 2012 12:56 am
by bluemoon
Have you setup a proper TSS?
once entered ring3 you need at least a minimal TSS(with SS0/ESP0 or 64-bit fields) for exception to work.

Re: error code of general protection fault

Posted: Wed May 23, 2012 12:58 am
by vjain20
Two thoghts:

1. Are you absolutely sure that it's a GPF, not a PF?

2. Are you sure you are looking at the error code? Are you looking at the right stack?
Yes I am sure that it's a GPF (interrupt 13). I have tested my interrupt handling mechanism.
Also I am sure that I am looking at the error code. This is as per tutorial and I have confirmed by
causing page faults in code which also throw error code.

-Thanks
Vaibhav Jain

Re: error code of general protection fault

Posted: Wed May 23, 2012 1:57 am
by serviper
Check your IDT entries. Some of them should have gate DPL 3.

Re: error code of general protection fault

Posted: Wed May 23, 2012 2:05 am
by bluemoon
You don't need DPL3 for IDT entry unless you use that for your syscall interface(i.e. directly callable from ring3).

Re: error code of general protection fault

Posted: Wed May 23, 2012 2:24 am
by Combuster
From the description of intel manual it doesn't seem that garbage error code can be pushed.
Ever heard of the phrase "garbage in, garbage out"? That number is coming from somewhere and I'm pretty sure you're responsible for it :wink:

Re: error code of general protection fault

Posted: Wed May 23, 2012 2:35 am
by vjain20
what about using bochs debugger?
Also, "If the fault condition was detected while loading a segment descriptor". Are you sure that exception was at this stage?
I debugged using the bochs debugger and found that the instruction mov %ax, %ds is faulting and causing a GPF.

Code: Select all

asm volatile("  \ 
     cli; \ 
     mov $0x23, %ax; \     
     mov %ax, %ds; \       \\ <<<<<<<<<<< FAULTING <<<<<<<<<<<<<<<
     mov %ax, %es; \ 
     mov %ax, %fs; \ 
     mov %ax, %gs; \ 
                   \ 
     mov %esp, %eax; \ 
     pushl $0x23; \ 
     pushl %eax; \ 
     pushf; \ 
     pushl $0x1B; \ 
     push $1f; \ 
     iret; \ 
   1: \ 
     ");
[/size]

I don't know why this is. I checked the stack and the error code is indeed 0x87F which I am unable to interpret.
The code for setting descriptors in gdt is same as given in the tutorial.

Thanks

Re: error code of general protection fault

Posted: Wed May 23, 2012 2:44 am
by Combuster
A good thing to learn is to stop guessing that things work and actually check it. In this case, check the GDT because that would determine if an exception would be thrown. Bochs has commands for that.

Re: error code of general protection fault

Posted: Wed May 23, 2012 3:36 am
by iansjack
Well that narrows it down. You are loading a selector into a segment register and getting a GPF. That means that the value you are loading doesn't point to a valid segment descriptor or that you have your privilege levels wrong. As Combuster says, check your GDT.

Re: error code of general protection fault

Posted: Wed May 23, 2012 9:25 pm
by vjain20
I am sorry. It was a stupid mistake which caused this. I wrote 023 in place of 0x23 in the code above
while I pasted the code directly from the tutorial. I figured it out while debugging for some time.
Really stupid of me. :(