OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:23 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: [SOLVED] GPF when calling ISR
PostPosted: Sat Jun 28, 2014 6:49 am 
Offline
Member
Member

Joined: Fri Jul 06, 2012 10:52 am
Posts: 25
UPDATE: This is solved. The initial long mode GDT had both size bit and long bit set to 1. The size bit has to be 0 for long mode to be valid.

I'm playing around with a x86_64 higher half kernel and trying to get interrupts working. The kernel enters long mode, installs an IDT successfully and busy waits. I registered an ISR for the keyboard but keep getting General Protection Fault when I press a key or manually generate an interrupt. The GPF was generated upon calling the ISR, not when returning from it.

I'm fairly new to x86_64 and am pretty confused on why segmentation still seems to have come into play.

Here's a consecutive snippet of QEMU log, generated using "-d int"
// This is the manual "int $1"
0: v=01 e=0000 i=1 cpl=0 IP=0008:ffffffff8010e730 pc=ffffffff8010e730 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=ffff801680000fff
RAX=ffff801680000fff RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000ffff00a1
RSI=0000ffffffff8010 RDI=000000000000008b RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=00000000001bfea0 R15=0000000000000008
RIP=ffffffff8010e730 RFL=00200246 [---Z-P-] CPL=0 II=1 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0001ffffffff0021 CCD=0000ffffffff8010 CCO=CLR
EFER=0000000000000500

// First GPF
check_exception old: 0xffffffff new 0xd
1: v=0d e=0012 i=0 cpl=0 IP=0008:ffffffff8010e730 pc=ffffffff8010e730 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=ffff801680000fff
RAX=ffff801680000fff RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000ffff00a1
RSI=0000ffffffff8010 RDI=000000000000008b RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=00000000001bfea0 R15=0000000000000008
RIP=ffffffff8010e730 RFL=00200246 [---Z-P-] CPL=0 II=1 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0001ffffffff0021 CCD=0000ffffffff8010 CCO=CLR
EFER=0000000000000500

// Second GPF
check_exception old: 0xd new 0xd
2: v=08 e=0000 i=0 cpl=0 IP=0008:ffffffff8010e730 pc=ffffffff8010e730 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=ffff801680000fff
RAX=ffff801680000fff RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000ffff00a1
RSI=0000ffffffff8010 RDI=000000000000008b RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=00000000001bfea0 R15=0000000000000008
RIP=ffffffff8010e730 RFL=00200246 [---Z-P-] CPL=0 II=1 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0001ffffffff0021 CCD=0000ffffffff8010 CCO=CLR
EFER=0000000000000500

check_exception old: 0x8 new 0xd

// Triple faults and resets

Any help would be appreciated, thanks!


Last edited by Dominator on Sun Jun 29, 2014 4:36 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 7:00 am 
Offline
Member
Member
User avatar

Joined: Wed Dec 01, 2010 3:41 am
Posts: 1761
Location: Hong Kong
1. use objdump to check what's on the fault address.
2. check the error code for the fault, it tell you what have went wrong.


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 8:33 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
Well, the OP seems to have done just that...
bluemoon wrote:
1. use objdump to check what's on the fault address.
Quote:
int $1

2. check the error code for the fault, it tell you what have went wrong.[/quote]
Quote:
e=0012


---

Quote:
I'm fairly new to x86_64 and am pretty confused on why segmentation still seems to have come into play.
It's a protection fault. That does not necessarily mean an error with segmentation, but also goes for all sorts of system structure errors and other generic problems.

Since this is actually a triple fault, there will have to be some error in the IDT/GDT/IST because the handler doesn't seem to allow itself to be invoked at all. If you try to use bochs, you will get a significantly more verbose log of what error happened exactly.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 8:50 am 
Offline
Member
Member
User avatar

Joined: Wed Dec 01, 2010 3:41 am
Posts: 1761
Location: Hong Kong
Combuster wrote:
Well, the OP seems to have done just that...


Hmm, that was too long that I missed it, but anyway, an error code of 0012 means problem with IDT entry 0010 (INT 1 handler).

Quote:
installs an IDT successfully

The error code hints that the IDT may be setup incorrectly.


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 10:32 am 
Offline
Member
Member
User avatar

Joined: Thu Dec 19, 2013 1:40 am
Posts: 100
Location: Asia, Singapore
I would suggest using bochs to check if the idt structure is correct using the debugger (You would have to compile it yourself but its worth the time spent)

_________________
CookieOS. Want a cookie? Its only black and white for now though, probably as bad as my baking skills.


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 2:31 pm 
Offline
Member
Member

Joined: Fri Jul 06, 2012 10:52 am
Posts: 25
Well, I compiled and installed bochs with x86_64 support, but it hangs in GRUB2.

The screen says "Booting kernel..." (GRUB2's message) while the last line of bochs log is

00018162983i[BIOS ] Booting from 07c0:0000

Seems like some infinite loop going on in GRUB2? QEMU is still booting it fine.

As for the IDT entry, I set it up with the address of the ISR handler, selector 0x08 and flags 0x8e. The flags correspond to:
P: 1
DPL: 00
S: 0
Type: 1110 (Interrupt gate)

I also believe the ISR handler (the function pointer) is valid since I can manually invoke it. Is there something wrong with the selector?


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 2:59 pm 
Offline

Joined: Sat Apr 19, 2014 6:51 am
Posts: 1
I had the same issue i think, it's not a bug in QEMU, if you are following bran's tutorial, when you do idt_flush and gdt_flush, as a parameter specify &gp and &idtp.

I have my kernel source on GitHub, and this is the commit that fixed that for me:
https://github.com/Enverbalalic/OSDev_K ... c3581918f0


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sat Jun 28, 2014 6:39 pm 
Offline
Member
Member

Joined: Fri Jul 06, 2012 10:52 am
Posts: 25
kemoba wrote:
I had the same issue i think, it's not a bug in QEMU, if you are following bran's tutorial, when you do idt_flush and gdt_flush, as a parameter specify &gp and &idtp.

I have my kernel source on GitHub, and this is the commit that fixed that for me:
https://github.com/Enverbalalic/OSDev_K ... c3581918f0


Thanks, but I don't think that's the issue. I've dumped the IDT entry and it seems perfectly valid.

Here's the triple fault log from a keyboard interrupt:

6: v=21 e=0000 i=0 cpl=0 IP=0008:ffffffff8010e5e0 pc=ffffffff8010e5e0 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=00000000000000a0
RAX=00000000000000a0 RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000001bff40
RSI=0000000000000018 RDI=ffffffff80168000 RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=00000000ffffffff
R12=80108e000008e5f0 R13=0000000000000000 R14=0000000000000000 R15=ffffffff80168000
RIP=ffffffff8010e5e0 RFL=00200246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000044 CCD=0000000000000000 CCO=EFLAGS
EFER=0000000000000500
check_exception old: 0xffffffff new 0xd
7: v=0d e=0008 i=0 cpl=0 IP=0008:ffffffff8010e5e0 pc=ffffffff8010e5e0 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=00000000000000a0
RAX=00000000000000a0 RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000001bff40
RSI=0000000000000018 RDI=ffffffff80168000 RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=00000000ffffffff
R12=80108e000008e5f0 R13=0000000000000000 R14=0000000000000000 R15=ffffffff80168000
RIP=ffffffff8010e5e0 RFL=00200246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000044 CCD=0000000000000000 CCO=EFLAGS
EFER=0000000000000500
check_exception old: 0xd new 0xd
8: v=08 e=0000 i=0 cpl=0 IP=0008:ffffffff8010e5e0 pc=ffffffff8010e5e0 SP=0010:ffffffff8010bfb0 env->regs[R_EAX]=00000000000000a0
RAX=00000000000000a0 RBX=0000000000000000 RCX=00000000001bfeb0 RDX=00000000001bff40
RSI=0000000000000018 RDI=ffffffff80168000 RBP=ffffffff8010bff0 RSP=ffffffff8010bfb0
R8 =0000000000000001 R9 =0000000000000000 R10=0000000000000000 R11=00000000ffffffff
R12=80108e000008e5f0 R13=0000000000000000 R14=0000000000000000 R15=ffffffff80168000
RIP=ffffffff8010e5e0 RFL=00200246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
CS =0008 0000000000000000 00000000 00609a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
DS =0010 0000000000000000 00000000 00609300 DPL=0 DS [-WA]
FS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffffffff801001b0 00000017
IDT= ffffffff80168000 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000101000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000044 CCD=0000000000000000 CCO=EFLAGS
EFER=0000000000000500
check_exception old: 0x8 new 0xd

I've dumped IDT[33] (keyboard interrupt) to R11 and R12, which reads 0x00000000ffffffff80108e000008e5f0

Parsing it, we get the address for the ISR handler as 0xffffffff8010e5f0, which is correct according to my objdump.
The selector is 0x08, which also seems right
The flag is 0x8e, which is also correct.

Once again the ISR wasn't invoked at all, as the GPF was triggered upon calling it. The value for PC corresponds to essentially a "jmp $1" I put at the end of the kernel's main function.

Also, do I need to fiddle with GDT in long mode? I also tried that before loading IDT, but again got GPF when I tried moving "0x08" into ss (stack selector). I checked the GDT entry and it also seemed perfectly valid.

Pretty confused now...


Top
 Profile  
 
 Post subject: Re: GPF when calling ISR -trying to make sense out of a QEMU
PostPosted: Sun Jun 29, 2014 4:33 pm 
Offline
Member
Member

Joined: Fri Jul 06, 2012 10:52 am
Posts: 25
Problem solved. The initial GDT was setup wrong, both the size bit and the long bit were 1. The size bit has to be 0 in long mode.

I didn't write that part of the code so I assumed it was correct :(, although I don't know why no GPF was triggered earlier (before the interrupt).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 74 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group