I am now trying to figure out why I am getting a General Protection Fault
instantly after an iret
. The return address of the iret
points to a valid location inside my kernel code. When using gdb
, if I step instructionwise, the GPF happens exactly as I execute the iret
, all the time, so I am pretty sure that it has to do something with what the CPU does after that.
I have the logs down below and as far as I understand, the Error lies within the GDT at index 2. Is my GDT wrong or missing something?
I am new to operating systems and just fiddeling around. If you need any more information, I'll gladly provide.
My gdt.s
:
.globl gdt
.section .data
gdt:
.short 0,0,0,0 # NULL Deskriptor
.short 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.short 0x0000 # base address=0
.short 0x9A00 # code read/exec
.short 0x00CF # granularity=4096,
.short 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.short 0x0000 # base address=0
.short 0x9200 # data read/write
.short 0x00CF # granularity=4096,
The qemu
Output with "-d int" (iret
from v=20 causes v=0d):
SMM: after RSM
EAX=000000b5 EBX=00007de3 ECX=00005678 EDX=00000003
ESI=07ecf5b0 EDI=07fbec5e EBP=00006924 ESP=00006924
EIP=00007de3 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =db00 000db000 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =ca00 000ca000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
0: v=20 e=0000 i=0 cpl=0 IP=0010:00102aae pc=00102aae SP=0018:001097b8 env->regs[R_EAX]=000b83dc
EAX=000b83dc EBX=00010000 ECX=000001e0 EDX=00000001
ESI=00000000 EDI=00000000 EBP=001097d8 ESP=001097b8
EIP=00102aae EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0010 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 00105000 00000012
IDT= 00105020 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=000b83dc CCO=EFLAGS
EFER=0000000000000000
check_exception old: 0xffffffff new 0xd
1: v=0d e=0010 i=0 cpl=0 IP=0008:00100336 pc=00100336 SP=0018:001097ac env->regs[R_EAX]=000b83dc
EAX=000b83dc EBX=00010000 ECX=000001e0 EDX=00000001
ESI=00000000 EDI=00000000 EBP=001097d8 ESP=001097ac
EIP=00100336 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00df9b00 DPL=0 CS32 [-RA]
SS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 00105000 00000012
IDT= 00105020 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=001097ac CCO=EFLAGS
EFER=0000000000000000
x/32b $esp
right before iret
:
0x1097ac: 0xae 0x2a 0x10 0x00 0x10 0x00 0x00 0x00
0x1097b4: 0x06 0x02 0x00 0x00 0x53 0x00 0x00 0x00
0x1097bc: 0x00 0x00 0x00 0x00 0x06 0x00 0x00 0x00
0x1097c4: 0x01 0x00 0x00 0x00 0x36 0x1d 0x10 0x00
my handler code:
.macro IRQ vector has_push
.align 8
interrupt_entry_\vector:
.if \has_push == 0
pushl $0
.endif
pushl %edx
pushl %ecx
pushl %eax
pushl %esp
pushl $\vector
call interrupt_handler
addl $8, %esp
popl %eax
popl %ecx
popl %edx
addl $4, %esp
iret
.endm
--------------------------- Update 1 ---------------------------
Minimal working Code-Example: pastebin
Additional findings:
The GPF only happens, if I run qemu
with -cdrom os.iso
. When running with -kernel bin/os.bin
, no GPF will happen.
--------------------------- Update 2 ---------------------------
I fixed the GDT Limit now to being 0x17. Output of qemu
with -cdrom os.iso
is now:
check_exception old: 0xffffffff new 0xd
40571: v=0d e=0010 i=0 cpl=0 IP=0008:00100335 pc=00100335 SP=0018:001087ec env->regs[R_EAX]=00000000
EAX=00000000 EBX=00010000 ECX=001047f8 EDX=000000a1
ESI=00000000 EDI=00000000 EBP=001087f8 ESP=001087ec
EIP=00100335 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0018 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 00103000 00000017
IDT= 00104000 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=001087e0 CCO=EFLAGS
EFER=0000000000000000
--------------------------- Update 3 ---------------------------
(gdb) x/64b $esp [right before call interrupt_handler]
0x1087d8: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x1087e0: 0xf8 0x47 0x10 0x00 0xa1 0x00 0x00 0x00
0x1087e8: 0x00 0x00 0x00 0x00 0x1e 0x1f 0x10 0x00
0x1087f0: 0x08 0x00 0x00 0x00 0x02 0x02 0x00 0x00
0x1087f8: 0x00 0x00 0x00 0x00 0x16 0x00 0x10 0x00
0x108800 <i>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x108808: 0x01 0x52 0x01 0x00 0x00 0x00 0x00 0x00
0x108810: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
(gdb) x/64b $esp [right after call interrupt_handler, before add $4]
0x1087d8: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x1087e0: 0xf8 0x47 0x10 0x00 0xa1 0x00 0x00 0x00
0x1087e8: 0x00 0x00 0x00 0x00 0x1e 0x1f 0x10 0x00
0x1087f0: 0x08 0x00 0x00 0x00 0x02 0x02 0x00 0x00
0x1087f8: 0x00 0x00 0x00 0x00 0x16 0x00 0x10 0x00
0x108800 <i>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x108808: 0x01 0x52 0x01 0x00 0x00 0x00 0x00 0x00
0x108810: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00