UnnamedOS
VM86

Virtual 8086 Mode. More...

+ Collaboration diagram for VM86:

Data Structures

struct  vm86_farptr_t
 A real mode far pointer. More...
 

Macros

#define CODE_ADDRESS   ((void*) 0x500)
 Where the assembly code will be located. More...
 
#define IVT_ADDRESS   ((void*) 0)
 The real mode IVT (= Interrupt Vector Table) lies at the start of memory. More...
 
#define OPERAND_SIZE   0x66
 opcode for overriding operand size
 
#define OPCODE_PUSHF   0x9C
 PUSHF triggers a GPF inside VM86 mode.
 
#define OPCODE_POPF   0x9D
 POPF triggers a GPF inside VM86 mode.
 
#define OPCODE_INT_3   0xCC
 INT $3 triggers a GPF inside VM86 mode.
 
#define OPCODE_INT   0xCD
 INT triggers a GPF inside VM86 mode.
 
#define OPCODE_IRET   0xCF
 IRET triggers a GPF inside VM86 mode.
 
#define OPCODE_CLI   0xFA
 CLI triggers a GPF inside VM86 mode.
 
#define OPCODE_STI   0xFB
 STI triggers a GPF inside VM86 mode.
 
#define CASE_IN(opcode, in_func, operand, inc, type)
 Emulates an IN instruction. More...
 
#define CASE_OUT(opcode, out_func, operand, inc)
 Emulates an OUT instruction. More...
 

Functions

static vm86_farptr_t vm86_get_farptr (void *addr)
 Translate an address into a far pointer. More...
 
static void vm86_write_farptr (uint16_t *segment, uint16_t *offset, vm86_farptr_t farptr)
 Writes a far pointer into another location. More...
 
static void * vm86_get_address (vm86_farptr_t farptr)
 Translate a far pointer into an address. More...
 
task_pid_t vm86_create_task (void *code_start, void *code_end, page_directory_t *page_directory, size_t kernel_stack_len, size_t user_stack_len, isr_registers_t *registers)
 Creates a VM86 task. More...
 
void vm86_call_bios (uint8_t interrupt, isr_registers_t *registers)
 Calls a BIOS interrupt. More...
 
static void vm86_push (cpu_state_t *cpu, uint16_t value)
 Emulates a PUSH instruction. More...
 
static uint16_t vm86_pop (cpu_state_t *cpu)
 Emulates a POP instruction. More...
 
static void vm86_increment_eip (cpu_state_t *cpu, size_t inc)
 Emulates the completion of an instruction. More...
 
static uint8_t vm86_monitor (cpu_state_t *cpu)
 Monitors a VM86 task by emulating sensitive instructions. More...
 
static cpu_state_tvm86_handle_gpf (cpu_state_t *cpu)
 Handles general protection faults. More...
 
void vm86_init ()
 Initializes VM86 mode.
 

Variables

static vm86_farptr_tivt = IVT_ADDRESS
 IVT needed to do BIOS calls.
 
const void vm86_call_bios_start
 start of the BIOS call code
 
const void vm86_call_bios_end
 end of the BIOS call code
 
const void vm86_interrupt_hook
 location of INT in the BIOS call code
 

Detailed Description

Virtual 8086 Mode.

The VM86 mode runs 16-bit code and calls BIOS functions. A VM86 monitor is needed to emulate sensitive instructions.

See also
vm86_asm.S
http://wiki.osdev.org/Virtual_8086_Mode
http://www.lowlevel.eu/wiki/Virtual_8086_Mode
http://osdev.berlios.de/v86.html
http://www.rcollins.org/articles/pvi1/pvi1.html
http://lowlevel.eu/wiki/Speicherbereiche
http://www.brokenthorn.com/Resources/OSDevVid2.html
http://ref.x86asm.net/coder32.html

Macro Definition Documentation

#define CASE_IN (   opcode,
  in_func,
  operand,
  inc,
  type 
)
Value:
case (opcode): \
*(type*) &cpu->r.eax = (in_func)(operand); \
vm86_increment_eip(cpu, (inc)); \
break;

Emulates an IN instruction.

Parameters
opcodethe opcode of the instruction to emulate
in_functhe function to call
operandthe input port
incthe instruction length in bytes
typein_func's return type

Definition at line 54 of file vm86.c.

#define CASE_OUT (   opcode,
  out_func,
  operand,
  inc 
)
Value:
case (opcode): \
(out_func)((operand), cpu->r.eax); \
vm86_increment_eip(cpu, (inc)); \
break;

Emulates an OUT instruction.

Parameters
opcodethe opcode of the instruction to emulate
out_functhe function to call
operandthe output port
incthe instruction length in bytes

Definition at line 67 of file vm86.c.

#define CODE_ADDRESS   ((void*) 0x500)

Where the assembly code will be located.

The code will be memcpy'd to this location. We set this to the beginning of conventional memory. This way only one VM86 task can be run at a time!

Definition at line 33 of file vm86.c.

#define IVT_ADDRESS   ((void*) 0)

The real mode IVT (= Interrupt Vector Table) lies at the start of memory.

One of the few occasions to dereference a null pointer ^^

Definition at line 36 of file vm86.c.

Function Documentation

void vm86_call_bios ( uint8_t  interrupt,
isr_registers_t registers 
)

Calls a BIOS interrupt.

Parameters
interruptthe interrupt vector to call
registersthe parameters for the call

Definition at line 205 of file vm86.c.

+ Here is the call graph for this function:

task_pid_t vm86_create_task ( void *  code_start,
void *  code_end,
page_directory_t page_directory,
size_t  kernel_stack_len,
size_t  user_stack_len,
isr_registers_t registers 
)

Creates a VM86 task.

See also
task_create_detailed
Parameters
code_startstart of the 16-bit code
code_endend of the 16-bit code
page_directorya page directory for the task, if 0 a new one is created
kernel_stack_lennumber of bytes to allocate for the kernel stack
user_stack_lennumber of bytes to allocate for the user stack
registersparameters to pass to the 16-bit code
Returns
the task's PID

Identity maps the first MiB so our VM86 task can operate inside it. Because this is not inside the user domain (1GiB and onwards), bypasses domain checking.

Copies the 16-bit code into conventional memory. We could map the code as virtual memory, but copying is easier ;) Note that this code might not reference any labels or so, because it needs to be position independent. For calling the BIOS this is enough, if we started writing real 16-bit programs, we would need to improve this.

The user stack is located after the code (we assume that's free memory).

Definition at line 145 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void* vm86_get_address ( vm86_farptr_t  farptr)
static

Translate a far pointer into an address.

Parameters
farptrthe far pointer
Returns
the address

Definition at line 129 of file vm86.c.

+ Here is the caller graph for this function:

static vm86_farptr_t vm86_get_farptr ( void *  addr)
static

Translate an address into a far pointer.

Parameters
addrthe address
Returns
the far pointer

There are many ways to translate an address into a far pointer. We do it in such a way that our code is likely to only use one segment (which is easier than handling multiple segments). The equation used is:

1 paddr = segment * 16 + offset

Definition at line 91 of file vm86.c.

+ Here is the caller graph for this function:

static cpu_state_t* vm86_handle_gpf ( cpu_state_t cpu)
static

Handles general protection faults.

Parameters
cputhe CPU state
Returns
a (possibly altered) CPU state

Definition at line 337 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vm86_increment_eip ( cpu_state_t cpu,
size_t  inc 
)
static

Emulates the completion of an instruction.

Parameters
cputhe CPU state to modify
incthe instruction length in bytes

Definition at line 249 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static uint8_t vm86_monitor ( cpu_state_t cpu)
static

Monitors a VM86 task by emulating sensitive instructions.

Parameters
cputhe task's CPU state
Returns
whether the monitor handled the GPF

Definition at line 260 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static uint16_t vm86_pop ( cpu_state_t cpu)
static

Emulates a POP instruction.

Parameters
cputhe CPU state to modify
Returns
the popped value

Definition at line 235 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vm86_push ( cpu_state_t cpu,
uint16_t  value 
)
static

Emulates a PUSH instruction.

Parameters
cputhe CPU state to modify
valuethe value to push

Definition at line 222 of file vm86.c.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void vm86_write_farptr ( uint16_t *  segment,
uint16_t *  offset,
vm86_farptr_t  farptr 
)
static

Writes a far pointer into another location.

Parameters
segmentwhere to write the segment
offsetwhere to write the offset
farptrthe far pointer to write

Definition at line 118 of file vm86.c.

+ Here is the caller graph for this function: