Posted: Fri Jul 13, 2007 11:16 pm
Hi...
Till now I couldn't get out of virtual mode without any exceptions...
I guess there's wrong with my vmm but I don't know what it's
here's what I'm doing: I check for my "quit" int which is 0x80,unset VM bit in eflags
and then I do far call to the selector of main().
would you guys check this code,when I execute it I get debug exception.
It execute int 10h successfuly but it dosen't go back for int 80h.
my GPF handler:
my virtual task:
Thanx.
Till now I couldn't get out of virtual mode without any exceptions...
I guess there's wrong with my vmm but I don't know what it's
here's what I'm doing: I check for my "quit" int which is 0x80,unset VM bit in eflags
and then I do far call to the selector of main().
would you guys check this code,when I execute it I get debug exception.
It execute int 10h successfuly but it dosen't go back for int 80h.
Code: Select all
void fault_handler(struct regs *r)
{
if(r->int_no<32)
{
if( r->eflags & 0x20000 && r->int_no == 13 )//vmode and GPF
gpf_handler(r);
else{
printf(exception_message[r->int_no]);
printf("\nException. System Halted!\n");
for(;;);
}
}
}
Code: Select all
static unsigned FP_TO_LINEAR(unsigned seg, unsigned off)
{
return ((seg & 0xFFFF) * 0x10) + off;
}
Code: Select all
void gpf_handler(struct regs *r)
{
// the IVT
word* ivt = (word*) 0;
// the stack, in 16-bit and 32-bit
word* stack = (word*) FP_TO_LINEAR( 0x20, r->useresp );
dword* stack32 = (dword*) stack;
// instruction pointer
byte* ip = (byte*) FP_TO_LINEAR( r->cs, r->eip );
// index of execution
dword exc = 0;
// operand and address sizes
int Op32 = 0, Addr32 = 0;
while(1)
{
switch( ip[0] )
{
case 0x66: // 32-bit operand
{
// we are using 32-bit operands
Op32 = 1;
// increment the IP
ip++;
// set the new EIP in the stack
r->eip++;
break;
}
case 0x67: // 32-bit address
{
// 32-bit addresses
Addr32 = 1;
// increment the IP
ip++;
// set the new EIP in the stack
r->eip++;
break;
}
case 0x9C: // PUSHF
{
// check for 32-bit
if( Op32==1)
{
// decrement the stack by 4 bytes
r->useresp = ( ( r->useresp & 0xFFFF ) - 4 ) & 0xFFFF;
// decrement the stack
stack32--;
// put the flags on the stack
stack32[0] = r->eflags & 0xDFF;
// see if we have interrupts enabled
if( r->eflags & 0x200 )
stack32[0] |= 0x200; // enable in flags
else
stack32[0] ^= 0x200; // disable
}
else
{
// decrement the stack by 2 bytes
r->useresp = ( ( r->useresp & 0xFFFF ) - 2 ) & 0xFFFF;
// decrement the stack
stack--;
// put the flags on the stack
stack[0] = r->eflags;
// see if we have interrupts enabled
if( r->eflags & 0x200 )
stack[0] |= 0x200; // enable in flags
else
stack[0] ^= 0x200; // disable
}
// increment eip
r->eip++;
// go back to task
return;
}
case 0x9D: // POPF
{
// check for 32-bit
if( Op32==1 )
{
// set the EFLAGS
r->eflags = 0x20200 | ( stack32[0] & 0xDDF );
// set the new stack pointer
r->useresp = ( ( r->useresp & 0xFFFF ) + 4 ) & 0xFFFF;
}
else
{
// set the EFLAGS
r->eflags = 0x20200 | stack[0];
// set the new stack pointer
r->useresp = ( ( r->useresp & 0xFFFF ) + 2 ) & 0xFFFF;
}
// increment eip
r->eip++;
// return to the task
return;
}
case 0xFA: // CLI
{
// take out the interrupt flag
if( r->eflags & 0x200 )
r->eflags ^= 0x200;
// increment eip
r->eip++;
// return to the task
return;
}
case 0xFB: // STI
{
// put in the interrupt flag
if( ( r->eflags & 0x200 ) == 0 )
r->eflags &= 0x200;
// increment eip
r->eip++;
// return to the task
return;
}
case 0xCD: // 0xCD: INT n
{
// int 80 quit
if( ip[1] == 0x80 )
{
r->eflags=0x202L;
far_call(0x28);
//0x28 selector of main();
return;
}
// decrement the stack 3 times
stack -= 3;
// put the data on the stack
stack[0] = (word) ( r->eip + exc + 2 );
stack[1] = r->cs;
stack[2] = (word) r->eflags;
// set the new stack pointer
r->useresp = ( ( r->useresp & 0xFFFF ) - 6 ) & 0xFFFF;
// set eflags
if( r->eflags & 0x200 )
r->eflags ^= 0x200;
// jump to the necessary location
r->cs = ivt[ ip[exc+1] * 2 + 1 ];
r->eip = ivt[ ip[exc+1] * 2 ];
// return, this will take us to the interrupt handler
return;
}
case 0xCF: // IRET
{
// set EFLAGS, CS and EIP, then refresh Ring3ESP
r->eip = stack[0];
r->cs = stack[1];
r->eflags = stack[2] | 0x20200;
// new stack pointer
r->useresp = ( ( r->useresp & 0xFFFF ) + 6 ) & 0xFFFF;
// return to the new place
return;
}
default:
printf("Invalid opcode\n");
} //switch
}//while
}
Code: Select all
global _vt
_vt:
mov ah,09h
mov al,'*'
mov bh,00h
mov bl,0dah
mov cx,5h
int 10h
int 80h ;quit from virtual mode