Page 1 of 1

32-bit TSS in long mode?

Posted: Sun Dec 28, 2014 10:23 pm
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!!

Re: 32-bit TSS in long mode?

Posted: Mon Dec 29, 2014 10:59 am
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.