Info written by Hans to describe the virtual flags used by DOSEmu

1. DOS sees only IF, but IF will never *really* set in the CPU flagregister,
   because this would block Linux. So Linus maintains a virtual IF (VIF),
   which he sets and resets accordingly to CLI, STI, POPFx, IRETx.
   Because the DOS programm cannot look directly into the flagregister
   (exception the low 8 bits, but the IF is in bit 9), it does not
   realize, that the IF isn't set. To see it, it has to perform
   PUSHF and look at the stack.
   Well, but PUSHF or INTxx is intercepted by vm86 and then Linus looks
   at his virtual IF to set the IF *on* the stack.
   Also, if IRETx or POPFx happen, Linus is getting the IF *from* the
   stack, sets VIF accordingly, but leaves the *real* IF untouched.

2. Now, how is this realized? This is a bit more complicated.
   We have 3 places were the eflagregister is stored in memory:

   vm86s.regs.eflags                    ( in user space, seen by dosemu )
   current->tss.v86flags                ( virtual flags, macro VEFLAGS )
   current->tss.vm86_info->regs.eflags  ( the *real* flags, CPU reg. VM86)    
   The last one is a kernel space copy of vm86_struct.regs.eflags.

   Also there are some masks to define, which bits of the flag
   should be passed to DOS and which should be taken from DOS:

   current->tss.v86mask         ( CPU model dependent bits)
   SAFE_MASK       (0xDD5)      ( used the way *to* DOS )
   RETURN_MASK     (0xDFF)      ( used the way *from* DOS )

   When sys_vm86 is entered, it first makes a copy of the whole
   vm86_struct vm86s (containing regs.eflags) and saves a pointer to it
   to current->tss.vm86_info. It merges the flags from 32-bit user
   space (NOTE: IF is always set) over SAFE_MASK and current->tss.v86mask
   into current->tss.v86mask. From this point on, all changes to
   VIF, VIP (virtual interrupt pending) are only done in VEFLAGS.
   To handle the flag setting there are macros within vm86.c,
   which do the following:

   set_IF, clear_IF  only modifies VEFLAGS;
   clear_TF          sets a bit in the *real* flags;
   set_vflags(x)     set flags x over SAFE_MASK  to *real* flags
                     (IF is not touched)
   x=get_vflags      returns *real* flags over RETURN_MASK and translates 
                     VIF of VEFLAGS to IF in x;
 

   When it's time to return from vm86() to user space, the *real* flags
   are merged together with VIF and VIP from VEFLAGS and put into
   the userspace vm86s.regs.eflags. This is done by save_v86_state()
   and this does *not* translate the VIF to IF, it should be as it
   was on entry of sys_vm86: set to 1.

3. Now what are we doing with eflags in dosemu ?
   Well, this I don't really know. I saw IF used (told it Larry), I saw
   VIF tested an set, I saw TF cleared, ... and NT flag....

   But I know what Linus thinks that we should do:
   Always interpret and set VIF, and let IF untouched, it will nevertheless
   set to 1 at entry of sys_vm86.

   How I think we should proceed? Well this I did describe in my last mail.


....and this from a follow-up mail:


NOTE: VIF and VIP in DOS-CPU-flagsregister are inherited from 32-bit,
====  so actually they are both ZERO.

      On return to 32-bit, *only* VIF will appear in vm86s.regs.eflags !
      VIP will be ZERO, again: VIP will be used only once !!!!
      ================         ===              =========


[ ... ]

I have to add, that VIP will be cleared, because it is not in any
of the masks of vm86.


So long,
Hans
<lermen@elserv.ffm.fgan.de>
