From: Oliver Upton <oupton@google.com> To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Paolo Bonzini <pbonzini@redhat.com>, Sean Christopherson <seanjc@google.com>, Marc Zyngier <maz@kernel.org>, Peter Shier <pshier@google.com>, Jim Mattson <jmattson@google.com>, David Matlack <dmatlack@google.com>, Ricardo Koller <ricarkol@google.com>, Jing Zhang <jingzhangos@google.com>, Raghavendra Rao Anata <rananta@google.com>, Oliver Upton <oupton@google.com> Subject: [PATCH 03/10] selftests: KVM: Introduce system_counter_state_test Date: Tue, 8 Jun 2021 21:47:35 +0000 [thread overview] Message-ID: <20210608214742.1897483-4-oupton@google.com> (raw) In-Reply-To: <20210608214742.1897483-1-oupton@google.com> Test that the KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls correctly configure the guest's view of the virtual counter-timer (CNTVCT_EL0). Reviewed-by: Jing Zhang <jingzhangos@google.com> Reviewed-by: Jim Mattson <jmattson@google.com> Reviewed-by: David Matlack <dmatlack@google.com> Reviewed-by: Peter Shier <pshier@google.com> Reviewed-by: Ricardo Koller <ricarkol@google.com> Signed-off-by: Oliver Upton <oupton@google.com> --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/aarch64/processor.h | 24 +++ .../selftests/kvm/system_counter_state_test.c | 199 ++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 tools/testing/selftests/kvm/system_counter_state_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index bd83158e0e0b..1a5782d8a0d4 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -34,6 +34,7 @@ /x86_64/xen_vmcall_test /x86_64/xss_msr_test /x86_64/vmx_pmu_msrs_test +/system_counter_state_test /demand_paging_test /dirty_log_test /dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index e439d027939d..b14f16dc954a 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -80,6 +80,7 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve TEST_GEN_PROGS_aarch64 += aarch64/vgic_init +TEST_GEN_PROGS_aarch64 += system_counter_state_test TEST_GEN_PROGS_aarch64 += demand_paging_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index b7fa0c8551db..48c964ce62ff 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -52,6 +52,30 @@ static inline void set_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t id, uint vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, ®); } +static inline uint64_t read_cntpct_ordered(void) +{ + uint64_t r; + + asm volatile("isb\n\t" + "mrs %0, cntpct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + +static inline uint64_t read_cntvct_ordered(void) +{ + uint64_t r; + + asm volatile("isb\n\t" + "mrs %0, cntvct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *init); void aarch64_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_init *init, void *guest_code); diff --git a/tools/testing/selftests/kvm/system_counter_state_test.c b/tools/testing/selftests/kvm/system_counter_state_test.c new file mode 100644 index 000000000000..059971f6cb87 --- /dev/null +++ b/tools/testing/selftests/kvm/system_counter_state_test.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * system_counter_state_test.c -- suite of tests for correctness of + * KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls. + * + * Copyright (c) 2021, Google LLC. + */ +#define _GNU_SOURCE +#include <asm/kvm.h> +#include <linux/kvm.h> +#include <stdint.h> + +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" + +#define VCPU_ID 0 + +#ifdef __aarch64__ + +enum counter { + VIRTUAL, + PHYSICAL, +}; + +static char *counter_name(enum counter counter) +{ + switch (counter) { + case VIRTUAL: + return "virtual"; + case PHYSICAL: + return "physical"; + default: + TEST_ASSERT(false, "unrecognized counter: %d", counter); + } + + /* never reached */ + return NULL; +} + +struct system_counter_state_test { + enum counter counter; + struct kvm_system_counter_state state; +}; + +static struct system_counter_state_test test_cases[] = { + { + .counter = VIRTUAL, + .state = { + .cntvoff = 0 + } + }, + { + .counter = VIRTUAL, + .state = { + .cntvoff = 1000000 + } + }, + { + .counter = VIRTUAL, + .state = { + .cntvoff = -1 + } + }, +}; + +static void pr_test(struct system_counter_state_test *test) +{ + pr_info("counter: %s, cntvoff: %lld\n", counter_name(test->counter), test->state.cntvoff); +} + +static struct kvm_system_counter_state * +get_system_counter_state(struct system_counter_state_test *test) +{ + return &test->state; +} + +/* + * Reads the guest counter-timer under test. + */ +static uint64_t guest_read_counter(struct system_counter_state_test *test) +{ + switch (test->counter) { + case PHYSICAL: + return read_cntpct_ordered(); + case VIRTUAL: + return read_cntvct_ordered(); + default: + GUEST_ASSERT(0); + } + + /* never reached */ + return -1; +} + +/* + * Reads the host physical counter-timer and transforms it into a guest value + * according to the kvm_system_counter_state structure. + */ +static uint64_t host_read_guest_counter(struct system_counter_state_test *test) +{ + uint64_t r; + + r = read_cntvct_ordered(); + switch (test->counter) { + case VIRTUAL: + r -= test->state.cntvoff; + break; + default: + TEST_ASSERT(false, "unrecognized counter: %d", test->counter); + } + + return r; +} + +#else +#error test not implemented for architecture being built! +#endif + +static void guest_main(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct system_counter_state_test *test = &test_cases[i]; + + GUEST_SYNC(guest_read_counter(test)); + } + + GUEST_DONE(); +} + +static bool enter_guest(struct kvm_vm *vm, uint64_t *guest_counter) +{ + struct ucall uc; + + vcpu_ioctl(vm, VCPU_ID, KVM_RUN, NULL); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_DONE: + return true; + case UCALL_SYNC: + if (guest_counter) + *guest_counter = uc.args[1]; + break; + case UCALL_ABORT: + TEST_ASSERT(false, "%s at %s:%ld", (const char *)uc.args[0], + __FILE__, uc.args[1]); + break; + default: + TEST_ASSERT(false, "unexpected exit: %s", + exit_reason_str(vcpu_state(vm, VCPU_ID)->exit_reason)); + break; + } + + /* more work to do in the guest */ + return false; +} + +static void run_tests(struct kvm_vm *vm) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct system_counter_state_test *test = &test_cases[i]; + uint64_t start, end, obs; + + pr_info("test %d: ", i); + pr_test(test); + + vcpu_ioctl(vm, VCPU_ID, KVM_SET_SYSTEM_COUNTER_STATE, + get_system_counter_state(test)); + + start = host_read_guest_counter(test); + TEST_ASSERT(!enter_guest(vm, &obs), "guest completed unexpectedly"); + end = host_read_guest_counter(test); + + TEST_ASSERT(start < obs && obs < end, + "guest counter value (%ld) outside expected bounds: (%ld, %ld)", + obs, start, end); + } + + TEST_ASSERT(enter_guest(vm, NULL), "guest didn't run to completion"); +} + +int main(void) +{ + struct kvm_vm *vm; + + if (!kvm_check_cap(KVM_CAP_SYSTEM_COUNTER_STATE)) { + print_skip("KVM_CAP_SYSTEM_COUNTER_STATE not supported"); + exit(KSFT_SKIP); + } + + vm = vm_create_default(0, 0, guest_main); + ucall_init(vm, NULL); + run_tests(vm); + kvm_vm_free(vm); +} -- 2.32.0.rc1.229.g3e70b5a671-goog
WARNING: multiple messages have this Message-ID (diff)
From: Oliver Upton <oupton@google.com> To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Oliver Upton <oupton@google.com>, Marc Zyngier <maz@kernel.org>, Raghavendra Rao Anata <rananta@google.com>, Peter Shier <pshier@google.com>, Sean Christopherson <seanjc@google.com>, David Matlack <dmatlack@google.com>, Paolo Bonzini <pbonzini@redhat.com>, Jim Mattson <jmattson@google.com> Subject: [PATCH 03/10] selftests: KVM: Introduce system_counter_state_test Date: Tue, 8 Jun 2021 21:47:35 +0000 [thread overview] Message-ID: <20210608214742.1897483-4-oupton@google.com> (raw) In-Reply-To: <20210608214742.1897483-1-oupton@google.com> Test that the KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls correctly configure the guest's view of the virtual counter-timer (CNTVCT_EL0). Reviewed-by: Jing Zhang <jingzhangos@google.com> Reviewed-by: Jim Mattson <jmattson@google.com> Reviewed-by: David Matlack <dmatlack@google.com> Reviewed-by: Peter Shier <pshier@google.com> Reviewed-by: Ricardo Koller <ricarkol@google.com> Signed-off-by: Oliver Upton <oupton@google.com> --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/aarch64/processor.h | 24 +++ .../selftests/kvm/system_counter_state_test.c | 199 ++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 tools/testing/selftests/kvm/system_counter_state_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index bd83158e0e0b..1a5782d8a0d4 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -34,6 +34,7 @@ /x86_64/xen_vmcall_test /x86_64/xss_msr_test /x86_64/vmx_pmu_msrs_test +/system_counter_state_test /demand_paging_test /dirty_log_test /dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index e439d027939d..b14f16dc954a 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -80,6 +80,7 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve TEST_GEN_PROGS_aarch64 += aarch64/vgic_init +TEST_GEN_PROGS_aarch64 += system_counter_state_test TEST_GEN_PROGS_aarch64 += demand_paging_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index b7fa0c8551db..48c964ce62ff 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -52,6 +52,30 @@ static inline void set_reg(struct kvm_vm *vm, uint32_t vcpuid, uint64_t id, uint vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, ®); } +static inline uint64_t read_cntpct_ordered(void) +{ + uint64_t r; + + asm volatile("isb\n\t" + "mrs %0, cntpct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + +static inline uint64_t read_cntvct_ordered(void) +{ + uint64_t r; + + asm volatile("isb\n\t" + "mrs %0, cntvct_el0\n\t" + "isb\n\t" + : "=r"(r)); + + return r; +} + void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *init); void aarch64_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_init *init, void *guest_code); diff --git a/tools/testing/selftests/kvm/system_counter_state_test.c b/tools/testing/selftests/kvm/system_counter_state_test.c new file mode 100644 index 000000000000..059971f6cb87 --- /dev/null +++ b/tools/testing/selftests/kvm/system_counter_state_test.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * system_counter_state_test.c -- suite of tests for correctness of + * KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls. + * + * Copyright (c) 2021, Google LLC. + */ +#define _GNU_SOURCE +#include <asm/kvm.h> +#include <linux/kvm.h> +#include <stdint.h> + +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" + +#define VCPU_ID 0 + +#ifdef __aarch64__ + +enum counter { + VIRTUAL, + PHYSICAL, +}; + +static char *counter_name(enum counter counter) +{ + switch (counter) { + case VIRTUAL: + return "virtual"; + case PHYSICAL: + return "physical"; + default: + TEST_ASSERT(false, "unrecognized counter: %d", counter); + } + + /* never reached */ + return NULL; +} + +struct system_counter_state_test { + enum counter counter; + struct kvm_system_counter_state state; +}; + +static struct system_counter_state_test test_cases[] = { + { + .counter = VIRTUAL, + .state = { + .cntvoff = 0 + } + }, + { + .counter = VIRTUAL, + .state = { + .cntvoff = 1000000 + } + }, + { + .counter = VIRTUAL, + .state = { + .cntvoff = -1 + } + }, +}; + +static void pr_test(struct system_counter_state_test *test) +{ + pr_info("counter: %s, cntvoff: %lld\n", counter_name(test->counter), test->state.cntvoff); +} + +static struct kvm_system_counter_state * +get_system_counter_state(struct system_counter_state_test *test) +{ + return &test->state; +} + +/* + * Reads the guest counter-timer under test. + */ +static uint64_t guest_read_counter(struct system_counter_state_test *test) +{ + switch (test->counter) { + case PHYSICAL: + return read_cntpct_ordered(); + case VIRTUAL: + return read_cntvct_ordered(); + default: + GUEST_ASSERT(0); + } + + /* never reached */ + return -1; +} + +/* + * Reads the host physical counter-timer and transforms it into a guest value + * according to the kvm_system_counter_state structure. + */ +static uint64_t host_read_guest_counter(struct system_counter_state_test *test) +{ + uint64_t r; + + r = read_cntvct_ordered(); + switch (test->counter) { + case VIRTUAL: + r -= test->state.cntvoff; + break; + default: + TEST_ASSERT(false, "unrecognized counter: %d", test->counter); + } + + return r; +} + +#else +#error test not implemented for architecture being built! +#endif + +static void guest_main(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct system_counter_state_test *test = &test_cases[i]; + + GUEST_SYNC(guest_read_counter(test)); + } + + GUEST_DONE(); +} + +static bool enter_guest(struct kvm_vm *vm, uint64_t *guest_counter) +{ + struct ucall uc; + + vcpu_ioctl(vm, VCPU_ID, KVM_RUN, NULL); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_DONE: + return true; + case UCALL_SYNC: + if (guest_counter) + *guest_counter = uc.args[1]; + break; + case UCALL_ABORT: + TEST_ASSERT(false, "%s at %s:%ld", (const char *)uc.args[0], + __FILE__, uc.args[1]); + break; + default: + TEST_ASSERT(false, "unexpected exit: %s", + exit_reason_str(vcpu_state(vm, VCPU_ID)->exit_reason)); + break; + } + + /* more work to do in the guest */ + return false; +} + +static void run_tests(struct kvm_vm *vm) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { + struct system_counter_state_test *test = &test_cases[i]; + uint64_t start, end, obs; + + pr_info("test %d: ", i); + pr_test(test); + + vcpu_ioctl(vm, VCPU_ID, KVM_SET_SYSTEM_COUNTER_STATE, + get_system_counter_state(test)); + + start = host_read_guest_counter(test); + TEST_ASSERT(!enter_guest(vm, &obs), "guest completed unexpectedly"); + end = host_read_guest_counter(test); + + TEST_ASSERT(start < obs && obs < end, + "guest counter value (%ld) outside expected bounds: (%ld, %ld)", + obs, start, end); + } + + TEST_ASSERT(enter_guest(vm, NULL), "guest didn't run to completion"); +} + +int main(void) +{ + struct kvm_vm *vm; + + if (!kvm_check_cap(KVM_CAP_SYSTEM_COUNTER_STATE)) { + print_skip("KVM_CAP_SYSTEM_COUNTER_STATE not supported"); + exit(KSFT_SKIP); + } + + vm = vm_create_default(0, 0, guest_main); + ucall_init(vm, NULL); + run_tests(vm); + kvm_vm_free(vm); +} -- 2.32.0.rc1.229.g3e70b5a671-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
next prev parent reply other threads:[~2021-06-08 21:49 UTC|newest] Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-06-08 21:47 [PATCH 00/10] KVM: Add idempotent controls for migrating system counter state Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 01/10] KVM: Introduce KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls Oliver Upton 2021-06-08 21:47 ` [PATCH 01/10] KVM: Introduce KVM_{GET, SET}_SYSTEM_COUNTER_STATE ioctls Oliver Upton 2021-06-08 21:47 ` [PATCH 02/10] KVM: arm64: Implement initial support for KVM_CAP_SYSTEM_COUNTER_STATE Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:55 ` Oliver Upton 2021-06-08 21:55 ` Oliver Upton 2021-06-09 10:23 ` Marc Zyngier 2021-06-09 10:23 ` Marc Zyngier 2021-06-09 14:51 ` Oliver Upton 2021-06-09 14:51 ` Oliver Upton 2021-06-10 6:54 ` Paolo Bonzini 2021-06-10 6:54 ` Paolo Bonzini 2021-06-10 6:26 ` Paolo Bonzini 2021-06-10 6:26 ` Paolo Bonzini 2021-06-08 21:47 ` Oliver Upton [this message] 2021-06-08 21:47 ` [PATCH 03/10] selftests: KVM: Introduce system_counter_state_test Oliver Upton 2021-06-08 21:47 ` [PATCH 04/10] KVM: arm64: Add userspace control of the guest's physical counter Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:58 ` Oliver Upton 2021-06-08 21:58 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 05/10] selftests: KVM: Add test cases for physical counter offsetting Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 06/10] selftests: KVM: Add counter emulation benchmark Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 07/10] KVM: x86: Refactor tsc synchronization code Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 08/10] KVM: x86: Implement KVM_CAP_SYSTEM_COUNTER_STATE Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 09/10] selftests: KVM: Add support for x86 to system_counter_state_test Oliver Upton 2021-06-08 21:47 ` Oliver Upton 2021-06-08 21:47 ` [PATCH 10/10] Documentation: KVM: Document KVM_{GET,SET}_SYSTEM_COUNTER_STATE ioctls Oliver Upton 2021-06-08 21:47 ` [PATCH 10/10] Documentation: KVM: Document KVM_{GET, SET}_SYSTEM_COUNTER_STATE ioctls Oliver Upton 2021-06-09 13:05 ` [PATCH 00/10] KVM: Add idempotent controls for migrating system counter state Paolo Bonzini 2021-06-09 13:05 ` Paolo Bonzini 2021-06-09 15:11 ` Oliver Upton 2021-06-09 15:11 ` Oliver Upton 2021-06-09 17:05 ` Paolo Bonzini 2021-06-09 17:05 ` Paolo Bonzini 2021-06-09 22:04 ` Oliver Upton 2021-06-09 22:04 ` Oliver Upton 2021-06-10 6:22 ` Paolo Bonzini 2021-06-10 6:22 ` Paolo Bonzini 2021-06-10 6:53 ` Christian Borntraeger 2021-06-10 6:53 ` Christian Borntraeger
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=20210608214742.1897483-4-oupton@google.com \ --to=oupton@google.com \ --cc=dmatlack@google.com \ --cc=jingzhangos@google.com \ --cc=jmattson@google.com \ --cc=kvm@vger.kernel.org \ --cc=kvmarm@lists.cs.columbia.edu \ --cc=maz@kernel.org \ --cc=pbonzini@redhat.com \ --cc=pshier@google.com \ --cc=rananta@google.com \ --cc=ricarkol@google.com \ --cc=seanjc@google.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: linkBe 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.