#include <kernel/kernel.h>
#include <kernel/thread.h>
#include <kernel/vmm.h>
#include <kernel/proc.h>
#include <stdio.h>
//! Convert an 8086-style seg:ofs address to a linear x86 address
#define LINEAR86(seg, ofs) (((addr_t) (seg) << 4) + (addr_t) (ofs))
//! The handler called in the event of a GPF in virtual 8086 mode
/*!
* If possible, this function emulates the faulting instruction in kernel mode.
* \param ctx The context structure passed on the stack as a result of the
* fault
* \return true if the page fault was handled (and it is safe for the thread
* to continue execution), false otherwise.
*/
bool sysV86Fault(context_t* ctx)
{
byte *ptr;
word *stack, *ivt;
bool handled = true;
ptr = (byte*) LINEAR86(ctx->cs, ctx->eip);
stack = (word*) LINEAR86(ctx->ss, ctx->esp);
ivt = (word*) 0;
switch (ptr[0])
{
case 0x6d: // INS
wprintf(L"V86: INS encountered at %04x:%04x\n", ctx->cs, ctx->eip);
//dump_context(ctx);
handled = false;
break;
case 0xcc: // INT3
wprintf(L"V86: breakpoint at %04x:%04x\n", ctx->cs, ctx->eip);
//dump_context(ctx);
handled = false;
ctx->eip++;
break;
case 0xcd: // INT n
stack[0] = (word) (ctx->eip + 2);
stack[-1] = ctx->cs;
stack[-2] = (word) ctx->eflags;
ctx->esp = ((ctx->esp & 0xffff) - 6) & 0xffff;
ctx->cs = ivt[ptr[1] * 2 + 1];
ctx->eip = ivt[ptr[1] * 2];
break;
case 0xcf: // IRET
ctx->eflags = EFLAG_VM | stack[1];
ctx->cs = stack[2];
ctx->eip = stack[3];
ctx->esp = ((ctx->esp & 0xffff) + 6) & 0xffff;
break;
case 0xec: // IN AL,DX
ctx->regs.eax = (ctx->regs.eax & ~0xff) | in((word) ctx->regs.edx);
ctx->eip++;
break;
case 0xed: // IN AX,DX
ctx->regs.eax = (ctx->regs.eax & ~0xffff) | in16((word) ctx->regs.edx);
ctx->eip++;
break;
case 0xee: // OUT DX,AL
out(ctx->regs.edx, ctx->regs.eax);
ctx->eip++;
break;
case 0xef: // OUT DX,AX
out16(ctx->regs.edx, ctx->regs.eax);
ctx->eip++;
break;
case 0xf4: // HLT
wprintf(L"V86: HLT encountered at %04x:%04x\n", ctx->cs, ctx->eip);
//dump_context(ctx);
ctx->eip++;
handled = false;
break;
}
if (!handled)
wprintf(L"%x %x %x\n", ptr[0], ptr[1], ptr[2]);
return handled;
}