aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-09 06:00:12 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-09 06:00:12 +0000
commit9580c7e85476f8de7fe236c4d43f10594f63a098 (patch)
treedf1ccb26decb5dd8062ef10828afbe499f3fe3b6
parent4a3b0ad6c9729dd9356ebf60b83ad44bd7861393 (diff)
parente9ebf262fc0229aefd9f2366fba8870c2b17fdf5 (diff)
downloadlinux-kselftest-android13-frc-extservices-release.tar.gz
Snap for 8558685 from e9ebf262fc0229aefd9f2366fba8870c2b17fdf5 to tm-frc-extservices-releaset_frc_ext_330443000android13-frc-extservices-release
Change-Id: Icc5eea74ad9185838f95783f94eefdbc0cb2e00c
-rw-r--r--Android.bp21
-rw-r--r--android/kselftest_test_list.mk1
-rw-r--r--android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch65
-rw-r--r--android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch246
-rw-r--r--android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch33
-rw-r--r--tools/testing/selftests/filesystems/binderfs/binderfs_test.c28
-rw-r--r--tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c174
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c2
8 files changed, 475 insertions, 95 deletions
diff --git a/Android.bp b/Android.bp
index 0b9166c56315..e9e4d049591a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -76,7 +76,6 @@ cc_defaults {
"-Wno-parentheses-equality",
"-Wno-pointer-arith",
"-Wno-sign-compare",
- "-Wno-unused-parameter",
"-Wno-shift-negative-value",
"-Wno-switch",
"-Wno-absolute-value",
@@ -126,6 +125,11 @@ cc_test {
"tools/testing/selftests/breakpoints/breakpoint_test.c",
],
},
+ x86_64: {
+ srcs: [
+ "tools/testing/selftests/breakpoints/breakpoint_test.c",
+ ],
+ },
},
}
@@ -340,6 +344,21 @@ cc_test {
defaults: ["kselftest_defaults"],
}
+// KVM test
+cc_test {
+ name: "kselftest_kvm_arm64_tests",
+ relative_install_path: "linux-kselftest/kvm/aarch64",
+ local_include_dirs: [ "tools/testing/selftests"],
+ enabled: false,
+ arch: {
+ arm64: {
+ enabled: true,
+ srcs: ["tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c"],
+ },
+ },
+ defaults: ["kselftest_defaults"],
+}
+
// Lib test
sh_test {
name: "kselftest_lib_printf",
diff --git a/android/kselftest_test_list.mk b/android/kselftest_test_list.mk
index 07df6fc5d758..46b9b92c58fb 100644
--- a/android/kselftest_test_list.mk
+++ b/android/kselftest_test_list.mk
@@ -31,6 +31,7 @@ kselftest_modules += \
kselftest_intel_pstate_tests_aperf \
kselftest_intel_pstate_tests_msr \
kselftest_kcmp_tests_kcmp_test \
+ kselftest_kvm_arm64_tests_pvm_wipe_mem \
kselftest_net_tests_psock_tpacket \
kselftest_net_tests_socket \
kselftest_net_tests_reuseaddr_conflict \
diff --git a/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch b/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch
deleted file mode 100644
index 7b1e1a1c32bc..000000000000
--- a/android/patches/0022-selftests-binderfs-skip-tests-for-unsupported-kernel.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 57b74c1b318625057398ccbe479a157507488d8c Mon Sep 17 00:00:00 2001
-From: Carlos Llamas <cmllamas@google.com>
-Date: Tue, 14 Dec 2021 05:58:48 +0000
-Subject: [PATCH] selftests/binderfs: skip tests for unsupported kernels
-
-Binderfs was first introduced in Linux 5.0 release, so we need to skip
-these tests for older kernels. Also, we force a successful exit as the
-current framework doesn't handle KSFT_SKIP return codes.
-
-Signed-off-by: Carlos Llamas <cmllamas@google.com>
----
- .../filesystems/binderfs/binderfs_test.c | 28 +++++++++++++++++++
- 1 file changed, 28 insertions(+)
-
-diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
-index 8c2ed962e1c7..be5a8f446066 100644
---- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
-+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
-@@ -12,6 +12,7 @@
- #include <sys/mount.h>
- #include <sys/stat.h>
- #include <sys/types.h>
-+#include <sys/utsname.h>
- #include <unistd.h>
- #include <linux/android/binder.h>
- #include <linux/android/binderfs.h>
-@@ -267,8 +268,35 @@ static void binderfs_test_unprivileged()
- __do_binderfs_test();
- }
-
-+/* binderfs first introduced in Linux 5.0 */
-+bool binderfs_supported(void)
-+{
-+ const int min_kernel_version = 5;
-+ struct utsname utsname;
-+ int ret, version;
-+
-+ ret = uname(&utsname);
-+ if (ret)
-+ ksft_exit_fail_msg("%s - Failed to get kernel version\n",
-+ strerror(errno));
-+
-+ ret = sscanf(utsname.release, "%d.", &version);
-+ if (ret != 1)
-+ ksft_exit_fail_msg("%s - Failed to parse uname: %s\n",
-+ strerror(errno), utsname.release);
-+
-+ return version >= min_kernel_version? true: false;
-+}
-+
-+
- int main(int argc, char *argv[])
- {
-+ /* Force success exit for older kernels */
-+ if (!binderfs_supported()) {
-+ ksft_print_msg("Skipping tests - binderfs not supported\n");
-+ ksft_exit_pass();
-+ }
-+
- binderfs_test_privileged();
- binderfs_test_unprivileged();
- ksft_exit_pass();
---
-2.34.1.173.g76aa8bc2d0-goog
-
diff --git a/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch b/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch
new file mode 100644
index 000000000000..590ee72368dc
--- /dev/null
+++ b/android/patches/0023-ANDROID-kvm-Test-that-pVM-memory-is-wiped-during-tea.patch
@@ -0,0 +1,246 @@
+From a9dc703806031c8535c84c9905979f86dfaec1d3 Mon Sep 17 00:00:00 2001
+From: Quentin Perret <qperret@google.com>
+Date: Thu, 17 Feb 2022 19:34:27 +0000
+Subject: [PATCH] ANDROID: kvm: Test that pVM memory is wiped during teardown
+
+In protected KVM mode, we expect the hypervisor to protect guest secrets
+when they are torn down. Add a test checking this property by running a
+minimal guest, and checking that the content of memory has been wiped by
+the hypervisor after teardown.
+
+Note: although some of the pKVM code has already landed upstream, the
+functionality tested here hasn't at the time of writing. Once it does,
+this test should be sent upstream for review to replace this ANDROID
+patch.
+
+Bug: 218934075
+Signed-off-by: Quentin Perret <qperret@google.com>
+Change-Id: I4a347908d189f2c4835fd576b26fae7c10ec9b22
+---
+ Android.bp | 15 ++
+ android/kselftest_test_list.mk | 1 +
+ .../selftests/kvm/aarch64/pvm_wipe_mem.c | 174 ++++++++++++++++++
+ 3 files changed, 190 insertions(+)
+ create mode 100644 tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c
+
+diff --git a/Android.bp b/Android.bp
+index 0b9166c56315..08805a161450 100644
+--- a/Android.bp
++++ b/Android.bp
+@@ -340,6 +340,21 @@ cc_test {
+ defaults: ["kselftest_defaults"],
+ }
+
++// KVM test
++cc_test {
++ name: "kselftest_kvm_arm64_tests",
++ relative_install_path: "linux-kselftest/kvm/aarch64",
++ local_include_dirs: [ "tools/testing/selftests"],
++ enabled: false,
++ arch: {
++ arm64: {
++ enabled: true,
++ srcs: ["tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c"],
++ },
++ },
++ defaults: ["kselftest_defaults"],
++}
++
+ // Lib test
+ sh_test {
+ name: "kselftest_lib_printf",
+diff --git a/android/kselftest_test_list.mk b/android/kselftest_test_list.mk
+index 07df6fc5d758..46b9b92c58fb 100644
+--- a/android/kselftest_test_list.mk
++++ b/android/kselftest_test_list.mk
+@@ -31,6 +31,7 @@ kselftest_modules += \
+ kselftest_intel_pstate_tests_aperf \
+ kselftest_intel_pstate_tests_msr \
+ kselftest_kcmp_tests_kcmp_test \
++ kselftest_kvm_arm64_tests_pvm_wipe_mem \
+ kselftest_net_tests_psock_tpacket \
+ kselftest_net_tests_socket \
+ kselftest_net_tests_reuseaddr_conflict \
+diff --git a/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c
+new file mode 100644
+index 000000000000..4af8ca3c4bad
+--- /dev/null
++++ b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c
+@@ -0,0 +1,174 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Test checking that memory of protected guests is wiped after teardown.
++ *
++ * Copyright (C) 2022, Google LLC.
++ */
++
++#define _GNU_SOURCE
++
++#include <err.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <linux/kvm.h>
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++
++#include "kselftest.h"
++
++#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31)
++
++#define REG_X(number) (0x6030000000100000ULL + (number) * 2UL)
++#define REG_PC 0x6030000000100040ULL
++
++static void set_one_reg(int vcpufd, uint64_t reg_id, uint64_t val)
++{
++ uint64_t reg_data;
++ struct kvm_one_reg reg;
++ int ret;
++
++ reg.addr = (__u64) &reg_data;
++ reg_data = val;
++ reg.id = reg_id;
++
++ ret = ioctl(vcpufd, KVM_SET_ONE_REG, &reg);
++ if (ret < 0)
++ ksft_exit_fail_msg("Failed to set reg: %d\n", ret);
++}
++
++static int get_kvm(void)
++{
++ size_t run_size;
++ int kvm, ret;
++
++ kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
++ if (kvm < 0)
++ ksft_exit_skip("KVM not supported\n");
++
++ ret = ioctl(kvm, KVM_GET_API_VERSION, NULL);
++ if (ret != 12)
++ ksft_exit_fail_msg("KVM_GET_API_VERSION %d, expected 12", ret);
++
++ run_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL);
++ if (run_size < sizeof(struct kvm_run))
++ ksft_exit_fail_msg("KVM_GET_VCPU_MMAP_SIZE unexpectedly small\n");
++
++ return kvm;
++}
++
++static int create_protected_vm(int kvm)
++{
++ int vmfd = ioctl(kvm, KVM_CREATE_VM, KVM_VM_TYPE_ARM_PROTECTED);
++
++ if (vmfd < 0)
++ ksft_exit_skip("Protected guests not supported: %d\n", vmfd);
++
++ return vmfd;
++}
++
++static int create_vcpu(int vmfd, struct kvm_run **run)
++{
++ struct kvm_vcpu_init vcpu_init;
++ int vcpufd, ret;
++
++ ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &vcpu_init);
++ if (ret)
++ ksft_exit_fail_msg("Failed to set kvm_vcpu_init %d\n", ret);
++
++ vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0);
++ if (vcpufd < 0)
++ ksft_exit_fail_msg("Failed to create VCPU: %d\n", vcpufd);
++
++ *run = mmap(NULL, sizeof(**run), PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
++ if (!run)
++ ksft_exit_fail_msg("Failed to mmap vcpu_run struct\n");
++
++ ret = ioctl(vcpufd, KVM_ARM_VCPU_INIT, &vcpu_init);
++ if (ret)
++ ksft_exit_fail_msg("Failed to initialize VCPU %d\n", ret);
++
++ return vcpufd;
++}
++
++static void teardown(int kvm, int vmfd, int vcpufd, struct kvm_run *run)
++{
++ int ret = munmap(run, sizeof(*run));
++
++ if (ret)
++ ksft_exit_fail_msg("Failed to unmap vCPU run: %d\n", ret);
++
++ ret = close(vcpufd);
++ if (ret)
++ ksft_exit_fail_msg("Failed to destroy VCPU: %d\n", ret);
++
++ ret = close(vmfd);
++ if (ret)
++ ksft_exit_fail_msg("Failed to destroy VM: %d\n", ret);
++
++ ret = close(kvm);
++ if (ret)
++ ksft_exit_fail_msg("Failed to close KVM fd: %d\n", ret);
++}
++
++int main(void)
++{
++ struct kvm_userspace_memory_region region;
++ long page_size = sysconf(_SC_PAGESIZE);
++ int ret, kvm, vmfd, vcpufd;
++ uint32_t guest_code[2];
++ struct kvm_run *run;
++ uint8_t *guest_mem;
++ size_t run_size;
++
++ kvm = get_kvm();
++ vmfd = create_protected_vm(kvm);
++ vcpufd = create_vcpu(vmfd, &run);
++
++ /* Create a one-page memslot for the guest */
++ guest_mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
++ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
++ if (guest_mem == MAP_FAILED)
++ ksft_exit_fail_msg("Failed to mmap guest memory\n");
++ region = (struct kvm_userspace_memory_region) {
++ .slot = 0,
++ .guest_phys_addr = 1UL << 30,
++ .memory_size = page_size,
++ .userspace_addr = (uint64_t)guest_mem,
++ };
++
++ /* Copy some code in guest memory. */
++ guest_code[0] = 0xf9400001; /* 1: ldr x1, [x0] */
++ guest_code[1] = 0x17ffffff; /* b 1b */
++ memcpy(guest_mem, guest_code, sizeof(guest_code));
++ ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region);
++ if (ret)
++ ksft_exit_fail_msg("Failed to set memory region: %d\n", ret);
++
++ /*
++ * Get the VCPU to run one instruction, to be sure the page containing
++ * the code has been faulted in.
++ */
++ set_one_reg(vcpufd, REG_PC, region.guest_phys_addr);
++ set_one_reg(vcpufd, REG_X(0), region.guest_phys_addr + region.memory_size);
++ ret = ioctl(vcpufd, KVM_RUN, NULL);
++ if (ret)
++ ksft_exit_fail_msg("Failed to run vcpu: %d\n", ret);
++ if (run->exit_reason != KVM_EXIT_MMIO)
++ ksft_exit_fail_msg("Unexpected KVM exit reason: %u\n", run->exit_reason);
++
++ /*
++ * Tear the guest down, and check that the donated memory has been
++ * wiped by the hypervisor.
++ */
++ teardown(kvm, vmfd, vcpufd, run);
++ if (!memcmp(guest_mem, guest_code, sizeof(guest_code)))
++ ksft_exit_fail_msg("Protected guest memory has not been poisoned\n");
++
++ ksft_exit_pass();
++}
+--
+2.35.1.473.g83b2b277ed-goog
+
diff --git a/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch b/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch
new file mode 100644
index 000000000000..0920fb307ed0
--- /dev/null
+++ b/android/patches/0025-selftests-userfaultfd-skip-if-unavailable.patch
@@ -0,0 +1,33 @@
+From 30c060a86f0e56c19e18ade48c0ee7592edfc317 Mon Sep 17 00:00:00 2001
+From: Edward Liaw <edliaw@google.com>
+Date: Thu, 24 Mar 2022 00:29:56 +0000
+Subject: [PATCH] selftests: userfaultfd skip if unavailable
+
+Skip userfaultfd selftest if the syscall is not available for this
+kernel.
+
+Bug: 207175332
+Bug: 206503000
+Test: atest vts_linux_kselftest_arm_64:vm_userfaultfd_shmem_arm_64
+Change-Id: I60e4d6cc5b3886048ffa1995e4b090f6fbe26b3d
+Signed-off-by: Edward Liaw <edliaw@google.com>
+---
+ tools/testing/selftests/vm/userfaultfd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
+index ffc78f3..17947fe 100644
+--- a/tools/testing/selftests/vm/userfaultfd.c
++++ b/tools/testing/selftests/vm/userfaultfd.c
+@@ -665,7 +665,7 @@ static int userfaultfd_open(int features)
+ if (errno == ENOSYS) {
+ fprintf(stderr,
+ "userfaultfd syscall not available in this kernel\n");
+- exit(KSFT_PASS);
++ exit(KSFT_SKIP);
+ }
+ fprintf(stderr,
+ "userfaultfd syscall failed with errno: %d\n", errno);
+--
+2.35.1.1021.g381101b075-goog
+
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
index 4465b4f6a81a..397bf265ba97 100644
--- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
@@ -12,7 +12,6 @@
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/utsname.h>
#include <unistd.h>
#include <linux/android/binder.h>
#include <linux/android/binderfs.h>
@@ -274,35 +273,8 @@ static void binderfs_test_unprivileged()
__do_binderfs_test();
}
-/* binderfs first introduced in Linux 5.0 */
-bool binderfs_supported(void)
-{
- const int min_kernel_version = 5;
- struct utsname utsname;
- int ret, version;
-
- ret = uname(&utsname);
- if (ret)
- ksft_exit_fail_msg("%s - Failed to get kernel version\n",
- strerror(errno));
-
- ret = sscanf(utsname.release, "%d.", &version);
- if (ret != 1)
- ksft_exit_fail_msg("%s - Failed to parse uname: %s\n",
- strerror(errno), utsname.release);
-
- return version >= min_kernel_version? true: false;
-}
-
-
int main(int argc, char *argv[])
{
- /* Force success exit for older kernels */
- if (!binderfs_supported()) {
- ksft_print_msg("Skipping tests - binderfs not supported\n");
- ksft_exit_pass();
- }
-
binderfs_test_privileged();
binderfs_test_unprivileged();
ksft_exit_pass();
diff --git a/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c
new file mode 100644
index 000000000000..4af8ca3c4bad
--- /dev/null
+++ b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test checking that memory of protected guests is wiped after teardown.
+ *
+ * Copyright (C) 2022, Google LLC.
+ */
+
+#define _GNU_SOURCE
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "kselftest.h"
+
+#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31)
+
+#define REG_X(number) (0x6030000000100000ULL + (number) * 2UL)
+#define REG_PC 0x6030000000100040ULL
+
+static void set_one_reg(int vcpufd, uint64_t reg_id, uint64_t val)
+{
+ uint64_t reg_data;
+ struct kvm_one_reg reg;
+ int ret;
+
+ reg.addr = (__u64) &reg_data;
+ reg_data = val;
+ reg.id = reg_id;
+
+ ret = ioctl(vcpufd, KVM_SET_ONE_REG, &reg);
+ if (ret < 0)
+ ksft_exit_fail_msg("Failed to set reg: %d\n", ret);
+}
+
+static int get_kvm(void)
+{
+ size_t run_size;
+ int kvm, ret;
+
+ kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
+ if (kvm < 0)
+ ksft_exit_skip("KVM not supported\n");
+
+ ret = ioctl(kvm, KVM_GET_API_VERSION, NULL);
+ if (ret != 12)
+ ksft_exit_fail_msg("KVM_GET_API_VERSION %d, expected 12", ret);
+
+ run_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL);
+ if (run_size < sizeof(struct kvm_run))
+ ksft_exit_fail_msg("KVM_GET_VCPU_MMAP_SIZE unexpectedly small\n");
+
+ return kvm;
+}
+
+static int create_protected_vm(int kvm)
+{
+ int vmfd = ioctl(kvm, KVM_CREATE_VM, KVM_VM_TYPE_ARM_PROTECTED);
+
+ if (vmfd < 0)
+ ksft_exit_skip("Protected guests not supported: %d\n", vmfd);
+
+ return vmfd;
+}
+
+static int create_vcpu(int vmfd, struct kvm_run **run)
+{
+ struct kvm_vcpu_init vcpu_init;
+ int vcpufd, ret;
+
+ ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &vcpu_init);
+ if (ret)
+ ksft_exit_fail_msg("Failed to set kvm_vcpu_init %d\n", ret);
+
+ vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0);
+ if (vcpufd < 0)
+ ksft_exit_fail_msg("Failed to create VCPU: %d\n", vcpufd);
+
+ *run = mmap(NULL, sizeof(**run), PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
+ if (!run)
+ ksft_exit_fail_msg("Failed to mmap vcpu_run struct\n");
+
+ ret = ioctl(vcpufd, KVM_ARM_VCPU_INIT, &vcpu_init);
+ if (ret)
+ ksft_exit_fail_msg("Failed to initialize VCPU %d\n", ret);
+
+ return vcpufd;
+}
+
+static void teardown(int kvm, int vmfd, int vcpufd, struct kvm_run *run)
+{
+ int ret = munmap(run, sizeof(*run));
+
+ if (ret)
+ ksft_exit_fail_msg("Failed to unmap vCPU run: %d\n", ret);
+
+ ret = close(vcpufd);
+ if (ret)
+ ksft_exit_fail_msg("Failed to destroy VCPU: %d\n", ret);
+
+ ret = close(vmfd);
+ if (ret)
+ ksft_exit_fail_msg("Failed to destroy VM: %d\n", ret);
+
+ ret = close(kvm);
+ if (ret)
+ ksft_exit_fail_msg("Failed to close KVM fd: %d\n", ret);
+}
+
+int main(void)
+{
+ struct kvm_userspace_memory_region region;
+ long page_size = sysconf(_SC_PAGESIZE);
+ int ret, kvm, vmfd, vcpufd;
+ uint32_t guest_code[2];
+ struct kvm_run *run;
+ uint8_t *guest_mem;
+ size_t run_size;
+
+ kvm = get_kvm();
+ vmfd = create_protected_vm(kvm);
+ vcpufd = create_vcpu(vmfd, &run);
+
+ /* Create a one-page memslot for the guest */
+ guest_mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (guest_mem == MAP_FAILED)
+ ksft_exit_fail_msg("Failed to mmap guest memory\n");
+ region = (struct kvm_userspace_memory_region) {
+ .slot = 0,
+ .guest_phys_addr = 1UL << 30,
+ .memory_size = page_size,
+ .userspace_addr = (uint64_t)guest_mem,
+ };
+
+ /* Copy some code in guest memory. */
+ guest_code[0] = 0xf9400001; /* 1: ldr x1, [x0] */
+ guest_code[1] = 0x17ffffff; /* b 1b */
+ memcpy(guest_mem, guest_code, sizeof(guest_code));
+ ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &region);
+ if (ret)
+ ksft_exit_fail_msg("Failed to set memory region: %d\n", ret);
+
+ /*
+ * Get the VCPU to run one instruction, to be sure the page containing
+ * the code has been faulted in.
+ */
+ set_one_reg(vcpufd, REG_PC, region.guest_phys_addr);
+ set_one_reg(vcpufd, REG_X(0), region.guest_phys_addr + region.memory_size);
+ ret = ioctl(vcpufd, KVM_RUN, NULL);
+ if (ret)
+ ksft_exit_fail_msg("Failed to run vcpu: %d\n", ret);
+ if (run->exit_reason != KVM_EXIT_MMIO)
+ ksft_exit_fail_msg("Unexpected KVM exit reason: %u\n", run->exit_reason);
+
+ /*
+ * Tear the guest down, and check that the donated memory has been
+ * wiped by the hypervisor.
+ */
+ teardown(kvm, vmfd, vcpufd, run);
+ if (!memcmp(guest_mem, guest_code, sizeof(guest_code)))
+ ksft_exit_fail_msg("Protected guest memory has not been poisoned\n");
+
+ ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index ffc78f3e4444..17947feb6d8e 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -665,7 +665,7 @@ static int userfaultfd_open(int features)
if (errno == ENOSYS) {
fprintf(stderr,
"userfaultfd syscall not available in this kernel\n");
- exit(KSFT_PASS);
+ exit(KSFT_SKIP);
}
fprintf(stderr,
"userfaultfd syscall failed with errno: %d\n", errno);