Test mremap on regions of various sizes and alignments and validate
data after remapping. Also provide total time for remapping
the region which is useful for performance comparison of the mremap
optimizations that move pages at the PMD/PUD levels if HAVE_MOVE_PMD
and/or HAVE_MOVE_PUD are enabled.
Signed-off-by: Kalesh Singh <kaleshsingh@xxxxxxxxxx>
---
tools/testing/selftests/vm/.gitignore | 1 +
tools/testing/selftests/vm/Makefile | 1 +
tools/testing/selftests/vm/mremap_test.c | 243 +++++++++++++++++++++++
tools/testing/selftests/vm/run_vmtests | 11 +
4 files changed, 256 insertions(+)
create mode 100644 tools/testing/selftests/vm/mremap_test.c
+
+#define MAKE_TEST(source_align, destination_align, size, \
+ overlaps, should_fail, test_name) \
+{ \
+ .name = test_name, \
+ .config = { \
+ .src_alignment = source_align, \
+ .dest_alignment = destination_align, \
+ .region_size = size, \
+ .overlapping = overlaps, \
+ }, \
+ .expect_failure = should_fail \
+}
+
+#define MAKE_SIMPLE_TEST(source_align, destination_align, size) \
+ MAKE_TEST(source_align, destination_align, size, 0, 0, \
+ #size " mremap - Source " #source_align \
+ " aligned, Destination " #destination_align \
+ " aligned")
+
+
+/* Returns the time taken for the remap on success else returns -1. */
+static long long remap_region(struct config c)
+{
+ void *addr, *src_addr, *dest_addr;
+ int i, j;
+ struct timespec t_start = {0, 0}, t_end = {0, 0};
+ long long start_ns, end_ns, align_mask, ret, offset;
+ char pattern[] = {0xa8, 0xcd, 0xfe};
+ int pattern_size = ARRAY_SIZE(pattern);
+
+ src_addr = get_source_mapping(c);
+ if (!src_addr) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Set byte pattern */
+ for (i = 0; i < c.region_size; i++) {
+ for (j = 0; i+j < c.region_size && j < pattern_size; j++)
+ memset((char *) src_addr + i+j, pattern[j], 1);
+ i += pattern_size-1;
+ }
+
+ align_mask = ~(c.dest_alignment - 1);
+ offset = (c.overlapping) ? -c.dest_alignment : c.dest_alignment;
+ start_ns = t_start.tv_sec * 1000000000ULL + t_start.tv_nsec;
+ end_ns = t_end.tv_sec * 1000000000ULL + t_end.tv_nsec;
+int main(int argc, char *argv[])
+{
+ int failures = 0;
+ int i;
+
+ struct test test_cases[] = {
+ /* Expected mremap failures */
+ MAKE_TEST(_4KB, _4KB, _4KB, 1 /* overlaps */, 1 /* fails */,
+ "mremap - Source and Destination Regions Overlapping"),
+ MAKE_TEST(_4KB, _1KB, _4KB, 0 /* overlaps */, 1 /* fails */,
+ "mremap - Destination Address Misaligned (1KB-aligned)"),
+ MAKE_TEST(_1KB, _4KB, _4KB, 0 /* overlaps */, 1 /* fails */,
+ "mremap - Source Address Misaligned (1KB-aligned)"),
+
+ /* Src addr PTE aligned */
+ MAKE_SIMPLE_TEST(PTE, PTE, _8KB),
+
+ /* Src addr 1MB aligned */
+ MAKE_SIMPLE_TEST(_1MB, PTE, _2MB),
+ MAKE_SIMPLE_TEST(_1MB, _1MB, _2MB),
+
+ /* Src addr PMD aligned */
+ MAKE_SIMPLE_TEST(PMD, PTE, _4MB),
+ MAKE_SIMPLE_TEST(PMD, _1MB, _4MB),
+ MAKE_SIMPLE_TEST(PMD, PMD, _4MB),
+
+ /* Src addr PUD aligned */
+ MAKE_SIMPLE_TEST(PUD, PTE, _2GB),
+ MAKE_SIMPLE_TEST(PUD, _1MB, _2GB),
+ MAKE_SIMPLE_TEST(PUD, PMD, _2GB),
+ MAKE_SIMPLE_TEST(PUD, PUD, _2GB),