diff options
Diffstat (limited to 'tools/testing')
-rw-r--r-- | tools/testing/cxl/test/cxl.c | 4 | ||||
-rw-r--r-- | tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc | 2 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/include/kvm_util_base.h | 6 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/kvm_binary_stats_test.c | 68 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/x86_64/set_sregs_test.c | 70 | ||||
-rwxr-xr-x | tools/testing/selftests/net/mptcp/mptcp_join.sh | 4 | ||||
-rw-r--r-- | tools/testing/selftests/rseq/rseq.c | 28 |
7 files changed, 112 insertions, 70 deletions
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index 0e78d8e19895..fb6ab9cef84f 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c @@ -999,10 +999,6 @@ static void mock_companion(struct acpi_device *adev, struct device *dev) #define SZ_64G (SZ_32G * 2) #endif -#ifndef SZ_512G -#define SZ_512G (SZ_64G * 8) -#endif - static __init int cxl_rch_init(void) { int rc, i; diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc index b89de1771655..f34b14ef9781 100644 --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc @@ -13,7 +13,7 @@ if grep -qF "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README ; the FPROBES=yes fi -if [ -z "$KPROBES" -a "$FPROBES" ] ; then +if [ -z "$KPROBES" -a -z "$FPROBES" ] ; then exit_unsupported fi diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 07732a157ccd..eb1ff597bcca 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -362,8 +362,10 @@ static inline void read_stats_header(int stats_fd, struct kvm_stats_header *head { ssize_t ret; - ret = read(stats_fd, header, sizeof(*header)); - TEST_ASSERT(ret == sizeof(*header), "Read stats header"); + ret = pread(stats_fd, header, sizeof(*header), 0); + TEST_ASSERT(ret == sizeof(*header), + "Failed to read '%lu' header bytes, ret = '%ld'", + sizeof(*header), ret); } struct kvm_stats_desc *read_stats_descriptors(int stats_fd, diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c index a7001e29dc06..698c1cfa3111 100644 --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c @@ -43,8 +43,10 @@ static void stats_test(int stats_fd) id = malloc(header.name_size); TEST_ASSERT(id, "Allocate memory for id string"); - ret = read(stats_fd, id, header.name_size); - TEST_ASSERT(ret == header.name_size, "Read id string"); + ret = pread(stats_fd, id, header.name_size, sizeof(header)); + TEST_ASSERT(ret == header.name_size, + "Expected header size '%u', read '%lu' bytes", + header.name_size, ret); /* Check id string, that should start with "kvm" */ TEST_ASSERT(!strncmp(id, "kvm", 3) && strlen(id) < header.name_size, @@ -165,23 +167,7 @@ static void stats_test(int stats_fd) free(stats_data); free(stats_desc); free(id); -} - - -static void vm_stats_test(struct kvm_vm *vm) -{ - int stats_fd = vm_get_stats_fd(vm); - - stats_test(stats_fd); - close(stats_fd); - TEST_ASSERT(fcntl(stats_fd, F_GETFD) == -1, "Stats fd not freed"); -} - -static void vcpu_stats_test(struct kvm_vcpu *vcpu) -{ - int stats_fd = vcpu_get_stats_fd(vcpu); - stats_test(stats_fd); close(stats_fd); TEST_ASSERT(fcntl(stats_fd, F_GETFD) == -1, "Stats fd not freed"); } @@ -199,6 +185,7 @@ static void vcpu_stats_test(struct kvm_vcpu *vcpu) int main(int argc, char *argv[]) { + int vm_stats_fds, *vcpu_stats_fds; int i, j; struct kvm_vcpu **vcpus; struct kvm_vm **vms; @@ -231,23 +218,58 @@ int main(int argc, char *argv[]) vcpus = malloc(sizeof(struct kvm_vcpu *) * max_vm * max_vcpu); TEST_ASSERT(vcpus, "Allocate memory for storing vCPU pointers"); + /* + * Not per-VM as the array is populated, used, and invalidated within a + * single for-loop iteration. + */ + vcpu_stats_fds = calloc(max_vm, sizeof(*vcpu_stats_fds)); + TEST_ASSERT(vcpu_stats_fds, "Allocate memory for VM stats fds"); + for (i = 0; i < max_vm; ++i) { vms[i] = vm_create_barebones(); for (j = 0; j < max_vcpu; ++j) vcpus[i * max_vcpu + j] = __vm_vcpu_add(vms[i], j); } - /* Check stats read for every VM and VCPU */ + /* + * Check stats read for every VM and vCPU, with a variety of flavors. + * Note, stats_test() closes the passed in stats fd. + */ for (i = 0; i < max_vm; ++i) { - vm_stats_test(vms[i]); + /* + * Verify that creating multiple userspace references to a + * single stats file works and doesn't cause explosions. + */ + vm_stats_fds = vm_get_stats_fd(vms[i]); + stats_test(dup(vm_stats_fds)); + + /* Verify userspace can instantiate multiple stats files. */ + stats_test(vm_get_stats_fd(vms[i])); + + for (j = 0; j < max_vcpu; ++j) { + vcpu_stats_fds[j] = vcpu_get_stats_fd(vcpus[i * max_vcpu + j]); + stats_test(dup(vcpu_stats_fds[j])); + stats_test(vcpu_get_stats_fd(vcpus[i * max_vcpu + j])); + } + + /* + * Close the VM fd and redo the stats tests. KVM should gift a + * reference (to the VM) to each stats fd, i.e. stats should + * still be accessible even after userspace has put its last + * _direct_ reference to the VM. + */ + kvm_vm_free(vms[i]); + + stats_test(vm_stats_fds); for (j = 0; j < max_vcpu; ++j) - vcpu_stats_test(vcpus[i * max_vcpu + j]); + stats_test(vcpu_stats_fds[j]); + ksft_test_result_pass("vm%i\n", i); } - for (i = 0; i < max_vm; ++i) - kvm_vm_free(vms[i]); free(vms); + free(vcpus); + free(vcpu_stats_fds); ksft_finished(); /* Print results and exit() accordingly */ } diff --git a/tools/testing/selftests/kvm/x86_64/set_sregs_test.c b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c index a284fcef6ed7..3610981d9162 100644 --- a/tools/testing/selftests/kvm/x86_64/set_sregs_test.c +++ b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c @@ -22,26 +22,25 @@ #include "kvm_util.h" #include "processor.h" -static void test_cr4_feature_bit(struct kvm_vcpu *vcpu, struct kvm_sregs *orig, - uint64_t feature_bit) -{ - struct kvm_sregs sregs; - int rc; - - /* Skip the sub-test, the feature is supported. */ - if (orig->cr4 & feature_bit) - return; - - memcpy(&sregs, orig, sizeof(sregs)); - sregs.cr4 |= feature_bit; - - rc = _vcpu_sregs_set(vcpu, &sregs); - TEST_ASSERT(rc, "KVM allowed unsupported CR4 bit (0x%lx)", feature_bit); - - /* Sanity check that KVM didn't change anything. */ - vcpu_sregs_get(vcpu, &sregs); - TEST_ASSERT(!memcmp(&sregs, orig, sizeof(sregs)), "KVM modified sregs"); -} +#define TEST_INVALID_CR_BIT(vcpu, cr, orig, bit) \ +do { \ + struct kvm_sregs new; \ + int rc; \ + \ + /* Skip the sub-test, the feature/bit is supported. */ \ + if (orig.cr & bit) \ + break; \ + \ + memcpy(&new, &orig, sizeof(sregs)); \ + new.cr |= bit; \ + \ + rc = _vcpu_sregs_set(vcpu, &new); \ + TEST_ASSERT(rc, "KVM allowed invalid " #cr " bit (0x%lx)", bit); \ + \ + /* Sanity check that KVM didn't change anything. */ \ + vcpu_sregs_get(vcpu, &new); \ + TEST_ASSERT(!memcmp(&new, &orig, sizeof(new)), "KVM modified sregs"); \ +} while (0) static uint64_t calc_supported_cr4_feature_bits(void) { @@ -80,7 +79,7 @@ int main(int argc, char *argv[]) struct kvm_vcpu *vcpu; struct kvm_vm *vm; uint64_t cr4; - int rc; + int rc, i; /* * Create a dummy VM, specifically to avoid doing KVM_SET_CPUID2, and @@ -92,6 +91,7 @@ int main(int argc, char *argv[]) vcpu_sregs_get(vcpu, &sregs); + sregs.cr0 = 0; sregs.cr4 |= calc_supported_cr4_feature_bits(); cr4 = sregs.cr4; @@ -103,16 +103,24 @@ int main(int argc, char *argv[]) sregs.cr4, cr4); /* Verify all unsupported features are rejected by KVM. */ - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_UMIP); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_LA57); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_VMXE); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMXE); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_FSGSBASE); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PCIDE); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_OSXSAVE); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMEP); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMAP); - test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PKE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_UMIP); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_LA57); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_VMXE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMXE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMEP); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMAP); + TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PKE); + + for (i = 32; i < 64; i++) + TEST_INVALID_CR_BIT(vcpu, cr0, sregs, BIT(i)); + + /* NW without CD is illegal, as is PG without PE. */ + TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_NW); + TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_PG); + kvm_vm_free(vm); /* Create a "real" VM and verify APIC_BASE can be set. */ diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index e6c9d5451c5b..3c2096ac97ef 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -162,9 +162,7 @@ check_tools() elif ! iptables -V &> /dev/null; then echo "SKIP: Could not run all tests without iptables tool" exit $ksft_skip - fi - - if ! ip6tables -V &> /dev/null; then + elif ! ip6tables -V &> /dev/null; then echo "SKIP: Could not run all tests without ip6tables tool" exit $ksft_skip fi diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c index 4e4aa006004c..a723da253244 100644 --- a/tools/testing/selftests/rseq/rseq.c +++ b/tools/testing/selftests/rseq/rseq.c @@ -34,9 +34,17 @@ #include "../kselftest.h" #include "rseq.h" -static const ptrdiff_t *libc_rseq_offset_p; -static const unsigned int *libc_rseq_size_p; -static const unsigned int *libc_rseq_flags_p; +/* + * Define weak versions to play nice with binaries that are statically linked + * against a libc that doesn't support registering its own rseq. + */ +__weak ptrdiff_t __rseq_offset; +__weak unsigned int __rseq_size; +__weak unsigned int __rseq_flags; + +static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset; +static const unsigned int *libc_rseq_size_p = &__rseq_size; +static const unsigned int *libc_rseq_flags_p = &__rseq_flags; /* Offset from the thread pointer to the rseq area. */ ptrdiff_t rseq_offset; @@ -155,9 +163,17 @@ unsigned int get_rseq_feature_size(void) static __attribute__((constructor)) void rseq_init(void) { - libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); - libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); - libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); + /* + * If the libc's registered rseq size isn't already valid, it may be + * because the binary is dynamically linked and not necessarily due to + * libc not having registered a restartable sequence. Try to find the + * symbols if that's the case. + */ + if (!*libc_rseq_size_p) { + libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); + libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); + libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags"); + } if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p && *libc_rseq_size_p != 0) { /* rseq registration owned by glibc */ |