// SPDX-License-Identifier: GPL-2.0-or-later static bool compare_legacy_flags(vm_flags_t legacy_flags, vma_flags_t flags) { const unsigned long legacy_val = legacy_flags; /* The lower word should contain the precise same value. */ const unsigned long flags_lower = flags.__vma_flags[0]; vma_flags_t converted_flags; #if NUM_VMA_FLAG_BITS > BITS_PER_LONG int i; /* All bits in higher flag values should be zero. */ for (i = 1; i < NUM_VMA_FLAG_BITS / BITS_PER_LONG; i++) { if (flags.__vma_flags[i] != 0) return false; } #endif static_assert(sizeof(legacy_flags) == sizeof(unsigned long)); /* Assert that legacy flag helpers work correctly. */ converted_flags = legacy_to_vma_flags(legacy_flags); ASSERT_FLAGS_SAME_MASK(&converted_flags, flags); ASSERT_EQ(vma_flags_to_legacy(flags), legacy_flags); return legacy_val == flags_lower; } static bool test_copy_vma(void) { vma_flags_t vma_flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT); struct mm_struct mm = {}; bool need_locks = false; VMA_ITERATOR(vmi, &mm, 0); struct vm_area_struct *vma, *vma_new, *vma_next; /* Move backwards and do not merge. */ vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vma_flags); vma_new = copy_vma(&vma, 0, 0x2000, 0, &need_locks); ASSERT_NE(vma_new, vma); ASSERT_EQ(vma_new->vm_start, 0); ASSERT_EQ(vma_new->vm_end, 0x2000); ASSERT_EQ(vma_new->vm_pgoff, 0); vma_assert_attached(vma_new); cleanup_mm(&mm, &vmi); /* Move a VMA into position next to another and merge the two. */ vma = alloc_and_link_vma(&mm, 0, 0x2000, 0, vma_flags); vma_next = alloc_and_link_vma(&mm, 0x6000, 0x8000, 6, vma_flags); vma_new = copy_vma(&vma, 0x4000, 0x2000, 4, &need_locks); vma_assert_attached(vma_new); ASSERT_EQ(vma_new, vma_next); cleanup_mm(&mm, &vmi); return true; } static bool test_vma_flags_unchanged(void) { vma_flags_t flags = EMPTY_VMA_FLAGS; vm_flags_t legacy_flags = 0; int bit; struct vm_area_struct vma; struct vm_area_desc desc; vma.flags = EMPTY_VMA_FLAGS; desc.vma_flags = EMPTY_VMA_FLAGS; for (bit = 0; bit < BITS_PER_LONG; bit++) { vma_flags_t mask = mk_vma_flags(bit); legacy_flags |= (1UL << bit); /* Individual flags. */ vma_flags_set(&flags, bit); ASSERT_TRUE(compare_legacy_flags(legacy_flags, flags)); /* Via mask. */ vma_flags_set_mask(&flags, mask); ASSERT_TRUE(compare_legacy_flags(legacy_flags, flags)); /* Same for VMA. */ vma_set_flags(&vma, bit); ASSERT_TRUE(compare_legacy_flags(legacy_flags, vma.flags)); vma_set_flags_mask(&vma, mask); ASSERT_TRUE(compare_legacy_flags(legacy_flags, vma.flags)); /* Same for VMA descriptor. */ vma_desc_set_flags(&desc, bit); ASSERT_TRUE(compare_legacy_flags(legacy_flags, desc.vma_flags)); vma_desc_set_flags_mask(&desc, mask); ASSERT_TRUE(compare_legacy_flags(legacy_flags, desc.vma_flags)); } return true; } static bool test_vma_flags_cleared(void) { const vma_flags_t empty = EMPTY_VMA_FLAGS; vma_flags_t flags; int i; /* Set all bits high. */ memset(&flags, 1, sizeof(flags)); /* Try to clear. */ vma_flags_clear_all(&flags); /* Equal to EMPTY_VMA_FLAGS? */ ASSERT_EQ(memcmp(&empty, &flags, sizeof(flags)), 0); /* Make sure every unsigned long entry in bitmap array zero. */ for (i = 0; i < sizeof(flags) / BITS_PER_LONG; i++) { const unsigned long val = flags.__vma_flags[i]; ASSERT_EQ(val, 0); } return true; } #if NUM_VMA_FLAG_BITS > 64 /* * Assert that VMA flag functions that operate at the system word level function * correctly. */ static bool test_vma_flags_word(void) { vma_flags_t flags = EMPTY_VMA_FLAGS; const vma_flags_t comparison = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT , 64, 65 ); /* Set some custom high flags. */ vma_flags_set(&flags, 64, 65); /* Now overwrite the first word. */ vma_flags_overwrite_word(&flags, VM_READ | VM_WRITE); /* Ensure they are equal. */ ASSERT_EQ(memcmp(&flags, &comparison, sizeof(flags)), 0); flags = EMPTY_VMA_FLAGS; vma_flags_set(&flags, 64, 65); /* Do the same with the _once() equivalent. */ vma_flags_overwrite_word_once(&flags, VM_READ | VM_WRITE); ASSERT_EQ(memcmp(&flags, &comparison, sizeof(flags)), 0); flags = EMPTY_VMA_FLAGS; vma_flags_set(&flags, 64, 65); /* Make sure we can set a word without disturbing other bits. */ vma_flags_set(&flags, VMA_WRITE_BIT); vma_flags_set_word(&flags, VM_READ); ASSERT_EQ(memcmp(&flags, &comparison, sizeof(flags)), 0); flags = EMPTY_VMA_FLAGS; vma_flags_set(&flags, 64, 65); /* Make sure we can clear a word without disturbing other bits. */ vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); vma_flags_clear_word(&flags, VM_EXEC); ASSERT_EQ(memcmp(&flags, &comparison, sizeof(flags)), 0); return true; } #endif /* NUM_VMA_FLAG_BITS > 64 */ /* Ensure that vma_flags_test() and friends works correctly. */ static bool test_vma_flags_test(void) { vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); struct vm_area_desc desc = { .vma_flags = flags, }; struct vm_area_struct vma = { .flags = flags, }; #define do_test(_flag) \ ASSERT_TRUE(vma_flags_test(&flags, _flag)); \ ASSERT_TRUE(vma_flags_test_single_mask(&flags, mk_vma_flags(_flag))); \ ASSERT_TRUE(vma_test(&vma, _flag)); \ ASSERT_TRUE(vma_test_single_mask(&vma, mk_vma_flags(_flag))); \ ASSERT_TRUE(vma_desc_test(&desc, _flag)) #define do_test_false(_flag) \ ASSERT_FALSE(vma_flags_test(&flags, _flag)); \ ASSERT_FALSE(vma_flags_test_single_mask(&flags, mk_vma_flags(_flag))); \ ASSERT_FALSE(vma_test(&vma, _flag)); \ ASSERT_FALSE(vma_test_single_mask(&vma, mk_vma_flags(_flag))); \ ASSERT_FALSE(vma_desc_test(&desc, _flag)) do_test(VMA_READ_BIT); do_test(VMA_WRITE_BIT); do_test(VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test(64); do_test(65); #endif do_test_false(VMA_MAYWRITE_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test_false(66); #endif #undef do_test #undef do_test_false /* We define the _single_mask() variants to return false if empty. */ ASSERT_FALSE(vma_flags_test_single_mask(&flags, EMPTY_VMA_FLAGS)); ASSERT_FALSE(vma_test_single_mask(&vma, EMPTY_VMA_FLAGS)); /* Even when both flags and tested flag mask are empty! */ flags = EMPTY_VMA_FLAGS; vma.flags = EMPTY_VMA_FLAGS; ASSERT_FALSE(vma_flags_test_single_mask(&flags, EMPTY_VMA_FLAGS)); ASSERT_FALSE(vma_test_single_mask(&vma, EMPTY_VMA_FLAGS)); return true; } /* Ensure that vma_flags_test_any() and friends works correctly. */ static bool test_vma_flags_test_any(void) { const vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); struct vm_area_struct vma = { .flags = flags, }; struct vm_area_desc desc = { .vma_flags = flags, }; #define do_test(...) \ ASSERT_TRUE(vma_flags_test_any(&flags, __VA_ARGS__)); \ ASSERT_TRUE(vma_desc_test_any(&desc, __VA_ARGS__)); \ ASSERT_TRUE(vma_test_any(&vma, __VA_ARGS__)); #define do_test_all_true(...) \ ASSERT_TRUE(vma_flags_test_all(&flags, __VA_ARGS__)); \ ASSERT_TRUE(vma_test_all(&vma, __VA_ARGS__)) #define do_test_all_false(...) \ ASSERT_FALSE(vma_flags_test_all(&flags, __VA_ARGS__)); \ ASSERT_FALSE(vma_test_all(&vma, __VA_ARGS__)) /* * Testing for some flags that are present, some that are not - should * pass. ANY flags matching should work. */ do_test(VMA_READ_BIT, VMA_MAYREAD_BIT, VMA_SEQ_READ_BIT); /* However, the ...test_all() variant should NOT pass. */ do_test_all_false(VMA_READ_BIT, VMA_MAYREAD_BIT, VMA_SEQ_READ_BIT); #if NUM_VMA_FLAG_BITS > 64 /* But should pass for flags present. */ do_test_all_true(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64, 65); /* Also subsets... */ do_test_all_true(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64); #endif do_test_all_true(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); do_test_all_true(VMA_READ_BIT, VMA_WRITE_BIT); do_test_all_true(VMA_READ_BIT); /* * Check _mask variant. We don't need to test extensively as macro * helper is the equivalent. */ ASSERT_TRUE(vma_flags_test_any_mask(&flags, flags)); ASSERT_TRUE(vma_flags_test_all_mask(&flags, flags)); /* Single bits. */ do_test(VMA_READ_BIT); do_test(VMA_WRITE_BIT); do_test(VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test(64); do_test(65); #endif /* Two bits. */ do_test(VMA_READ_BIT, VMA_WRITE_BIT); do_test(VMA_READ_BIT, VMA_EXEC_BIT); do_test(VMA_WRITE_BIT, VMA_EXEC_BIT); /* Ordering shouldn't matter. */ do_test(VMA_WRITE_BIT, VMA_READ_BIT); do_test(VMA_EXEC_BIT, VMA_READ_BIT); do_test(VMA_EXEC_BIT, VMA_WRITE_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test(VMA_READ_BIT, 64); do_test(VMA_WRITE_BIT, 64); do_test(64, VMA_READ_BIT); do_test(64, VMA_WRITE_BIT); do_test(VMA_READ_BIT, 65); do_test(VMA_WRITE_BIT, 65); do_test(65, VMA_READ_BIT); do_test(65, VMA_WRITE_BIT); #endif /* Three bits. */ do_test(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 /* No need to consider every single permutation. */ do_test(VMA_READ_BIT, VMA_WRITE_BIT, 64); do_test(VMA_READ_BIT, VMA_WRITE_BIT, 65); /* Four bits. */ do_test(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64); do_test(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 65); /* Five bits. */ do_test(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64, 65); #endif /* Testing all flags against none trivially succeeds. */ ASSERT_TRUE(vma_flags_test_all_mask(&flags, EMPTY_VMA_FLAGS)); ASSERT_TRUE(vma_test_all_mask(&vma, EMPTY_VMA_FLAGS)); #undef do_test #undef do_test_all_true #undef do_test_all_false return true; } /* Ensure that vma_flags_clear() and friends works correctly. */ static bool test_vma_flags_clear(void) { vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); vma_flags_t mask = mk_vma_flags(VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64 #endif ); struct vm_area_struct vma = { .flags = flags, }; struct vm_area_desc desc = { .vma_flags = flags, }; /* Cursory check of _mask() variant, as the helper macros imply. */ vma_flags_clear_mask(&flags, mask); vma_clear_flags_mask(&vma, mask); vma_desc_clear_flags_mask(&desc, mask); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FALSE(vma_flags_test_any(&flags, VMA_EXEC_BIT, 64)); ASSERT_FALSE(vma_test_any(&vma, VMA_EXEC_BIT, 64)); ASSERT_FALSE(vma_desc_test_any(&desc, VMA_EXEC_BIT, 64)); /* Reset. */ vma_flags_set(&flags, VMA_EXEC_BIT, 64); vma_set_flags(&vma, VMA_EXEC_BIT, 64); vma_desc_set_flags(&desc, VMA_EXEC_BIT, 64); #endif /* * Clear the flags and assert clear worked, then reset flags back to * include specified flags. */ #define do_test_and_reset(...) \ vma_flags_clear(&flags, __VA_ARGS__); \ vma_clear_flags(&vma, __VA_ARGS__); \ vma_desc_clear_flags(&desc, __VA_ARGS__); \ ASSERT_FALSE(vma_flags_test_any(&flags, __VA_ARGS__)); \ ASSERT_FALSE(vma_test_any(&vma, __VA_ARGS__)); \ ASSERT_FALSE(vma_desc_test_any(&desc, __VA_ARGS__)); \ vma_flags_set(&flags, __VA_ARGS__); \ vma_set_flags(&vma, __VA_ARGS__); \ vma_desc_set_flags(&desc, __VA_ARGS__) /* Single flags. */ do_test_and_reset(VMA_READ_BIT); do_test_and_reset(VMA_WRITE_BIT); do_test_and_reset(VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test_and_reset(64); do_test_and_reset(65); #endif /* Two flags, in different orders. */ do_test_and_reset(VMA_READ_BIT, VMA_WRITE_BIT); do_test_and_reset(VMA_READ_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test_and_reset(VMA_READ_BIT, 64); do_test_and_reset(VMA_READ_BIT, 65); #endif do_test_and_reset(VMA_WRITE_BIT, VMA_READ_BIT); do_test_and_reset(VMA_WRITE_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test_and_reset(VMA_WRITE_BIT, 64); do_test_and_reset(VMA_WRITE_BIT, 65); #endif do_test_and_reset(VMA_EXEC_BIT, VMA_READ_BIT); do_test_and_reset(VMA_EXEC_BIT, VMA_WRITE_BIT); #if NUM_VMA_FLAG_BITS > 64 do_test_and_reset(VMA_EXEC_BIT, 64); do_test_and_reset(VMA_EXEC_BIT, 65); do_test_and_reset(64, VMA_READ_BIT); do_test_and_reset(64, VMA_WRITE_BIT); do_test_and_reset(64, VMA_EXEC_BIT); do_test_and_reset(64, 65); do_test_and_reset(65, VMA_READ_BIT); do_test_and_reset(65, VMA_WRITE_BIT); do_test_and_reset(65, VMA_EXEC_BIT); do_test_and_reset(65, 64); #endif /* Three flags. */ #undef do_test_some_missing #undef do_test_and_reset return true; } /* Ensure that vma_flags_empty() works correctly. */ static bool test_vma_flags_empty(void) { vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); ASSERT_FLAGS_NONEMPTY(&flags); vma_flags_clear(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FLAGS_NONEMPTY(&flags); vma_flags_clear(&flags, 64, 65); ASSERT_FLAGS_EMPTY(&flags); #else ASSERT_FLAGS_EMPTY(&flags); #endif return true; } /* Ensure that vma_flags_diff_pair() works correctly. */ static bool test_vma_flags_diff(void) { vma_flags_t flags1 = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); vma_flags_t flags2 = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65, 66, 67 #endif ); vma_flags_t diff = vma_flags_diff_pair(&flags1, &flags2); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FLAGS_SAME(&diff, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT, 66, 67); #else ASSERT_FLAGS_SAME(&diff, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT); #endif /* Should be the same even if re-ordered. */ diff = vma_flags_diff_pair(&flags2, &flags1); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FLAGS_SAME(&diff, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT, 66, 67); #else ASSERT_FLAGS_SAME(&diff, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT); #endif /* Should be no difference when applied against themselves. */ diff = vma_flags_diff_pair(&flags1, &flags1); ASSERT_FLAGS_EMPTY(&diff); diff = vma_flags_diff_pair(&flags2, &flags2); ASSERT_FLAGS_EMPTY(&diff); /* One set of flags against an empty one should equal the original. */ flags2 = EMPTY_VMA_FLAGS; diff = vma_flags_diff_pair(&flags1, &flags2); ASSERT_FLAGS_SAME_MASK(&diff, flags1); /* A subset should work too. */ flags2 = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT); diff = vma_flags_diff_pair(&flags1, &flags2); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FLAGS_SAME(&diff, VMA_EXEC_BIT, 64, 65); #else ASSERT_FLAGS_SAME(&diff, VMA_EXEC_BIT); #endif return true; } /* Ensure that vma_flags_and() and friends work correctly. */ static bool test_vma_flags_and(void) { vma_flags_t flags1 = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); vma_flags_t flags2 = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65, 66, 67 #endif ); vma_flags_t flags3 = mk_vma_flags(VMA_IO_BIT, VMA_MAYBE_GUARD_BIT #if NUM_VMA_FLAG_BITS > 64 , 68, 69 #endif ); vma_flags_t and = vma_flags_and_mask(&flags1, flags2); #if NUM_VMA_FLAG_BITS > 64 ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64, 65); #else ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #endif and = vma_flags_and_mask(&flags1, flags1); ASSERT_FLAGS_SAME_MASK(&and, flags1); and = vma_flags_and_mask(&flags2, flags2); ASSERT_FLAGS_SAME_MASK(&and, flags2); and = vma_flags_and_mask(&flags1, flags3); ASSERT_FLAGS_EMPTY(&and); and = vma_flags_and_mask(&flags2, flags3); ASSERT_FLAGS_EMPTY(&and); and = vma_flags_and(&flags1, VMA_READ_BIT); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT); and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT); and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64); and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64, 65); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, 64, 65); #endif /* And against some missing values. */ and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, VMA_IO_BIT); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, VMA_IO_BIT, VMA_RAND_READ_BIT); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #if NUM_VMA_FLAG_BITS > 64 and = vma_flags_and(&flags1, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT, VMA_IO_BIT, VMA_RAND_READ_BIT, 69); ASSERT_FLAGS_SAME(&and, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); #endif return true; } /* Ensure append_vma_flags() acts as expected. */ static bool test_append_vma_flags(void) { vma_flags_t flags = append_vma_flags(VMA_REMAP_FLAGS, VMA_READ_BIT, VMA_WRITE_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); ASSERT_FLAGS_SAME(&flags, VMA_IO_BIT, VMA_PFNMAP_BIT, VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT, VMA_READ_BIT, VMA_WRITE_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); flags = append_vma_flags(EMPTY_VMA_FLAGS, VMA_READ_BIT, VMA_WRITE_BIT); ASSERT_FLAGS_SAME(&flags, VMA_READ_BIT, VMA_WRITE_BIT); return true; } /* Assert that vma_flags_count() behaves as expected. */ static bool test_vma_flags_count(void) { vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT #if NUM_VMA_FLAG_BITS > 64 , 64, 65 #endif ); #if NUM_VMA_FLAG_BITS > 64 ASSERT_EQ(vma_flags_count(&flags), 5); vma_flags_clear(&flags, 64); ASSERT_EQ(vma_flags_count(&flags), 4); vma_flags_clear(&flags, 65); #endif ASSERT_EQ(vma_flags_count(&flags), 3); vma_flags_clear(&flags, VMA_EXEC_BIT); ASSERT_EQ(vma_flags_count(&flags), 2); vma_flags_clear(&flags, VMA_WRITE_BIT); ASSERT_EQ(vma_flags_count(&flags), 1); vma_flags_clear(&flags, VMA_READ_BIT); ASSERT_EQ(vma_flags_count(&flags), 0); return true; } static void run_vma_tests(int *num_tests, int *num_fail) { TEST(copy_vma); TEST(vma_flags_unchanged); TEST(vma_flags_cleared); #if NUM_VMA_FLAG_BITS > 64 TEST(vma_flags_word); #endif TEST(vma_flags_test); TEST(vma_flags_test_any); TEST(vma_flags_clear); TEST(vma_flags_empty); TEST(vma_flags_diff); TEST(vma_flags_and); TEST(append_vma_flags); TEST(vma_flags_count); }