Caveats of VME (when CR4.VME=1)
VME is wonderful for reducing the complexity of the OS, but
isn't without its caveats. Some of the quirks are natural
extensions of VME or the underlying architecture, while others
might not make any sense.
- While an Ev86 task is running, the IF-sensitive flags
commit fakery to fool the Ev86 task into thinking that it
is actually setting and clearing the IF flag. When a
fault occurs to the monitor, the monitor sees the actual
values of VIF, VIP and IF unfiltered. This gives the
monitor direct control over virtual interrupts, and
hardware interrupts.
- Software-generated exceptions are not influenced by the
IR bit map. INT1,[1] INT3, INTO, and
BOUND[2] are not subject to the IR
bit map. Instead, these opcodes will always invoke the
protected mode exception handler.[3]
- VIF will never transition from 0 to 1 while a virtual
interrupt is pending when IOPL<3. This condition will
always cause a general protection fault (#GP(0)) before
VIF is set. This can best be described as follows: while
the Ev86 task is in an uninterruptible state (VIF=0), a
timer tick occurs, and causes a transition to the
protected mode interrupt handler. The timer-tick routine
sets VIP on the stack frame, and returns to the Ev86
task. The Ev86 task performs an STI instruction, which
will put the program into an interruptible state. Before
VIF is actually set, the #GP occurs. (This behavior can
be observed by inspecting the EFLAGS image on the CPL-0
stack frame.) This behavioral characteristic is the basis
for Intel's British Patent application which claims
"if the VIP bit is in its 'pending' state, then the
STI instruction can be executed and an awaiting interrupt
serviced by using the emulation software without first
changing the VIF bit from its CLI state to its STI
state."
- VIP functions in IOPL=3 in a strange manner. When
IOPL<3, and VIP=1, any transition from VIF=0 to VIF=1
will cause a general protection fault before VIF is
actually set. When IOPL=3, this behavior is different.
VIF must actually be set before the #GP occurs.
- PUSHFD, POPFD, and IRETD will all generate a general
protection fault in an Ev86 task when IOPL<3.
- The behavior of POPF and IRET is inconsistent in how it
handles the trap flag (TF) from the flags image on the
stack. When POPF is invoked with TF=1 on the stack image,
a general protection fault occurs. When IRET is invoked
under the same condition, the general protection fault
does not occur.
- IRET is no longer IOPL-sensitive when CR4.VME=1. Consider
that the Ev86 task is running and an interrupt's
associated IR bit is set. When this interrupt is invoked,
it will cause a fault to the monitor, or the protected
mode interrupt will be invoked (depending on IOPL). The
interrupt is then reflected back to the Ev86 task. When
IOPL=3, the behavior of the fault and subsequent IRET
matches non-Ev86 behavior. When IOPL<3, the subsequent
IRET from the interrupt service routine doesn't cause a
fault back to the monitor, as IRET is no longer
IOPL-sensitive. This behavior is inconsistent with its
non-Ev86 counterpart.
- When IOPL=3, the CPU never updates VIF, though software
can manipulate it in CPL-0. This can lead to the next
caveat...
- The CPU will generate a general protection fault (#GP(0))
whenever VIF=1, and VIP=1 and running in CPL-3. This is
regardless of whether or not the code is an Ev86 task.
- In CPL-0, IRETD has the ability to set VIF and VIP, but
POPFD does not.
Endnotes
- An undocumented opcode which generates
an INT-1 exception. Also known as ICEBP.
- Opcodes 0xF1, 0xCC, 0xCE, 0x62
respectively.
- Assuming that all other protection
attributes will permit the transition to occur.
Back to article
Virtual Mode Extensions on the Pentium Processor
Back to Books and Articles
home page
|