On Tue, Feb 12, 2019 at 10:56:32AM +0800, Peter Xu wrote: > This patch adds uffd tests for write protection. > > Instead of introducing new tests for it, let's simply squashing uffd-wp > tests into existing uffd-missing test cases. Changes are: > > (1) Bouncing tests > > We do the write-protection in two ways during the bouncing test: > > - By using UFFDIO_COPY_MODE_WP when resolving MISSING pages: then > we'll make sure for each bounce process every single page will be > at least fault twice: once for MISSING, once for WP. > > - By direct call UFFDIO_WRITEPROTECT on existing faulted memories: > To further torture the explicit page protection procedures of > uffd-wp, we split each bounce procedure into two halves (in the > background thread): the first half will be MISSING+WP for each > page as explained above. After the first half, we write protect > the faulted region in the background thread to make sure at least > half of the pages will be write protected again which is the first > half to test the new UFFDIO_WRITEPROTECT call. Then we continue > with the 2nd half, which will contain both MISSING and WP faulting > tests for the 2nd half and WP-only faults from the 1st half. > > (2) Event/Signal test > > Mostly previous tests but will do MISSING+WP for each page. For > sigbus-mode test we'll need to provide standalone path to handle the > write protection faults. > > For all tests, do statistics as well for uffd-wp pages. > > Signed-off-by: Peter Xu <peterx@xxxxxxxxxx> > --- > tools/testing/selftests/vm/userfaultfd.c | 154 ++++++++++++++++++----- > 1 file changed, 126 insertions(+), 28 deletions(-) > > diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c > index e5d12c209e09..57b5ac02080a 100644 > --- a/tools/testing/selftests/vm/userfaultfd.c > +++ b/tools/testing/selftests/vm/userfaultfd.c > @@ -56,6 +56,7 @@ > #include <linux/userfaultfd.h> > #include <setjmp.h> > #include <stdbool.h> > +#include <assert.h> > > #include "../kselftest.h" > > @@ -78,6 +79,8 @@ static int test_type; > #define ALARM_INTERVAL_SECS 10 > static volatile bool test_uffdio_copy_eexist = true; > static volatile bool test_uffdio_zeropage_eexist = true; > +/* Whether to test uffd write-protection */ > +static bool test_uffdio_wp = false; > > static bool map_shared; > static int huge_fd; > @@ -92,6 +95,7 @@ pthread_attr_t attr; > struct uffd_stats { > int cpu; > unsigned long missing_faults; > + unsigned long wp_faults; > }; > > /* pthread_mutex_t starts at page offset 0 */ > @@ -141,9 +145,29 @@ static void uffd_stats_reset(struct uffd_stats *uffd_stats, > for (i = 0; i < n_cpus; i++) { > uffd_stats[i].cpu = i; > uffd_stats[i].missing_faults = 0; > + uffd_stats[i].wp_faults = 0; > } > } > > +static void uffd_stats_report(struct uffd_stats *stats, int n_cpus) > +{ > + int i; > + unsigned long long miss_total = 0, wp_total = 0; > + > + for (i = 0; i < n_cpus; i++) { > + miss_total += stats[i].missing_faults; > + wp_total += stats[i].wp_faults; > + } > + > + printf("userfaults: %llu missing (", miss_total); > + for (i = 0; i < n_cpus; i++) > + printf("%lu+", stats[i].missing_faults); > + printf("\b), %llu wp (", wp_total); > + for (i = 0; i < n_cpus; i++) > + printf("%lu+", stats[i].wp_faults); > + printf("\b)\n"); > +} > + > static int anon_release_pages(char *rel_area) > { > int ret = 0; > @@ -264,19 +288,15 @@ struct uffd_test_ops { > void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset); > }; > > -#define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \ > - (1 << _UFFDIO_COPY) | \ > - (1 << _UFFDIO_ZEROPAGE)) > - > static struct uffd_test_ops anon_uffd_test_ops = { > - .expected_ioctls = ANON_EXPECTED_IOCTLS, > + .expected_ioctls = UFFD_API_RANGE_IOCTLS, > .allocate_area = anon_allocate_area, > .release_pages = anon_release_pages, > .alias_mapping = noop_alias_mapping, > }; > > static struct uffd_test_ops shmem_uffd_test_ops = { > - .expected_ioctls = ANON_EXPECTED_IOCTLS, > + .expected_ioctls = UFFD_API_RANGE_IOCTLS, Isn't UFFD_API_RANGE_IOCTLS includes UFFDIO_WP which is not supported for shmem? > .allocate_area = shmem_allocate_area, > .release_pages = shmem_release_pages, > .alias_mapping = noop_alias_mapping, ... -- Sincerely yours, Mike.