vmexit: refine vmexit loop

- move vmexit handling into vmexit_handler
- add error handling, failure will inject #GP

Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Jason Chen CJ 2018-05-22 14:33:13 +08:00 committed by lijinxia
parent 2ff7bf826e
commit 67dfec8799
3 changed files with 34 additions and 21 deletions

View File

@ -156,10 +156,16 @@ static const struct vm_exit_dispatch dispatch_table[] = {
.need_exit_qualification = 1} .need_exit_qualification = 1}
}; };
struct vm_exit_dispatch *vmexit_handler(struct vcpu *vcpu) int vmexit_handler(struct vcpu *vcpu)
{ {
struct vm_exit_dispatch *dispatch = HV_NULL; struct vm_exit_dispatch *dispatch = HV_NULL;
uint16_t basic_exit_reason; uint16_t basic_exit_reason;
int ret;
if ((int)get_cpu_id() != vcpu->pcpu_id) {
pr_fatal("vcpu is not running on its pcpu!");
return -EINVAL;
}
/* Obtain interrupt info */ /* Obtain interrupt info */
vcpu->arch_vcpu.idt_vectoring_info = vcpu->arch_vcpu.idt_vectoring_info =
@ -190,8 +196,19 @@ struct vm_exit_dispatch *vmexit_handler(struct vcpu *vcpu)
/* Update current vcpu in VM that caused vm exit */ /* Update current vcpu in VM that caused vm exit */
vcpu->vm->current_vcpu = vcpu; vcpu->vm->current_vcpu = vcpu;
/* Return pointer to exit dispatch entry */ /* exit dispatch handling */
return dispatch; if (basic_exit_reason == VMX_EXIT_REASON_EXTERNAL_INTERRUPT) {
/* Handling external_interrupt
* should disable intr
*/
ret = dispatch->handler(vcpu);
} else {
CPU_IRQ_ENABLE();
ret = dispatch->handler(vcpu);
CPU_IRQ_DISABLE();
}
return ret;
} }
static int unhandled_vmexit_handler(__unused struct vcpu *vcpu) static int unhandled_vmexit_handler(__unused struct vcpu *vcpu)

View File

@ -53,7 +53,6 @@ void vcpu_thread(struct vcpu *vcpu)
uint64_t vmexit_begin = 0, vmexit_end = 0; uint64_t vmexit_begin = 0, vmexit_end = 0;
uint16_t basic_exit_reason = 0; uint16_t basic_exit_reason = 0;
uint64_t tsc_aux_hyp_cpu = vcpu->pcpu_id; uint64_t tsc_aux_hyp_cpu = vcpu->pcpu_id;
struct vm_exit_dispatch *vmexit_hdlr;
int ret = 0; int ret = 0;
/* If vcpu is not launched, we need to do init_vmcs first */ /* If vcpu is not launched, we need to do init_vmcs first */
@ -97,7 +96,11 @@ void vcpu_thread(struct vcpu *vcpu)
} }
ret = start_vcpu(vcpu); ret = start_vcpu(vcpu);
ASSERT(ret == 0, "vcpu resume failed"); if (ret != 0) {
pr_fatal("vcpu resume failed");
pause_vcpu(vcpu, VCPU_ZOMBIE);
continue;
}
vmexit_begin = rdtsc(); vmexit_begin = rdtsc();
@ -106,28 +109,21 @@ void vcpu_thread(struct vcpu *vcpu)
CPU_MSR_READ(MSR_IA32_TSC_AUX, &vcpu->msr_tsc_aux_guest); CPU_MSR_READ(MSR_IA32_TSC_AUX, &vcpu->msr_tsc_aux_guest);
/* Restore native TSC_AUX */ /* Restore native TSC_AUX */
CPU_MSR_WRITE(MSR_IA32_TSC_AUX, tsc_aux_hyp_cpu); CPU_MSR_WRITE(MSR_IA32_TSC_AUX, tsc_aux_hyp_cpu);
ASSERT((int)get_cpu_id() == vcpu->pcpu_id, "");
/* Dispatch handler */ /* Dispatch handler */
vmexit_hdlr = vmexit_handler(vcpu); ret = vmexit_handler(vcpu);
ASSERT(vmexit_hdlr != 0, if (ret < 0) {
"Unable to dispatch VM exit handler!"); pr_fatal("dispatch VM exit handler failed for reason"
" %d, ret = %d!",
vcpu->arch_vcpu.exit_reason & 0xFFFF, ret);
vcpu_inject_gp(vcpu);
continue;
}
basic_exit_reason = vcpu->arch_vcpu.exit_reason & 0xFFFF; basic_exit_reason = vcpu->arch_vcpu.exit_reason & 0xFFFF;
per_cpu(vmexit_cnt, vcpu->pcpu_id)[basic_exit_reason]++; per_cpu(vmexit_cnt, vcpu->pcpu_id)[basic_exit_reason]++;
TRACE_2L(TRACE_VM_EXIT, basic_exit_reason, TRACE_2L(TRACE_VM_EXIT, basic_exit_reason,
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip); vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip);
if (basic_exit_reason == VMX_EXIT_REASON_EXTERNAL_INTERRUPT) {
/* Handling external_interrupt
* should disable intr
*/
vmexit_hdlr->handler(vcpu);
} else {
CPU_IRQ_ENABLE();
vmexit_hdlr->handler(vcpu);
CPU_IRQ_DISABLE();
}
} while (1); } while (1);
} }

View File

@ -36,7 +36,7 @@ struct vm_exit_dispatch {
uint32_t need_exit_qualification; uint32_t need_exit_qualification;
}; };
struct vm_exit_dispatch *vmexit_handler(struct vcpu *vcpu); int vmexit_handler(struct vcpu *vcpu);
int vmcall_vmexit_handler(struct vcpu *vcpu); int vmcall_vmexit_handler(struct vcpu *vcpu);
int cpuid_vmexit_handler(struct vcpu *vcpu); int cpuid_vmexit_handler(struct vcpu *vcpu);
int cr_access_vmexit_handler(struct vcpu *vcpu); int cr_access_vmexit_handler(struct vcpu *vcpu);