Use our ioctl overload to enable kcov capture around every ioctl.
---
 lib/igt_aux.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 lib/igt_aux.h |  5 ++++
 2 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index fb1dac2..71067b3 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -60,6 +60,7 @@
 #include "config.h"
 #include "intel_reg.h"
 #include "ioctl_wrappers.h"
+#include "igt_kcov.h"
 #include "igt_kms.h"
 #include "igt_pm.h"
 #include "igt_stats.h"
@@ -74,6 +75,77 @@
  * fit into any other topic.
  */
 
+static struct __igt_kcov_ioctl_global {
+       struct igt_kcov kcov;
+       void (*trace)(struct igt_kcov *, void *data);
+       void *data;
+       bool enable;
+} __igt_kcov_ioctl;
+
+static int
+__kcov_ioctl(int fd, unsigned long request, void *arg)
+{
+       int ret;
+
+       if (__igt_kcov_ioctl.enable)
+               igt_kcov_enable(&__igt_kcov_ioctl.kcov);
+
+       ret = ioctl(fd, request, arg);
+
+       if (__igt_kcov_ioctl.enable) {
+               int err = errno;
+
+               igt_kcov_disable(&__igt_kcov_ioctl.kcov);
+               __igt_kcov_ioctl.trace(&__igt_kcov_ioctl.kcov,
+                                      __igt_kcov_ioctl.data);
+               igt_kcov_reset(&__igt_kcov_ioctl.kcov);
+               errno = err;
+       }
+
+       return ret;
+}
+
+static int
+kcov_ioctl(int fd, unsigned long request, void *arg)
+{
+       int ret;
+       do {
+               ret = __kcov_ioctl(fd, request, arg);
+       } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+       return ret;
+}
+
+void igt_kcov_setup(void (*trace)(struct igt_kcov *, void *),
+                   void *data)
+{
+       if (!trace) {
+               igt_kcov_fini(&__igt_kcov_ioctl.kcov);
+               memset(&__igt_kcov_ioctl, 0, sizeof(__igt_kcov_ioctl));
+               return;
+       }
+
+       if (igt_kcov_init(&__igt_kcov_ioctl.kcov))
+               return;
+
+       __igt_kcov_ioctl.trace = trace;
+       __igt_kcov_ioctl.data = data;
+}
+
+void igt_kcov_start(void)
+{
+       if (__igt_kcov_ioctl.trace) {
+               __igt_kcov_ioctl.enable = true;
+               igt_ioctl = kcov_ioctl;
+       } else
+               igt_ioctl = drmIoctl;
+}
+
+void igt_kcov_stop(void)
+{
+       __igt_kcov_ioctl.enable = false;
+       igt_ioctl = drmIoctl;
+}
+
 
 /* signal interrupt helpers */
 
@@ -86,6 +158,7 @@
 #define sigev_notify_thread_id _sigev_un._tid
 
 static struct __igt_sigiter_global {
+       int (*old_ioctl)(int fd, unsigned long request, void *arg);
        pid_t tid;
        timer_t timer;
        struct timespec offset;
@@ -118,8 +191,8 @@ sig_ioctl(int fd, unsigned long request, void *arg)
        memset(&its, 0, sizeof(its));
        if (timer_settime(__igt_sigiter.timer, 0, &its, NULL)) {
                /* oops, we didn't undo the interrupter (i.e. !unwound abort) */
-               igt_ioctl = drmIoctl;
-               return drmIoctl(fd, request, arg);
+               igt_ioctl = __igt_sigiter.old_ioctl;
+               return igt_ioctl(fd, request, arg);
        }
 
        its.it_value = __igt_sigiter.offset;
@@ -131,7 +204,7 @@ sig_ioctl(int fd, unsigned long request, void *arg)
                ret = 0;
                serial = __igt_sigiter.stat.signals;
                igt_assert(timer_settime(__igt_sigiter.timer, 0, &its, NULL) == 
0);
-               if (ioctl(fd, request, arg))
+               if (__kcov_ioctl(fd, request, arg))
                        ret = errno;
                if (__igt_sigiter.stat.signals == serial)
                        __igt_sigiter.stat.miss++;
@@ -166,7 +239,7 @@ static bool igt_sigiter_start(struct __igt_sigiter *iter, 
bool enable)
         * tests, we cannot assume the state of the igt_ioctl indirection.
         */
        SIG_ASSERT(igt_ioctl == drmIoctl);
-       igt_ioctl = drmIoctl;
+       igt_ioctl = __igt_sigiter.old_ioctl;
 
        if (enable) {
                struct timespec start, end;
@@ -174,6 +247,7 @@ static bool igt_sigiter_start(struct __igt_sigiter *iter, 
bool enable)
                struct sigaction act;
                struct itimerspec its;
 
+               __igt_sigiter.old_ioctl = igt_ioctl;
                igt_ioctl = sig_ioctl;
                __igt_sigiter.tid = gettid();
 
@@ -226,7 +300,7 @@ static bool igt_sigiter_stop(struct __igt_sigiter *iter, 
bool enable)
 
                SIG_ASSERT(igt_ioctl == sig_ioctl);
                SIG_ASSERT(__igt_sigiter.tid == gettid());
-               igt_ioctl = drmIoctl;
+               igt_ioctl = __igt_sigiter.old_ioctl;
 
                timer_delete(__igt_sigiter.timer);
 
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index be0d2d6..3bfe3af 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -43,6 +43,11 @@ void igt_stop_signal_helper(void);
 void igt_fork_hang_detector(int fd);
 void igt_stop_hang_detector(void);
 
+struct igt_kcov;
+void igt_kcov_setup(void (*trace)(struct igt_kcov *, void *), void *data);
+void igt_kcov_start(void);
+void igt_kcov_stop(void);
+
 struct __igt_sigiter {
        unsigned pass;
 };
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to