// SPDX-License-Identifier: GPL-2.0
 #include <string.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <dirent.h>
 #include <inttypes.h>
                flags += flaglen;
        }
 }
+
+/*
+ * Open an fd at /proc/$pid/maps and configure procmap_out ready for
+ * PROCMAP_QUERY query. Returns 0 on success, or an error code otherwise.
+ */
+int open_procmap(pid_t pid, struct procmap_fd *procmap_out)
+{
+       char path[256];
+       int ret = 0;
+
+       memset(procmap_out, '\0', sizeof(*procmap_out));
+       sprintf(path, "/proc/%d/maps", pid);
+       procmap_out->query.size = sizeof(procmap_out->query);
+       procmap_out->fd = open(path, O_RDONLY);
+       if (procmap_out < 0)
+               ret = -errno;
+
+       return ret;
+}
+
+/* Perform PROCMAP_QUERY. Returns 0 on success, or an error code otherwise. */
+int query_procmap(struct procmap_fd *procmap)
+{
+       int ret = 0;
+
+       if (ioctl(procmap->fd, PROCMAP_QUERY, &procmap->query) == -1)
+               ret = -errno;
+
+       return ret;
+}
+
+/*
+ * Try to find the VMA at specified address, returns true if found, false if not
+ * found, and the test is failed if any other error occurs.
+ *
+ * On success, procmap->query is populated with the results.
+ */
+bool find_vma_procmap(struct procmap_fd *procmap, void *address)
+{
+       int err;
+
+       procmap->query.query_flags = 0;
+       procmap->query.query_addr = (unsigned long)address;
+       err = query_procmap(procmap);
+       if (!err)
+               return true;
+
+       if (err != -ENOENT)
+               ksft_exit_fail_msg("%s: Error %d on ioctl(PROCMAP_QUERY)\n",
+                                  __func__, err);
+       return false;
+}
+
+/*
+ * Close fd used by PROCMAP_QUERY mechanism. Returns 0 on success, or an error
+ * code otherwise.
+ */
+int close_procmap(struct procmap_fd *procmap)
+{
+       return close(procmap->fd);
+}
 
 #include <strings.h> /* ffsl() */
 #include <unistd.h> /* _SC_PAGESIZE */
 #include "../kselftest.h"
+#include <linux/fs.h>
 
 #define BIT_ULL(nr)                   (1ULL << (nr))
 #define PM_SOFT_DIRTY                 BIT_ULL(55)
 extern unsigned int __page_size;
 extern unsigned int __page_shift;
 
+/*
+ * Represents an open fd and PROCMAP_QUERY state for binary (via ioctl)
+ * /proc/$pid/[s]maps lookup.
+ */
+struct procmap_fd {
+       int fd;
+       struct procmap_query query;
+};
+
 static inline unsigned int psize(void)
 {
        if (!__page_size)
                              bool miss, bool wp, bool minor, uint64_t *ioctls);
 unsigned long get_free_hugepages(void);
 bool check_vmflag_io(void *addr);
+int open_procmap(pid_t pid, struct procmap_fd *procmap_out);
+int query_procmap(struct procmap_fd *procmap);
+bool find_vma_procmap(struct procmap_fd *procmap, void *address);
+int close_procmap(struct procmap_fd *procmap);
+
+static inline int open_self_procmap(struct procmap_fd *procmap_out)
+{
+       pid_t pid = getpid();
+
+       return open_procmap(pid, procmap_out);
+}
 
 /*
  * On ppc64 this will only work with radix 2M hugepage size