Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1441798 > unrolled thread

[PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

Started byBandan Das <bsd@redhat.com>
First post2016-07-13 00:20 +0200
Last post2016-07-14 21:00 +0200
Articles 18 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors Bandan Das <bsd@redhat.com> - 2016-07-13 00:20 +0200
    [PATCH v2 2/5] mmu: don't set the present bit unconditionally Bandan Das <bsd@redhat.com> - 2016-07-13 00:30 +0200
      Re: [PATCH v2 2/5] mmu: don't set the present bit unconditionally Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 10:20 +0200
    [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap Bandan Das <bsd@redhat.com> - 2016-07-13 00:30 +0200
      Re: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in  fault bitmap Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 10:30 +0200
        Re: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in  fault bitmap Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 11:10 +0200
    [PATCH v2 3/5] mmu: remove is_present_gpte() Bandan Das <bsd@redhat.com> - 2016-07-13 00:30 +0200
    [PATCH v2 5/5] vmx: advertise support for ept execute only Bandan Das <bsd@redhat.com> - 2016-07-13 00:30 +0200
    Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 11:30 +0200
      Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Fam Zheng <famz@redhat.com> - 2016-07-13 12:00 +0200
        Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 12:10 +0200
      Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors Bandan Das <bsd@redhat.com> - 2016-07-13 17:10 +0200
        Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Paolo Bonzini <pbonzini@redhat.com> - 2016-07-13 17:30 +0200
          Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors Bandan Das <bsd@redhat.com> - 2016-07-13 17:50 +0200
            Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Paolo Bonzini <pbonzini@redhat.com> - 2016-07-14 09:00 +0200
              Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors Bandan Das <bsd@redhat.com> - 2016-07-14 19:40 +0200
                Re: [PATCH v2 0/5] Add support for EPT execute only for nested  hypervisors Paolo Bonzini <pbonzini@redhat.com> - 2016-07-14 20:30 +0200
                  Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors Bandan Das <bsd@redhat.com> - 2016-07-14 21:00 +0200

#1441798 — [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromBandan Das <bsd@redhat.com>
Date2016-07-13 00:20 +0200
Subject[PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUec2-2Bd-9@gated-at.bofh.it>
v1 of this series posted at https://lkml.org/lkml/2016/6/28/7

Changes since v1:
 - 1/5 : modify is_shadow_present_pte to check against 0xffffffff
   Reasoning provided in commit message.
 - 2/5 : Removed 2/5 from v1 since kvm doesn't use execute only.
   3/5 from v1 is now 2/5. Introduce shadow_present_mask that
   signifies whether ept execute only is supported. Add/remove some
   comments as suggested in v1.
 - 3/5 : 4/5 from v1 is now 3/5.
 - 4/5 : update_permission_bitmask now sets u=1 only if host doesn't
   support ept execute only.
 - 5/5 : No change
 
These patches are based on reviews to my RFC
http://www.spinics.net/lists/kvm/msg134440.html

Changes since RFC:
 - Remove shadow_xonly_valid, it's not needed
 - Remove checks from is_shadow_present_pte()
 - In reset_tdp_shadow_zero_bits_mask, pass correct execonly to __reset_rsvds_bits_mask_ept
 - Reuse shadow_user_mask in set_spte()
 - Remove is_present_gpte() and inline the operation at the two call sites

I spoke to Paolo about this a while back and thought to post this as
RFC while I am thinking of adding some unit tests.

Background: ESX refuses to run as L1 if support for EPT execute only isn't
found. I am not really sure if it uses it for anything since just advertising
the bits seems to work but adding the necessary plumbing seemed like a good idea.

Xiao, I took the liberty of adding you based on "git blame" :)

Thanks in advance.

Bandan Das (5):
  mmu: extend the is_present check to 32 bits
  mmu: don't set the present bit unconditionally
  mmu: remove is_present_gpte()
  mmu: change unconditional setting of the u bit in fault bitmap
  vmx: advertise support for ept execute only

 arch/x86/include/asm/kvm_host.h |  2 +-
 arch/x86/kvm/mmu.c              | 26 ++++++++++++++++++--------
 arch/x86/kvm/mmu.h              |  5 -----
 arch/x86/kvm/paging_tmpl.h      | 10 ++++++++--
 arch/x86/kvm/vmx.c              | 10 ++++++++--
 arch/x86/kvm/x86.c              |  6 +++---
 6 files changed, 38 insertions(+), 21 deletions(-)

-- 
2.5.5

[toc] | [next] | [standalone]


#1441804 — [PATCH v2 2/5] mmu: don't set the present bit unconditionally

FromBandan Das <bsd@redhat.com>
Date2016-07-13 00:30 +0200
Subject[PATCH v2 2/5] mmu: don't set the present bit unconditionally
Message-ID<rUelI-2F3-21@gated-at.bofh.it>
In reply to#1441798
To support execute only mappings on behalf of L1
hypervisors, we teach set_spte() to honor L1's valid XWR
bits. This is only if host supports EPT execute only. Reuse
ACC_USER_MASK to signify if the L1 hypervisor has the R bit
set. Add a new variable "shadow_present_mask" that is
set for non EPT cases and preserves the existing behavior
for those cases.

Signed-off-by: Bandan Das <bsd@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |  2 +-
 arch/x86/kvm/mmu.c              | 15 ++++++++++++---
 arch/x86/kvm/paging_tmpl.h      |  8 +++++++-
 arch/x86/kvm/vmx.c              |  7 +++++--
 arch/x86/kvm/x86.c              |  4 ++--
 5 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 69e62862..c0acc66 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1026,7 +1026,7 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 87b62dc..ae80aa4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -175,6 +175,7 @@ static u64 __read_mostly shadow_user_mask;
 static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
+static u64 __read_mostly shadow_present_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -282,13 +283,14 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
 	shadow_dirty_mask = dirty_mask;
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
+	shadow_present_mask = p_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2515,13 +2517,20 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		    gfn_t gfn, kvm_pfn_t pfn, bool speculative,
 		    bool can_unsync, bool host_writable)
 {
-	u64 spte;
+	u64 spte = 0;
 	int ret = 0;
 
 	if (set_mmio_spte(vcpu, sptep, gfn, pfn, pte_access))
 		return 0;
 
-	spte = PT_PRESENT_MASK;
+	/*
+	 * In the non-EPT case, execonly is not valid and so
+	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
+	 * For the EPT case, shadow_present_mask is 0 if hardware
+	 * supports it and we honor whatever way the guest set it.
+	 * See: FNAME(gpte_access) in paging_tmpl.h
+	 */
+	spte |= shadow_present_mask;
 	if (!speculative)
 		spte |= shadow_accessed_mask;
 
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index bc019f7..f2741db 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -181,13 +181,19 @@ no_present:
 	return true;
 }
 
+/*
+ * For PTTYPE_EPT, a page table can be executable but not readable
+ * on supported processors. Therefore, set_spte does not automatically
+ * set bit 0 if execute only is supported. Here, we repurpose ACC_USER_MASK
+ * to signify readability since it isn't used in the EPT case
+ */
 static inline unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, u64 gpte)
 {
 	unsigned access;
 #if PTTYPE == PTTYPE_EPT
 	access = ((gpte & VMX_EPT_WRITABLE_MASK) ? ACC_WRITE_MASK : 0) |
 		((gpte & VMX_EPT_EXECUTABLE_MASK) ? ACC_EXEC_MASK : 0) |
-		ACC_USER_MASK;
+		((gpte & VMX_EPT_READABLE_MASK) ? ACC_USER_MASK : 0);
 #else
 	BUILD_BUG_ON(ACC_EXEC_MASK != PT_PRESENT_MASK);
 	BUILD_BUG_ON(ACC_EXEC_MASK != 1);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 64a79f2..f73b5dc 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6366,10 +6366,13 @@ static __init int hardware_setup(void)
 	vmx_disable_intercept_msr_write_x2apic(0x83f);
 
 	if (enable_ept) {
-		kvm_mmu_set_mask_ptes(0ull,
+		kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
 			(enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull,
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
-			0ull, VMX_EPT_EXECUTABLE_MASK);
+			0ull, VMX_EPT_EXECUTABLE_MASK,
+			cpu_has_vmx_ept_execute_only() ?
+				      0ull : PT_PRESENT_MASK);
+		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7da5dd2..b15f214 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5867,8 +5867,8 @@ int kvm_arch_init(void *opaque)
 	kvm_x86_ops = ops;
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
-			PT_DIRTY_MASK, PT64_NX_MASK, 0);
-
+			PT_DIRTY_MASK, PT64_NX_MASK, 0,
+			PT_PRESENT_MASK);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1442155 — Re: [PATCH v2 2/5] mmu: don't set the present bit unconditionally

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 10:20 +0200
SubjectRe: [PATCH v2 2/5] mmu: don't set the present bit unconditionally
Message-ID<rUnyG-oj-9@gated-at.bofh.it>
In reply to#1441804

On 13/07/2016 00:18, Bandan Das wrote:
> +	/*
> +	 * In the non-EPT case, execonly is not valid and so
> +	 * the following line is equivalent to spte |= PT_PRESENT_MASK.

I think the comment need not mention non-EPT.

> +	 * For the EPT case, shadow_present_mask is 0 if hardware
> +	 * supports it and we honor whatever way the guest set it.

if hardware supports exec-only page table entries.

> +	 * See: FNAME(gpte_access) in paging_tmpl.h
> +	 */
> +	spte |= shadow_present_mask;
>  	if (!speculative)
>  		spte |= shadow_accessed_mask;
>  
> diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> index bc019f7..f2741db 100644
> --- a/arch/x86/kvm/paging_tmpl.h
> +++ b/arch/x86/kvm/paging_tmpl.h
> @@ -181,13 +181,19 @@ no_present:
>  	return true;
>  }
>  
> +/*
> + * For PTTYPE_EPT, a page table can be executable but not readable
> + * on supported processors. Therefore, set_spte does not automatically
> + * set bit 0 if execute only is supported. Here, we repurpose ACC_USER_MASK
> + * to signify readability since it isn't used in the EPT case
> + */
>  static inline unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, u64 gpte)
>  {
>  	unsigned access;
>  #if PTTYPE == PTTYPE_EPT
>  	access = ((gpte & VMX_EPT_WRITABLE_MASK) ? ACC_WRITE_MASK : 0) |
>  		((gpte & VMX_EPT_EXECUTABLE_MASK) ? ACC_EXEC_MASK : 0) |
> -		ACC_USER_MASK;
> +		((gpte & VMX_EPT_READABLE_MASK) ? ACC_USER_MASK : 0);
>  #else
>  	BUILD_BUG_ON(ACC_EXEC_MASK != PT_PRESENT_MASK);
>  	BUILD_BUG_ON(ACC_EXEC_MASK != 1);
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 64a79f2..f73b5dc 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -6366,10 +6366,13 @@ static __init int hardware_setup(void)
>  	vmx_disable_intercept_msr_write_x2apic(0x83f);
>  
>  	if (enable_ept) {
> -		kvm_mmu_set_mask_ptes(0ull,
> +		kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
>  			(enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull,
>  			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
> -			0ull, VMX_EPT_EXECUTABLE_MASK);
> +			0ull, VMX_EPT_EXECUTABLE_MASK,
> +			cpu_has_vmx_ept_execute_only() ?
> +				      0ull : PT_PRESENT_MASK);

Better to use VMX_EPT_READABLE_MASK here, which removes the need for the
BUILD_BUG_ON.

I can do these changes myself.

Paolo

> +		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);

[toc] | [prev] | [next] | [standalone]


#1441805 — [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap

FromBandan Das <bsd@redhat.com>
Date2016-07-13 00:30 +0200
Subject[PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap
Message-ID<rUelH-2F3-7@gated-at.bofh.it>
In reply to#1441798
For the nested EPT case, we assume that the read bit (u) is
always set since we used to unconditionally set it in set_spte().
Modify it to only be set when host ept execute only support
isn't present.

Signed-off-by: Bandan Das <bsd@redhat.com>
---
 arch/x86/kvm/mmu.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c364dcb..566eea5 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3923,9 +3923,10 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
 				 *   clearer.
 				 */
 				smap = cr4_smap && u && !uf && !ff;
-			} else
-				/* Not really needed: no U/S accesses on ept  */
-				u = 1;
+			} else {
+				if (shadow_present_mask)
+					u = 1;
+			}
 
 			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
 				(smapf && smap);
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1442168 — Re: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 10:30 +0200
SubjectRe: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap
Message-ID<rUnIl-rS-19@gated-at.bofh.it>
In reply to#1441805

On 13/07/2016 00:18, Bandan Das wrote:
> For the nested EPT case, we assume that the read bit (u) is
> always set since we used to unconditionally set it in set_spte().
> Modify it to only be set when host ept execute only support
> isn't present.
> 
> Signed-off-by: Bandan Das <bsd@redhat.com>
> ---
>  arch/x86/kvm/mmu.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index c364dcb..566eea5 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -3923,9 +3923,10 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>  				 *   clearer.
>  				 */
>  				smap = cr4_smap && u && !uf && !ff;
> -			} else
> -				/* Not really needed: no U/S accesses on ept  */
> -				u = 1;
> +			} else {
> +				if (shadow_present_mask)
> +					u = 1;
> +			}
>  
>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
>  				(smapf && smap);
> 

This is needed too, in order to look up with the correct uf:

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 003618e324ce..941d345ebd2c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6014,12 +6014,14 @@ static int handle_ept_violation(struct kvm_vcpu
*vcpu)
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 	trace_kvm_page_fault(gpa, exit_qualification);

-	/* It is a write fault? */
+	/* it is a read fault? */
+	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
+	/* it is a write fault? */
 	error_code = exit_qualification & PFERR_WRITE_MASK;
 	/* It is a fetch fault? */
 	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
 	/* ept page table is present? */
-	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
+	error_code |= (exit_qualification & 0x38) != 0;

 	vcpu->arch.exit_qualification = exit_qualification;


Otherwise you always lookup the permission bitmap for an uf=0 case.
This was the meaning of the "Not really needed" comment.

Paolo

[toc] | [prev] | [next] | [standalone]


#1442242 — Re: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 11:10 +0200
SubjectRe: [PATCH v2 4/5] mmu: change unconditional setting of the u bit in fault bitmap
Message-ID<rUol3-VT-13@gated-at.bofh.it>
In reply to#1442168

On 13/07/2016 10:23, Paolo Bonzini wrote:
> 
> 
> On 13/07/2016 00:18, Bandan Das wrote:
>> For the nested EPT case, we assume that the read bit (u) is
>> always set since we used to unconditionally set it in set_spte().
>> Modify it to only be set when host ept execute only support
>> isn't present.
>>
>> Signed-off-by: Bandan Das <bsd@redhat.com>
>> ---
>>  arch/x86/kvm/mmu.c | 7 ++++---
>>  1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>> index c364dcb..566eea5 100644
>> --- a/arch/x86/kvm/mmu.c
>> +++ b/arch/x86/kvm/mmu.c
>> @@ -3923,9 +3923,10 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>>  				 *   clearer.
>>  				 */
>>  				smap = cr4_smap && u && !uf && !ff;
>> -			} else
>> -				/* Not really needed: no U/S accesses on ept  */
>> -				u = 1;
>> +			} else {
>> +				if (shadow_present_mask)
>> +					u = 1;

... in fact I think this should be removed completely.

If shadow_present_mask is set, the R bit will always be set in a present
PTE and FNAME(gpte_access) will change that to ACC_USER_MASK---which in
turn means that u=1.

Paolo

>> +			}
>>  
>>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
>>  				(smapf && smap);
>>
> 
> This is needed too, in order to look up with the correct uf:
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 003618e324ce..941d345ebd2c 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -6014,12 +6014,14 @@ static int handle_ept_violation(struct kvm_vcpu
> *vcpu)
>  	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>  	trace_kvm_page_fault(gpa, exit_qualification);
> 
> -	/* It is a write fault? */
> +	/* it is a read fault? */
> +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
> +	/* it is a write fault? */
>  	error_code = exit_qualification & PFERR_WRITE_MASK;
>  	/* It is a fetch fault? */
>  	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
>  	/* ept page table is present? */
> -	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
> +	error_code |= (exit_qualification & 0x38) != 0;
> 
>  	vcpu->arch.exit_qualification = exit_qualification;
> 
> 
> Otherwise you always lookup the permission bitmap for an uf=0 case.
> This was the meaning of the "Not really needed" comment.
> 
> Paolo
> 

[toc] | [prev] | [next] | [standalone]


#1441808 — [PATCH v2 3/5] mmu: remove is_present_gpte()

FromBandan Das <bsd@redhat.com>
Date2016-07-13 00:30 +0200
Subject[PATCH v2 3/5] mmu: remove is_present_gpte()
Message-ID<rUelI-2F3-23@gated-at.bofh.it>
In reply to#1441798
We have two versions of the above function.
To prevent confusion and bugs in the future, remove
the non-FNAME version entirely and replace all calls
with the actual check.

Signed-off-by: Bandan Das <bsd@redhat.com>
---
 arch/x86/kvm/mmu.c         | 2 +-
 arch/x86/kvm/mmu.h         | 5 -----
 arch/x86/kvm/paging_tmpl.h | 2 +-
 arch/x86/kvm/x86.c         | 2 +-
 4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index ae80aa4..c364dcb 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3198,7 +3198,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
 		MMU_WARN_ON(VALID_PAGE(root));
 		if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) {
 			pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i);
-			if (!is_present_gpte(pdptr)) {
+			if (!(pdptr & PT_PRESENT_MASK)) {
 				vcpu->arch.mmu.pae_root[i] = 0;
 				continue;
 			}
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 66b33b9..ddc56e9 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -93,11 +93,6 @@ static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
 	return kvm_mmu_load(vcpu);
 }
 
-static inline int is_present_gpte(unsigned long pte)
-{
-	return pte & PT_PRESENT_MASK;
-}
-
 /*
  * Currently, we have two sorts of write-protection, a) the first one
  * write-protects guest page to sync the guest modification, b) another one is
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index f2741db..a011054 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -131,7 +131,7 @@ static inline void FNAME(protect_clean_gpte)(unsigned *access, unsigned gpte)
 static inline int FNAME(is_present_gpte)(unsigned long pte)
 {
 #if PTTYPE != PTTYPE_EPT
-	return is_present_gpte(pte);
+	return pte & PT_PRESENT_MASK;
 #else
 	return pte & 7;
 #endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b15f214..2e8618f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -537,7 +537,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3)
 		goto out;
 	}
 	for (i = 0; i < ARRAY_SIZE(pdpte); ++i) {
-		if (is_present_gpte(pdpte[i]) &&
+		if ((pdpte[i] & PT_PRESENT_MASK) &&
 		    (pdpte[i] &
 		     vcpu->arch.mmu.guest_rsvd_check.rsvd_bits_mask[0][2])) {
 			ret = 0;
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1441809 — [PATCH v2 5/5] vmx: advertise support for ept execute only

FromBandan Das <bsd@redhat.com>
Date2016-07-13 00:30 +0200
Subject[PATCH v2 5/5] vmx: advertise support for ept execute only
Message-ID<rUelI-2F3-29@gated-at.bofh.it>
In reply to#1441798
MMU now knows about execute only mappings, so
advertise the feature to L1 hypervisors

Signed-off-by: Bandan Das <bsd@redhat.com>
---
 arch/x86/kvm/vmx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f73b5dc..2c49355f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2717,6 +2717,9 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
 		vmx->nested.nested_vmx_ept_caps = VMX_EPT_PAGE_WALK_4_BIT |
 			 VMX_EPTP_WB_BIT | VMX_EPT_2MB_PAGE_BIT |
 			 VMX_EPT_INVEPT_BIT;
+		if (cpu_has_vmx_ept_execute_only())
+			vmx->nested.nested_vmx_ept_caps |=
+				VMX_EPT_EXECUTE_ONLY_BIT;
 		vmx->nested.nested_vmx_ept_caps &= vmx_capability.ept;
 		/*
 		 * For nested guests, we don't do anything specific
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1442256 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 11:30 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUoEp-13x-19@gated-at.bofh.it>
In reply to#1441798

On 13/07/2016 00:18, Bandan Das wrote:
> v1 of this series posted at https://lkml.org/lkml/2016/6/28/7
> 
> Changes since v1:
>  - 1/5 : modify is_shadow_present_pte to check against 0xffffffff
>    Reasoning provided in commit message.
>  - 2/5 : Removed 2/5 from v1 since kvm doesn't use execute only.
>    3/5 from v1 is now 2/5. Introduce shadow_present_mask that
>    signifies whether ept execute only is supported. Add/remove some
>    comments as suggested in v1.
>  - 3/5 : 4/5 from v1 is now 3/5.
>  - 4/5 : update_permission_bitmask now sets u=1 only if host doesn't
>    support ept execute only.
>  - 5/5 : No change

These are the diffs I have after review, do they look okay?

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 190c0559c221..bd2535fdb9eb 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2524,11 +2524,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		return 0;
 
 	/*
-	 * In the non-EPT case, execonly is not valid and so
-	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
 	 * For the EPT case, shadow_present_mask is 0 if hardware
-	 * supports it and we honor whatever way the guest set it.
-	 * See: FNAME(gpte_access) in paging_tmpl.h
+	 * supports exec-only page table entries.  In that case,
+	 * ACC_USER_MASK and shadow_user_mask are used to represent
+	 * read access.  See FNAME(gpte_access) in paging_tmpl.h.
 	 */
 	spte |= shadow_present_mask;
 	if (!speculative)
@@ -3923,9 +3922,6 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
 				 *   clearer.
 				 */
 				smap = cr4_smap && u && !uf && !ff;
-			} else {
-				if (shadow_present_mask)
-					u = 1;
 			}
 
 			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 576c47cda1a3..dfef081e76c0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6120,12 +6120,14 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 	trace_kvm_page_fault(gpa, exit_qualification);
 
-	/* It is a write fault? */
+	/* it is a read fault? */
+	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
+	/* it is a write fault? */
 	error_code = exit_qualification & PFERR_WRITE_MASK;
 	/* It is a fetch fault? */
 	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
 	/* ept page table is present? */
-	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
+	error_code |= (exit_qualification & 0x38) != 0;
 
 	vcpu->arch.exit_qualification = exit_qualification;
 
@@ -6474,8 +6476,7 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : PT_PRESENT_MASK);
-		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else

[toc] | [prev] | [next] | [standalone]


#1442280 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromFam Zheng <famz@redhat.com>
Date2016-07-13 12:00 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUp7s-1hq-19@gated-at.bofh.it>
In reply to#1442256
On Wed, 07/13 11:20, Paolo Bonzini wrote:
> 
> 
> On 13/07/2016 00:18, Bandan Das wrote:
> > v1 of this series posted at https://lkml.org/lkml/2016/6/28/7
> > 
> > Changes since v1:
> >  - 1/5 : modify is_shadow_present_pte to check against 0xffffffff
> >    Reasoning provided in commit message.
> >  - 2/5 : Removed 2/5 from v1 since kvm doesn't use execute only.
> >    3/5 from v1 is now 2/5. Introduce shadow_present_mask that
> >    signifies whether ept execute only is supported. Add/remove some
> >    comments as suggested in v1.
> >  - 3/5 : 4/5 from v1 is now 3/5.
> >  - 4/5 : update_permission_bitmask now sets u=1 only if host doesn't
> >    support ept execute only.
> >  - 5/5 : No change
> 
> These are the diffs I have after review, do they look okay?
> 
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 190c0559c221..bd2535fdb9eb 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -2524,11 +2524,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
>  		return 0;
>  
>  	/*
> -	 * In the non-EPT case, execonly is not valid and so
> -	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
>  	 * For the EPT case, shadow_present_mask is 0 if hardware
> -	 * supports it and we honor whatever way the guest set it.
> -	 * See: FNAME(gpte_access) in paging_tmpl.h
> +	 * supports exec-only page table entries.  In that case,
> +	 * ACC_USER_MASK and shadow_user_mask are used to represent
> +	 * read access.  See FNAME(gpte_access) in paging_tmpl.h.
>  	 */
>  	spte |= shadow_present_mask;
>  	if (!speculative)
> @@ -3923,9 +3922,6 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>  				 *   clearer.
>  				 */
>  				smap = cr4_smap && u && !uf && !ff;
> -			} else {
> -				if (shadow_present_mask)
> -					u = 1;
>  			}
>  
>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 576c47cda1a3..dfef081e76c0 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -6120,12 +6120,14 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
>  	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>  	trace_kvm_page_fault(gpa, exit_qualification);
>  
> -	/* It is a write fault? */
> +	/* it is a read fault? */
> +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
> +	/* it is a write fault? */
>  	error_code = exit_qualification & PFERR_WRITE_MASK;

Did you mean s/=/|=/ for this line?

Fam

>  	/* It is a fetch fault? */
>  	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
>  	/* ept page table is present? */
> -	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
> +	error_code |= (exit_qualification & 0x38) != 0;
>  
>  	vcpu->arch.exit_qualification = exit_qualification;
>  
> @@ -6474,8 +6476,7 @@ static __init int hardware_setup(void)
>  			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
>  			0ull, VMX_EPT_EXECUTABLE_MASK,
>  			cpu_has_vmx_ept_execute_only() ?
> -				      0ull : PT_PRESENT_MASK);
> -		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
> +				      0ull : VMX_EPT_READABLE_MASK);
>  		ept_set_mmio_spte_mask();
>  		kvm_enable_tdp();
>  	} else
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[toc] | [prev] | [next] | [standalone]


#1442288 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 12:10 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUph8-1FZ-19@gated-at.bofh.it>
In reply to#1442280

On 13/07/2016 11:49, Fam Zheng wrote:
> > +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
> > +	/* it is a write fault? */
> >  	error_code = exit_qualification & PFERR_WRITE_MASK;
>
> Did you mean s/=/|=/ for this line?

Ugh, yes.

[toc] | [prev] | [next] | [standalone]


#1442537

FromBandan Das <bsd@redhat.com>
Date2016-07-13 17:10 +0200
Message-ID<rUtXs-4Ju-23@gated-at.bofh.it>
In reply to#1442256
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 13/07/2016 00:18, Bandan Das wrote:
>> v1 of this series posted at https://lkml.org/lkml/2016/6/28/7
>> 
>> Changes since v1:
>>  - 1/5 : modify is_shadow_present_pte to check against 0xffffffff
>>    Reasoning provided in commit message.
>>  - 2/5 : Removed 2/5 from v1 since kvm doesn't use execute only.
>>    3/5 from v1 is now 2/5. Introduce shadow_present_mask that
>>    signifies whether ept execute only is supported. Add/remove some
>>    comments as suggested in v1.
>>  - 3/5 : 4/5 from v1 is now 3/5.
>>  - 4/5 : update_permission_bitmask now sets u=1 only if host doesn't
>>    support ept execute only.
>>  - 5/5 : No change
>
> These are the diffs I have after review, do they look okay?
>
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 190c0559c221..bd2535fdb9eb 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -2524,11 +2524,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
>  		return 0;
>  
>  	/*
> -	 * In the non-EPT case, execonly is not valid and so
> -	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
>  	 * For the EPT case, shadow_present_mask is 0 if hardware
> -	 * supports it and we honor whatever way the guest set it.
> -	 * See: FNAME(gpte_access) in paging_tmpl.h
> +	 * supports exec-only page table entries.  In that case,
> +	 * ACC_USER_MASK and shadow_user_mask are used to represent
> +	 * read access.  See FNAME(gpte_access) in paging_tmpl.h.
>  	 */

I would still prefer a note about the non-EPT case, makes it easy to
understand.

>  	spte |= shadow_present_mask;
>  	if (!speculative)
> @@ -3923,9 +3922,6 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>  				 *   clearer.
>  				 */
>  				smap = cr4_smap && u && !uf && !ff;
> -			} else {
> -				if (shadow_present_mask)
> -					u = 1;
>  			}
>  
>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 576c47cda1a3..dfef081e76c0 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -6120,12 +6120,14 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
>  	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>  	trace_kvm_page_fault(gpa, exit_qualification);
>  
> -	/* It is a write fault? */
> +	/* it is a read fault? */
> +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
> +	/* it is a write fault? */
>  	error_code = exit_qualification & PFERR_WRITE_MASK;
>  	/* It is a fetch fault? */
>  	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
>  	/* ept page table is present? */
> -	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
> +	error_code |= (exit_qualification & 0x38) != 0;
>

Thank you for the thorough review here. I missed that we didn't set the read bit
at all. I am still a little unclear how permission_fault works though...


>  	vcpu->arch.exit_qualification = exit_qualification;
>  
> @@ -6474,8 +6476,7 @@ static __init int hardware_setup(void)
>  			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
>  			0ull, VMX_EPT_EXECUTABLE_MASK,
>  			cpu_has_vmx_ept_execute_only() ?
> -				      0ull : PT_PRESENT_MASK);
> -		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
> +				      0ull : VMX_EPT_READABLE_MASK);

I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
is an assumption all throughout. I wanted to use this section to catch mismatches.

Bandan

>  		ept_set_mmio_spte_mask();
>  		kvm_enable_tdp();
>  	} else

[toc] | [prev] | [next] | [standalone]


#1442553 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-13 17:30 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUugP-4RD-35@gated-at.bofh.it>
In reply to#1442537

On 13/07/2016 17:06, Bandan Das wrote:
>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>> index 190c0559c221..bd2535fdb9eb 100644
>> --- a/arch/x86/kvm/mmu.c
>> +++ b/arch/x86/kvm/mmu.c
>> @@ -2524,11 +2524,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
>>  		return 0;
>>  
>>  	/*
>> -	 * In the non-EPT case, execonly is not valid and so
>> -	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
>>  	 * For the EPT case, shadow_present_mask is 0 if hardware
>> -	 * supports it and we honor whatever way the guest set it.
>> -	 * See: FNAME(gpte_access) in paging_tmpl.h
>> +	 * supports exec-only page table entries.  In that case,
>> +	 * ACC_USER_MASK and shadow_user_mask are used to represent
>> +	 * read access.  See FNAME(gpte_access) in paging_tmpl.h.
>>  	 */
> 
> I would still prefer a note about the non-EPT case, makes it easy to
> understand.

I can add "shadow_present_mask is PT_PRESENT_MASK in the non-EPT case"
but it's a bit of a tautology.

>>  	spte |= shadow_present_mask;
>>  	if (!speculative)
>> @@ -3923,9 +3922,6 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>>  				 *   clearer.
>>  				 */
>>  				smap = cr4_smap && u && !uf && !ff;
>> -			} else {
>> -				if (shadow_present_mask)
>> -					u = 1;
>>  			}
>>  
>>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index 576c47cda1a3..dfef081e76c0 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -6120,12 +6120,14 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
>>  	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>>  	trace_kvm_page_fault(gpa, exit_qualification);
>>  
>> -	/* It is a write fault? */
>> +	/* it is a read fault? */
>> +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
>> +	/* it is a write fault? */
>>  	error_code = exit_qualification & PFERR_WRITE_MASK;
>>  	/* It is a fetch fault? */
>>  	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
>>  	/* ept page table is present? */
>> -	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
>> +	error_code |= (exit_qualification & 0x38) != 0;
>>
> 
> Thank you for the thorough review here. I missed that we didn't set the read bit
> at all. I am still a little unclear how permission_fault works though...
> 
>>  	vcpu->arch.exit_qualification = exit_qualification;
>>  
>> @@ -6474,8 +6476,7 @@ static __init int hardware_setup(void)
>>  			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
>>  			0ull, VMX_EPT_EXECUTABLE_MASK,
>>  			cpu_has_vmx_ept_execute_only() ?
>> -				      0ull : PT_PRESENT_MASK);
>> -		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
>> +				      0ull : VMX_EPT_READABLE_MASK);
> 
> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
> is an assumption all throughout. I wanted to use this section to catch mismatches.

I think there's no such assumption anymore, actually.  Can you double
check?  If there are any, that's where the BUILD_BUG_ON should be.

Paolo

[toc] | [prev] | [next] | [standalone]


#1442567

FromBandan Das <bsd@redhat.com>
Date2016-07-13 17:50 +0200
Message-ID<rUuA9-4Zu-11@gated-at.bofh.it>
In reply to#1442553
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 13/07/2016 17:06, Bandan Das wrote:
>>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>>> index 190c0559c221..bd2535fdb9eb 100644
>>> --- a/arch/x86/kvm/mmu.c
>>> +++ b/arch/x86/kvm/mmu.c
>>> @@ -2524,11 +2524,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
>>>  		return 0;
>>>  
>>>  	/*
>>> -	 * In the non-EPT case, execonly is not valid and so
>>> -	 * the following line is equivalent to spte |= PT_PRESENT_MASK.
>>>  	 * For the EPT case, shadow_present_mask is 0 if hardware
>>> -	 * supports it and we honor whatever way the guest set it.
>>> -	 * See: FNAME(gpte_access) in paging_tmpl.h
>>> +	 * supports exec-only page table entries.  In that case,
>>> +	 * ACC_USER_MASK and shadow_user_mask are used to represent
>>> +	 * read access.  See FNAME(gpte_access) in paging_tmpl.h.
>>>  	 */
>> 
>> I would still prefer a note about the non-EPT case, makes it easy to
>> understand.
>
> I can add "shadow_present_mask is PT_PRESENT_MASK in the non-EPT case"
> but it's a bit of a tautology.

shadow_present_mask actually signifies different things for ept/non-ept
cases and it doesn't hurt to mention it. But I get your point, maybe,
it's self-explanatory.

>>>  	spte |= shadow_present_mask;
>>>  	if (!speculative)
>>> @@ -3923,9 +3922,6 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
>>>  				 *   clearer.
>>>  				 */
>>>  				smap = cr4_smap && u && !uf && !ff;
>>> -			} else {
>>> -				if (shadow_present_mask)
>>> -					u = 1;
>>>  			}
>>>  
>>>  			fault = (ff && !x) || (uf && !u) || (wf && !w) ||
>>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>>> index 576c47cda1a3..dfef081e76c0 100644
>>> --- a/arch/x86/kvm/vmx.c
>>> +++ b/arch/x86/kvm/vmx.c
>>> @@ -6120,12 +6120,14 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
>>>  	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
>>>  	trace_kvm_page_fault(gpa, exit_qualification);
>>>  
>>> -	/* It is a write fault? */
>>> +	/* it is a read fault? */
>>> +	error_code = (exit_qualification << 2) & PFERR_USER_MASK;
>>> +	/* it is a write fault? */
>>>  	error_code = exit_qualification & PFERR_WRITE_MASK;
>>>  	/* It is a fetch fault? */
>>>  	error_code |= (exit_qualification << 2) & PFERR_FETCH_MASK;
>>>  	/* ept page table is present? */
>>> -	error_code |= (exit_qualification >> 3) & PFERR_PRESENT_MASK;
>>> +	error_code |= (exit_qualification & 0x38) != 0;
>>>
>> 
>> Thank you for the thorough review here. I missed that we didn't set the read bit
>> at all. I am still a little unclear how permission_fault works though...
>> 
>>>  	vcpu->arch.exit_qualification = exit_qualification;
>>>  
>>> @@ -6474,8 +6476,7 @@ static __init int hardware_setup(void)
>>>  			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
>>>  			0ull, VMX_EPT_EXECUTABLE_MASK,
>>>  			cpu_has_vmx_ept_execute_only() ?
>>> -				      0ull : PT_PRESENT_MASK);
>>> -		BUILD_BUG_ON(PT_PRESENT_MASK != VMX_EPT_READABLE_MASK);
>>> +				      0ull : VMX_EPT_READABLE_MASK);
>> 
>> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
>> is an assumption all throughout. I wanted to use this section to catch mismatches.
>
> I think there's no such assumption anymore, actually.  Can you double
> check?  If there are any, that's where the BUILD_BUG_ON should be.

What I meant is how they are the same bit.  is_shadow_present_pte() is probably one
and another one is link_shadow_page() which already has a BUILD_BUG_ON().

> Paolo

[toc] | [prev] | [next] | [standalone]


#1443110 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-14 09:00 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUIMO-64Y-13@gated-at.bofh.it>
In reply to#1442567

On 13/07/2016 17:47, Bandan Das wrote:
>>> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
>>> is an assumption all throughout. I wanted to use this section to catch mismatches.
>>
>> I think there's no such assumption anymore, actually.  Can you double
>> check?  If there are any, that's where the BUILD_BUG_ON should be.
> 
> What I meant is how they are the same bit.  is_shadow_present_pte() is probably one
> and another one is link_shadow_page() which already has a BUILD_BUG_ON().

You're right about link_shadow_page()!  We probably should change the
PT_PRESENT_MASK to shadow_present_mask there (and then readability in
the EPT execonly case is still provided by shadow_user_mask).

For is_shadow_present_pte() you have removed it in patch 1 though.

Paolo

[toc] | [prev] | [next] | [standalone]


#1443631

FromBandan Das <bsd@redhat.com>
Date2016-07-14 19:40 +0200
Message-ID<rUSMa-4cH-27@gated-at.bofh.it>
In reply to#1443110
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 13/07/2016 17:47, Bandan Das wrote:
>>>> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
>>>> is an assumption all throughout. I wanted to use this section to catch mismatches.
>>>
>>> I think there's no such assumption anymore, actually.  Can you double
>>> check?  If there are any, that's where the BUILD_BUG_ON should be.
>> 
>> What I meant is how they are the same bit.  is_shadow_present_pte() is probably one
>> and another one is link_shadow_page() which already has a BUILD_BUG_ON().
>
> You're right about link_shadow_page()!  We probably should change the
> PT_PRESENT_MASK to shadow_present_mask there (and then readability in
> the EPT execonly case is still provided by shadow_user_mask).

Makes sense. Would you like a new version with that added or can that be a
separate patch ?

> For is_shadow_present_pte() you have removed it in patch 1 though.

Right. But the assumption is still that is_shadow_present_pte() works because
EPT_READABLE and PT_PRESENT are the same.

> Paolo

[toc] | [prev] | [next] | [standalone]


#1443666 — Re: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors

FromPaolo Bonzini <pbonzini@redhat.com>
Date2016-07-14 20:30 +0200
SubjectRe: [PATCH v2 0/5] Add support for EPT execute only for nested hypervisors
Message-ID<rUTyy-4Je-43@gated-at.bofh.it>
In reply to#1443631

On 14/07/2016 19:38, Bandan Das wrote:
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
>> On 13/07/2016 17:47, Bandan Das wrote:
>>>>> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
>>>>> is an assumption all throughout. I wanted to use this section to catch mismatches.
>>>>
>>>> I think there's no such assumption anymore, actually.  Can you double
>>>> check?  If there are any, that's where the BUILD_BUG_ON should be.
>>>
>>> What I meant is how they are the same bit.  is_shadow_present_pte() is probably one
>>> and another one is link_shadow_page() which already has a BUILD_BUG_ON().
>>
>> You're right about link_shadow_page()!  We probably should change the
>> PT_PRESENT_MASK to shadow_present_mask there (and then readability in
>> the EPT execonly case is still provided by shadow_user_mask).
> 
> Makes sense. Would you like a new version with that added or can that be a
> separate patch ?

I've already done it and pushed it to kvm/next. :)

>> For is_shadow_present_pte() you have removed it in patch 1 though.
> 
> Right. But the assumption is still that is_shadow_present_pte() works because
> EPT_READABLE and PT_PRESENT are the same.

is_shadow_present_pte() tests 0xFFFFFFFF, so it does not depend on bit 0
alone, for neither EPT nor "normal" page tables.

Paolo

[toc] | [prev] | [next] | [standalone]


#1443701

FromBandan Das <bsd@redhat.com>
Date2016-07-14 21:00 +0200
Message-ID<rUU1A-4Tq-29@gated-at.bofh.it>
In reply to#1443666
Paolo Bonzini <pbonzini@redhat.com> writes:

> On 14/07/2016 19:38, Bandan Das wrote:
>> Paolo Bonzini <pbonzini@redhat.com> writes:
>> 
>>> On 13/07/2016 17:47, Bandan Das wrote:
>>>>>> I wanted to keep it the former way because "PT_PRESENT_MASK is equal to VMX_EPT_READABLE_MASK"
>>>>>> is an assumption all throughout. I wanted to use this section to catch mismatches.
>>>>>
>>>>> I think there's no such assumption anymore, actually.  Can you double
>>>>> check?  If there are any, that's where the BUILD_BUG_ON should be.
>>>>
>>>> What I meant is how they are the same bit.  is_shadow_present_pte() is probably one
>>>> and another one is link_shadow_page() which already has a BUILD_BUG_ON().
>>>
>>> You're right about link_shadow_page()!  We probably should change the
>>> PT_PRESENT_MASK to shadow_present_mask there (and then readability in
>>> the EPT execonly case is still provided by shadow_user_mask).
>> 
>> Makes sense. Would you like a new version with that added or can that be a
>> separate patch ?
>
> I've already done it and pushed it to kvm/next. :)

Ah, thank you!

>>> For is_shadow_present_pte() you have removed it in patch 1 though.
>> 
>> Right. But the assumption is still that is_shadow_present_pte() works because
>> EPT_READABLE and PT_PRESENT are the same.
>
> is_shadow_present_pte() tests 0xFFFFFFFF, so it does not depend on bit 0
> alone, for neither EPT nor "normal" page tables.

Yeah... Let me rephrase, is_shadow_present_pte works because the assumption
is that both of the bits are in the first 32 bits :) You proved me wrong though,
this assumption does not mean a BUILD_BUG for the equal condition is required here.

Bandan

> Paolo

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web