Virtual Mode Monitor problems
Posted: Wed May 23, 2007 2:50 am
I'm trying to implement my Virtual 8086 mode monitor to handle interrupts (so far) from v8086 code.
I have a couple of questions. Firstly, which stack do I push the EFLAGS, CS, and EIP so that when the interrupt I'm jumping to in the IVT's iret takes it to where I want it. Is it the user stack, or the tss stack? I ask this because I keep on getting an invalid opcode error on every iret from the handled interrupts (at EIP 0x3?).
Secondly, this is my IVT dump:
I looked up Bochs code and found that F000:FF53 is just a dummy interrupt handler, nothing more than an 'iret'. Any ideas why my IVT is wrong? Does GRUB toy with it?
Finally, how do you guys handle invalid instructions that can't be handled? Do you just kill the process and then reschedule?
Edit: OK, this is my virtual mode monitor ATM:
This always crashes:
I have a couple of questions. Firstly, which stack do I push the EFLAGS, CS, and EIP so that when the interrupt I'm jumping to in the IVT's iret takes it to where I want it. Is it the user stack, or the tss stack? I ask this because I keep on getting an invalid opcode error on every iret from the handled interrupts (at EIP 0x3?).
Secondly, this is my IVT dump:
Code: Select all
<snip>Offsets were wrong...
Finally, how do you guys handle invalid instructions that can't be handled? Do you just kill the process and then reschedule?
Edit: OK, this is my virtual mode monitor ATM:
Code: Select all
// the IVT
uint16_t* ivt = (uint16_t*) 0;
// the stack
uint16_t* stack = (uint16_t*) r->useresp;
// instruction pointer
uint8_t* ip = (uint8_t*) r->eip;
// what was the instruction?
switch( ip[0] )
{
// 0xCD: INT n
case 0xCD:
// interrupt!
// decrement the stack 3 times
stack -= 3;
// set the new stack pointer
r->useresp = ( ( r->useresp & 0xFFFF ) - 6 ) & 0xFFFF;
// put the data on the stack
stack[0] = (uint16_t) ( r->eip + 2 );
stack[1] = r->cs;
stack[2] = (uint16_t) r->eflags;
// clear the interrupt flag
if( r->eflags & 0x200 )
r->eflags ^= 0x200;
// jump to the necessary location
r->cs = ivt[ ip[1] * 2 + 1 ];
r->eip = ivt[ ip[1] * 2 ];
// return, this will take us to the interrupt handler
return;
// default: ???
default:
// tell the user
kprintf( "Unknown opcode at EIP 0x%x: 0x%x!\n", r->eip, ip[0] );
}
Code: Select all
I've been rudely interrupted by the processor with this message for you:
Invalid Opcode
Crash at 0x 3 EFLAGS: 0x 33082
Registers at time of crash:
Error code: 0
Interrupt number: 6
EAX: 0x 0 EBX: 0x 0 ECX: 0x 0 EDX: 0x 0
EBP: 0x 0 ESP: 0x 110784 ESI: 0x 0 EDI: 0x 0
V8086 SS:ESP
SS: 0x 20 ESP: 0x 28fe
Segments at time of crash:
CS: 0x 0 DS: 0x 0 ES: 0x 0
FS: 0x 0 GS: 0x 0 SS: 0x 20
Control registers:
CR0: 0x 11 CR2: 0x 0 CR3: 0x 0