selftests/mm: let uffd_handle_page_fault() take wp parameter
Make the handler optionally apply WP bit when resolving page faults for either missing or minor page faults. This moves towards removing global test_uffdio_wp outside of the common code. Link: https://lkml.kernel.org/r/20230412164341.328618-1-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com> Cc: Axel Rasmussen <axelrasmussen@google.com> Cc: David Hildenbrand <david@redhat.com> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Mike Kravetz <mike.kravetz@oracle.com> Cc: Mike Rapoport (IBM) <rppt@kernel.org> Cc: Zach O'Keefe <zokeefe@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
508340845d
commit
0210c43ef6
@ -353,7 +353,7 @@ void wp_range(int ufd, __u64 start, __u64 len, bool wp)
|
||||
err("clear WP failed: address=0x%"PRIx64, (uint64_t)start);
|
||||
}
|
||||
|
||||
static void continue_range(int ufd, __u64 start, __u64 len)
|
||||
static void continue_range(int ufd, __u64 start, __u64 len, bool wp)
|
||||
{
|
||||
struct uffdio_continue req;
|
||||
int ret;
|
||||
@ -361,7 +361,7 @@ static void continue_range(int ufd, __u64 start, __u64 len)
|
||||
req.range.start = start;
|
||||
req.range.len = len;
|
||||
req.mode = 0;
|
||||
if (test_uffdio_wp)
|
||||
if (wp)
|
||||
req.mode |= UFFDIO_CONTINUE_MODE_WP;
|
||||
|
||||
if (ioctl(ufd, UFFDIO_CONTINUE, &req))
|
||||
@ -429,7 +429,8 @@ void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args)
|
||||
area_dst_alias));
|
||||
for (b = 0; b < page_size; ++b)
|
||||
area[b] = ~area[b];
|
||||
continue_range(uffd, msg->arg.pagefault.address, page_size);
|
||||
continue_range(uffd, msg->arg.pagefault.address, page_size,
|
||||
args->apply_wp);
|
||||
args->minor_faults++;
|
||||
} else {
|
||||
/*
|
||||
@ -459,7 +460,7 @@ void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args)
|
||||
offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
|
||||
offset &= ~(page_size-1);
|
||||
|
||||
if (copy_page(uffd, offset))
|
||||
if (copy_page(uffd, offset, args->apply_wp))
|
||||
args->missing_faults++;
|
||||
}
|
||||
}
|
||||
@ -555,7 +556,7 @@ static void wake_range(int ufd, unsigned long addr, unsigned long len)
|
||||
addr), exit(1);
|
||||
}
|
||||
|
||||
int __copy_page(int ufd, unsigned long offset, bool retry)
|
||||
int __copy_page(int ufd, unsigned long offset, bool retry, bool wp)
|
||||
{
|
||||
struct uffdio_copy uffdio_copy;
|
||||
|
||||
@ -564,7 +565,7 @@ int __copy_page(int ufd, unsigned long offset, bool retry)
|
||||
uffdio_copy.dst = (unsigned long) area_dst + offset;
|
||||
uffdio_copy.src = (unsigned long) area_src + offset;
|
||||
uffdio_copy.len = page_size;
|
||||
if (test_uffdio_wp)
|
||||
if (wp)
|
||||
uffdio_copy.mode = UFFDIO_COPY_MODE_WP;
|
||||
else
|
||||
uffdio_copy.mode = 0;
|
||||
@ -587,7 +588,7 @@ int __copy_page(int ufd, unsigned long offset, bool retry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_page(int ufd, unsigned long offset)
|
||||
int copy_page(int ufd, unsigned long offset, bool wp)
|
||||
{
|
||||
return __copy_page(ufd, offset, false);
|
||||
return __copy_page(ufd, offset, false, wp);
|
||||
}
|
||||
|
@ -72,6 +72,8 @@
|
||||
/* Userfaultfd test statistics */
|
||||
struct uffd_args {
|
||||
int cpu;
|
||||
/* Whether apply wr-protects when installing pages */
|
||||
bool apply_wp;
|
||||
unsigned long missing_faults;
|
||||
unsigned long wp_faults;
|
||||
unsigned long minor_faults;
|
||||
@ -104,8 +106,8 @@ void userfaultfd_open(uint64_t *features);
|
||||
int uffd_read_msg(int ufd, struct uffd_msg *msg);
|
||||
void wp_range(int ufd, __u64 start, __u64 len, bool wp);
|
||||
void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args);
|
||||
int __copy_page(int ufd, unsigned long offset, bool retry);
|
||||
int copy_page(int ufd, unsigned long offset);
|
||||
int __copy_page(int ufd, unsigned long offset, bool retry, bool wp);
|
||||
int copy_page(int ufd, unsigned long offset, bool wp);
|
||||
void *uffd_poll_thread(void *arg);
|
||||
|
||||
#define TEST_ANON 1
|
||||
|
@ -96,6 +96,7 @@ static void uffd_stats_reset(struct uffd_args *args, unsigned long n_cpus)
|
||||
|
||||
for (i = 0; i < n_cpus; i++) {
|
||||
args[i].cpu = i;
|
||||
args[i].apply_wp = test_uffdio_wp;
|
||||
args[i].missing_faults = 0;
|
||||
args[i].wp_faults = 0;
|
||||
args[i].minor_faults = 0;
|
||||
@ -155,7 +156,7 @@ static void *locking_thread(void *arg)
|
||||
|
||||
static int copy_page_retry(int ufd, unsigned long offset)
|
||||
{
|
||||
return __copy_page(ufd, offset, true);
|
||||
return __copy_page(ufd, offset, true, test_uffdio_wp);
|
||||
}
|
||||
|
||||
pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
@ -308,7 +309,7 @@ static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
|
||||
* This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
|
||||
* feature. Using monitor thread, verify no userfault events are generated.
|
||||
*/
|
||||
static int faulting_process(int signal_test)
|
||||
static int faulting_process(int signal_test, bool wp)
|
||||
{
|
||||
unsigned long nr;
|
||||
unsigned long long count;
|
||||
@ -343,7 +344,7 @@ static int faulting_process(int signal_test)
|
||||
if (steps == 1) {
|
||||
/* This is a MISSING request */
|
||||
steps++;
|
||||
if (copy_page(uffd, offset))
|
||||
if (copy_page(uffd, offset, wp))
|
||||
signalled++;
|
||||
} else {
|
||||
/* This is a WP request */
|
||||
@ -507,6 +508,7 @@ static int userfaultfd_events_test(void)
|
||||
true, test_uffdio_wp, false))
|
||||
err("register failure");
|
||||
|
||||
args.apply_wp = test_uffdio_wp;
|
||||
if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &args))
|
||||
err("uffd_poll_thread create");
|
||||
|
||||
@ -515,7 +517,7 @@ static int userfaultfd_events_test(void)
|
||||
err("fork");
|
||||
|
||||
if (!pid)
|
||||
exit(faulting_process(0));
|
||||
exit(faulting_process(0, test_uffdio_wp));
|
||||
|
||||
waitpid(pid, &err, 0);
|
||||
if (err)
|
||||
@ -551,11 +553,12 @@ static int userfaultfd_sig_test(void)
|
||||
true, test_uffdio_wp, false))
|
||||
err("register failure");
|
||||
|
||||
if (faulting_process(1))
|
||||
if (faulting_process(1, test_uffdio_wp))
|
||||
err("faulting process failed");
|
||||
|
||||
uffd_test_ops->release_pages(area_dst);
|
||||
|
||||
args.apply_wp = test_uffdio_wp;
|
||||
if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &args))
|
||||
err("uffd_poll_thread create");
|
||||
|
||||
@ -564,7 +567,7 @@ static int userfaultfd_sig_test(void)
|
||||
err("fork");
|
||||
|
||||
if (!pid)
|
||||
exit(faulting_process(2));
|
||||
exit(faulting_process(2, test_uffdio_wp));
|
||||
|
||||
waitpid(pid, &err, 0);
|
||||
if (err)
|
||||
@ -628,6 +631,7 @@ static int userfaultfd_minor_test(void)
|
||||
page_size);
|
||||
}
|
||||
|
||||
args.apply_wp = test_uffdio_wp;
|
||||
if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &args))
|
||||
err("uffd_poll_thread create");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user