Example #1
0
int __vmx_vmexit_inject_exception(uint32_t vector, uint32_t error, uint64_t cr2)
{
   __vmx_prepare_event_injection(vm_entry_ctrls.int_info,
                                 VMCS_EVT_INFO_TYPE_HW_EXCP,
                                 vector);
   switch(vector)
   {
   case PF_EXCP:
      vm_state.cr2.raw = cr2;
      vmcs_dirty(vm_state.cr2);
   case DF_EXCP:
   case TS_EXCP:
   case NP_EXCP:
   case SS_EXCP:
   case GP_EXCP:
   case AC_EXCP:
      vm_entry_ctrls.int_info.dec = 1;
      vm_entry_ctrls.err_code.raw = error;
      vmcs_dirty(vm_entry_ctrls.err_code);
      break;

   default:
      break;
   }

   debug(VMX_EXCP, "inject exception #%d err 0x%x\n", vector, error);
   return 1;
}
Example #2
0
static int __vmx_vmexit_lgdt(dt_reg_t *dt_reg)
{
   if(vmx_cpl)
      return VM_FAIL;

   debug(VMX_DT, "lgdt 0x%X:0x%x\n", dt_reg->base.raw, dt_reg->limit);

   vm_state.gdtr.base.raw = dt_reg->base.raw;
   vm_state.gdtr.limit.wlow = dt_reg->limit;
   vmcs_dirty(vm_state.gdtr.base);
   vmcs_dirty(vm_state.gdtr.limit);
   return VM_DONE;
}
Example #3
0
/*
** Hardware exec traps are checked before
** insn execution. But hardware data, i/o
** and single-step traps are checked after.
**
** If we emulated an insn, we may loose
** a #DB condition, so take care here.
**
** We do not inject #DB, we use pending db
*/
static int vmx_db_check_pending_any()
{
   if(!__vmexit_on_insn())
   {
#ifdef CONFIG_VMX_DB_DBG
      if(vm_state.rflags.tf)
      {
         vmcs_read(vm_state.activity);
         vmcs_read(vm_state.interrupt);
         debug(VMX_DB,
               "TF is set, pending #DB: be:%d bs:%d sti:%d mss:%d activity:0x%x\n"
               ,vm_state.dbg_excp.be, vm_state.dbg_excp.bs
               ,vm_state.interrupt.sti, vm_state.interrupt.mss
               ,vm_state.activity.raw);
      }
#endif
      return VM_IGNORE;
   }

   if(vmx_db_check_pending_stp() == VM_DONE)
   {
      debug(VMX_DB, "pending #DB: set stp\n");
      vm_state.dbg_excp.bs = 1;
      vmcs_dirty(vm_state.dbg_excp);
   }

   /* XXX: missing data/io */

   return VM_DONE;
}
Example #4
0
void __vmx_clear_event_injection()
{
   if(!vm_entry_ctrls.int_info.v)
      return;

   if(vm_entry_ctrls.int_info.type == VMCS_EVT_INFO_TYPE_HW_EXCP &&
      vm_entry_ctrls.int_info.vector == PF_EXCP)
      vmcs_clear(vm_state.cr2);

   vm_entry_ctrls.int_info.v = 0;
   vmcs_dirty(vm_entry_ctrls.int_info);
}
Example #5
0
static int __vmx_vmexit_lidt(dt_reg_t *dt_reg)
{
   if(vmx_cpl)
      return VM_FAIL;

   debug(VMX_DT, "lidt 0x%X:0x%x\n", dt_reg->base.raw, dt_reg->limit);

   if(info->vm.idt_limit != dt_reg->limit)
      info->vm.idt_limit = dt_reg->limit;

   vm_state.idtr.base.raw = dt_reg->base.raw;
   vmcs_dirty(vm_state.idtr.base);
   return VM_DONE;
}
Example #6
0
/*
** Hardware exec traps are checked before
** insn execution. But hardware data, i/o
** and single-step traps are checked after.
**
** If we emulated an insn, we may loose
** a #DB condition, so take care here.
**
** We do not inject #DB, we use pending db
*/
static int vmx_db_check_pending_any()
{
   if(!__vmexit_on_insn())
      return VM_IGNORE;

   /* XXX: missing data/io */
   if(vmx_db_check_pending_stp() == VM_DONE)
   {
      vm_state.dbg_excp.bs = 1;
      vmcs_dirty(vm_state.dbg_excp);
   }

   return VM_DONE;
}
Example #7
0
 void vmx_vmcs_dirty_entry()
{
   vmcs_dirty(vm_entry_ctrls.msr_load_addr);
   vmcs_dirty(vm_entry_ctrls.entry);
   vmcs_dirty(vm_entry_ctrls.msr_load_count);
   vmcs_dirty(vm_entry_ctrls.int_info);
   vmcs_dirty(vm_entry_ctrls.err_code);
   vmcs_dirty(vm_entry_ctrls.insn_len);
}
Example #8
0
static int __vmx_vmexit_resolve_msr_sysenter_cs(uint8_t wr)
{
   if(wr)
   {
      vm_state.ia32_sysenter_cs.raw = info->vm.cpu.gpr->rax.low;
      vmcs_dirty(vm_state.ia32_sysenter_cs);
   }
   else
   {
      vmcs_read(vm_state.ia32_sysenter_cs);
      info->vm.cpu.gpr->rax.low = vm_state.ia32_sysenter_cs.raw;
   }

   return VM_DONE;
}
Example #9
0
static int __vmx_vmexit_resolve_msr_perf(uint8_t wr)
{
   if(wr)
   {
      vm_state.ia32_perf.low  = info->vm.cpu.gpr->rax.low;
      vm_state.ia32_perf.high = info->vm.cpu.gpr->rdx.low;
      vmcs_dirty(vm_state.ia32_perf);
   }
   else
   {
      vmcs_read(vm_state.ia32_perf);
      info->vm.cpu.gpr->rax.low = vm_state.ia32_perf.low;
      info->vm.cpu.gpr->rdx.low = vm_state.ia32_perf.high;
   }

   return VM_DONE;
}
Example #10
0
static int __vmx_vmexit_resolve_msr_dbgctl(uint8_t wr)
{
   if(wr)
   {
      vm_state.ia32_dbgctl.low  = info->vm.cpu.gpr->rax.low;
      vm_state.ia32_dbgctl.high = info->vm.cpu.gpr->rdx.low;
      /* check in vmx_check_dbgctl() */
      vmcs_dirty(vm_state.ia32_dbgctl);
   }
   else
   {
      vmcs_read(vm_state.ia32_dbgctl);
      info->vm.cpu.gpr->rax.low = vm_state.ia32_dbgctl.low;
      info->vm.cpu.gpr->rdx.low = vm_state.ia32_dbgctl.high;
   }

   return VM_DONE;
}
Example #11
0
static void vmx_vmexit_post_hdl(raw64_t tsc)
{
   vmx_db_check_pending();

   if(controller() & (VM_FAIL|VM_FAULT))
      vmx_vmexit_failure();

   vmx_check_dbgctl();

   vm_state.rsp.raw = info->vm.cpu.gpr->rsp.raw;
   vmcs_dirty(vm_state.rsp);

   info->vm.cpu.emu_sts = EMU_STS_AVL;

   info->vmm.ctrl.vmexit_cnt.raw++;
   vmx_vmexit_tsc_rebase(tsc);

   vmx_vmcs_commit(info);
}
Example #12
0
/*
** Vol. 3C-32.2 (Virtualization of System Resources)
*/
void vmx_check_dbgctl()
{
   vmcs_read(vm_state.activity);
   vmcs_read(vm_state.interrupt);

#ifdef CONFIG_VMX_DB_DBG
   vmcs_read(vm_state.dbg_excp);

   if(vm_state.dbg_excp.be || vm_state.dbg_excp.bs)
      debug(VMX_DB, "pending #DB: be:%d bs:%d 0x%X\n"
            ,vm_state.dbg_excp.be, vm_state.dbg_excp.bs
            ,vm_state.dbg_excp.raw);
#endif

   if(!vm_state.interrupt.sti && !vm_state.interrupt.mss &&
      vm_state.activity.raw != VMX_VMCS_GUEST_ACTIVITY_STATE_HALT)
      return;

#ifdef CONFIG_VMX_DB_DBG
   debug(VMX_DB, "pending #DB: sti:%d mss:%d activity:0x%x\n"
         ,vm_state.interrupt.sti, vm_state.interrupt.mss
         ,vm_state.activity.raw);
#endif

   vmcs_read(vm_state.ia32_dbgctl);
   vmcs_read(vm_state.dbg_excp);

   if(vm_state.rflags.tf && !vm_state.ia32_dbgctl.btf)
   {
      debug(VMX_DB, "pending #DB (sti/mss/hlt): set sstep\n");
      vm_state.dbg_excp.bs = 1;
   }
   else if(vm_state.dbg_excp.bs)
   {
      debug(VMX_DB, "pending #DB (sti/mss/hlt): clr sstep\n");
      vm_state.dbg_excp.bs = 0;
   }

   vmcs_dirty(vm_state.dbg_excp);
}
Example #13
0
/*
** Vol. 3C-32.2 (Virtualization of System Resources)
*/
void vmx_check_dbgctl()
{
   vmcs_read(vm_state.activity);
   vmcs_read(vm_state.interrupt);

   if(!vm_state.interrupt.sti && !vm_state.interrupt.mss &&
      vm_state.activity.raw != VMX_VMCS_GUEST_ACTIVITY_STATE_HALT)
      return;

   vmcs_read(vm_state.ia32_dbgctl);
   vmcs_read(vm_state.dbg_excp);

   if(vm_state.rflags.tf && !vm_state.ia32_dbgctl.btf)
   {
      debug(VMX_DB, "setting pending #DB for sstep\n");
      vm_state.dbg_excp.bs = 1;
   }

   if(!vm_state.rflags.tf || vm_state.ia32_dbgctl.btf)
      vm_state.dbg_excp.bs = 0;

   vmcs_dirty(vm_state.dbg_excp);
}
Example #14
0
int vmx_vmexit_idt_deliver()
{
   vmcs_read(vm_exit_info.idt_info);

   if(!vm_exit_info.idt_info.v)
   {
      vmcs_read(vm_exit_info.int_info);

      if(vm_exit_info.int_info.nmi && vm_exit_info.int_info.vector != DF_EXCP)
      {
	 vmcs_read(vm_state.interrupt);
	 vm_state.interrupt.nmi = 1;
	 vmcs_dirty(vm_state.interrupt);
      }

      return VM_DONE;
   }

   if(__rmode())
      return __vmx_vmexit_idt_deliver_rmode();

   return __vmx_vmexit_idt_deliver_pmode();
}
Example #15
0
static int __vmx_vmexit_resolve_msr_efer(uint8_t wr)
{
   if(wr)
   {
      ia32_efer_msr_t update;

      update.low = info->vm.efer.low ^ info->vm.cpu.gpr->rax.low;

      info->vm.efer.low  = info->vm.cpu.gpr->rax.low;
      info->vm.efer.high = info->vm.cpu.gpr->rdx.low;

      vm_state.ia32_efer.low  = info->vm.efer.low;
      vm_state.ia32_efer.high = info->vm.efer.high;

      vmcs_read(vm_entry_ctrls.entry);
      vm_state.ia32_efer.lme = vm_state.ia32_efer.lma = vm_entry_ctrls.entry.ia32e;
      vmcs_dirty(vm_state.ia32_efer);

      if(info->vm.efer.lma && !info->vm.efer.lme)
	 info->vm.efer.lma = 0;

      if(update.lme && __cr0.pg)
      {
	 debug(VMX_MSR, "modifying LME while paging-on #GP\n");
	 __inject_exception(GP_EXCP, 0, 0);
	 return VM_FAULT;
      }
   }
   else
   {
      info->vm.cpu.gpr->rax.low = info->vm.efer.low;
      info->vm.cpu.gpr->rdx.low = info->vm.efer.high;
   }

   return VM_DONE;
}
Example #16
0
int __vmx_vmexit_idt_deliver_pmode()
{
   vmcs_read(vm_entry_ctrls.int_info);

   /*
   ** cpu was delivering
   ** we have nothing to inject
   ** so we resume delivering
   */
   if(!vm_entry_ctrls.int_info.v)
   {
      debug(VMX_IDT, "idt[0x%x:%d] eax 0x%x\n"
	    ,vm_exit_info.idt_info.vector
	    ,vm_exit_info.idt_info.type
	    ,info->vm.cpu.gpr->rax.low);

      if(vm_exit_info.idt_info.type == VMCS_EVT_INFO_TYPE_SW_INT)
      {
	 vm_entry_ctrls.insn_len.raw = 2;
	 vmcs_dirty(vm_entry_ctrls.insn_len);
      }

      if(vm_exit_info.idt_info.v_err)
      {
	 vmcs_read(vm_exit_info.idt_err_code);
	 vm_entry_ctrls.err_code.raw = vm_exit_info.idt_err_code.raw;
	 vmcs_dirty(vm_entry_ctrls.err_code);
      }

      /*
      ** - interrupt shadow
      ** - read 31.7.1.1 reflecting exceptions to guest software
      */
      debug_warning();

      vm_entry_ctrls.int_info.raw = vm_exit_info.idt_info.raw;
      vm_entry_ctrls.int_info.r = 0; /* take care of reserved bits */
      vmcs_dirty(vm_entry_ctrls.int_info);

      return VM_DONE;
   }

   debug(VMX_IDT, "already injecting: %d (%d)\n"
	 ,vm_entry_ctrls.int_info.vector, vm_entry_ctrls.int_info.type);

   /*
   ** cpu was delivering
   ** we have something to inject
   */
/*    /\* exception (to be injected) while delivering exception *\/ */
/*    if(vm_exit_info.idt_info.type  == VMCS_EVT_INFO_TYPE_HW_EXCP && */
/*       vm_entry_ctrls.int_info.type == VMCS_EVT_INFO_TYPE_HW_EXCP) */
/*    { */
/*       uint8_t e1 = vm_exit_info.idt_info.vector; */
/*       uint8_t e2 = vm_entry_ctrls.int_info.vector; */

/*       if(triple_fault(e1)) */
/*       { */
/* 	 debug(VMX, "triple-fault\n"); */
/* 	 return VM_FAIL; */
/*       } */

/*       if(double_fault(e1, e2)) */
/*       { */
/* 	 debug(VMX, "double-fault: %d raised while %d\n", e2, e1); */
/* 	 return __vmx_vmexit_inject_exception(DOUBLEFAULT_EXCEPTION, 0, 0); */
/*       } */

/*       /\* handled serially *\/ */
/*       debug(VMX_IDT, "handle serially: deliver(%d:%d)/inject(%d:%d)\n" */
/* 	    , vm_exit_info.idt_info.type, vm_exit_info.idt_info.vector */
/* 	    , vm_entry_ctrls.int_info.type, vm_entry_ctrls.int_info.vector); */
/*       return VM_DONE; */
/*    } */

/* /\* */
/*    if(vm_exit_info.idt_info.type  == VMCS_EVT_INFORMATION_TYPE_HW_INT && */
/*        vm_entry_ctrls.int_info.type == VMCS_EVT_INFORMATION_TYPE_HW_EXCP) */
/*    { */
/*    } */
/* *\/ */

   debug(VMX_IDT, "idt deliver PM: unhandled scenario\n");
   return VM_FAIL;
}
Example #17
0
void vmx_vmcs_dirty_guest()
{
   vmcs_dirty(vm_state.es.selector);
   vmcs_dirty(vm_state.cs.selector);
   vmcs_dirty(vm_state.ss.selector);
   vmcs_dirty(vm_state.ds.selector);
   vmcs_dirty(vm_state.fs.selector);
   vmcs_dirty(vm_state.gs.selector);
   vmcs_dirty(vm_state.ldtr.selector);
   vmcs_dirty(vm_state.tr.selector);

   vmcs_dirty(vm_state.vmcs_link_ptr);
   vmcs_dirty(vm_state.ia32_dbgctl);

   if(vm_entry_ctrls.entry.load_ia32_pat)
      vmcs_dirty(vm_state.ia32_pat);

   if(vm_entry_ctrls.entry.load_ia32_efer)
      vmcs_dirty(vm_state.ia32_efer);

   if(vm_entry_ctrls.entry.load_ia32_perf)
      vmcs_dirty(vm_state.ia32_perf);

   vmcs_dirty(vm_state.pdpe_0);
   vmcs_dirty(vm_state.pdpe_1);
   vmcs_dirty(vm_state.pdpe_2);
   vmcs_dirty(vm_state.pdpe_3);

   vmcs_dirty(vm_state.es.limit);
   vmcs_dirty(vm_state.cs.limit);
   vmcs_dirty(vm_state.ss.limit);
   vmcs_dirty(vm_state.ds.limit);
   vmcs_dirty(vm_state.fs.limit);
   vmcs_dirty(vm_state.gs.limit);
   vmcs_dirty(vm_state.ldtr.limit);
   vmcs_dirty(vm_state.tr.limit);
   vmcs_dirty(vm_state.gdtr.limit);
   vmcs_dirty(vm_state.idtr.limit);
   vmcs_dirty(vm_state.es.attributes);
   vmcs_dirty(vm_state.cs.attributes);
   vmcs_dirty(vm_state.ss.attributes);
   vmcs_dirty(vm_state.ds.attributes);
   vmcs_dirty(vm_state.fs.attributes);
   vmcs_dirty(vm_state.gs.attributes);
   vmcs_dirty(vm_state.ldtr.attributes);
   vmcs_dirty(vm_state.tr.attributes);
   vmcs_dirty(vm_state.interrupt);
   vmcs_dirty(vm_state.activity);
#ifdef CONFIG_VMX_FEAT_VMCS_SMBASE
   vmcs_dirty(vm_state.smbase);
#endif
   vmcs_dirty(vm_state.ia32_sysenter_cs);

   if(info->vm.vmx_fx_pin.allow_1.preempt)
      vmcs_dirty(vm_state.preempt_timer);

   vmx_set_fixed(vm_state.cr0.low, info->vm.vmx_fx_cr0);
   vmcs_dirty(vm_state.cr0);
   vmcs_dirty(vm_state.cr3);
   vmx_set_fixed(vm_state.cr4.low, info->vm.vmx_fx_cr4);
   vmcs_dirty(vm_state.cr4);
   vmcs_dirty(vm_state.es.base);
   vmcs_dirty(vm_state.cs.base);
   vmcs_dirty(vm_state.ss.base);
   vmcs_dirty(vm_state.ds.base);
   vmcs_dirty(vm_state.fs.base);
   vmcs_dirty(vm_state.gs.base);
   vmcs_dirty(vm_state.tr.base);
   vmcs_dirty(vm_state.ldtr.base);
   vmcs_dirty(vm_state.gdtr.base);
   vmcs_dirty(vm_state.idtr.base);
   vmcs_dirty(vm_state.dr7);
   vmcs_dirty(vm_state.rsp);
   vmcs_dirty(vm_state.rip);
   vmcs_dirty(vm_state.rflags);
   vmcs_dirty(vm_state.dbg_excp);
   vmcs_dirty(vm_state.ia32_sysenter_esp);
   vmcs_dirty(vm_state.ia32_sysenter_eip);

   /* Fake fields */
   vmcs_dirty(vm_state.cr2);
   vmcs_dirty(vm_state.dr6);
}
Example #18
0
void vmx_vmcs_dirty_exec()
{
   vmcs_dirty(vm_exec_ctrls.vpid);
   vmcs_dirty(vm_exec_ctrls.io_bitmap_a);
   vmcs_dirty(vm_exec_ctrls.io_bitmap_b);
   vmcs_dirty(vm_exec_ctrls.msr_bitmap);

#ifdef CONFIG_VMX_FEAT_VMCS_EXEC_PTR
   vmcs_dirty(vm_exec_ctrls.executive_vmcs_ptr);
#endif
   vmcs_dirty(vm_exec_ctrls.tsc_offset);

   if(info->vm.vmx_fx_proc.allow_1.tprs)
      vmcs_dirty(vm_exec_ctrls.vapic_addr);

   if(info->vm.vmx_fx_proc2.allow_1.vapic)
      vmcs_dirty(vm_exec_ctrls.apic_addr);

   vmcs_dirty(vm_exec_ctrls.eptp);
   vmcs_dirty(vm_exec_ctrls.pin);
   vmcs_dirty(vm_exec_ctrls.proc);
   vmcs_dirty(vm_exec_ctrls.excp_bitmap);
   vmcs_dirty(vm_exec_ctrls.pagefault_err_code_mask);
   vmcs_dirty(vm_exec_ctrls.pagefault_err_code_match);
   vmcs_dirty(vm_exec_ctrls.cr3_target_count);

   vmcs_dirty(vm_exec_ctrls.tpr_threshold);
   vmcs_dirty(vm_exec_ctrls.proc2);

   /* vmcs_dirty(vm_exec_ctrls.ple_gap); */
   /* vmcs_dirty(vm_exec_ctrls.ple_win); */

   vmcs_dirty(vm_exec_ctrls.cr0_mask);
   vmcs_dirty(vm_exec_ctrls.cr4_mask);
   vmcs_dirty(vm_exec_ctrls.cr0_read_shadow);
   vmcs_dirty(vm_exec_ctrls.cr4_read_shadow);
   vmcs_dirty(vm_exec_ctrls.cr3_target_0);
   vmcs_dirty(vm_exec_ctrls.cr3_target_1);
   vmcs_dirty(vm_exec_ctrls.cr3_target_2);
   vmcs_dirty(vm_exec_ctrls.cr3_target_3);
}