Page 2 of 2

Posted: Fri Jul 13, 2007 11:16 pm
by xyjamepa
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.

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;
} 
my GPF handler:

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 

}
my virtual task:

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
Thanx.

Posted: Fri Jul 13, 2007 11:16 pm
by xyjamepa
sorry double post

Posted: Fri Jul 13, 2007 11:31 pm
by pcmattman
The far call doesn't happen in the GPF handler! It happens after you call int 0x80 :D

Posted: Sat Jul 14, 2007 1:43 am
by xyjamepa
Hi...

cpu after executing BIOS int 10h ,dosen't execute any code after that.
it fires debug exceptions immediately,so I think it dosen't see any
code after int 10h.
I tried to print a char after int 10h but I couldn't do that.
so I think there's a problem with my gpf_handler or with my fault_handler.


Thanx.

Posted: Sat Jul 14, 2007 5:14 am
by Combuster
have you pinpointed the instruction that is actually causing the debug? is it before or after the int 10, before or after the int 80, some instruction in the bios, some instruction in your kernel? have you tried using bochs to determine the cpu state at that point?