32-bit TSS in long mode?

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
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

32-bit TSS in long mode?

Post by eryjus »

Hi,

I have a few issues going on at the moment, but I am trying to focus on getting my 64-bit TSS flags right since I believe that is the root of at least some of my issues. Please forgive the long post as I lay out the background.

I am getting a spurious IRQ when enabling interrupts for which I did not have a handler written yet. So I wrote very simple one (mostly ignoring LPT1 for now):

Code: Select all

;----------------------------------------------------------------------------------------------
; SpurHandler -- This is the Interrupt handler for IRQ7.  It will be called with each spurious
;                interrupt.  It will also be called for any LPT1 interrupt, so we will need
;                to be careful with this.
;
; Keep in mind that this 'function' does not have a normal entry process or exit process.  We
; need to be particularly careful about saving and restoring EVERYTHING we will touch.
;----------------------------------------------------------------------------------------------

SpurHandler:
                push        rbp                     ; save the interrupted process's frame
                mov.q       rbp,rsp                 ; we want our own frame
                push        rax                     ; yes, we even save rax

;----------------------------------------------------------------------------------------------
; check if it is a spurious interrupt
;----------------------------------------------------------------------------------------------

                mov.q       rax,pic                 ; get the pic interface structure
                mov.q       rax,[rax+PIC.readISR]   ; get the ReadISR fucntion address
                call        rax                     ; do we have an interrupt
                test.q      rax,0x80                ; test bit 7
                jz          .eoi                    ; we have a real interrupt; ack it

                mov.q       rax,spurCount           ; get the counter address
                inc         qword [rax]             ; increment the count

%ifndef DISABLE_DBG_CONSOLE
                mov.q       rax,spurIntRcvd         ; get the text address
                push        rax                     ; put it on the stack
                call        DbgConsolePutString     ; write it to the console
                add.q       rsp,8                   ; clean up the stack
%endif
                jmp         .out                    ; go exit

.eoi:           mov.q       rax,pic                 ; get the pic interface structure
                mov.q       rax,[rax+PIC.eoi]       ; get the EOI fucntion address
                push        0x07                    ; we need to ack IRQ7
                call        rax                     ; do we have an interrupt

.out:           pop         rax                     ; restore rax
                pop         rbp                     ; restore rbp
                iretq

;==============================================================================================
Bochs confirms that I am getting a spurious interrupter (0x27) followed by a page fault on exit:
00169419906d[CPU0 ] inhibit interrupts mask = 1
00169419908d[CPU0 ] interrupt(): vector = 27, TYPE = 0, EXT = 1
00169419908d[CPU0 ] page walk for address 0xffffa000000b8340
00169419908d[CPU0 ] interrupt(long mode): INTERRUPT TO SAME PRIVILEGE
00169419908d[CPU0 ] interrupt(long mode): trap to IST, vector = 2
00169419908d[CPU0 ] page walk for address 0xfffff00200017ff8
00169419908d[CPU0 ] page walk for address 0xffffa000000b806d
00169419949d[CPU0 ] LONG MODE IRET
00169419949d[CPU0 ] page walk for address 0x0000000000003e40
00169419949d[CPU0 ] PAE PTE: entry not present
00169419949d[CPU0 ] page fault for address 0000000000003e40 @ ffff800000104f59
00169419949d[CPU0 ] exception(0x0e): error_code=0000
00169419949d[CPU0 ] interrupt(): vector = 0e, TYPE = 3, EXT = 1
00169419949d[CPU0 ] interrupt(long mode): INTERRUPT TO SAME PRIVILEGE
00169419949d[CPU0 ] interrupt(long mode): trap to IST, vector = 5
00169419949d[CPU0 ] page walk for address 0xfffff00200023ff8
00169420038d[CPU0 ] page walk for address 0x00000000000b8000
00169466708i[CPU0 ] WARNING: HLT instruction with IF=0!
One thing I find odd is that DbgConsolePutString() is not writing any string to the serial port....

At any rate, I investigate my GDT and I see the following:

Code: Select all

Global Descriptor Table (base=0xffffa000000b8060, limit=55):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0x00000fff, Execute/Read, Non-Conforming, Accessed, 64-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0x00000fff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0x00000fff, Execute/Read, Non-Conforming, 64-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0x00000fff, Read/Write
GDT[0x05]=32-Bit TSS (Busy) at 0xfff00000, length 0x00067
GDT[0x06]=??? descriptor hi=0x00000000, lo=0xffffff7f
I have read the Intel manual vol 3A sections 3.5 and 7.2.3 several times and I've convinced myself (probably wrongly) I have my bits setup correctly:

Code: Select all

0xffffa000000b8060 <bogus+       0>:	0x00000000	0x00000000	0x00000000	0x00a09b00
0xffffa000000b8070 <bogus+      16>:	0x00000000	0x00809300	0x00000000	0x00a0fa00
0xffffa000000b8080 <bogus+      32>:	0x00000000	0x0080f200	0x00000067	0xff808bf0
0xffffa000000b8090 <bogus+      48>:	0xffffff7f	0x00000000
In particular, I am expecting "0xff808bf0" to tell me that I have a 64-bit TSS in GDT[0x05] ('busy' in fact). However, as above, Bochs is reporting a 32-bit TSS.

Bochs reports that I am using long mode, which is what I understand the distinguishing factor to be:
00820800009i[CPU0 ] CPU is in long mode (halted)
00820800009i[CPU0 ] CS.mode = 64 bit
00820800009i[CPU0 ] SS.mode = 64 bit
00820800009i[CPU0 ] EFER = 0x00000500
00820800009i[CPU0 ] | RAX=ffff800000101d0e RBX=ffff800000105a28
00820800009i[CPU0 ] | RCX=00000000e0000011 RDX=0000000000000020
00820800009i[CPU0 ] | RSP=fffff00200023ef8 RBP=fffff00200023f00
00820800009i[CPU0 ] | RSI=0000000000000000 RDI=00000000000b800c
00820800009i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00820800009i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00820800009i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00820800009i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00820800009i[CPU0 ] | IOPL=0 ID vip vif ac vm rf nt of df if tf sf zf af pf cf
00820800009i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00820800009i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 00000fff 1 0
00820800009i[CPU0 ] | MSR_FS_BASE:0000000000000000
00820800009i[CPU0 ] | MSR_GS_BASE:0000000000000000
00820800009i[CPU0 ] | RIP=ffff800000101d10 (ffff800000101d10)
00820800009i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000003e40
00820800009i[CPU0 ] | CR3=0x00400000 CR4=0x00000020
I'm sure I'm missing something rather obvious with the GDT flags somewhere. Can someone please help me out or point me in the right direction?


Thanks in advance!!
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: 32-bit TSS in long mode?

Post by eryjus »

After reading Bochs code this morning, I have opened a but with the Bochs project: here. In short, I believe the support for 16 byte GDT entries in the Bochs built-in debugger is incomplete.
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
Post Reply