[dpdk-dev] [PATCH 1/2] Move EAL source files into common directory.

Ravi Kerur rkerur at gmail.com
Tue Dec 16 19:52:35 CET 2014


Move eal_alarm.c eal_interrupts.c and eal_debug.c from linuxapp and
bsdapp directories into common directory.

Use RTE_EXEC_ENV_BSDAPP to differentiate between BSD and Linux.

Signed-off-by: Ravi Kerur <rkerur at gmail.com>
---
 lib/librte_eal/bsdapp/eal/eal_alarm.c         |  60 --
 lib/librte_eal/bsdapp/eal/eal_debug.c         | 113 ----
 lib/librte_eal/bsdapp/eal/eal_interrupts.c    |  71 ---
 lib/librte_eal/common/eal_common_alarm.c      | 268 +++++++++
 lib/librte_eal/common/eal_common_debug.c      | 113 ++++
 lib/librte_eal/common/eal_common_interrupts.c | 826
++++++++++++++++++++++++++
 lib/librte_eal/common/eal_vfio.h              |  55 ++
 lib/librte_eal/linuxapp/eal/eal_alarm.c       | 268 ---------
 lib/librte_eal/linuxapp/eal/eal_debug.c       | 113 ----
 lib/librte_eal/linuxapp/eal/eal_interrupts.c  | 826
--------------------------
 lib/librte_eal/linuxapp/eal/eal_vfio.h        |  55 --
 11 files changed, 1262 insertions(+), 1506 deletions(-)
 delete mode 100644 lib/librte_eal/bsdapp/eal/eal_alarm.c
 delete mode 100644 lib/librte_eal/bsdapp/eal/eal_debug.c
 delete mode 100644 lib/librte_eal/bsdapp/eal/eal_interrupts.c
 create mode 100644 lib/librte_eal/common/eal_common_alarm.c
 create mode 100644 lib/librte_eal/common/eal_common_debug.c
 create mode 100644 lib/librte_eal/common/eal_common_interrupts.c
 create mode 100644 lib/librte_eal/common/eal_vfio.h
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_alarm.c
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_debug.c
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_interrupts.c
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio.h

diff --git a/lib/librte_eal/bsdapp/eal/eal_alarm.c
b/lib/librte_eal/bsdapp/eal/eal_alarm.c
deleted file mode 100644
index 204df85..0000000
--- a/lib/librte_eal/bsdapp/eal/eal_alarm.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdlib.h>
-#include <errno.h>
-
-#include <rte_alarm.h>
-#include <rte_common.h>
-#include "eal_private.h"
-
-int
-rte_eal_alarm_init(void)
-{
-       return 0;
-}
-
-
-int
-rte_eal_alarm_set(uint64_t us __rte_unused,
-               rte_eal_alarm_callback cb_fn __rte_unused,
-               void *cb_arg __rte_unused)
-{
-       return -ENOTSUP;
-}
-
-int
-rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn __rte_unused,
-               void *cb_arg __rte_unused)
-{
-       return -ENOTSUP;
-}
diff --git a/lib/librte_eal/bsdapp/eal/eal_debug.c
b/lib/librte_eal/bsdapp/eal/eal_debug.c
deleted file mode 100644
index 44fc4f3..0000000
--- a/lib/librte_eal/bsdapp/eal/eal_debug.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <execinfo.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-
-#include <rte_log.h>
-#include <rte_debug.h>
-#include <rte_common.h>
-
-#define BACKTRACE_SIZE 256
-
-/* dump the stack of the calling core */
-void rte_dump_stack(void)
-{
-       void *func[BACKTRACE_SIZE];
-       char **symb = NULL;
-       int size;
-
-       size = backtrace(func, BACKTRACE_SIZE);
-       symb = backtrace_symbols(func, size);
-       while (size > 0) {
-               rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL,
-                       "%d: [%s]\n", size, symb[size - 1]);
-               size --;
-       }
-}
-
-/* not implemented in this environment */
-void rte_dump_registers(void)
-{
-       return;
-}
-
-/* call abort(), it will generate a coredump if enabled */
-void __rte_panic(const char *funcname, const char *format, ...)
-{
-       va_list ap;
-
-       /* disable history */
-       rte_log_set_history(0);
-
-       rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n",
funcname);
-       va_start(ap, format);
-       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
-       va_end(ap);
-       rte_dump_stack();
-       rte_dump_registers();
-       abort();
-}
-
-/*
- * Like rte_panic this terminates the application. However, no traceback is
- * provided and no core-dump is generated.
- */
-void
-rte_exit(int exit_code, const char *format, ...)
-{
-       va_list ap;
-
-       /* disable history */
-       rte_log_set_history(0);
-
-       if (exit_code != 0)
-               RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-                               "  Cause: ", exit_code);
-
-       va_start(ap, format);
-       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
-       va_end(ap);
-
-#ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR
-       exit(exit_code);
-#else
-       rte_dump_stack();
-       rte_dump_registers();
-       abort();
-#endif
-}
diff --git a/lib/librte_eal/bsdapp/eal/eal_interrupts.c
b/lib/librte_eal/bsdapp/eal/eal_interrupts.c
deleted file mode 100644
index cb7d4f1..0000000
--- a/lib/librte_eal/bsdapp/eal/eal_interrupts.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <rte_common.h>
-#include <rte_interrupts.h>
-#include "eal_private.h"
-
-int
-rte_intr_callback_register(struct rte_intr_handle *intr_handle
__rte_unused,
-                       rte_intr_callback_fn cb __rte_unused,
-                       void *cb_arg __rte_unused)
-{
-       return -ENOTSUP;
-}
-
-int
-rte_intr_callback_unregister(struct rte_intr_handle *intr_handle
__rte_unused,
-                       rte_intr_callback_fn cb_fn __rte_unused,
-                       void *cb_arg __rte_unused)
-{
-       return -ENOTSUP;
-}
-
-int
-rte_intr_enable(struct rte_intr_handle *intr_handle __rte_unused)
-{
-       return -ENOTSUP;
-}
-
-int
-rte_intr_disable(struct rte_intr_handle *intr_handle __rte_unused)
-{
-       return -ENOTSUP;
-}
-
-int
-rte_eal_intr_init(void)
-{
-       return 0;
-}
-
diff --git a/lib/librte_eal/common/eal_common_alarm.c
b/lib/librte_eal/common/eal_common_alarm.c
new file mode 100644
index 0000000..e8da32f
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_alarm.c
@@ -0,0 +1,268 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+#include <sys/timerfd.h>
+
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_interrupts.h>
+#include <rte_alarm.h>
+#include <rte_common.h>
+#include <rte_per_lcore.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_spinlock.h>
+#include <eal_private.h>
+
+#ifndef        TFD_NONBLOCK
+#include <fcntl.h>
+#define        TFD_NONBLOCK    O_NONBLOCK
+#endif
+
+#define NS_PER_US 1000
+#define US_PER_MS 1000
+#define MS_PER_S 1000
+#define US_PER_S (US_PER_MS * MS_PER_S)
+
+struct alarm_entry {
+       LIST_ENTRY(alarm_entry) next;
+       struct timeval time;
+       rte_eal_alarm_callback cb_fn;
+       void *cb_arg;
+       volatile uint8_t executing;
+       volatile pthread_t executing_id;
+};
+
+static LIST_HEAD(alarm_list, alarm_entry) alarm_list =
LIST_HEAD_INITIALIZER();
+static rte_spinlock_t alarm_list_lk = RTE_SPINLOCK_INITIALIZER;
+
+static struct rte_intr_handle intr_handle = {.fd = -1 };
+static int handler_registered = 0;
+static void eal_alarm_callback(struct rte_intr_handle *hdl, void *arg);
+
+int
+rte_eal_alarm_init(void)
+{
+       intr_handle.type = RTE_INTR_HANDLE_ALARM;
+       /* create a timerfd file descriptor */
+       intr_handle.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+       if (intr_handle.fd == -1)
+               goto error;
+
+       return 0;
+
+error:
+       rte_errno = errno;
+       return -1;
+}
+
+static void
+eal_alarm_callback(struct rte_intr_handle *hdl __rte_unused,
+               void *arg __rte_unused)
+{
+       struct timeval now;
+       struct alarm_entry *ap;
+
+       rte_spinlock_lock(&alarm_list_lk);
+       while ((ap = LIST_FIRST(&alarm_list)) !=NULL &&
+                       gettimeofday(&now, NULL) == 0 &&
+                       (ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec
== now.tv_sec &&
+                                               ap->time.tv_usec <=
now.tv_usec))){
+               ap->executing = 1;
+               ap->executing_id = pthread_self();
+               rte_spinlock_unlock(&alarm_list_lk);
+
+               ap->cb_fn(ap->cb_arg);
+
+               rte_spinlock_lock(&alarm_list_lk);
+
+               LIST_REMOVE(ap, next);
+               rte_free(ap);
+       }
+
+       if (!LIST_EMPTY(&alarm_list)) {
+               struct itimerspec atime = { .it_interval = { 0, 0 } };
+
+               ap = LIST_FIRST(&alarm_list);
+               atime.it_value.tv_sec = ap->time.tv_sec;
+               atime.it_value.tv_nsec = ap->time.tv_usec * NS_PER_US;
+               /* perform borrow for subtraction if necessary */
+               if (now.tv_usec > ap->time.tv_usec)
+                       atime.it_value.tv_sec--, atime.it_value.tv_nsec +=
US_PER_S * NS_PER_US;
+
+               atime.it_value.tv_sec -= now.tv_sec;
+               atime.it_value.tv_nsec -= now.tv_usec * NS_PER_US;
+               timerfd_settime(intr_handle.fd, 0, &atime, NULL);
+       }
+       rte_spinlock_unlock(&alarm_list_lk);
+}
+
+int
+rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg)
+{
+       struct timeval now;
+       int ret = 0;
+       struct alarm_entry *ap, *new_alarm;
+
+       /* Check parameters, including that us won't cause a uint64_t
overflow */
+       if (us < 1 || us > (UINT64_MAX - US_PER_S) || cb_fn == NULL)
+               return -EINVAL;
+
+       new_alarm = rte_zmalloc(NULL, sizeof(*new_alarm), 0);
+       if (new_alarm == NULL)
+               return -ENOMEM;
+
+       /* use current time to calculate absolute time of alarm */
+       gettimeofday(&now, NULL);
+
+       new_alarm->cb_fn = cb_fn;
+       new_alarm->cb_arg = cb_arg;
+       new_alarm->time.tv_usec = (now.tv_usec + us) % US_PER_S;
+       new_alarm->time.tv_sec = now.tv_sec + ((now.tv_usec + us) /
US_PER_S);
+
+       rte_spinlock_lock(&alarm_list_lk);
+       if (!handler_registered) {
+               ret |= rte_intr_callback_register(&intr_handle,
+                               eal_alarm_callback, NULL);
+               handler_registered = (ret == 0) ? 1 : 0;
+       }
+
+       if (LIST_EMPTY(&alarm_list))
+               LIST_INSERT_HEAD(&alarm_list, new_alarm, next);
+       else {
+               LIST_FOREACH(ap, &alarm_list, next) {
+                       if (ap->time.tv_sec > new_alarm->time.tv_sec ||
+                                       (ap->time.tv_sec ==
new_alarm->time.tv_sec &&
+                                                       ap->time.tv_usec >
new_alarm->time.tv_usec)){
+                               LIST_INSERT_BEFORE(ap, new_alarm, next);
+                               break;
+                       }
+                       if (LIST_NEXT(ap, next) == NULL) {
+                               LIST_INSERT_AFTER(ap, new_alarm, next);
+                               break;
+                       }
+               }
+       }
+
+       if (LIST_FIRST(&alarm_list) == new_alarm) {
+               struct itimerspec alarm_time = {
+                       .it_interval = {0, 0},
+                       .it_value = {
+                               .tv_sec = us / US_PER_S,
+                               .tv_nsec = (us % US_PER_S) * NS_PER_US,
+                       },
+               };
+               ret |= timerfd_settime(intr_handle.fd, 0, &alarm_time,
NULL);
+       }
+       rte_spinlock_unlock(&alarm_list_lk);
+
+       return ret;
+}
+
+int
+rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
+{
+       struct alarm_entry *ap, *ap_prev;
+       int count = 0;
+       int err = 0;
+       int executing;
+
+       if (!cb_fn) {
+               rte_errno = EINVAL;
+               return -1;
+       }
+
+       do {
+               executing = 0;
+               rte_spinlock_lock(&alarm_list_lk);
+               /* remove any matches at the start of the list */
+               while ((ap = LIST_FIRST(&alarm_list)) != NULL &&
+                               cb_fn == ap->cb_fn &&
+                               (cb_arg == (void *)-1 || cb_arg ==
ap->cb_arg)) {
+
+                       if (ap->executing == 0) {
+                               LIST_REMOVE(ap, next);
+                               rte_free(ap);
+                               count++;
+                       } else {
+                               /* If calling from other context, mark that
alarm is executing
+                                * so loop can spin till it finish.
Otherwise we are trying to
+                                * cancel our self - mark it by EINPROGRESS
*/
+                               if (pthread_equal(ap->executing_id,
pthread_self()) == 0)
+                                       executing++;
+                               else
+                                       err = EINPROGRESS;
+
+                               break;
+                       }
+               }
+               ap_prev = ap;
+
+               /* now go through list, removing entries not at start */
+               LIST_FOREACH(ap, &alarm_list, next) {
+                       /* this won't be true first time through */
+                       if (cb_fn == ap->cb_fn &&
+                                       (cb_arg == (void *)-1 || cb_arg ==
ap->cb_arg)) {
+
+                               if (ap->executing == 0) {
+                                       LIST_REMOVE(ap, next);
+                                       rte_free(ap);
+                                       count++;
+                                       ap = ap_prev;
+                               } else if (pthread_equal(ap->executing_id,
pthread_self()) == 0)
+                                       executing++;
+                               else
+                                       err = EINPROGRESS;
+                       }
+                       ap_prev = ap;
+               }
+               rte_spinlock_unlock(&alarm_list_lk);
+       } while (executing != 0);
+
+       if (count == 0 && err == 0)
+               rte_errno = ENOENT;
+       else if (err)
+               rte_errno = err;
+
+       return count;
+}
diff --git a/lib/librte_eal/common/eal_common_debug.c
b/lib/librte_eal/common/eal_common_debug.c
new file mode 100644
index 0000000..44fc4f3
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_debug.c
@@ -0,0 +1,113 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <execinfo.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_common.h>
+
+#define BACKTRACE_SIZE 256
+
+/* dump the stack of the calling core */
+void rte_dump_stack(void)
+{
+       void *func[BACKTRACE_SIZE];
+       char **symb = NULL;
+       int size;
+
+       size = backtrace(func, BACKTRACE_SIZE);
+       symb = backtrace_symbols(func, size);
+       while (size > 0) {
+               rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL,
+                       "%d: [%s]\n", size, symb[size - 1]);
+               size --;
+       }
+}
+
+/* not implemented in this environment */
+void rte_dump_registers(void)
+{
+       return;
+}
+
+/* call abort(), it will generate a coredump if enabled */
+void __rte_panic(const char *funcname, const char *format, ...)
+{
+       va_list ap;
+
+       /* disable history */
+       rte_log_set_history(0);
+
+       rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n",
funcname);
+       va_start(ap, format);
+       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+       va_end(ap);
+       rte_dump_stack();
+       rte_dump_registers();
+       abort();
+}
+
+/*
+ * Like rte_panic this terminates the application. However, no traceback is
+ * provided and no core-dump is generated.
+ */
+void
+rte_exit(int exit_code, const char *format, ...)
+{
+       va_list ap;
+
+       /* disable history */
+       rte_log_set_history(0);
+
+       if (exit_code != 0)
+               RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
+                               "  Cause: ", exit_code);
+
+       va_start(ap, format);
+       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+       va_end(ap);
+
+#ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR
+       exit(exit_code);
+#else
+       rte_dump_stack();
+       rte_dump_registers();
+       abort();
+#endif
+}
diff --git a/lib/librte_eal/common/eal_common_interrupts.c
b/lib/librte_eal/common/eal_common_interrupts.c
new file mode 100644
index 0000000..dc2668a
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_interrupts.c
@@ -0,0 +1,826 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
+#include <sys/ioctl.h>
+
+#include <rte_common.h>
+#include <rte_interrupts.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_mempool.h>
+#include <rte_pci.h>
+#include <rte_malloc.h>
+#include <rte_errno.h>
+#include <rte_spinlock.h>
+
+#include "eal_private.h"
+#include "eal_vfio.h"
+
+#define EAL_INTR_EPOLL_WAIT_FOREVER (-1)
+
+/**
+ * union for pipe fds.
+ */
+union intr_pipefds{
+       struct {
+               int pipefd[2];
+       };
+       struct {
+               int readfd;
+               int writefd;
+       };
+};
+
+/**
+ * union buffer for reading on different devices
+ */
+union rte_intr_read_buffer {
+       int uio_intr_count;              /* for uio device */
+#ifdef VFIO_PRESENT
+       uint64_t vfio_intr_count;        /* for vfio device */
+#endif
+       uint64_t timerfd_num;            /* for timerfd */
+       char charbuf[16];                /* for others */
+};
+
+TAILQ_HEAD(rte_intr_cb_list, rte_intr_callback);
+TAILQ_HEAD(rte_intr_source_list, rte_intr_source);
+
+struct rte_intr_callback {
+       TAILQ_ENTRY(rte_intr_callback) next;
+       rte_intr_callback_fn cb_fn;  /**< callback address */
+       void *cb_arg;                /**< parameter for callback */
+};
+
+struct rte_intr_source {
+       TAILQ_ENTRY(rte_intr_source) next;
+       struct rte_intr_handle intr_handle; /**< interrupt handle */
+       struct rte_intr_cb_list callbacks;  /**< user callbacks */
+       uint32_t active;
+};
+
+/* global spinlock for interrupt data operation */
+static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
+
+/* union buffer for pipe read/write */
+static union intr_pipefds intr_pipe;
+
+/* interrupt sources list */
+static struct rte_intr_source_list intr_sources;
+
+/* interrupt handling thread */
+static pthread_t intr_thread;
+
+/* VFIO interrupts */
+#ifdef VFIO_PRESENT
+
+#define IRQ_SET_BUF_LEN  (sizeof(struct vfio_irq_set) + sizeof(int))
+
+/* enable legacy (INTx) interrupts */
+static int
+vfio_enable_intx(struct rte_intr_handle *intr_handle) {
+       struct vfio_irq_set *irq_set;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       int len, ret;
+       int *fd_ptr;
+
+       len = sizeof(irq_set_buf);
+
+       /* enable INTx */
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+       irq_set->start = 0;
+       fd_ptr = (int *) &irq_set->data;
+       *fd_ptr = intr_handle->fd;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error enabling INTx interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+
+       /* unmask INTx after enabling */
+       memset(irq_set, 0, len);
+       len = sizeof(struct vfio_irq_set);
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_UNMASK;
+       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+       return 0;
+}
+
+/* disable legacy (INTx) interrupts */
+static int
+vfio_disable_intx(struct rte_intr_handle *intr_handle) {
+       struct vfio_irq_set *irq_set;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       int len, ret;
+
+       len = sizeof(struct vfio_irq_set);
+
+       /* mask interrupts before disabling */
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_UNMASK;
+       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+
+       /* disable INTx*/
+       memset(irq_set, 0, len);
+       irq_set->argsz = len;
+       irq_set->count = 0;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL,
+                       "Error disabling INTx interrupts for fd %d\n",
intr_handle->fd);
+               return -1;
+       }
+       return 0;
+}
+
+/* enable MSI-X interrupts */
+static int
+vfio_enable_msi(struct rte_intr_handle *intr_handle) {
+       int len, ret;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       struct vfio_irq_set *irq_set;
+       int *fd_ptr;
+
+       len = sizeof(irq_set_buf);
+
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
+       irq_set->start = 0;
+       fd_ptr = (int *) &irq_set->data;
+       *fd_ptr = intr_handle->fd;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error enabling MSI interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+
+       /* manually trigger interrupt to enable it */
+       memset(irq_set, 0, len);
+       len = sizeof(struct vfio_irq_set);
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error triggering MSI interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+       return 0;
+}
+
+/* disable MSI-X interrupts */
+static int
+vfio_disable_msi(struct rte_intr_handle *intr_handle) {
+       struct vfio_irq_set *irq_set;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       int len, ret;
+
+       len = sizeof(struct vfio_irq_set);
+
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 0;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret)
+               RTE_LOG(ERR, EAL,
+                       "Error disabling MSI interrupts for fd %d\n",
intr_handle->fd);
+
+       return ret;
+}
+
+/* enable MSI-X interrupts */
+static int
+vfio_enable_msix(struct rte_intr_handle *intr_handle) {
+       int len, ret;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       struct vfio_irq_set *irq_set;
+       int *fd_ptr;
+
+       len = sizeof(irq_set_buf);
+
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+       irq_set->start = 0;
+       fd_ptr = (int *) &irq_set->data;
+       *fd_ptr = intr_handle->fd;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error enabling MSI-X interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+
+       /* manually trigger interrupt to enable it */
+       memset(irq_set, 0, len);
+       len = sizeof(struct vfio_irq_set);
+       irq_set->argsz = len;
+       irq_set->count = 1;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret) {
+               RTE_LOG(ERR, EAL, "Error triggering MSI-X interrupts for fd
%d\n",
+                                               intr_handle->fd);
+               return -1;
+       }
+       return 0;
+}
+
+/* disable MSI-X interrupts */
+static int
+vfio_disable_msix(struct rte_intr_handle *intr_handle) {
+       struct vfio_irq_set *irq_set;
+       char irq_set_buf[IRQ_SET_BUF_LEN];
+       int len, ret;
+
+       len = sizeof(struct vfio_irq_set);
+
+       irq_set = (struct vfio_irq_set *) irq_set_buf;
+       irq_set->argsz = len;
+       irq_set->count = 0;
+       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
+       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+       irq_set->start = 0;
+
+       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
+
+       if (ret)
+               RTE_LOG(ERR, EAL,
+                       "Error disabling MSI-X interrupts for fd %d\n",
intr_handle->fd);
+
+       return ret;
+}
+#endif
+
+int
+rte_intr_callback_register(struct rte_intr_handle *intr_handle,
+                       rte_intr_callback_fn cb, void *cb_arg)
+{
+       int ret, wake_thread;
+       struct rte_intr_source *src;
+       struct rte_intr_callback *callback;
+
+       wake_thread = 0;
+
+       /* first do parameter checking */
+       if (intr_handle == NULL || intr_handle->fd < 0 || cb == NULL) {
+               RTE_LOG(ERR, EAL,
+                       "Registering with invalid input parameter\n");
+               return -EINVAL;
+       }
+
+       /* allocate a new interrupt callback entity */
+       callback = rte_zmalloc("interrupt callback list",
+                               sizeof(*callback), 0);
+       if (callback == NULL) {
+               RTE_LOG(ERR, EAL, "Can not allocate memory\n");
+               return -ENOMEM;
+       }
+       callback->cb_fn = cb;
+       callback->cb_arg = cb_arg;
+
+       rte_spinlock_lock(&intr_lock);
+
+       /* check if there is at least one callback registered for the fd */
+       TAILQ_FOREACH(src, &intr_sources, next) {
+               if (src->intr_handle.fd == intr_handle->fd) {
+                       /* we had no interrupts for this */
+                       if TAILQ_EMPTY(&src->callbacks)
+                               wake_thread = 1;
+
+                       TAILQ_INSERT_TAIL(&(src->callbacks), callback,
next);
+                       ret = 0;
+                       break;
+               }
+       }
+
+       /* no existing callbacks for this - add new source */
+       if (src == NULL) {
+               if ((src = rte_zmalloc("interrupt source list",
+                               sizeof(*src), 0)) == NULL) {
+                       RTE_LOG(ERR, EAL, "Can not allocate memory\n");
+                       rte_free(callback);
+                       ret = -ENOMEM;
+               } else {
+                       src->intr_handle = *intr_handle;
+                       TAILQ_INIT(&src->callbacks);
+                       TAILQ_INSERT_TAIL(&(src->callbacks), callback,
next);
+                       TAILQ_INSERT_TAIL(&intr_sources, src, next);
+                       wake_thread = 1;
+                       ret = 0;
+               }
+       }
+
+       rte_spinlock_unlock(&intr_lock);
+
+       /**
+        * check if need to notify the pipe fd waited by epoll_wait to
+        * rebuild the wait list.
+        */
+       if (wake_thread)
+               if (write(intr_pipe.writefd, "1", 1) < 0)
+                       return -EPIPE;
+
+       return (ret);
+}
+
+int
+rte_intr_callback_unregister(struct rte_intr_handle *intr_handle,
+                       rte_intr_callback_fn cb_fn, void *cb_arg)
+{
+       int ret;
+       struct rte_intr_source *src;
+       struct rte_intr_callback *cb, *next;
+
+       /* do parameter checking first */
+       if (intr_handle == NULL || intr_handle->fd < 0) {
+               RTE_LOG(ERR, EAL,
+               "Unregistering with invalid input parameter\n");
+               return -EINVAL;
+       }
+
+       rte_spinlock_lock(&intr_lock);
+
+       /* check if the insterrupt source for the fd is existent */
+       TAILQ_FOREACH(src, &intr_sources, next)
+               if (src->intr_handle.fd == intr_handle->fd)
+                       break;
+
+       /* No interrupt source registered for the fd */
+       if (src == NULL) {
+               ret = -ENOENT;
+
+       /* interrupt source has some active callbacks right now. */
+       } else if (src->active != 0) {
+               ret = -EAGAIN;
+
+       /* ok to remove. */
+       } else {
+               ret = 0;
+
+               /*walk through the callbacks and remove all that match. */
+               for (cb = TAILQ_FIRST(&src->callbacks); cb != NULL; cb =
next) {
+
+                       next = TAILQ_NEXT(cb, next);
+
+                       if (cb->cb_fn == cb_fn && (cb_arg == (void *)-1 ||
+                                       cb->cb_arg == cb_arg)) {
+                               TAILQ_REMOVE(&src->callbacks, cb, next);
+                               rte_free(cb);
+                               ret++;
+                       }
+               }
+
+               /* all callbacks for that source are removed. */
+               if (TAILQ_EMPTY(&src->callbacks)) {
+                       TAILQ_REMOVE(&intr_sources, src, next);
+                       rte_free(src);
+               }
+       }
+
+       rte_spinlock_unlock(&intr_lock);
+
+       /* notify the pipe fd waited by epoll_wait to rebuild the wait list
*/
+       if (ret >= 0 && write(intr_pipe.writefd, "1", 1) < 0) {
+               ret = -EPIPE;
+       }
+
+       return (ret);
+}
+
+int
+rte_intr_enable(struct rte_intr_handle *intr_handle)
+{
+       const int value = 1;
+
+       if (!intr_handle || intr_handle->fd < 0)
+               return -1;
+
+       switch (intr_handle->type){
+       /* write to the uio fd to enable the interrupt */
+       case RTE_INTR_HANDLE_UIO:
+               if (write(intr_handle->fd, &value, sizeof(value)) < 0) {
+                       RTE_LOG(ERR, EAL,
+                               "Error enabling interrupts for fd %d\n",
+                                                       intr_handle->fd);
+                       return -1;
+               }
+               break;
+       /* not used at this moment */
+       case RTE_INTR_HANDLE_ALARM:
+               return -1;
+#ifdef VFIO_PRESENT
+       case RTE_INTR_HANDLE_VFIO_MSIX:
+               if (vfio_enable_msix(intr_handle))
+                       return -1;
+               break;
+       case RTE_INTR_HANDLE_VFIO_MSI:
+               if (vfio_enable_msi(intr_handle))
+                       return -1;
+               break;
+       case RTE_INTR_HANDLE_VFIO_LEGACY:
+               if (vfio_enable_intx(intr_handle))
+                       return -1;
+               break;
+#endif
+       /* unknown handle type */
+       default:
+               RTE_LOG(ERR, EAL,
+                       "Unknown handle type of fd %d\n",
+                                       intr_handle->fd);
+               return -1;
+       }
+
+       return 0;
+}
+
+int
+rte_intr_disable(struct rte_intr_handle *intr_handle)
+{
+       const int value = 0;
+
+       if (!intr_handle || intr_handle->fd < 0)
+               return -1;
+
+       switch (intr_handle->type){
+       /* write to the uio fd to disable the interrupt */
+       case RTE_INTR_HANDLE_UIO:
+               if (write(intr_handle->fd, &value, sizeof(value)) < 0){
+                       RTE_LOG(ERR, EAL,
+                               "Error disabling interrupts for fd %d\n",
+                                                       intr_handle->fd);
+                       return -1;
+               }
+               break;
+       /* not used at this moment */
+       case RTE_INTR_HANDLE_ALARM:
+               return -1;
+#ifdef VFIO_PRESENT
+       case RTE_INTR_HANDLE_VFIO_MSIX:
+               if (vfio_disable_msix(intr_handle))
+                       return -1;
+               break;
+       case RTE_INTR_HANDLE_VFIO_MSI:
+               if (vfio_disable_msi(intr_handle))
+                       return -1;
+               break;
+       case RTE_INTR_HANDLE_VFIO_LEGACY:
+               if (vfio_disable_intx(intr_handle))
+                       return -1;
+               break;
+#endif
+       /* unknown handle type */
+       default:
+               RTE_LOG(ERR, EAL,
+                       "Unknown handle type of fd %d\n",
+                                       intr_handle->fd);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+eal_intr_process_interrupts(struct epoll_event *events, int nfds)
+{
+       int n, bytes_read;
+       struct rte_intr_source *src;
+       struct rte_intr_callback *cb;
+       union rte_intr_read_buffer buf;
+       struct rte_intr_callback active_cb;
+
+       for (n = 0; n < nfds; n++) {
+
+               /**
+                * if the pipe fd is ready to read, return out to
+                * rebuild the wait list.
+                */
+               if (events[n].data.fd == intr_pipe.readfd){
+                       int r = read(intr_pipe.readfd, buf.charbuf,
+                                       sizeof(buf.charbuf));
+                       RTE_SET_USED(r);
+                       return -1;
+               }
+               rte_spinlock_lock(&intr_lock);
+               TAILQ_FOREACH(src, &intr_sources, next)
+                       if (src->intr_handle.fd ==
+                                       events[n].data.fd)
+                               break;
+               if (src == NULL){
+                       rte_spinlock_unlock(&intr_lock);
+                       continue;
+               }
+
+               /* mark this interrupt source as active and release the
lock. */
+               src->active = 1;
+               rte_spinlock_unlock(&intr_lock);
+
+               /* set the length to be read dor different handle type */
+               switch (src->intr_handle.type) {
+               case RTE_INTR_HANDLE_UIO:
+                       bytes_read = sizeof(buf.uio_intr_count);
+                       break;
+               case RTE_INTR_HANDLE_ALARM:
+                       bytes_read = sizeof(buf.timerfd_num);
+                       break;
+#ifdef VFIO_PRESENT
+               case RTE_INTR_HANDLE_VFIO_MSIX:
+               case RTE_INTR_HANDLE_VFIO_MSI:
+               case RTE_INTR_HANDLE_VFIO_LEGACY:
+                       bytes_read = sizeof(buf.vfio_intr_count);
+                       break;
+#endif
+               default:
+                       bytes_read = 1;
+                       break;
+               }
+
+               /**
+                * read out to clear the ready-to-be-read flag
+                * for epoll_wait.
+                */
+               bytes_read = read(events[n].data.fd, &buf, bytes_read);
+
+               if (bytes_read < 0)
+                       RTE_LOG(ERR, EAL, "Error reading from file "
+                               "descriptor %d: %s\n", events[n].data.fd,
+                                                       strerror(errno));
+               else if (bytes_read == 0)
+                       RTE_LOG(ERR, EAL, "Read nothing from file "
+                               "descriptor %d\n", events[n].data.fd);
+
+               /* grab a lock, again to call callbacks and update status.
*/
+               rte_spinlock_lock(&intr_lock);
+
+               if (bytes_read > 0) {
+
+                       /* Finally, call all callbacks. */
+                       TAILQ_FOREACH(cb, &src->callbacks, next) {
+
+                               /* make a copy and unlock. */
+                               active_cb = *cb;
+                               rte_spinlock_unlock(&intr_lock);
+
+                               /* call the actual callback */
+                               active_cb.cb_fn(&src->intr_handle,
+                                       active_cb.cb_arg);
+
+                               /*get the lock back. */
+                               rte_spinlock_lock(&intr_lock);
+                       }
+               }
+
+               /* we done with that interrupt source, release it. */
+               src->active = 0;
+               rte_spinlock_unlock(&intr_lock);
+       }
+
+       return 0;
+}
+
+/**
+ * It handles all the interrupts.
+ *
+ * @param pfd
+ *  epoll file descriptor.
+ * @param totalfds
+ *  The number of file descriptors added in epoll.
+ *
+ * @return
+ *  void
+ */
+static void
+eal_intr_handle_interrupts(int pfd, unsigned totalfds)
+{
+       struct epoll_event events[totalfds];
+       int nfds = 0;
+
+       for(;;) {
+               nfds = epoll_wait(pfd, events, totalfds,
+                       EAL_INTR_EPOLL_WAIT_FOREVER);
+               /* epoll_wait fail */
+               if (nfds < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       RTE_LOG(ERR, EAL,
+                               "epoll_wait returns with fail\n");
+                       return;
+               }
+               /* epoll_wait timeout, will never happens here */
+               else if (nfds == 0)
+                       continue;
+               /* epoll_wait has at least one fd ready to read */
+               if (eal_intr_process_interrupts(events, nfds) < 0)
+                       return;
+       }
+}
+
+/**
+ * It builds/rebuilds up the epoll file descriptor with all the
+ * file descriptors being waited on. Then handles the interrupts.
+ *
+ * @param arg
+ *  pointer. (unused)
+ *
+ * @return
+ *  never return;
+ */
+static __attribute__((noreturn)) void *
+eal_intr_thread_main(__rte_unused void *arg)
+{
+       struct epoll_event ev;
+
+       /* host thread, never break out */
+       for (;;) {
+               /* build up the epoll fd with all descriptors we are to
+                * wait on then pass it to the handle_interrupts function
+                */
+               static struct epoll_event pipe_event = {
+                       .events = EPOLLIN | EPOLLPRI,
+               };
+               struct rte_intr_source *src;
+               unsigned numfds = 0;
+
+               /* create epoll fd */
+               int pfd = epoll_create(1);
+               if (pfd < 0)
+                       rte_panic("Cannot create epoll instance\n");
+
+               pipe_event.data.fd = intr_pipe.readfd;
+               /**
+                * add pipe fd into wait list, this pipe is used to
+                * rebuild the wait list.
+                */
+               if (epoll_ctl(pfd, EPOLL_CTL_ADD, intr_pipe.readfd,
+                                               &pipe_event) < 0) {
+                       rte_panic("Error adding fd to %d epoll_ctl, %s\n",
+                                       intr_pipe.readfd, strerror(errno));
+               }
+               numfds++;
+
+               rte_spinlock_lock(&intr_lock);
+
+               TAILQ_FOREACH(src, &intr_sources, next) {
+                       if (src->callbacks.tqh_first == NULL)
+                               continue; /* skip those with no callbacks */
+                       ev.events = EPOLLIN | EPOLLPRI;
+                       ev.data.fd = src->intr_handle.fd;
+
+                       /**
+                        * add all the uio device file descriptor
+                        * into wait list.
+                        */
+                       if (epoll_ctl(pfd, EPOLL_CTL_ADD,
+                                       src->intr_handle.fd, &ev) < 0){
+                               rte_panic("Error adding fd %d epoll_ctl,
%s\n",
+                                       src->intr_handle.fd,
strerror(errno));
+                       }
+                       else
+                               numfds++;
+               }
+               rte_spinlock_unlock(&intr_lock);
+               /* serve the interrupt */
+               eal_intr_handle_interrupts(pfd, numfds);
+
+               /**
+                * when we return, we need to rebuild the
+                * list of fds to monitor.
+                */
+               close(pfd);
+       }
+}
+
+int
+rte_eal_intr_init(void)
+{
+       int ret = 0;
+
+       /* init the global interrupt source head */
+       TAILQ_INIT(&intr_sources);
+
+       /**
+        * create a pipe which will be waited by epoll and notified to
+        * rebuild the wait list of epoll.
+        */
+       if (pipe(intr_pipe.pipefd) < 0)
+               return -1;
+
+       /* create the host thread to wait/handle the interrupt */
+       ret = pthread_create(&intr_thread, NULL,
+                       eal_intr_thread_main, NULL);
+       if (ret != 0)
+               RTE_LOG(ERR, EAL,
+                       "Failed to create thread for interrupt handling\n");
+
+       return -ret;
+}
+
diff --git a/lib/librte_eal/common/eal_vfio.h
b/lib/librte_eal/common/eal_vfio.h
new file mode 100644
index 0000000..03e693e
--- /dev/null
+++ b/lib/librte_eal/common/eal_vfio.h
@@ -0,0 +1,55 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EAL_VFIO_H_
+#define EAL_VFIO_H_
+
+/*
+ * determine if VFIO is present on the system
+ */
+#ifdef RTE_EAL_VFIO
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+#include <linux/vfio.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#define RTE_PCI_MSIX_TABLE_BIR 0x7
+#else
+#define RTE_PCI_MSIX_TABLE_BIR PCI_MSIX_TABLE_BIR
+#endif
+
+#define VFIO_PRESENT
+#endif /* kernel version */
+#endif /* RTE_EAL_VFIO */
+
+#endif /* EAL_VFIO_H_ */
diff --git a/lib/librte_eal/linuxapp/eal/eal_alarm.c
b/lib/librte_eal/linuxapp/eal/eal_alarm.c
deleted file mode 100644
index e8da32f..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_alarm.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <stdint.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-#include <sys/timerfd.h>
-
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_interrupts.h>
-#include <rte_alarm.h>
-#include <rte_common.h>
-#include <rte_per_lcore.h>
-#include <rte_tailq.h>
-#include <rte_eal.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#include <rte_errno.h>
-#include <rte_malloc.h>
-#include <rte_spinlock.h>
-#include <eal_private.h>
-
-#ifndef        TFD_NONBLOCK
-#include <fcntl.h>
-#define        TFD_NONBLOCK    O_NONBLOCK
-#endif
-
-#define NS_PER_US 1000
-#define US_PER_MS 1000
-#define MS_PER_S 1000
-#define US_PER_S (US_PER_MS * MS_PER_S)
-
-struct alarm_entry {
-       LIST_ENTRY(alarm_entry) next;
-       struct timeval time;
-       rte_eal_alarm_callback cb_fn;
-       void *cb_arg;
-       volatile uint8_t executing;
-       volatile pthread_t executing_id;
-};
-
-static LIST_HEAD(alarm_list, alarm_entry) alarm_list =
LIST_HEAD_INITIALIZER();
-static rte_spinlock_t alarm_list_lk = RTE_SPINLOCK_INITIALIZER;
-
-static struct rte_intr_handle intr_handle = {.fd = -1 };
-static int handler_registered = 0;
-static void eal_alarm_callback(struct rte_intr_handle *hdl, void *arg);
-
-int
-rte_eal_alarm_init(void)
-{
-       intr_handle.type = RTE_INTR_HANDLE_ALARM;
-       /* create a timerfd file descriptor */
-       intr_handle.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-       if (intr_handle.fd == -1)
-               goto error;
-
-       return 0;
-
-error:
-       rte_errno = errno;
-       return -1;
-}
-
-static void
-eal_alarm_callback(struct rte_intr_handle *hdl __rte_unused,
-               void *arg __rte_unused)
-{
-       struct timeval now;
-       struct alarm_entry *ap;
-
-       rte_spinlock_lock(&alarm_list_lk);
-       while ((ap = LIST_FIRST(&alarm_list)) !=NULL &&
-                       gettimeofday(&now, NULL) == 0 &&
-                       (ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec
== now.tv_sec &&
-                                               ap->time.tv_usec <=
now.tv_usec))){
-               ap->executing = 1;
-               ap->executing_id = pthread_self();
-               rte_spinlock_unlock(&alarm_list_lk);
-
-               ap->cb_fn(ap->cb_arg);
-
-               rte_spinlock_lock(&alarm_list_lk);
-
-               LIST_REMOVE(ap, next);
-               rte_free(ap);
-       }
-
-       if (!LIST_EMPTY(&alarm_list)) {
-               struct itimerspec atime = { .it_interval = { 0, 0 } };
-
-               ap = LIST_FIRST(&alarm_list);
-               atime.it_value.tv_sec = ap->time.tv_sec;
-               atime.it_value.tv_nsec = ap->time.tv_usec * NS_PER_US;
-               /* perform borrow for subtraction if necessary */
-               if (now.tv_usec > ap->time.tv_usec)
-                       atime.it_value.tv_sec--, atime.it_value.tv_nsec +=
US_PER_S * NS_PER_US;
-
-               atime.it_value.tv_sec -= now.tv_sec;
-               atime.it_value.tv_nsec -= now.tv_usec * NS_PER_US;
-               timerfd_settime(intr_handle.fd, 0, &atime, NULL);
-       }
-       rte_spinlock_unlock(&alarm_list_lk);
-}
-
-int
-rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg)
-{
-       struct timeval now;
-       int ret = 0;
-       struct alarm_entry *ap, *new_alarm;
-
-       /* Check parameters, including that us won't cause a uint64_t
overflow */
-       if (us < 1 || us > (UINT64_MAX - US_PER_S) || cb_fn == NULL)
-               return -EINVAL;
-
-       new_alarm = rte_zmalloc(NULL, sizeof(*new_alarm), 0);
-       if (new_alarm == NULL)
-               return -ENOMEM;
-
-       /* use current time to calculate absolute time of alarm */
-       gettimeofday(&now, NULL);
-
-       new_alarm->cb_fn = cb_fn;
-       new_alarm->cb_arg = cb_arg;
-       new_alarm->time.tv_usec = (now.tv_usec + us) % US_PER_S;
-       new_alarm->time.tv_sec = now.tv_sec + ((now.tv_usec + us) /
US_PER_S);
-
-       rte_spinlock_lock(&alarm_list_lk);
-       if (!handler_registered) {
-               ret |= rte_intr_callback_register(&intr_handle,
-                               eal_alarm_callback, NULL);
-               handler_registered = (ret == 0) ? 1 : 0;
-       }
-
-       if (LIST_EMPTY(&alarm_list))
-               LIST_INSERT_HEAD(&alarm_list, new_alarm, next);
-       else {
-               LIST_FOREACH(ap, &alarm_list, next) {
-                       if (ap->time.tv_sec > new_alarm->time.tv_sec ||
-                                       (ap->time.tv_sec ==
new_alarm->time.tv_sec &&
-                                                       ap->time.tv_usec >
new_alarm->time.tv_usec)){
-                               LIST_INSERT_BEFORE(ap, new_alarm, next);
-                               break;
-                       }
-                       if (LIST_NEXT(ap, next) == NULL) {
-                               LIST_INSERT_AFTER(ap, new_alarm, next);
-                               break;
-                       }
-               }
-       }
-
-       if (LIST_FIRST(&alarm_list) == new_alarm) {
-               struct itimerspec alarm_time = {
-                       .it_interval = {0, 0},
-                       .it_value = {
-                               .tv_sec = us / US_PER_S,
-                               .tv_nsec = (us % US_PER_S) * NS_PER_US,
-                       },
-               };
-               ret |= timerfd_settime(intr_handle.fd, 0, &alarm_time,
NULL);
-       }
-       rte_spinlock_unlock(&alarm_list_lk);
-
-       return ret;
-}
-
-int
-rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
-{
-       struct alarm_entry *ap, *ap_prev;
-       int count = 0;
-       int err = 0;
-       int executing;
-
-       if (!cb_fn) {
-               rte_errno = EINVAL;
-               return -1;
-       }
-
-       do {
-               executing = 0;
-               rte_spinlock_lock(&alarm_list_lk);
-               /* remove any matches at the start of the list */
-               while ((ap = LIST_FIRST(&alarm_list)) != NULL &&
-                               cb_fn == ap->cb_fn &&
-                               (cb_arg == (void *)-1 || cb_arg ==
ap->cb_arg)) {
-
-                       if (ap->executing == 0) {
-                               LIST_REMOVE(ap, next);
-                               rte_free(ap);
-                               count++;
-                       } else {
-                               /* If calling from other context, mark that
alarm is executing
-                                * so loop can spin till it finish.
Otherwise we are trying to
-                                * cancel our self - mark it by EINPROGRESS
*/
-                               if (pthread_equal(ap->executing_id,
pthread_self()) == 0)
-                                       executing++;
-                               else
-                                       err = EINPROGRESS;
-
-                               break;
-                       }
-               }
-               ap_prev = ap;
-
-               /* now go through list, removing entries not at start */
-               LIST_FOREACH(ap, &alarm_list, next) {
-                       /* this won't be true first time through */
-                       if (cb_fn == ap->cb_fn &&
-                                       (cb_arg == (void *)-1 || cb_arg ==
ap->cb_arg)) {
-
-                               if (ap->executing == 0) {
-                                       LIST_REMOVE(ap, next);
-                                       rte_free(ap);
-                                       count++;
-                                       ap = ap_prev;
-                               } else if (pthread_equal(ap->executing_id,
pthread_self()) == 0)
-                                       executing++;
-                               else
-                                       err = EINPROGRESS;
-                       }
-                       ap_prev = ap;
-               }
-               rte_spinlock_unlock(&alarm_list_lk);
-       } while (executing != 0);
-
-       if (count == 0 && err == 0)
-               rte_errno = ENOENT;
-       else if (err)
-               rte_errno = err;
-
-       return count;
-}
diff --git a/lib/librte_eal/linuxapp/eal/eal_debug.c
b/lib/librte_eal/linuxapp/eal/eal_debug.c
deleted file mode 100644
index 44fc4f3..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_debug.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <execinfo.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-
-#include <rte_log.h>
-#include <rte_debug.h>
-#include <rte_common.h>
-
-#define BACKTRACE_SIZE 256
-
-/* dump the stack of the calling core */
-void rte_dump_stack(void)
-{
-       void *func[BACKTRACE_SIZE];
-       char **symb = NULL;
-       int size;
-
-       size = backtrace(func, BACKTRACE_SIZE);
-       symb = backtrace_symbols(func, size);
-       while (size > 0) {
-               rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL,
-                       "%d: [%s]\n", size, symb[size - 1]);
-               size --;
-       }
-}
-
-/* not implemented in this environment */
-void rte_dump_registers(void)
-{
-       return;
-}
-
-/* call abort(), it will generate a coredump if enabled */
-void __rte_panic(const char *funcname, const char *format, ...)
-{
-       va_list ap;
-
-       /* disable history */
-       rte_log_set_history(0);
-
-       rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n",
funcname);
-       va_start(ap, format);
-       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
-       va_end(ap);
-       rte_dump_stack();
-       rte_dump_registers();
-       abort();
-}
-
-/*
- * Like rte_panic this terminates the application. However, no traceback is
- * provided and no core-dump is generated.
- */
-void
-rte_exit(int exit_code, const char *format, ...)
-{
-       va_list ap;
-
-       /* disable history */
-       rte_log_set_history(0);
-
-       if (exit_code != 0)
-               RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-                               "  Cause: ", exit_code);
-
-       va_start(ap, format);
-       rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
-       va_end(ap);
-
-#ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR
-       exit(exit_code);
-#else
-       rte_dump_stack();
-       rte_dump_registers();
-       abort();
-#endif
-}
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
deleted file mode 100644
index dc2668a..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <sys/epoll.h>
-#include <sys/signalfd.h>
-#include <sys/ioctl.h>
-
-#include <rte_common.h>
-#include <rte_interrupts.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_launch.h>
-#include <rte_tailq.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_lcore.h>
-#include <rte_atomic.h>
-#include <rte_branch_prediction.h>
-#include <rte_ring.h>
-#include <rte_debug.h>
-#include <rte_log.h>
-#include <rte_mempool.h>
-#include <rte_pci.h>
-#include <rte_malloc.h>
-#include <rte_errno.h>
-#include <rte_spinlock.h>
-
-#include "eal_private.h"
-#include "eal_vfio.h"
-
-#define EAL_INTR_EPOLL_WAIT_FOREVER (-1)
-
-/**
- * union for pipe fds.
- */
-union intr_pipefds{
-       struct {
-               int pipefd[2];
-       };
-       struct {
-               int readfd;
-               int writefd;
-       };
-};
-
-/**
- * union buffer for reading on different devices
- */
-union rte_intr_read_buffer {
-       int uio_intr_count;              /* for uio device */
-#ifdef VFIO_PRESENT
-       uint64_t vfio_intr_count;        /* for vfio device */
-#endif
-       uint64_t timerfd_num;            /* for timerfd */
-       char charbuf[16];                /* for others */
-};
-
-TAILQ_HEAD(rte_intr_cb_list, rte_intr_callback);
-TAILQ_HEAD(rte_intr_source_list, rte_intr_source);
-
-struct rte_intr_callback {
-       TAILQ_ENTRY(rte_intr_callback) next;
-       rte_intr_callback_fn cb_fn;  /**< callback address */
-       void *cb_arg;                /**< parameter for callback */
-};
-
-struct rte_intr_source {
-       TAILQ_ENTRY(rte_intr_source) next;
-       struct rte_intr_handle intr_handle; /**< interrupt handle */
-       struct rte_intr_cb_list callbacks;  /**< user callbacks */
-       uint32_t active;
-};
-
-/* global spinlock for interrupt data operation */
-static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER;
-
-/* union buffer for pipe read/write */
-static union intr_pipefds intr_pipe;
-
-/* interrupt sources list */
-static struct rte_intr_source_list intr_sources;
-
-/* interrupt handling thread */
-static pthread_t intr_thread;
-
-/* VFIO interrupts */
-#ifdef VFIO_PRESENT
-
-#define IRQ_SET_BUF_LEN  (sizeof(struct vfio_irq_set) + sizeof(int))
-
-/* enable legacy (INTx) interrupts */
-static int
-vfio_enable_intx(struct rte_intr_handle *intr_handle) {
-       struct vfio_irq_set *irq_set;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       int len, ret;
-       int *fd_ptr;
-
-       len = sizeof(irq_set_buf);
-
-       /* enable INTx */
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
-       irq_set->start = 0;
-       fd_ptr = (int *) &irq_set->data;
-       *fd_ptr = intr_handle->fd;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error enabling INTx interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-
-       /* unmask INTx after enabling */
-       memset(irq_set, 0, len);
-       len = sizeof(struct vfio_irq_set);
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_UNMASK;
-       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-       return 0;
-}
-
-/* disable legacy (INTx) interrupts */
-static int
-vfio_disable_intx(struct rte_intr_handle *intr_handle) {
-       struct vfio_irq_set *irq_set;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       int len, ret;
-
-       len = sizeof(struct vfio_irq_set);
-
-       /* mask interrupts before disabling */
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_UNMASK;
-       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-
-       /* disable INTx*/
-       memset(irq_set, 0, len);
-       irq_set->argsz = len;
-       irq_set->count = 0;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL,
-                       "Error disabling INTx interrupts for fd %d\n",
intr_handle->fd);
-               return -1;
-       }
-       return 0;
-}
-
-/* enable MSI-X interrupts */
-static int
-vfio_enable_msi(struct rte_intr_handle *intr_handle) {
-       int len, ret;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       struct vfio_irq_set *irq_set;
-       int *fd_ptr;
-
-       len = sizeof(irq_set_buf);
-
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
-       irq_set->start = 0;
-       fd_ptr = (int *) &irq_set->data;
-       *fd_ptr = intr_handle->fd;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error enabling MSI interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-
-       /* manually trigger interrupt to enable it */
-       memset(irq_set, 0, len);
-       len = sizeof(struct vfio_irq_set);
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error triggering MSI interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-       return 0;
-}
-
-/* disable MSI-X interrupts */
-static int
-vfio_disable_msi(struct rte_intr_handle *intr_handle) {
-       struct vfio_irq_set *irq_set;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       int len, ret;
-
-       len = sizeof(struct vfio_irq_set);
-
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 0;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSI_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret)
-               RTE_LOG(ERR, EAL,
-                       "Error disabling MSI interrupts for fd %d\n",
intr_handle->fd);
-
-       return ret;
-}
-
-/* enable MSI-X interrupts */
-static int
-vfio_enable_msix(struct rte_intr_handle *intr_handle) {
-       int len, ret;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       struct vfio_irq_set *irq_set;
-       int *fd_ptr;
-
-       len = sizeof(irq_set_buf);
-
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
-       irq_set->start = 0;
-       fd_ptr = (int *) &irq_set->data;
-       *fd_ptr = intr_handle->fd;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error enabling MSI-X interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-
-       /* manually trigger interrupt to enable it */
-       memset(irq_set, 0, len);
-       len = sizeof(struct vfio_irq_set);
-       irq_set->argsz = len;
-       irq_set->count = 1;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret) {
-               RTE_LOG(ERR, EAL, "Error triggering MSI-X interrupts for fd
%d\n",
-                                               intr_handle->fd);
-               return -1;
-       }
-       return 0;
-}
-
-/* disable MSI-X interrupts */
-static int
-vfio_disable_msix(struct rte_intr_handle *intr_handle) {
-       struct vfio_irq_set *irq_set;
-       char irq_set_buf[IRQ_SET_BUF_LEN];
-       int len, ret;
-
-       len = sizeof(struct vfio_irq_set);
-
-       irq_set = (struct vfio_irq_set *) irq_set_buf;
-       irq_set->argsz = len;
-       irq_set->count = 0;
-       irq_set->flags = VFIO_IRQ_SET_DATA_NONE |
VFIO_IRQ_SET_ACTION_TRIGGER;
-       irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
-       irq_set->start = 0;
-
-       ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS,
irq_set);
-
-       if (ret)
-               RTE_LOG(ERR, EAL,
-                       "Error disabling MSI-X interrupts for fd %d\n",
intr_handle->fd);
-
-       return ret;
-}
-#endif
-
-int
-rte_intr_callback_register(struct rte_intr_handle *intr_handle,
-                       rte_intr_callback_fn cb, void *cb_arg)
-{
-       int ret, wake_thread;
-       struct rte_intr_source *src;
-       struct rte_intr_callback *callback;
-
-       wake_thread = 0;
-
-       /* first do parameter checking */
-       if (intr_handle == NULL || intr_handle->fd < 0 || cb == NULL) {
-               RTE_LOG(ERR, EAL,
-                       "Registering with invalid input parameter\n");
-               return -EINVAL;
-       }
-
-       /* allocate a new interrupt callback entity */
-       callback = rte_zmalloc("interrupt callback list",
-                               sizeof(*callback), 0);
-       if (callback == NULL) {
-               RTE_LOG(ERR, EAL, "Can not allocate memory\n");
-               return -ENOMEM;
-       }
-       callback->cb_fn = cb;
-       callback->cb_arg = cb_arg;
-
-       rte_spinlock_lock(&intr_lock);
-
-       /* check if there is at least one callback registered for the fd */
-       TAILQ_FOREACH(src, &intr_sources, next) {
-               if (src->intr_handle.fd == intr_handle->fd) {
-                       /* we had no interrupts for this */
-                       if TAILQ_EMPTY(&src->callbacks)
-                               wake_thread = 1;
-
-                       TAILQ_INSERT_TAIL(&(src->callbacks), callback,
next);
-                       ret = 0;
-                       break;
-               }
-       }
-
-       /* no existing callbacks for this - add new source */
-       if (src == NULL) {
-               if ((src = rte_zmalloc("interrupt source list",
-                               sizeof(*src), 0)) == NULL) {
-                       RTE_LOG(ERR, EAL, "Can not allocate memory\n");
-                       rte_free(callback);
-                       ret = -ENOMEM;
-               } else {
-                       src->intr_handle = *intr_handle;
-                       TAILQ_INIT(&src->callbacks);
-                       TAILQ_INSERT_TAIL(&(src->callbacks), callback,
next);
-                       TAILQ_INSERT_TAIL(&intr_sources, src, next);
-                       wake_thread = 1;
-                       ret = 0;
-               }
-       }
-
-       rte_spinlock_unlock(&intr_lock);
-
-       /**
-        * check if need to notify the pipe fd waited by epoll_wait to
-        * rebuild the wait list.
-        */
-       if (wake_thread)
-               if (write(intr_pipe.writefd, "1", 1) < 0)
-                       return -EPIPE;
-
-       return (ret);
-}
-
-int
-rte_intr_callback_unregister(struct rte_intr_handle *intr_handle,
-                       rte_intr_callback_fn cb_fn, void *cb_arg)
-{
-       int ret;
-       struct rte_intr_source *src;
-       struct rte_intr_callback *cb, *next;
-
-       /* do parameter checking first */
-       if (intr_handle == NULL || intr_handle->fd < 0) {
-               RTE_LOG(ERR, EAL,
-               "Unregistering with invalid input parameter\n");
-               return -EINVAL;
-       }
-
-       rte_spinlock_lock(&intr_lock);
-
-       /* check if the insterrupt source for the fd is existent */
-       TAILQ_FOREACH(src, &intr_sources, next)
-               if (src->intr_handle.fd == intr_handle->fd)
-                       break;
-
-       /* No interrupt source registered for the fd */
-       if (src == NULL) {
-               ret = -ENOENT;
-
-       /* interrupt source has some active callbacks right now. */
-       } else if (src->active != 0) {
-               ret = -EAGAIN;
-
-       /* ok to remove. */
-       } else {
-               ret = 0;
-
-               /*walk through the callbacks and remove all that match. */
-               for (cb = TAILQ_FIRST(&src->callbacks); cb != NULL; cb =
next) {
-
-                       next = TAILQ_NEXT(cb, next);
-
-                       if (cb->cb_fn == cb_fn && (cb_arg == (void *)-1 ||
-                                       cb->cb_arg == cb_arg)) {
-                               TAILQ_REMOVE(&src->callbacks, cb, next);
-                               rte_free(cb);
-                               ret++;
-                       }
-               }
-
-               /* all callbacks for that source are removed. */
-               if (TAILQ_EMPTY(&src->callbacks)) {
-                       TAILQ_REMOVE(&intr_sources, src, next);
-                       rte_free(src);
-               }
-       }
-
-       rte_spinlock_unlock(&intr_lock);
-
-       /* notify the pipe fd waited by epoll_wait to rebuild the wait list
*/
-       if (ret >= 0 && write(intr_pipe.writefd, "1", 1) < 0) {
-               ret = -EPIPE;
-       }
-
-       return (ret);
-}
-
-int
-rte_intr_enable(struct rte_intr_handle *intr_handle)
-{
-       const int value = 1;
-
-       if (!intr_handle || intr_handle->fd < 0)
-               return -1;
-
-       switch (intr_handle->type){
-       /* write to the uio fd to enable the interrupt */
-       case RTE_INTR_HANDLE_UIO:
-               if (write(intr_handle->fd, &value, sizeof(value)) < 0) {
-                       RTE_LOG(ERR, EAL,
-                               "Error enabling interrupts for fd %d\n",
-                                                       intr_handle->fd);
-                       return -1;
-               }
-               break;
-       /* not used at this moment */
-       case RTE_INTR_HANDLE_ALARM:
-               return -1;
-#ifdef VFIO_PRESENT
-       case RTE_INTR_HANDLE_VFIO_MSIX:
-               if (vfio_enable_msix(intr_handle))
-                       return -1;
-               break;
-       case RTE_INTR_HANDLE_VFIO_MSI:
-               if (vfio_enable_msi(intr_handle))
-                       return -1;
-               break;
-       case RTE_INTR_HANDLE_VFIO_LEGACY:
-               if (vfio_enable_intx(intr_handle))
-                       return -1;
-               break;
-#endif
-       /* unknown handle type */
-       default:
-               RTE_LOG(ERR, EAL,
-                       "Unknown handle type of fd %d\n",
-                                       intr_handle->fd);
-               return -1;
-       }
-
-       return 0;
-}
-
-int
-rte_intr_disable(struct rte_intr_handle *intr_handle)
-{
-       const int value = 0;
-
-       if (!intr_handle || intr_handle->fd < 0)
-               return -1;
-
-       switch (intr_handle->type){
-       /* write to the uio fd to disable the interrupt */
-       case RTE_INTR_HANDLE_UIO:
-               if (write(intr_handle->fd, &value, sizeof(value)) < 0){
-                       RTE_LOG(ERR, EAL,
-                               "Error disabling interrupts for fd %d\n",
-                                                       intr_handle->fd);
-                       return -1;
-               }
-               break;
-       /* not used at this moment */
-       case RTE_INTR_HANDLE_ALARM:
-               return -1;
-#ifdef VFIO_PRESENT
-       case RTE_INTR_HANDLE_VFIO_MSIX:
-               if (vfio_disable_msix(intr_handle))
-                       return -1;
-               break;
-       case RTE_INTR_HANDLE_VFIO_MSI:
-               if (vfio_disable_msi(intr_handle))
-                       return -1;
-               break;
-       case RTE_INTR_HANDLE_VFIO_LEGACY:
-               if (vfio_disable_intx(intr_handle))
-                       return -1;
-               break;
-#endif
-       /* unknown handle type */
-       default:
-               RTE_LOG(ERR, EAL,
-                       "Unknown handle type of fd %d\n",
-                                       intr_handle->fd);
-               return -1;
-       }
-
-       return 0;
-}
-
-static int
-eal_intr_process_interrupts(struct epoll_event *events, int nfds)
-{
-       int n, bytes_read;
-       struct rte_intr_source *src;
-       struct rte_intr_callback *cb;
-       union rte_intr_read_buffer buf;
-       struct rte_intr_callback active_cb;
-
-       for (n = 0; n < nfds; n++) {
-
-               /**
-                * if the pipe fd is ready to read, return out to
-                * rebuild the wait list.
-                */
-               if (events[n].data.fd == intr_pipe.readfd){
-                       int r = read(intr_pipe.readfd, buf.charbuf,
-                                       sizeof(buf.charbuf));
-                       RTE_SET_USED(r);
-                       return -1;
-               }
-               rte_spinlock_lock(&intr_lock);
-               TAILQ_FOREACH(src, &intr_sources, next)
-                       if (src->intr_handle.fd ==
-                                       events[n].data.fd)
-                               break;
-               if (src == NULL){
-                       rte_spinlock_unlock(&intr_lock);
-                       continue;
-               }
-
-               /* mark this interrupt source as active and release the
lock. */
-               src->active = 1;
-               rte_spinlock_unlock(&intr_lock);
-
-               /* set the length to be read dor different handle type */
-               switch (src->intr_handle.type) {
-               case RTE_INTR_HANDLE_UIO:
-                       bytes_read = sizeof(buf.uio_intr_count);
-                       break;
-               case RTE_INTR_HANDLE_ALARM:
-                       bytes_read = sizeof(buf.timerfd_num);
-                       break;
-#ifdef VFIO_PRESENT
-               case RTE_INTR_HANDLE_VFIO_MSIX:
-               case RTE_INTR_HANDLE_VFIO_MSI:
-               case RTE_INTR_HANDLE_VFIO_LEGACY:
-                       bytes_read = sizeof(buf.vfio_intr_count);
-                       break;
-#endif
-               default:
-                       bytes_read = 1;
-                       break;
-               }
-
-               /**
-                * read out to clear the ready-to-be-read flag
-                * for epoll_wait.
-                */
-               bytes_read = read(events[n].data.fd, &buf, bytes_read);
-
-               if (bytes_read < 0)
-                       RTE_LOG(ERR, EAL, "Error reading from file "
-                               "descriptor %d: %s\n", events[n].data.fd,
-                                                       strerror(errno));
-               else if (bytes_read == 0)
-                       RTE_LOG(ERR, EAL, "Read nothing from file "
-                               "descriptor %d\n", events[n].data.fd);
-
-               /* grab a lock, again to call callbacks and update status.
*/
-               rte_spinlock_lock(&intr_lock);
-
-               if (bytes_read > 0) {
-
-                       /* Finally, call all callbacks. */
-                       TAILQ_FOREACH(cb, &src->callbacks, next) {
-
-                               /* make a copy and unlock. */
-                               active_cb = *cb;
-                               rte_spinlock_unlock(&intr_lock);
-
-                               /* call the actual callback */
-                               active_cb.cb_fn(&src->intr_handle,
-                                       active_cb.cb_arg);
-
-                               /*get the lock back. */
-                               rte_spinlock_lock(&intr_lock);
-                       }
-               }
-
-               /* we done with that interrupt source, release it. */
-               src->active = 0;
-               rte_spinlock_unlock(&intr_lock);
-       }
-
-       return 0;
-}
-
-/**
- * It handles all the interrupts.
- *
- * @param pfd
- *  epoll file descriptor.
- * @param totalfds
- *  The number of file descriptors added in epoll.
- *
- * @return
- *  void
- */
-static void
-eal_intr_handle_interrupts(int pfd, unsigned totalfds)
-{
-       struct epoll_event events[totalfds];
-       int nfds = 0;
-
-       for(;;) {
-               nfds = epoll_wait(pfd, events, totalfds,
-                       EAL_INTR_EPOLL_WAIT_FOREVER);
-               /* epoll_wait fail */
-               if (nfds < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       RTE_LOG(ERR, EAL,
-                               "epoll_wait returns with fail\n");
-                       return;
-               }
-               /* epoll_wait timeout, will never happens here */
-               else if (nfds == 0)
-                       continue;
-               /* epoll_wait has at least one fd ready to read */
-               if (eal_intr_process_interrupts(events, nfds) < 0)
-                       return;
-       }
-}
-
-/**
- * It builds/rebuilds up the epoll file descriptor with all the
- * file descriptors being waited on. Then handles the interrupts.
- *
- * @param arg
- *  pointer. (unused)
- *
- * @return
- *  never return;
- */
-static __attribute__((noreturn)) void *
-eal_intr_thread_main(__rte_unused void *arg)
-{
-       struct epoll_event ev;
-
-       /* host thread, never break out */
-       for (;;) {
-               /* build up the epoll fd with all descriptors we are to
-                * wait on then pass it to the handle_interrupts function
-                */
-               static struct epoll_event pipe_event = {
-                       .events = EPOLLIN | EPOLLPRI,
-               };
-               struct rte_intr_source *src;
-               unsigned numfds = 0;
-
-               /* create epoll fd */
-               int pfd = epoll_create(1);
-               if (pfd < 0)
-                       rte_panic("Cannot create epoll instance\n");
-
-               pipe_event.data.fd = intr_pipe.readfd;
-               /**
-                * add pipe fd into wait list, this pipe is used to
-                * rebuild the wait list.
-                */
-               if (epoll_ctl(pfd, EPOLL_CTL_ADD, intr_pipe.readfd,
-                                               &pipe_event) < 0) {
-                       rte_panic("Error adding fd to %d epoll_ctl, %s\n",
-                                       intr_pipe.readfd, strerror(errno));
-               }
-               numfds++;
-
-               rte_spinlock_lock(&intr_lock);
-
-               TAILQ_FOREACH(src, &intr_sources, next) {
-                       if (src->callbacks.tqh_first == NULL)
-                               continue; /* skip those with no callbacks */
-                       ev.events = EPOLLIN | EPOLLPRI;
-                       ev.data.fd = src->intr_handle.fd;
-
-                       /**
-                        * add all the uio device file descriptor
-                        * into wait list.
-                        */
-                       if (epoll_ctl(pfd, EPOLL_CTL_ADD,
-                                       src->intr_handle.fd, &ev) < 0){
-                               rte_panic("Error adding fd %d epoll_ctl,
%s\n",
-                                       src->intr_handle.fd,
strerror(errno));
-                       }
-                       else
-                               numfds++;
-               }
-               rte_spinlock_unlock(&intr_lock);
-               /* serve the interrupt */
-               eal_intr_handle_interrupts(pfd, numfds);
-
-               /**
-                * when we return, we need to rebuild the
-                * list of fds to monitor.
-                */
-               close(pfd);
-       }
-}
-
-int
-rte_eal_intr_init(void)
-{
-       int ret = 0;
-
-       /* init the global interrupt source head */
-       TAILQ_INIT(&intr_sources);
-
-       /**
-        * create a pipe which will be waited by epoll and notified to
-        * rebuild the wait list of epoll.
-        */
-       if (pipe(intr_pipe.pipefd) < 0)
-               return -1;
-
-       /* create the host thread to wait/handle the interrupt */
-       ret = pthread_create(&intr_thread, NULL,
-                       eal_intr_thread_main, NULL);
-       if (ret != 0)
-               RTE_LOG(ERR, EAL,
-                       "Failed to create thread for interrupt handling\n");
-
-       return -ret;
-}
-
diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.h
b/lib/librte_eal/linuxapp/eal/eal_vfio.h
deleted file mode 100644
index 03e693e..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_vfio.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef EAL_VFIO_H_
-#define EAL_VFIO_H_
-
-/*
- * determine if VFIO is present on the system
- */
-#ifdef RTE_EAL_VFIO
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
-#include <linux/vfio.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
-#define RTE_PCI_MSIX_TABLE_BIR 0x7
-#else
-#define RTE_PCI_MSIX_TABLE_BIR PCI_MSIX_TABLE_BIR
-#endif
-
-#define VFIO_PRESENT
-#endif /* kernel version */
-#endif /* RTE_EAL_VFIO */
-
-#endif /* EAL_VFIO_H_ */
--
1.9.1


More information about the dev mailing list