Title: 8086 emulation
18086 emulation
- Using Virtual-8086 mode to execute real-mode
procedures in a protected-mode environment
2Features of real-mode
- At power-up the Pentium begins executing in
real-address mode (memory addressing does not
require use of descriptor tables) - CPU privilege-restrictions are not imposed
- Memory addresses are limited to 20-bits
- Interrupt-routing is handled using the IVT
- Multitasking and paging are unsupported
- Lots of legacy software exists for 8086
3Rationale for 8086 emulation
- It is desirable to run multiple 8086 tasks in an
environment that protects each task from
interference by other tasks, yet offers each
task the illusion of being in control of the
system (as in real-mode environment) - Duplicate the environment of an 8086 cpu
- Synchronize access to shared resources, (such as
files and peripheral i/o devices)
4The VM-bit in EFLAGS
- The CPU executes in Virtual-8086 mode when the
VM-bit (bit 17) in EFLAGS is 1 - POPFL instruction cannot modify VM-bit
- Two methods for entering VM86-mode
- 1) use the IRET instruction (.code32)
- 2) use a task-switch to a new 386 TSS
- The only way to leave VM86-mode is with an
interrupt (either hardware or software) or by
resetting the processor (i.e., reboot)
5Entering a VM86-mode procedure
Ring-0 Stack-Frame
GS-image
FS-image
DS-image
Execute IRET instruction from 32-bit
code-segment while in protected-mode at
privilege-level 0
ES-image
SS-image
SP-image
EFLAGS ( VM1, NT0 )
CS-image
IP-image
SSESP
6I/O-sensitive Instructions
- While in VM86-mode, certain instructions are
sensitive to the current value of the
IOPL-field in EFLAGS - The CLI and STI instructions
- The PUSHF and POPF instructions
- The PUSHFL and POPFL instructions
- The IRET and IRETL instructions
- The INT-nn instruction
- The above instructions will generate a General
Protection Exception (INT-13) unless IOPL3
7The EFLAGS register
31
17 13 12
0
0
0
0
0
0
0
0
0
0
0
I D
V I P
V I F
A C
V M
R F
0
N T
I O P L
O F
D F
I F
T F
S F
Z F
0
A F
0
P F
1
C F
Legend VM Virtual-8086 Mode (1yes,
0no) IOPL I/O Privilege-Level
(0,1,2,3) VIF Virtual Interrupt-Flag (if
CR4.0 1) VIP Virtual Interrupt Pending (if
CR4.0 1) ID CPUID-supported (1yes,
0no) CF Carry-Flag TF Trap-Flag PF
Parity-Flag IF Interrupt-Flag AF
Auxilliary-Flag DF Direction-Flag ZF
Zero-Flag RF Resume-Flag SF Sign-Flag NT
Nested Task OF Overflow-Flag AC
Alignment Check
8Emulating I/O-sensitive instructions
- Suppose a task executing in VM86-mode tries to
disable device-interrupts, using a cli
instruction - If IOPLlt3, this instruction will cause a GP-fault
(exception 0x0D) with an error-code equal to 0 - The exception-handler can examine the opcode
(using the saved CSEIP address on its stack) - If the opcode equals 0xFA (i.e., cli), then the
handler can clear bit 9 in the saved EFLAGS
image (i.e., the IF-bit), increment the saved
EIP, then execute IRET to resume the VM86 task
9When IOPL 3
- A VM86-task executes at privilege-level 3
- If IOPL3, then the VM86 task is allowed to
execute all the IO-sensitive instructions (except
INT-nn) without generating a fault - If the VME-bit (bit 0) in Control Register 4 is
set to 1, Virtual Mode Extensions will be
enabled, and then INT-nn instructions can also be
executed without triggering a fault (provided a
bitmap in the TSS permits it)
10How to leave VM-8086 mode?
- In VM86-mode, certain instructions trigger a
General Protection Fault regardless of the
current value in EFLAGS IOPL-field - One of these is the halt-instruction (hlt)
- The GP fault-handler can examine the opcode that
triggered the fault (using the saved CSEIP
address on its ring0 stack) and, if it is 0xF4
(i.e., hlt), can terminate the VM86 task, if
that is what is desired
11IO-permission Bitmap
- For tasks that execute in VM86-mode, the ability
to execute IN/OUT instructions can be controlled
on a port-by-port basis, using a bitmap
data-structure within the TSS - The bitmap can be up to 8192 bytes long (one bit
for each of the 65536 i/o ports) - The CPU finds this bitmap by using the value at
offset 0x66 within the TSS, which holds the
bitmaps starting TSS offset
12Layout of the Task-State Segment
I/O Permission Bitmap
Software Interrupt Redirection Bitmap (if DR4.0
1)
IOMAP
0x66
TSS Base-Address
13Trapping I/O
- If you do not want a VM86 task to directly
perform I/O operations on a specific port, you
can set that ports bit within the bitmap - For example, to prevent a VM86 task from reading
mouse-data (io-port 0x60), just set bit 0x60
within that tasks io-permission bitmap this
will causes a GP-fault if the instruction in
0x60, al is encountered
14Demo-program tryvm86.s
- This demo illustrates entering and leaving a
Virtual-8086 procedure within a 386 task that is
executing in protected-mode - The procedure draws directly to video ram,
changing all the characters attribute-bytes to a
blue-colored background (turn_blue) - It executes with device-interrupts disabled
- It includes no io-sensitive instructions
- It uses hlt to exit from Virtual-8086 mode
15In-class exercise 1
- Try modifying the tryvm86.s demo -- to do
something thats much more interesting - Replace the turn_blue routine with code that
would call ROM-BIOS services (via interrupt 0x10)
to print a message at the current cursor location - You will need to add code to the GP-fault handler
that emulates an int-nn opcode
16Steps for int-nn emulation
- Determine the interrupts ID-number
- Advance the saved IP-value by 2 bytes (to skip
the emulated interrupt-instruction) - Simulate the push of FLAGS, CS, and IP onto the
VM86 tasks ring3 stack - Copy vector from IVT onto ring0 stack
- Clear IF and TF bits in the saved EFLAGS
- NOTE You may need to block all device interrupts
(by setting PIC mask registers)
17Emulating int-nn
Ring-3 Stack
Ring-0 Stack
GS
FS
DS
FLAGS
ES
CS
SS
IP
SP
EFLAGS
Real-Mode IVT
CS
CS
IP
IP
SSESP
18Other emulations if IOPL lt 3
- If you try executing code in Virtual-8086 mode
without IOPL3, then youre likely to need to
emulate the other io-sensitive instructions
(iret, cli, sti, pushf, popf) - The CLI and STI instructions are easy
- The PUSHF/POPF are a little harder
- The IRET is the most complex of these
19Emulating cli or sti
Ring-0 Stack
GS
FS
DS
ES
Simply adjust bit number 9 in the
saved image of the EFLAGS register
on the ring0 stack
SS
SP
EFLAGS
CS
IP
SSESP
20Emulating popf
Ring-3 Stack
Ring-0 Stack
GS
FS
DS
ES
SS
FLAGS
SP
Copy the topmost word from the ring3 stack
to the low-half of the saved EFLAGS-image
on the ring0 stack Add 2 to
the saved SP-value Add 1 to the
saved IP-value then execute IRET to
resume
EFLAGS
CS
IP
SSESP
21Emulating iret
Ring-3 Stack
Ring-0 Stack
GS
FS
DS
FLAGS
ES
CS
SS
IP
SP
Copy topmost 3 words from the ring3 stack to
the low-halves of the topmost 3 double-words
on the ring0 stack Add 6 to the saved
SP-value then execute IRET to resume
EFLAGS
CS
IP
SSESP
22In-class exercise 2
- Include a counter in your GP-fault handler
- Display the counter-value when finishing
- Then enable Virtual-Mode Extensions (by setting
bit 0 in Control Register 4) - Re-execute your demo notice the new value of
the GP-fault handlers counter!