Page 1 of 1

vm86, iret and TSS

Posted: Thu Mar 08, 2007 3:06 am
by xyz1
I have the code, to enter in vm86:

vm86_bios:
;B+ Call bios interrupt in virtual 86 mode
push dword 0x1000 ;gs
push dword 0x1000 ;fs
push dword 0x1000 ;ds
push dword 0x1000 ;es
push dword 0x1000 ;ss
push dword 0xffff ;esp
;===EFLAGS=== pushfd with vm86 bit = 1
push dword 0x23202 ;0x20200 ;0x23202
push dword 0x1000 ;cs
push dword vm86-0x10000 ;eip
iret ;<--################################
.exit:
;pop stack ...
add esp,9*4
ret

use16
vm86:
;B+ Test
; end only...
; int 0x40
jmp $ ;<--$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;E:.
use32
;E:.

If I start this code, than I receive the error:
interrupt(): SS is not writable data segment
Wath is wrong???

Debugging this code with bochs, I found, that:

BEFORE:
esp:0x0007ff94 eip:0x000190a0
eflags:0x00000297 = IF+SF+AF+PF+CF
cs:s=0x0008, dl=0x0000ffff, dh=0x00df9a00, valid=1
ss:s=0x08b0, dl=0x000000ff, dh=0x01d09308, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00df9300, valid=3
es:s=0x0010, dl=0x0000ffff, dh=0x00df9300, valid=1
tr:s=0x0090, dl=0x07800080, dh=0x00108904, valid=1
gdtr:base=0x00019e61, limit=0xc47
idtr:base=0x0001aab1, limit=0x807

AFTER:
esp:0x0000fffd eip:0x000090a6
eflags:0x00023202 = 100011001000000010 = VM+IOPL=3+IF
cs:s=0x1000, dl=0x0000ffff, dh=0x0000fb01, valid=1
ss:s=0x1000, dl=0x0000ffff, dh=0x0000f301, valid=5
ds:s=0x1000, dl=0x0000ffff, dh=0x0000f301, valid=1
es:s=0x1000, dl=0x0000ffff, dh=0x0000f301, valid=1
tr:s=0x0090, dl=0x07800080, dh=0x00108904, valid=1
gdtr:base=0x00019e61, limit=0xc47
idtr:base=0x0001aab1, limit=0x807

This is only for additional information.

Posted: Thu Mar 08, 2007 3:10 am
by Combuster
Does bochs panic during vm entry or during vm exit? (i.e. what is the failing instruction)?

Posted: Thu Mar 08, 2007 3:12 am
by pcmattman
You aren't pushing the right value for SS onto the stack. Make sure that the right values are being used, and remember that you can't access memory above the 1MB mark.

Edit: I think that's what is happening...

Posted: Thu Mar 08, 2007 4:19 am
by xyz1
>Does bochs panic during vm entry or during vm exit?
Case is "during vm exit". I wrote essential row in bold:
interrupt(): SS is not writable data segment
The log file is (i.e. only the end):

Code: Select all

01857301543e[CPU0 ] interrupt(): SS is not writable data segment
01857301543e[CPU0 ] interrupt(): SS is not writable data segment
01857301543e[CPU0 ] interrupt(): SS is not writable data segment
01857301543i[CPU0 ] v8086 mode
01857301543i[CPU0 ] CS.d_b = 16 bit
01857301543i[CPU0 ] SS.d_b = 16 bit
01857301543i[CPU0 ] | EAX=00000002  EBX=0001000a  ECX=00eaea0e  EDX=00000028
01857301543i[CPU0 ] | ESP=0000ffff  EBP=00000002  ESI=00787cd8  EDI=0000003e
01857301543i[CPU0 ] | IOPL=3 id vip vif ac VM RF nt of df IF tf sf zf af pf cf
01857301543i[CPU0 ] | SEG selector     base    limit G D
01857301543i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
01857301543i[CPU0 ] |  CS:1000( 0001| 0|  3) 00010000 0000ffff 0 0
01857301543i[CPU0 ] |  DS:1000( 0002| 0|  3) 00010000 0000ffff 0 0
01857301543i[CPU0 ] |  SS:1100( 0116| 0|  3) 00011000 0000ffff 0 0
01857301543i[CPU0 ] |  ES:1000( 0002| 0|  3) 00010000 0000ffff 0 0
01857301543i[CPU0 ] |  FS:1000( 0002| 0|  3) 00010000 0000ffff 0 0
01857301543i[CPU0 ] |  GS:1000( 0002| 0|  3) 00010000 0000ffff 0 0
01857301543i[CPU0 ] | EIP=000090a5 (000090a5)
01857301543i[CPU0 ] | CR0=0x00000019 CR1=0 CR2=0x00000000
01857301543i[CPU0 ] | CR3=0x00070018 CR4=0x00000000
01857301543i[CPU0 ] >> jmp .+0xfffe (0x000190a5) : EBFE
01857301543e[CPU0 ] exception(): 3rd (10) exception with no resolution, shutdown status is 00h, resetting
>You aren't pushing the right value for SS onto the stack.
No, the value is correct! This is vm86 stack value. I even use "push ax" in vm86 mode, and it is working!

Posted: Thu Mar 08, 2007 4:38 am
by pcmattman
Just shows what I know about V8086 mode :D :lol:

Posted: Thu Mar 08, 2007 8:39 am
by Combuster
I think you forgot to correctly load the SS0/ESP0 fields in the TSS

Posted: Fri Mar 09, 2007 1:33 am
by xyz1
I think you forgot to correctly load the SS0/ESP0 fields in the TSS
Tank you! This solve the problem.

But I have one another question:
If I am in vm86, and some hrdware interrupt occure, then GPF will be send. Haw can I handle this events correctly (i.e. to find int number).

Posted: Fri Mar 09, 2007 3:31 am
by Pype.Clicker
xyz1 wrote: If I am in vm86, and some hrdware interrupt occure, then GPF will be send. Haw can I handle this events correctly (i.e. to find int number).
Hmm, not to my knowledge. Hardware interrupts are still delivered through the IDT, not through the old interrupt vector table of real mode.

Unless you configured the processor to use VirtualModeExtensions (which i bet you didn't) and unless you have no descriptor installed for IRQs in your IDT, you shouldn't get GPFs but rather see the proper descriptor invoked on SS0:ESP0.