lkml.org 
[lkml]   [2019]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v3 7/8] KVM: selftests: Time guest demand paging
    From
    In order to quantify demand paging performance, time guest execution
    during demand paging.

    Signed-off-by: Ben Gardon <bgardon@google.com>
    ---
    .../selftests/kvm/demand_paging_test.c | 68 +++++++++++++++++++
    1 file changed, 68 insertions(+)

    diff --git a/tools/testing/selftests/kvm/demand_paging_test.c b/tools/testing/selftests/kvm/demand_paging_test.c
    index 2b80f614dd537..d93d72bdea4a3 100644
    --- a/tools/testing/selftests/kvm/demand_paging_test.c
    +++ b/tools/testing/selftests/kvm/demand_paging_test.c
    @@ -32,6 +32,12 @@

    #define DEFAULT_GUEST_TEST_MEM_SIZE (1 << 30) /* 1G */

    +#ifdef PRINT_PER_PAGE_UPDATES
    +#define PER_PAGE_DEBUG(...) DEBUG(__VA_ARGS__)
    +#else
    +#define PER_PAGE_DEBUG(...)
    +#endif
    +
    #ifdef PRINT_PER_VCPU_UPDATES
    #define PER_VCPU_DEBUG(...) DEBUG(__VA_ARGS__)
    #else
    @@ -62,6 +68,26 @@ static uint64_t guest_test_phys_mem;
    */
    static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;

    +int64_t to_ns(struct timespec ts)
    +{
    + return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
    +}
    +
    +struct timespec diff(struct timespec start, struct timespec end)
    +{
    + struct timespec temp;
    +
    + if ((end.tv_nsec-start.tv_nsec) < 0) {
    + temp.tv_sec = end.tv_sec - start.tv_sec - 1;
    + temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
    + } else {
    + temp.tv_sec = end.tv_sec - start.tv_sec;
    + temp.tv_nsec = end.tv_nsec - start.tv_nsec;
    + }
    +
    + return temp;
    +}
    +
    /*
    * Continuously write to the first 8 bytes of each page in the demand paging
    * memory region.
    @@ -96,11 +122,15 @@ static void *vcpu_worker(void *data)
    uint64_t gva = args->gva;
    uint64_t pages = args->pages;
    struct kvm_run *run;
    + struct timespec start;
    + struct timespec end;

    vcpu_args_set(vm, vcpu_id, 2, gva, pages);

    run = vcpu_state(vm, vcpu_id);

    + clock_gettime(CLOCK_MONOTONIC, &start);
    +
    /* Let the guest access its memory */
    ret = _vcpu_run(vm, vcpu_id);
    TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret);
    @@ -110,6 +140,11 @@ static void *vcpu_worker(void *data)
    exit_reason_str(run->exit_reason));
    }

    + clock_gettime(CLOCK_MONOTONIC, &end);
    + PER_VCPU_DEBUG("vCPU %d execution time: %lld.%.9lds\n", vcpu_id,
    + (long long)(diff(start, end).tv_sec),
    + diff(start, end).tv_nsec);
    +
    return NULL;
    }

    @@ -145,6 +180,8 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, int vcpus,
    static int handle_uffd_page_request(int uffd, uint64_t addr)
    {
    pid_t tid;
    + struct timespec start;
    + struct timespec end;
    struct uffdio_copy copy;
    int r;

    @@ -155,6 +192,8 @@ static int handle_uffd_page_request(int uffd, uint64_t addr)
    copy.len = host_page_size;
    copy.mode = 0;

    + clock_gettime(CLOCK_MONOTONIC, &start);
    +
    r = ioctl(uffd, UFFDIO_COPY, &copy);
    if (r == -1) {
    DEBUG("Failed Paged in 0x%lx from thread %d with errno: %d\n",
    @@ -162,6 +201,13 @@ static int handle_uffd_page_request(int uffd, uint64_t addr)
    return r;
    }

    + clock_gettime(CLOCK_MONOTONIC, &end);
    +
    + PER_PAGE_DEBUG("UFFDIO_COPY %d \t%lld ns\n", tid,
    + (long long)to_ns(diff(start, end)));
    + PER_PAGE_DEBUG("Paged in %ld bytes at 0x%lx from thread %d\n",
    + host_page_size, addr, tid);
    +
    return 0;
    }

    @@ -178,7 +224,10 @@ static void *uffd_handler_thread_fn(void *arg)
    int uffd = uffd_args->uffd;
    useconds_t delay = uffd_args->delay;
    int64_t pages = 0;
    + struct timespec start;
    + struct timespec end;

    + clock_gettime(CLOCK_MONOTONIC, &start);
    while (!quit_uffd_thread) {
    struct uffd_msg msg;
    struct pollfd pollfd[1];
    @@ -241,6 +290,13 @@ static void *uffd_handler_thread_fn(void *arg)
    pages++;
    }

    + clock_gettime(CLOCK_MONOTONIC, &end);
    + PER_VCPU_DEBUG("userfaulted %ld pages over %lld.%.9lds. (%f/sec)\n",
    + pages, (long long)(diff(start, end).tv_sec),
    + diff(start, end).tv_nsec, pages /
    + ((double)diff(start, end).tv_sec +
    + (double)diff(start, end).tv_nsec / 100000000.0));
    +
    return NULL;
    }

    @@ -303,6 +359,8 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
    uint64_t guest_num_pages;
    int vcpu_id;
    int r;
    + struct timespec start;
    + struct timespec end;

    vm = create_vm(mode, vcpus, vcpu_wss);

    @@ -417,6 +475,8 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,

    DEBUG("Finished creating vCPUs and starting uffd threads\n");

    + clock_gettime(CLOCK_MONOTONIC, &start);
    +
    for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
    pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
    &vcpu_args[vcpu_id]);
    @@ -432,6 +492,8 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,

    DEBUG("All vCPU threads joined\n");

    + clock_gettime(CLOCK_MONOTONIC, &end);
    +
    if (use_uffd) {
    /* Tell the user fault fd handler threads to quit */
    quit_uffd_thread = true;
    @@ -439,6 +501,12 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
    pthread_join(uffd_handler_threads[vcpu_id], NULL);
    }

    + DEBUG("Total guest execution time: %lld.%.9lds\n",
    + (long long)(diff(start, end).tv_sec), diff(start, end).tv_nsec);
    + DEBUG("Overall demand paging rate: %f pgs/sec\n",
    + guest_num_pages / ((double)diff(start, end).tv_sec +
    + (double)diff(start, end).tv_nsec / 100000000.0));
    +
    ucall_uninit(vm);
    kvm_vm_free(vm);

    --
    2.24.1.735.g03f4e72817-goog
    \
     
     \ /
      Last update: 2019-12-16 22:40    [W:4.111 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site