Long Mode Interrupts - Stack Alignment

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
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Long Mode Interrupts - Stack Alignment

Post by AJ »

Hi All,

I was really hoping to solve this without posting, but it's really getting annoying now - I think I have made a small mistake which is causing me 64 bit interrupt handing problems. I think that whenever I IRET, my stack has somehow become misaligned. My ISR:

Code: Select all

[BITS 64]
%macro mIRQ 1			;Hardware IRQ
    [global irq%1]
    irq%1:
        cli
        push 	qword %1
        push 	qword %1+IRQ_START
        jmp		int_common	;see below for this routine
%endmacro

;	16 IRQs
%assign i 0
%rep 16
    mIRQ i
    %assign i i+1
%endrep

int_common:
                ; when I have this working, I will push regs and call a C++ handler here
	add	rsp,	16  ;remove error code and irq #
iret
Fairly simple, then. but, the first time the timer IRQ fires, the IRET causes a GPF:

Code: Select all

00023924389e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (38)
Fine - I would expect the GDT index to be outside the limits with a selector of 0xF007, but why is it trying to load that descriptor? If I pop 5 registers manually from the stack before the IRET and then do a HLT, I see my expected values of RIP, CS, RFLAGS, RSP and SS in Bochs.

Of course, the GPF keeps happening after the first IRQ and I eventually triple fault when I run out of stack space. Oh - I am using proper 64 bit IDT entries with IST set to zero.

In case it helps, here is the Bochs Register Dump:

Code: Select all

00023924389e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (38)
... (above line * loads of times)...
00023924389i[CPU0 ] long mode
00023924389i[CPU0 ] CS.d_b = 16 bit
00023924389i[CPU0 ] SS.d_b = 16 bit
00023924389i[CPU0 ] EFER   = 0x00000501
00023924389i[CPU0 ] | RAX=fffff00000005380  RBX=fffff00000006bf0
00023924389i[CPU0 ] | RCX=000000000000008e  RDX=0000000000000008
00023924389i[CPU0 ] | RSP=ffffffbfffff0018  RBP=0000000000000000
00023924389i[CPU0 ] | RSI=00000000fffff000  RDI=fffff00000006370
00023924389i[CPU0 ] |  R8=0000000000000000   R9=fffff00000005380
00023924389i[CPU0 ] | R10=000000000000000a  R11=0000000000000258
00023924389i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00023924389i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00023924389i[CPU0 ] | IOPL=0 ID vip vif ac vm RF nt of df if tf SF zf af PF cf
00023924389i[CPU0 ] | SEG selector     base    limit G D
00023924389i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00023924389i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 0
00023924389i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00023924389i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00023924389i[CPU0 ] | RIP=fffff00000002069 (fffff00000002069)
00023924389i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0xffffffbffffefff8
00023924389i[CPU0 ] | CR3=0x0141d000 CR4=0x00000031
00023924389i[CPU0 ] >> iretd  : CF
00023924389p[CPU0 ] >>PANIC<< exception(): 3rd (14) exception with no resolution
You can see here what I mean about overrunning the stack - this is fine and is not the immediate problem as I haven't written my stack-space paging code yet.

So, what really obvious point have I missed in the AMD 64 bit architecture guide?

Cheers,
Adam

[edit - I just posted that I had fixed this, but I hadn't - same problem after an update to Bochs 2.3.6]
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

Yeah i had this problem too. Looked for errors a complete day until i noticed the last line of the int handler iret and realised this is 64-bit country lets chane it to iretq. Seems you are doing the same
Author of COBOS
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

You're joking - it worked :o ! My mistake was that I assumed using the NASM [BITS 64] directive would assume a 64 bit IRET.

Thank you so much - that little problem has caused me a lot of baldness over the course of today!

Cheers,
Adam
gedobbles
Posts: 6
Joined: Sat Nov 28, 2020 8:51 am

Re: Long Mode Interrupts - Stack Alignment

Post by gedobbles »

Thats totally it!

I searched for this about 3 days #-o
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Long Mode Interrupts - Stack Alignment

Post by kzinti »

Classic.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Long Mode Interrupts - Stack Alignment

Post by sj95126 »

This is one of those times when virtual machines (you mentioned Bochs) could do more to help us.

There should be an option to warn you that RSP was modified by anything other than an 8-byte aligned value. We could solve these kinds of issues in minutes rather than days.
Post Reply