Message ID | 20191216213901.106941-5-bgardon@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Create a userfaultfd demand paging test | expand |
On Mon, Dec 16, 2019 at 01:38:57PM -0800, Ben Gardon wrote: > Add an argument to allow the demand paging test to work on larger and > smaller guest sizes. > > Signed-off-by: Ben Gardon <bgardon@google.com> > --- > .../selftests/kvm/demand_paging_test.c | 56 ++++++++++++------- > 1 file changed, 35 insertions(+), 21 deletions(-) > > diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c > index 11de5b58995fb..4aa90a3fce99c 100644 > --- a/tools/testing/selftests/kvm/demand_paging_test.c > +++ b/tools/testing/selftests/kvm/demand_paging_test.c > @@ -32,6 +32,8 @@ > /* Default guest test virtual memory offset */ > #define DEFAULT_GUEST_TEST_MEM 0xc0000000 > > +#define DEFAULT_GUEST_TEST_MEM_SIZE (1 << 30) /* 1G */ > + > /* > * Guest/Host shared variables. Ensure addr_gva2hva() and/or > * sync_global_to/from_guest() are used when accessing from > @@ -264,11 +266,10 @@ static int setup_demand_paging(struct kvm_vm *vm, > return 0; > } > > -#define GUEST_MEM_SHIFT 30 /* 1G */ > #define PAGE_SHIFT_4K 12 > > static void run_test(enum vm_guest_mode mode, bool use_uffd, > - useconds_t uffd_delay) > + useconds_t uffd_delay, uint64_t guest_memory_bytes) > { > pthread_t vcpu_thread; > pthread_t uffd_handler_thread; > @@ -276,33 +277,40 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd, > int r; > > /* > - * We reserve page table for 2 times of extra dirty mem which > - * will definitely cover the original (1G+) test range. Here > - * we do the calculation with 4K page size which is the > - * smallest so the page number will be enough for all archs > - * (e.g., 64K page size guest will need even less memory for > - * page tables). > + * We reserve page table for twice the ammount of memory we intend > + * to use in the test region for demand paging. Here we do the > + * calculation with 4K page size which is the smallest so the page > + * number will be enough for all archs. (e.g., 64K page size guest > + * will need even less memory for page tables). > */ > vm = create_vm(mode, VCPU_ID, > - 2ul << (GUEST_MEM_SHIFT - PAGE_SHIFT_4K), > + (2 * guest_memory_bytes) >> PAGE_SHIFT_4K, > guest_code); > > guest_page_size = vm_get_page_size(vm); > - /* > - * A little more than 1G of guest page sized pages. Cover the > - * case where the size is not aligned to 64 pages. > - */ > - guest_num_pages = (1ul << (GUEST_MEM_SHIFT - > - vm_get_page_shift(vm))) + 16; > + > + TEST_ASSERT(guest_memory_bytes % guest_page_size == 0, > + "Guest memory size is not guest page size aligned."); > + > + guest_num_pages = guest_memory_bytes / guest_page_size; > + > #ifdef __s390x__ > /* Round up to multiple of 1M (segment size) */ > guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; > #endif > + /* > + * If there should be more memory in the guest test region than there > + * can be pages in the guest, it will definitely cause problems. > + */ > + TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm), > + "Requested more guest memory than address space allows.\n" > + " guest pages: %lx max gfn: %lx\n", > + guest_num_pages, vm_get_max_gfn(vm)); > > host_page_size = getpagesize(); > - host_num_pages = (guest_num_pages * guest_page_size) / host_page_size + > - !!((guest_num_pages * guest_page_size) % > - host_page_size); > + TEST_ASSERT(guest_memory_bytes % host_page_size == 0, > + "Guest memory size is not host page size aligned."); > + host_num_pages = guest_memory_bytes / host_page_size; > > guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) * > guest_page_size; > @@ -381,7 +389,8 @@ static void help(char *name) > int i; > > puts(""); > - printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n", name); > + printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n" > + " [-b bytes test memory]\n", name); > printf(" -m: specify the guest mode ID to test\n" > " (default: test all supported modes)\n" > " This option may be used multiple times.\n" > @@ -395,6 +404,8 @@ static void help(char *name) > printf(" -d: add a delay in usec to the User Fault\n" > " FD handler to simulate demand paging\n" > " overheads. Ignored without -u.\n"); > + printf(" -b: specify the number of bytes of memory which should be\n" > + " allocated to the guest.\n"); Can we input in megabytes instead? And also it might be nice to output the default size here. > puts(""); > exit(0); > } > @@ -402,6 +413,7 @@ static void help(char *name) > int main(int argc, char *argv[]) > { > bool mode_selected = false; > + uint64_t guest_memory_bytes = DEFAULT_GUEST_TEST_MEM_SIZE; > unsigned int mode; > int opt, i; > bool use_uffd = false; > @@ -414,7 +426,7 @@ int main(int argc, char *argv[]) > vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); > #endif > > - while ((opt = getopt(argc, argv, "hm:ud:")) != -1) { > + while ((opt = getopt(argc, argv, "hm:ud:b:")) != -1) { > switch (opt) { > case 'm': > if (!mode_selected) { > @@ -435,6 +447,8 @@ int main(int argc, char *argv[]) > TEST_ASSERT(uffd_delay >= 0, > "A negative UFFD delay is not supported."); > break; > + case 'b': > + guest_memory_bytes = strtoull(optarg, NULL, 0); Missing break. So it doesn't look like this was tested. > case 'h': > default: > help(argv[0]); > @@ -448,7 +462,7 @@ int main(int argc, char *argv[]) > TEST_ASSERT(vm_guest_mode_params[i].supported, > "Guest mode ID %d (%s) not supported.", > i, vm_guest_mode_string(i)); > - run_test(i, use_uffd, uffd_delay); > + run_test(i, use_uffd, uffd_delay, guest_memory_bytes); > } > > return 0; > -- > 2.24.1.735.g03f4e72817-goog > Thanks, drew
On Tue, Jan 7, 2020 at 7:02 AM Andrew Jones <drjones@redhat.com> wrote: > > On Mon, Dec 16, 2019 at 01:38:57PM -0800, Ben Gardon wrote: > > Add an argument to allow the demand paging test to work on larger and > > smaller guest sizes. > > > > Signed-off-by: Ben Gardon <bgardon@google.com> > > --- > > .../selftests/kvm/demand_paging_test.c | 56 ++++++++++++------- > > 1 file changed, 35 insertions(+), 21 deletions(-) > > > > diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c > > index 11de5b58995fb..4aa90a3fce99c 100644 > > --- a/tools/testing/selftests/kvm/demand_paging_test.c > > +++ b/tools/testing/selftests/kvm/demand_paging_test.c > > @@ -32,6 +32,8 @@ > > /* Default guest test virtual memory offset */ > > #define DEFAULT_GUEST_TEST_MEM 0xc0000000 > > > > +#define DEFAULT_GUEST_TEST_MEM_SIZE (1 << 30) /* 1G */ > > + > > /* > > * Guest/Host shared variables. Ensure addr_gva2hva() and/or > > * sync_global_to/from_guest() are used when accessing from > > @@ -264,11 +266,10 @@ static int setup_demand_paging(struct kvm_vm *vm, > > return 0; > > } > > > > -#define GUEST_MEM_SHIFT 30 /* 1G */ > > #define PAGE_SHIFT_4K 12 > > > > static void run_test(enum vm_guest_mode mode, bool use_uffd, > > - useconds_t uffd_delay) > > + useconds_t uffd_delay, uint64_t guest_memory_bytes) > > { > > pthread_t vcpu_thread; > > pthread_t uffd_handler_thread; > > @@ -276,33 +277,40 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd, > > int r; > > > > /* > > - * We reserve page table for 2 times of extra dirty mem which > > - * will definitely cover the original (1G+) test range. Here > > - * we do the calculation with 4K page size which is the > > - * smallest so the page number will be enough for all archs > > - * (e.g., 64K page size guest will need even less memory for > > - * page tables). > > + * We reserve page table for twice the ammount of memory we intend > > + * to use in the test region for demand paging. Here we do the > > + * calculation with 4K page size which is the smallest so the page > > + * number will be enough for all archs. (e.g., 64K page size guest > > + * will need even less memory for page tables). > > */ > > vm = create_vm(mode, VCPU_ID, > > - 2ul << (GUEST_MEM_SHIFT - PAGE_SHIFT_4K), > > + (2 * guest_memory_bytes) >> PAGE_SHIFT_4K, > > guest_code); > > > > guest_page_size = vm_get_page_size(vm); > > - /* > > - * A little more than 1G of guest page sized pages. Cover the > > - * case where the size is not aligned to 64 pages. > > - */ > > - guest_num_pages = (1ul << (GUEST_MEM_SHIFT - > > - vm_get_page_shift(vm))) + 16; > > + > > + TEST_ASSERT(guest_memory_bytes % guest_page_size == 0, > > + "Guest memory size is not guest page size aligned."); > > + > > + guest_num_pages = guest_memory_bytes / guest_page_size; > > + > > #ifdef __s390x__ > > /* Round up to multiple of 1M (segment size) */ > > guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; > > #endif > > + /* > > + * If there should be more memory in the guest test region than there > > + * can be pages in the guest, it will definitely cause problems. > > + */ > > + TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm), > > + "Requested more guest memory than address space allows.\n" > > + " guest pages: %lx max gfn: %lx\n", > > + guest_num_pages, vm_get_max_gfn(vm)); > > > > host_page_size = getpagesize(); > > - host_num_pages = (guest_num_pages * guest_page_size) / host_page_size + > > - !!((guest_num_pages * guest_page_size) % > > - host_page_size); > > + TEST_ASSERT(guest_memory_bytes % host_page_size == 0, > > + "Guest memory size is not host page size aligned."); > > + host_num_pages = guest_memory_bytes / host_page_size; > > > > guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) * > > guest_page_size; > > @@ -381,7 +389,8 @@ static void help(char *name) > > int i; > > > > puts(""); > > - printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n", name); > > + printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n" > > + " [-b bytes test memory]\n", name); > > printf(" -m: specify the guest mode ID to test\n" > > " (default: test all supported modes)\n" > > " This option may be used multiple times.\n" > > @@ -395,6 +404,8 @@ static void help(char *name) > > printf(" -d: add a delay in usec to the User Fault\n" > > " FD handler to simulate demand paging\n" > > " overheads. Ignored without -u.\n"); > > + printf(" -b: specify the number of bytes of memory which should be\n" > > + " allocated to the guest.\n"); > > Can we input in megabytes instead? And also it might be nice to output the > default size here. I added a little function to parse size arguments so users can specify 2M or 7G. I also changed this to print the default value. > > > puts(""); > > exit(0); > > } > > @@ -402,6 +413,7 @@ static void help(char *name) > > int main(int argc, char *argv[]) > > { > > bool mode_selected = false; > > + uint64_t guest_memory_bytes = DEFAULT_GUEST_TEST_MEM_SIZE; > > unsigned int mode; > > int opt, i; > > bool use_uffd = false; > > @@ -414,7 +426,7 @@ int main(int argc, char *argv[]) > > vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); > > #endif > > > > - while ((opt = getopt(argc, argv, "hm:ud:")) != -1) { > > + while ((opt = getopt(argc, argv, "hm:ud:b:")) != -1) { > > switch (opt) { > > case 'm': > > if (!mode_selected) { > > @@ -435,6 +447,8 @@ int main(int argc, char *argv[]) > > TEST_ASSERT(uffd_delay >= 0, > > "A negative UFFD delay is not supported."); > > break; > > + case 'b': > > + guest_memory_bytes = strtoull(optarg, NULL, 0); > > Missing break. So it doesn't look like this was tested. Woops, you're right, I must not have tested this commit. The break is added in commit 6/8 and I only tested at the end of the series. I'll have the break in this commit in the next version of this series. > > > case 'h': > > default: > > help(argv[0]); > > @@ -448,7 +462,7 @@ int main(int argc, char *argv[]) > > TEST_ASSERT(vm_guest_mode_params[i].supported, > > "Guest mode ID %d (%s) not supported.", > > i, vm_guest_mode_string(i)); > > - run_test(i, use_uffd, uffd_delay); > > + run_test(i, use_uffd, uffd_delay, guest_memory_bytes); > > } > > > > return 0; > > -- > > 2.24.1.735.g03f4e72817-goog > > > > Thanks, > drew >
diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c index 11de5b58995fb..4aa90a3fce99c 100644 --- a/tools/testing/selftests/kvm/demand_paging_test.c +++ b/tools/testing/selftests/kvm/demand_paging_test.c @@ -32,6 +32,8 @@ /* Default guest test virtual memory offset */ #define DEFAULT_GUEST_TEST_MEM 0xc0000000 +#define DEFAULT_GUEST_TEST_MEM_SIZE (1 << 30) /* 1G */ + /* * Guest/Host shared variables. Ensure addr_gva2hva() and/or * sync_global_to/from_guest() are used when accessing from @@ -264,11 +266,10 @@ static int setup_demand_paging(struct kvm_vm *vm, return 0; } -#define GUEST_MEM_SHIFT 30 /* 1G */ #define PAGE_SHIFT_4K 12 static void run_test(enum vm_guest_mode mode, bool use_uffd, - useconds_t uffd_delay) + useconds_t uffd_delay, uint64_t guest_memory_bytes) { pthread_t vcpu_thread; pthread_t uffd_handler_thread; @@ -276,33 +277,40 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd, int r; /* - * We reserve page table for 2 times of extra dirty mem which - * will definitely cover the original (1G+) test range. Here - * we do the calculation with 4K page size which is the - * smallest so the page number will be enough for all archs - * (e.g., 64K page size guest will need even less memory for - * page tables). + * We reserve page table for twice the ammount of memory we intend + * to use in the test region for demand paging. Here we do the + * calculation with 4K page size which is the smallest so the page + * number will be enough for all archs. (e.g., 64K page size guest + * will need even less memory for page tables). */ vm = create_vm(mode, VCPU_ID, - 2ul << (GUEST_MEM_SHIFT - PAGE_SHIFT_4K), + (2 * guest_memory_bytes) >> PAGE_SHIFT_4K, guest_code); guest_page_size = vm_get_page_size(vm); - /* - * A little more than 1G of guest page sized pages. Cover the - * case where the size is not aligned to 64 pages. - */ - guest_num_pages = (1ul << (GUEST_MEM_SHIFT - - vm_get_page_shift(vm))) + 16; + + TEST_ASSERT(guest_memory_bytes % guest_page_size == 0, + "Guest memory size is not guest page size aligned."); + + guest_num_pages = guest_memory_bytes / guest_page_size; + #ifdef __s390x__ /* Round up to multiple of 1M (segment size) */ guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; #endif + /* + * If there should be more memory in the guest test region than there + * can be pages in the guest, it will definitely cause problems. + */ + TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm), + "Requested more guest memory than address space allows.\n" + " guest pages: %lx max gfn: %lx\n", + guest_num_pages, vm_get_max_gfn(vm)); host_page_size = getpagesize(); - host_num_pages = (guest_num_pages * guest_page_size) / host_page_size + - !!((guest_num_pages * guest_page_size) % - host_page_size); + TEST_ASSERT(guest_memory_bytes % host_page_size == 0, + "Guest memory size is not host page size aligned."); + host_num_pages = guest_memory_bytes / host_page_size; guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) * guest_page_size; @@ -381,7 +389,8 @@ static void help(char *name) int i; puts(""); - printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n", name); + printf("usage: %s [-h] [-m mode] [-u] [-d uffd_delay_usec]\n" + " [-b bytes test memory]\n", name); printf(" -m: specify the guest mode ID to test\n" " (default: test all supported modes)\n" " This option may be used multiple times.\n" @@ -395,6 +404,8 @@ static void help(char *name) printf(" -d: add a delay in usec to the User Fault\n" " FD handler to simulate demand paging\n" " overheads. Ignored without -u.\n"); + printf(" -b: specify the number of bytes of memory which should be\n" + " allocated to the guest.\n"); puts(""); exit(0); } @@ -402,6 +413,7 @@ static void help(char *name) int main(int argc, char *argv[]) { bool mode_selected = false; + uint64_t guest_memory_bytes = DEFAULT_GUEST_TEST_MEM_SIZE; unsigned int mode; int opt, i; bool use_uffd = false; @@ -414,7 +426,7 @@ int main(int argc, char *argv[]) vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); #endif - while ((opt = getopt(argc, argv, "hm:ud:")) != -1) { + while ((opt = getopt(argc, argv, "hm:ud:b:")) != -1) { switch (opt) { case 'm': if (!mode_selected) { @@ -435,6 +447,8 @@ int main(int argc, char *argv[]) TEST_ASSERT(uffd_delay >= 0, "A negative UFFD delay is not supported."); break; + case 'b': + guest_memory_bytes = strtoull(optarg, NULL, 0); case 'h': default: help(argv[0]); @@ -448,7 +462,7 @@ int main(int argc, char *argv[]) TEST_ASSERT(vm_guest_mode_params[i].supported, "Guest mode ID %d (%s) not supported.", i, vm_guest_mode_string(i)); - run_test(i, use_uffd, uffd_delay); + run_test(i, use_uffd, uffd_delay, guest_memory_bytes); } return 0;
Add an argument to allow the demand paging test to work on larger and smaller guest sizes. Signed-off-by: Ben Gardon <bgardon@google.com> --- .../selftests/kvm/demand_paging_test.c | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-)