virtual mode monitor

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

sorry double post
Last edited by xyjamepa on Sat Jul 14, 2007 1:24 am, edited 1 time in total.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

The far call doesn't happen in the GPF handler! It happens after you call int 0x80 :D
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post 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?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply