@@ -2892,12 +2892,18 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
28922892 vmx -> nested .nested_vmx_vmcs_enum = 0x2e ;
28932893}
28942894
2895+ /*
2896+ * if fixed0[i] == 1: val[i] must be 1
2897+ * if fixed1[i] == 0: val[i] must be 0
2898+ */
2899+ static inline bool fixed_bits_valid (u64 val , u64 fixed0 , u64 fixed1 )
2900+ {
2901+ return ((val & fixed1 ) | fixed0 ) == val ;
2902+ }
2903+
28952904static inline bool vmx_control_verify (u32 control , u32 low , u32 high )
28962905{
2897- /*
2898- * Bits 0 in high must be 0, and bits 1 in low must be 1.
2899- */
2900- return ((control & high ) | low ) == control ;
2906+ return fixed_bits_valid (control , low , high );
29012907}
29022908
29032909static inline u64 vmx_control_msr (u32 low , u32 high )
@@ -4132,6 +4138,40 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
41324138 (unsigned long * )& vcpu -> arch .regs_dirty );
41334139}
41344140
4141+ static bool nested_guest_cr0_valid (struct kvm_vcpu * vcpu , unsigned long val )
4142+ {
4143+ u64 fixed0 = to_vmx (vcpu )-> nested .nested_vmx_cr0_fixed0 ;
4144+ u64 fixed1 = to_vmx (vcpu )-> nested .nested_vmx_cr0_fixed1 ;
4145+ struct vmcs12 * vmcs12 = get_vmcs12 (vcpu );
4146+
4147+ if (to_vmx (vcpu )-> nested .nested_vmx_secondary_ctls_high &
4148+ SECONDARY_EXEC_UNRESTRICTED_GUEST &&
4149+ nested_cpu_has2 (vmcs12 , SECONDARY_EXEC_UNRESTRICTED_GUEST ))
4150+ fixed0 &= ~(X86_CR0_PE | X86_CR0_PG );
4151+
4152+ return fixed_bits_valid (val , fixed0 , fixed1 );
4153+ }
4154+
4155+ static bool nested_host_cr0_valid (struct kvm_vcpu * vcpu , unsigned long val )
4156+ {
4157+ u64 fixed0 = to_vmx (vcpu )-> nested .nested_vmx_cr0_fixed0 ;
4158+ u64 fixed1 = to_vmx (vcpu )-> nested .nested_vmx_cr0_fixed1 ;
4159+
4160+ return fixed_bits_valid (val , fixed0 , fixed1 );
4161+ }
4162+
4163+ static bool nested_cr4_valid (struct kvm_vcpu * vcpu , unsigned long val )
4164+ {
4165+ u64 fixed0 = to_vmx (vcpu )-> nested .nested_vmx_cr4_fixed0 ;
4166+ u64 fixed1 = to_vmx (vcpu )-> nested .nested_vmx_cr4_fixed1 ;
4167+
4168+ return fixed_bits_valid (val , fixed0 , fixed1 );
4169+ }
4170+
4171+ /* No difference in the restrictions on guest and host CR4 in VMX operation. */
4172+ #define nested_guest_cr4_valid nested_cr4_valid
4173+ #define nested_host_cr4_valid nested_cr4_valid
4174+
41354175static int vmx_set_cr4 (struct kvm_vcpu * vcpu , unsigned long cr4 );
41364176
41374177static void ept_update_paging_mode_cr0 (unsigned long * hw_cr0 ,
@@ -4260,8 +4300,8 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
42604300 if (!nested_vmx_allowed (vcpu ))
42614301 return 1 ;
42624302 }
4263- if ( to_vmx ( vcpu ) -> nested . vmxon &&
4264- (( cr4 & VMXON_CR4_ALWAYSON ) != VMXON_CR4_ALWAYSON ))
4303+
4304+ if ( to_vmx ( vcpu ) -> nested . vmxon && ! nested_cr4_valid ( vcpu , cr4 ))
42654305 return 1 ;
42664306
42674307 vcpu -> arch .cr4 = cr4 ;
@@ -5826,18 +5866,6 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
58265866 hypercall [2 ] = 0xc1 ;
58275867}
58285868
5829- static bool nested_cr0_valid (struct kvm_vcpu * vcpu , unsigned long val )
5830- {
5831- unsigned long always_on = VMXON_CR0_ALWAYSON ;
5832- struct vmcs12 * vmcs12 = get_vmcs12 (vcpu );
5833-
5834- if (to_vmx (vcpu )-> nested .nested_vmx_secondary_ctls_high &
5835- SECONDARY_EXEC_UNRESTRICTED_GUEST &&
5836- nested_cpu_has2 (vmcs12 , SECONDARY_EXEC_UNRESTRICTED_GUEST ))
5837- always_on &= ~(X86_CR0_PE | X86_CR0_PG );
5838- return (val & always_on ) == always_on ;
5839- }
5840-
58415869/* called to set cr0 as appropriate for a mov-to-cr0 exit. */
58425870static int handle_set_cr0 (struct kvm_vcpu * vcpu , unsigned long val )
58435871{
@@ -5856,7 +5884,7 @@ static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
58565884 val = (val & ~vmcs12 -> cr0_guest_host_mask ) |
58575885 (vmcs12 -> guest_cr0 & vmcs12 -> cr0_guest_host_mask );
58585886
5859- if (!nested_cr0_valid (vcpu , val ))
5887+ if (!nested_guest_cr0_valid (vcpu , val ))
58605888 return 1 ;
58615889
58625890 if (kvm_set_cr0 (vcpu , val ))
@@ -5865,8 +5893,9 @@ static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
58655893 return 0 ;
58665894 } else {
58675895 if (to_vmx (vcpu )-> nested .vmxon &&
5868- (( val & VMXON_CR0_ALWAYSON ) != VMXON_CR0_ALWAYSON ))
5896+ ! nested_host_cr0_valid ( vcpu , val ))
58695897 return 1 ;
5898+
58705899 return kvm_set_cr0 (vcpu , val );
58715900 }
58725901}
@@ -10325,15 +10354,15 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
1032510354 goto out ;
1032610355 }
1032710356
10328- if ((( vmcs12 -> host_cr0 & VMXON_CR0_ALWAYSON ) != VMXON_CR0_ALWAYSON ) ||
10329- (( vmcs12 -> host_cr4 & VMXON_CR4_ALWAYSON ) != VMXON_CR4_ALWAYSON )) {
10357+ if (! nested_host_cr0_valid ( vcpu , vmcs12 -> host_cr0 ) ||
10358+ ! nested_host_cr4_valid ( vcpu , vmcs12 -> host_cr4 )) {
1033010359 nested_vmx_failValid (vcpu ,
1033110360 VMXERR_ENTRY_INVALID_HOST_STATE_FIELD );
1033210361 goto out ;
1033310362 }
1033410363
10335- if (!nested_cr0_valid (vcpu , vmcs12 -> guest_cr0 ) ||
10336- (( vmcs12 -> guest_cr4 & VMXON_CR4_ALWAYSON ) != VMXON_CR4_ALWAYSON )) {
10364+ if (!nested_guest_cr0_valid (vcpu , vmcs12 -> guest_cr0 ) ||
10365+ ! nested_guest_cr4_valid ( vcpu , vmcs12 -> guest_cr4 )) {
1033710366 nested_vmx_entry_failure (vcpu , vmcs12 ,
1033810367 EXIT_REASON_INVALID_STATE , ENTRY_FAIL_DEFAULT );
1033910368 goto out ;
0 commit comments