Unverified Commit f096b3cd authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files
parents bad6743b 419ae6ed
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -4917,24 +4917,35 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
		| FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX;

	/*
	 * Note, KVM cannot rely on hardware to perform the CR0/CR4 #UD checks
	 * that have higher priority than VM-Exit (see Intel SDM's pseudocode
	 * for VMXON), as KVM must load valid CR0/CR4 values into hardware while
	 * running the guest, i.e. KVM needs to check the _guest_ values.
	 * Manually check CR4.VMXE checks, KVM must force CR4.VMXE=1 to enter
	 * the guest and so cannot rely on hardware to perform the check,
	 * which has higher priority than VM-Exit (see Intel SDM's pseudocode
	 * for VMXON).
	 *
	 * Rely on hardware for the other two pre-VM-Exit checks, !VM86 and
	 * !COMPATIBILITY modes.  KVM may run the guest in VM86 to emulate Real
	 * Mode, but KVM will never take the guest out of those modes.
	 * Rely on hardware for the other pre-VM-Exit checks, CR0.PE=1, !VM86
	 * and !COMPATIBILITY modes.  For an unrestricted guest, KVM doesn't
	 * force any of the relevant guest state.  For a restricted guest, KVM
	 * does force CR0.PE=1, but only to also force VM86 in order to emulate
	 * Real Mode, and so there's no need to check CR0.PE manually.
	 */
	if (!nested_host_cr0_valid(vcpu, kvm_read_cr0(vcpu)) ||
	    !nested_host_cr4_valid(vcpu, kvm_read_cr4(vcpu))) {
	if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) {
		kvm_queue_exception(vcpu, UD_VECTOR);
		return 1;
	}

	/*
	 * CPL=0 and all other checks that are lower priority than VM-Exit must
	 * be checked manually.
	 * The CPL is checked for "not in VMX operation" and for "in VMX root",
	 * and has higher priority than the VM-Fail due to being post-VMXON,
	 * i.e. VMXON #GPs outside of VMX non-root if CPL!=0.  In VMX non-root,
	 * VMXON causes VM-Exit and KVM unconditionally forwards VMXON VM-Exits
	 * from L2 to L1, i.e. there's no need to check for the vCPU being in
	 * VMX non-root.
	 *
	 * Forwarding the VM-Exit unconditionally, i.e. without performing the
	 * #UD checks (see above), is functionally ok because KVM doesn't allow
	 * L1 to run L2 without CR4.VMXE=0, and because KVM never modifies L2's
	 * CR0 or CR4, i.e. it's L2's responsibility to emulate #UDs that are
	 * missed by hardware due to shadowing CR0 and/or CR4.
	 */
	if (vmx_get_cpl(vcpu)) {
		kvm_inject_gp(vcpu, 0);
@@ -4944,6 +4955,17 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
	if (vmx->nested.vmxon)
		return nested_vmx_fail(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);

	/*
	 * Invalid CR0/CR4 generates #GP.  These checks are performed if and
	 * only if the vCPU isn't already in VMX operation, i.e. effectively
	 * have lower priority than the VM-Fail above.
	 */
	if (!nested_host_cr0_valid(vcpu, kvm_read_cr0(vcpu)) ||
	    !nested_host_cr4_valid(vcpu, kvm_read_cr4(vcpu))) {
		kvm_inject_gp(vcpu, 0);
		return 1;
	}

	if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
			!= VMXON_NEEDED_FEATURES) {
		kvm_inject_gp(vcpu, 0);