Page 1 of 1

#GP when returning from a 64-bit mode interrupt handler

Posted: Wed Jul 08, 2015 1:29 pm
by songziming
I created a 64-bit mode IDT and interrupts is ok. Problems arise when I want to return from interrupt handlers.

the code of the No.32 interrupt entry is:

Code: Select all

hwint32:
    inc     byte [0xb8000]
    iretq
and in my code, I invoke that interrupt using inline assembly:

Code: Select all

__asm__ volatile ("int $32");
However, I got a #GP exception with errcode=0. And return RIP shows that it is "iretq" instruction caused the exception.

I did all the thing in ring0, so there won't be any privilege changes. But I'm still getting this exception. Am I missing anything to implement 64-bit mode interrupt? How did you achieve interrupts under 64-bit mode?

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Wed Jul 08, 2015 1:36 pm
by xenos
Are you running your code in Bochs? If yes, what does the log say?

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Wed Jul 08, 2015 1:57 pm
by songziming
I use QEMU to run my OS. Because my OS use GRUB to boot, and GRUB uses INT 15 AX=00c0, BX=0000, which Bochs does not support.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Wed Jul 08, 2015 2:01 pm
by stlw
songziming wrote:I use QEMU to run my OS. Because my OS use GRUB to boot, and GRUB uses INT 15 AX=00c0, BX=0000, which Bochs does not support.
What do you mean 'doesn't support' ?
QEMU uses SeaBIOS which works perfectly with Bochs as well.
BTW, you claim that Bochs BIOS doesn't have that function while SeaBIOS has and GRUB fails because of that - so it is imply enough to write a request to port INT 15 AX=00c0, BX=0000 from SeaBIOS to Bochs BIOS, if you like.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Wed Jul 08, 2015 2:01 pm
by kzinti
songziming wrote:I use QEMU to run my OS. Because my OS use GRUB to boot, and GRUB uses INT 15 AX=00c0, BX=0000, which Bochs does not support.
I assure you, GRUB works perfectly fine in Bochs.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Thu Jul 09, 2015 6:39 am
by songziming
When I run my OS from Bochs, it crashes on the instruction "lgdt [gdt_ptr]". But QEMU can execute this instruction just fine

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Thu Jul 09, 2015 7:17 am
by stlw
songziming wrote:When I run my OS from Bochs, it crashes on the instruction "lgdt [gdt_ptr]". But QEMU can execute this instruction just fine
I guess you didn't run your OS doesn't run on real hardware yet ?
What is the Bochs error message printed ?
Might be QEMU doesn't emulate lgdt correctly enough

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Thu Jul 09, 2015 11:05 am
by kzinti
This means there is a problem with your GDT / GDT_PTR.

Bochs validates a lot of things. QEMU doesn't. I have run into many many bugs in my code running it through Bochs, even though QEMU was happy with it.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Sat Jul 11, 2015 10:10 pm
by songziming
Finally, I found out that bochs will not work if I use 2MB or 1GB pages. If I use 4KB pages only, bochs works just fine.

Now I know the reason for #GP is CS-selector being null.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Sun Jul 12, 2015 5:26 am
by stlw
songziming wrote:Finally, I found out that bochs will not work if I use 2MB or 1GB pages. If I use 4KB pages only, bochs works just fine.

Now I know the reason for #GP is CS-selector being null.
Again, you most likely doing smth wrong with 2M or 1G pages.
Bochs works well with 2M pages in many scenarios, if you believe your is different - you always could write into Bochs mailing list or post on forum.

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Sun Jul 12, 2015 9:49 am
by Roman
stlw wrote:
songziming wrote:Finally, I found out that bochs will not work if I use 2MB or 1GB pages. If I use 4KB pages only, bochs works just fine.

Now I know the reason for #GP is CS-selector being null.
Again, you most likely doing smth wrong with 2M or 1G pages.
Bochs works well with 2M pages in many scenarios, if you believe your is different - you always could write into Bochs mailing list or post on forum.
Maybe his Bochs build was just not configured to support 2 MiB pages?

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Mon Jul 13, 2015 1:22 am
by songziming
Now the problem returned to the 64-bit interrupt.

I've checked the stack content of the interrupt routine, and all the addresses and selectors seem valid. I also checked GDT, also no problem found. But Bochs still says return CS selector null, I don't understand why.

My Bochs session is (at the time just before iretq instruction):

Code: Select all

(0) Breakpoint 1, 0x0000000000100b1b in ?? ()
Next at t=61530965
(0) [0x000000100b1b] 0008:0000000000100b1b (unk. ctxt): iret                      ; cf
<bochs:3> r
CPU0:
rax: 00000000_00000040 rcx: 00000000_00000040
rdx: 00000000_00000007 rbx: 00000000_00200003
rsp: 00000000_00105f58 rbp: 00000000_00105ff0
rsi: 00000000_0010a7f8 rdi: 40000000_00000000
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00100b1b
eflags 0x00000002: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af pf cf
<bochs:4> xp /40bx 0x105f58
[bochs]:
0x0000000000105f58 <bogus+       0>:	0x7d	0x05	0x10	0x00	0x00	0x00	0x00	0x00
0x0000000000105f60 <bogus+       8>:	0x08	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x0000000000105f68 <bogus+      16>:	0x02	0x00	0x00	0x00	0x00	0x00	0x00	0x00
0x0000000000105f70 <bogus+      24>:	0x80	0x5f	0x10	0x00	0x00	0x00	0x00	0x00
0x0000000000105f78 <bogus+      32>:	0x10	0x00	0x00	0x00	0x00	0x00	0x00	0x00
<bochs:5> 

Re: #GP when returning from a 64-bit mode interrupt handler

Posted: Mon Jul 13, 2015 1:29 am
by thepowersgang
You need to explicitly use 'iretq' in 64-bit mode (which encodes to '48 cf'), otherwise only 32-bit state will be popped from the stack.