mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 06:51:49 +00:00
hv: optimize run_vcpu() for nested
This patch implements a separate path for L2 VMEntry in run_vcpu(), which has several benefits: - keep run_vcpu() clean, to reduce the number of is_vcpu_in_l2_guest() statements: - current code has three is_vcpu_in_l2_guest() already. - supposed to have another 2 statement so that nested VMEntry won't hit the "Starting vCPU" and "vCPU launched" pr_info() and a few other statements in the VM launch path. - save few other things in run_vcpu() that are not needed for nested. Tracked-On: #6289 Signed-off-by: Zide Chen <zide.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@Intel.com>
This commit is contained in:
parent
0c677fd3b4
commit
e48962faa6
@ -667,79 +667,83 @@ int32_t run_vcpu(struct acrn_vcpu *vcpu)
|
|||||||
write_cached_registers(vcpu);
|
write_cached_registers(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this VCPU is not already launched, launch it */
|
if (is_vcpu_in_l2_guest(vcpu)) {
|
||||||
if (!vcpu->launched) {
|
int32_t launch_type;
|
||||||
pr_info("VM %d Starting VCPU %hu",
|
|
||||||
vcpu->vm->vm_id, vcpu->vcpu_id);
|
|
||||||
|
|
||||||
/* VMX_VPID for l2 guests is not managed in this way */
|
if (vcpu->launched) {
|
||||||
if (!is_vcpu_in_l2_guest(vcpu) && (vcpu->arch.vpid != 0U)) {
|
/* for nested VM-exits that don't need to be reflected to L1 hypervisor */
|
||||||
exec_vmwrite16(VMX_VPID, vcpu->arch.vpid);
|
launch_type = VM_RESUME;
|
||||||
|
} else {
|
||||||
|
/* for VMEntry case, VMCS02 was VMCLEARed by ACRN */
|
||||||
|
launch_type = VM_LAUNCH;
|
||||||
|
vcpu->launched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
status = exec_vmentry(ctx, launch_type, ibrs_type);
|
||||||
* A power-up or a reset invalidates all linear mappings,
|
} else {
|
||||||
* guest-physical mappings, and combined mappings
|
/* If this VCPU is not already launched, launch it */
|
||||||
*/
|
if (!vcpu->launched) {
|
||||||
if (!is_vcpu_in_l2_guest(vcpu)) {
|
pr_info("VM %d Starting VCPU %hu",
|
||||||
|
vcpu->vm->vm_id, vcpu->vcpu_id);
|
||||||
|
|
||||||
|
if (vcpu->arch.vpid != 0U) {
|
||||||
|
exec_vmwrite16(VMX_VPID, vcpu->arch.vpid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A power-up or a reset invalidates all linear mappings,
|
||||||
|
* guest-physical mappings, and combined mappings
|
||||||
|
*/
|
||||||
flush_vpid_global();
|
flush_vpid_global();
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_HYPERV_ENABLED
|
#ifdef CONFIG_HYPERV_ENABLED
|
||||||
if (is_vcpu_bsp(vcpu)) {
|
if (is_vcpu_bsp(vcpu)) {
|
||||||
hyperv_init_time(vcpu->vm);
|
hyperv_init_time(vcpu->vm);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set vcpu launched */
|
/* Set vcpu launched */
|
||||||
vcpu->launched = true;
|
vcpu->launched = true;
|
||||||
|
|
||||||
/* avoid VMCS recycling RSB usage, set IBPB.
|
/* avoid VMCS recycling RSB usage, set IBPB.
|
||||||
* NOTE: this should be done for any time vmcs got switch
|
* NOTE: this should be done for any time vmcs got switch
|
||||||
* currently, there is no other place to do vmcs switch
|
* currently, there is no other place to do vmcs switch
|
||||||
* Please add IBPB set for future vmcs switch case(like trusty)
|
* Please add IBPB set for future vmcs switch case(like trusty)
|
||||||
*/
|
*/
|
||||||
if (ibrs_type == IBRS_RAW) {
|
if (ibrs_type == IBRS_RAW) {
|
||||||
msr_write(MSR_IA32_PRED_CMD, PRED_SET_IBPB);
|
msr_write(MSR_IA32_PRED_CMD, PRED_SET_IBPB);
|
||||||
}
|
|
||||||
|
|
||||||
/* Launch the VM */
|
|
||||||
status = exec_vmentry(ctx, VM_LAUNCH, ibrs_type);
|
|
||||||
|
|
||||||
/* See if VM launched successfully */
|
|
||||||
if (status == 0) {
|
|
||||||
if (is_vcpu_bsp(vcpu)) {
|
|
||||||
pr_info("VM %d VCPU %hu successfully launched",
|
|
||||||
vcpu->vm->vm_id, vcpu->vcpu_id);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
/* Launch the VM */
|
||||||
/* This VCPU was already launched, check if the last guest
|
status = exec_vmentry(ctx, VM_LAUNCH, ibrs_type);
|
||||||
* instruction needs to be repeated and resume VCPU accordingly
|
|
||||||
*/
|
/* See if VM launched successfully */
|
||||||
if (vcpu->arch.inst_len != 0U) {
|
if (status == 0) {
|
||||||
exec_vmwrite(VMX_GUEST_RIP, vcpu_get_rip(vcpu) + vcpu->arch.inst_len);
|
if (is_vcpu_bsp(vcpu)) {
|
||||||
|
pr_info("VM %d VCPU %hu successfully launched",
|
||||||
|
vcpu->vm->vm_id, vcpu->vcpu_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* This VCPU was already launched, check if the last guest
|
||||||
|
* instruction needs to be repeated and resume VCPU accordingly
|
||||||
|
*/
|
||||||
|
if (vcpu->arch.inst_len != 0U) {
|
||||||
|
exec_vmwrite(VMX_GUEST_RIP, vcpu_get_rip(vcpu) + vcpu->arch.inst_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume the VM */
|
||||||
|
status = exec_vmentry(ctx, VM_RESUME, ibrs_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume the VM */
|
|
||||||
status = exec_vmentry(ctx, VM_RESUME, ibrs_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
vcpu->reg_cached = 0UL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* - can not call vcpu_get_xxx() when vmcs02 is current, or it could mess up
|
|
||||||
* the cached registers for the L1 guest
|
|
||||||
* - the L2 guests' vcpu mode is managed by L1 hypervisor
|
|
||||||
* - ctx->cpu_regs.regs.rsp doesn't cache nested guests' RSP
|
|
||||||
*/
|
|
||||||
if (!is_vcpu_in_l2_guest(vcpu)) {
|
|
||||||
cs_attr = exec_vmread32(VMX_GUEST_CS_ATTR);
|
cs_attr = exec_vmread32(VMX_GUEST_CS_ATTR);
|
||||||
ia32_efer = vcpu_get_efer(vcpu);
|
ia32_efer = vcpu_get_efer(vcpu);
|
||||||
cr0 = vcpu_get_cr0(vcpu);
|
cr0 = vcpu_get_cr0(vcpu);
|
||||||
set_vcpu_mode(vcpu, cs_attr, ia32_efer, cr0);
|
set_vcpu_mode(vcpu, cs_attr, ia32_efer, cr0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vcpu->reg_cached = 0UL;
|
||||||
|
|
||||||
/* Obtain current VCPU instruction length */
|
/* Obtain current VCPU instruction length */
|
||||||
vcpu->arch.inst_len = exec_vmread32(VMX_EXIT_INSTR_LEN);
|
vcpu->arch.inst_len = exec_vmread32(VMX_EXIT_INSTR_LEN);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user