All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: David Matlack <dmatlack@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Ben Gardon <bgardon@google.com>,
	Sean Christopherson <seanjc@google.com>,
	Oliver Upton <oupton@google.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Andrew Jones <drjones@redhat.com>,
	"open list:KERNEL VIRTUAL MACHINE (KVM)" <kvm@vger.kernel.org>
Subject: Re: [PATCH 2/9] KVM: selftests: Add option to create 2M and 1G EPT mappings
Date: Mon, 16 May 2022 16:32:10 -0400	[thread overview]
Message-ID: <YoK0yptPVNqOSlD6@xz-m1.local> (raw)
In-Reply-To: <20220429183935.1094599-3-dmatlack@google.com>

On Fri, Apr 29, 2022 at 06:39:28PM +0000, David Matlack wrote:
> The current EPT mapping code in the selftests only supports mapping 4K
> pages. This commit extends that support with an option to map at 2M or
> 1G. This will be used in a future commit to create large page mappings
> to test eager page splitting.
> 
> No functional change intended.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
>  tools/testing/selftests/kvm/lib/x86_64/vmx.c | 105 ++++++++++---------
>  1 file changed, 57 insertions(+), 48 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
> index d089d8b850b5..1fa2d1059ade 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/vmx.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
> @@ -392,27 +392,60 @@ void nested_vmx_check_supported(void)
>  	}
>  }
>  
> -void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
> -		   uint64_t nested_paddr, uint64_t paddr)
> +static void nested_create_upper_pte(struct kvm_vm *vm,
> +				    struct eptPageTableEntry *pte,
> +				    uint64_t nested_paddr,
> +				    uint64_t paddr,
> +				    int current_level,
> +				    int target_level)
> +{
> +	if (!pte->readable) {
> +		pte->writable = true;
> +		pte->readable = true;
> +		pte->executable = true;
> +		pte->page_size = (current_level == target_level);
> +		if (pte->page_size)
> +			pte->address = paddr >> vm->page_shift;
> +		else
> +			pte->address = vm_alloc_page_table(vm) >> vm->page_shift;
> +	} else {
> +		/*
> +		 * Entry already present.  Assert that the caller doesn't want
> +		 * a hugepage at this level, and that there isn't a hugepage at
> +		 * this level.
> +		 */
> +		TEST_ASSERT(current_level != target_level,
> +			    "Cannot create hugepage at level: %u, nested_paddr: 0x%lx\n",
> +			    current_level, nested_paddr);
> +		TEST_ASSERT(!pte->page_size,
> +			    "Cannot create page table at level: %u, nested_paddr: 0x%lx\n",
> +			    current_level, nested_paddr);
> +	}
> +}
> +
> +
> +void __nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
> +		     uint64_t nested_paddr, uint64_t paddr, int target_level)
>  {
> +	const uint64_t page_size = PG_LEVEL_SIZE(target_level);
> +	struct eptPageTableEntry *pt;
>  	uint16_t index[4];
> -	struct eptPageTableEntry *pml4e;
>  
>  	TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
>  		    "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
>  
> -	TEST_ASSERT((nested_paddr % vm->page_size) == 0,
> +	TEST_ASSERT((nested_paddr % page_size) == 0,
>  		    "Nested physical address not on page boundary,\n"
> -		    "  nested_paddr: 0x%lx vm->page_size: 0x%x",
> -		    nested_paddr, vm->page_size);
> +		    "  nested_paddr: 0x%lx page_size: 0x%lx",
> +		    nested_paddr, page_size);
>  	TEST_ASSERT((nested_paddr >> vm->page_shift) <= vm->max_gfn,
>  		    "Physical address beyond beyond maximum supported,\n"
>  		    "  nested_paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
>  		    paddr, vm->max_gfn, vm->page_size);
> -	TEST_ASSERT((paddr % vm->page_size) == 0,
> +	TEST_ASSERT((paddr % page_size) == 0,
>  		    "Physical address not on page boundary,\n"
> -		    "  paddr: 0x%lx vm->page_size: 0x%x",
> -		    paddr, vm->page_size);
> +		    "  paddr: 0x%lx page_size: 0x%lx",
> +		    paddr, page_size);
>  	TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
>  		    "Physical address beyond beyond maximum supported,\n"
>  		    "  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
> @@ -423,49 +456,25 @@ void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
>  	index[2] = (nested_paddr >> 30) & 0x1ffu;
>  	index[3] = (nested_paddr >> 39) & 0x1ffu;
>  
> -	/* Allocate page directory pointer table if not present. */
> -	pml4e = vmx->eptp_hva;
> -	if (!pml4e[index[3]].readable) {
> -		pml4e[index[3]].address = vm_alloc_page_table(vm) >> vm->page_shift;
> -		pml4e[index[3]].writable = true;
> -		pml4e[index[3]].readable = true;
> -		pml4e[index[3]].executable = true;
> -	}
> +	pt = vmx->eptp_hva;
>  
> -	/* Allocate page directory table if not present. */
> -	struct eptPageTableEntry *pdpe;
> -	pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
> -	if (!pdpe[index[2]].readable) {
> -		pdpe[index[2]].address = vm_alloc_page_table(vm) >> vm->page_shift;
> -		pdpe[index[2]].writable = true;
> -		pdpe[index[2]].readable = true;
> -		pdpe[index[2]].executable = true;
> -	}
> +	for (int current_level = 3; current_level >= 0; current_level--) {
> +		struct eptPageTableEntry *pte = &pt[index[current_level]];
>  
> -	/* Allocate page table if not present. */
> -	struct eptPageTableEntry *pde;
> -	pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
> -	if (!pde[index[1]].readable) {
> -		pde[index[1]].address = vm_alloc_page_table(vm) >> vm->page_shift;
> -		pde[index[1]].writable = true;
> -		pde[index[1]].readable = true;
> -		pde[index[1]].executable = true;
> -	}
> +		nested_create_upper_pte(vm, pte, nested_paddr, paddr,
> +					current_level, target_level);

This is going to run for the last level pte too, so maybe remove the
"upper" prefix in the helper?

>  
> -	/* Fill in page table entry. */
> -	struct eptPageTableEntry *pte;
> -	pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
> -	pte[index[0]].address = paddr >> vm->page_shift;
> -	pte[index[0]].writable = true;
> -	pte[index[0]].readable = true;
> -	pte[index[0]].executable = true;
> +		if (pte->page_size)
> +			break;
>  
> -	/*
> -	 * For now mark these as accessed and dirty because the only
> -	 * testcase we have needs that.  Can be reconsidered later.
> -	 */
> -	pte[index[0]].accessed = true;
> -	pte[index[0]].dirty = true;

Is it intended to to drop the access/dirty bits here?

> +		pt = addr_gpa2hva(vm, pte->address * vm->page_size);
> +	}
> +}
> +
> +void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
> +		   uint64_t nested_paddr, uint64_t paddr)
> +{
> +	__nested_pg_map(vmx, vm, nested_paddr, paddr, PG_LEVEL_4K);
>  }
>  
>  /*
> -- 
> 2.36.0.464.gb9c8b46e94-goog
> 

-- 
Peter Xu


  reply	other threads:[~2022-05-16 20:57 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-29 18:39 [PATCH 0/9] KVM: selftests: Add nested support to dirty_log_perf_test David Matlack
2022-04-29 18:39 ` [PATCH 1/9] KVM: selftests: Replace x86_page_size with raw levels David Matlack
2022-05-13 20:04   ` Peter Xu
2022-05-16 22:38     ` David Matlack
2022-04-29 18:39 ` [PATCH 2/9] KVM: selftests: Add option to create 2M and 1G EPT mappings David Matlack
2022-05-16 20:32   ` Peter Xu [this message]
2022-05-16 22:38     ` David Matlack
2022-04-29 18:39 ` [PATCH 3/9] KVM: selftests: Drop stale function parameter comment for nested_map() David Matlack
2022-05-16 20:32   ` Peter Xu
2022-04-29 18:39 ` [PATCH 4/9] KVM: selftests: Refactor nested_map() to specify target level David Matlack
2022-05-16 20:34   ` Peter Xu
2022-04-29 18:39 ` [PATCH 5/9] KVM: selftests: Move VMX_EPT_VPID_CAP_AD_BITS to vmx.h David Matlack
2022-05-16 22:12   ` Peter Xu
2022-04-29 18:39 ` [PATCH 6/9] KVM: selftests: Add a helper to check EPT/VPID capabilities David Matlack
2022-05-16 20:42   ` Peter Xu
2022-04-29 18:39 ` [PATCH 7/9] KVM: selftests: Link selftests directly with lib object files David Matlack
2022-05-16 22:15   ` Peter Xu
2022-04-29 18:39 ` [PATCH 8/9] KVM: selftests: Clean up LIBKVM files in Makefile David Matlack
2022-05-16 22:15   ` Peter Xu
2022-04-29 18:39 ` [PATCH 9/9] KVM: selftests: Add option to run dirty_log_perf_test vCPUs in L2 David Matlack
2022-05-16 22:17   ` Peter Xu
2022-05-16 22:34     ` David Matlack
2022-05-16 23:42       ` Peter Xu
2022-05-16 23:47         ` David Matlack

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YoK0yptPVNqOSlD6@xz-m1.local \
    --to=peterx@redhat.com \
    --cc=bgardon@google.com \
    --cc=dmatlack@google.com \
    --cc=drjones@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=oupton@google.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=vkuznets@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.