SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mp.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_utils.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += linux/mlx5_os.c
 
 # Basic CFLAGS.
 CFLAGS += -O3
 
--- /dev/null
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020 Mellanox Technologies, Ltd
+
+includes += include_directories('.')
+sources += files(
+       'mlx5_os.c',
+)
+
 
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2015 6WIND S.A.
+ * Copyright 2020 Mellanox Technologies, Ltd
+ */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/mman.h>
+#include <linux/rtnetlink.h>
+#include <fcntl.h>
+
+/* Verbs header. */
+/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
+#ifdef PEDANTIC
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+#include <infiniband/verbs.h>
+#ifdef PEDANTIC
+#pragma GCC diagnostic error "-Wpedantic"
+#endif
+
+#include <rte_malloc.h>
+#include <rte_ethdev_driver.h>
+#include <rte_ethdev_pci.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_common.h>
+#include <rte_kvargs.h>
+#include <rte_rwlock.h>
+#include <rte_spinlock.h>
+#include <rte_string_fns.h>
+#include <rte_alarm.h>
+
+#include <mlx5_glue.h>
+#include <mlx5_devx_cmds.h>
+#include <mlx5_common.h>
+
+#include "mlx5_defs.h"
+#include "mlx5.h"
+#include "mlx5_utils.h"
+#include "mlx5_rxtx.h"
+#include "mlx5_autoconf.h"
+#include "mlx5_mr.h"
+#include "mlx5_flow.h"
+#include "rte_pmd_mlx5.h"
+
+/**
+ * Get ibv device name. Given an ibv_context pointer - return a
+ * pointer to the corresponding device name.
+ *
+ * @param[in] ctx
+ *   Pointer to ibv context.
+ *
+ * @return
+ *   Pointer to device name if ctx is valid, NULL otherwise.
+ */
+const char *
+mlx5_os_get_ctx_device_name(void *ctx)
+{
+       if (!ctx)
+               return NULL;
+       return ((struct ibv_context *)ctx)->device->name;
+}
+
+/**
+ * Get ibv device path name. Given an ibv_context pointer - return a
+ * pointer to the corresponding device path name.
+ *
+ * @param[in] ctx
+ *   Pointer to ibv context.
+ *
+ * @return
+ *   Pointer to device path name if ctx is valid, NULL otherwise.
+ */
+const char *
+mlx5_os_get_ctx_device_path(void *ctx)
+{
+       if (!ctx)
+               return NULL;
+
+       return ((struct ibv_context *)ctx)->device->ibdev_path;
+}
 
 # Copyright 2018 6WIND S.A.
 # Copyright 2018 Mellanox Technologies, Ltd
 
-if not is_linux
+if not (is_linux or is_windows)
        build = false
-       reason = 'only supported on Linux'
+       reason = 'only supported on Linux and Windows'
        subdir_done()
 endif
 
 else
        cflags += [ '-UPEDANTIC' ]
 endif
+subdir(exec_env)
 
        int flags;
 
        sh->intr_handle.fd = -1;
-       flags = fcntl(sh->ctx->async_fd, F_GETFL);
-       ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
+       flags = fcntl(((struct ibv_context *)sh->ctx)->async_fd, F_GETFL);
+       ret = fcntl(((struct ibv_context *)sh->ctx)->async_fd,
+                   F_SETFL, flags | O_NONBLOCK);
        if (ret) {
                DRV_LOG(INFO, "failed to change file descriptor async event"
                        " queue");
        } else {
-               sh->intr_handle.fd = sh->ctx->async_fd;
+               sh->intr_handle.fd = ((struct ibv_context *)sh->ctx)->async_fd;
                sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
                if (rte_intr_callback_register(&sh->intr_handle,
                                        mlx5_dev_interrupt_handler, sh)) {
        }
        sh->refcnt = 1;
        sh->max_port = spawn->max_port;
-       strncpy(sh->ibdev_name, sh->ctx->device->name,
-               sizeof(sh->ibdev_name));
-       strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path,
-               sizeof(sh->ibdev_path));
+       strncpy(sh->ibdev_name, mlx5_os_get_ctx_device_name(sh->ctx),
+               sizeof(sh->ibdev_name) - 1);
+       strncpy(sh->ibdev_path, mlx5_os_get_ctx_device_path(sh->ctx),
+               sizeof(sh->ibdev_path) - 1);
        /*
         * Setting port_id to max unallowed value means
         * there is no interrupt subhandler installed for
                return;
        DRV_LOG(DEBUG, "port %u closing device \"%s\"",
                dev->data->port_id,
-               ((priv->sh->ctx != NULL) ? priv->sh->ctx->device->name : ""));
+               ((priv->sh->ctx != NULL) ?
+               mlx5_os_get_ctx_device_name(priv->sh->ctx) : ""));
        /*
         * If default mreg copy action is removed at the stop stage,
         * the search will return none and nothing will be done anymore.
 
        uint32_t refcnt;
        uint32_t devx:1; /* Opened with DV. */
        uint32_t max_port; /* Maximal IB device port index. */
-       struct ibv_context *ctx; /* Verbs/DV context. */
+       void *ctx; /* Verbs/DV/DevX context. */
        struct ibv_pd *pd; /* Protection Domain. */
        uint32_t pdn; /* Protection Domain number. */
        uint32_t tdn; /* Transport Domain number. */
                                         struct rte_flow_error *error);
 void mlx5_flow_meter_detach(struct mlx5_flow_meter *fm);
 
+/* mlx5_os.c */
+const char *mlx5_os_get_ctx_device_name(void *ctx);
+const char *mlx5_os_get_ctx_device_path(void *ctx);
+
 #endif /* RTE_PMD_MLX5_H_ */
 
        case MLX5_MP_REQ_VERBS_CMD_FD:
                mp_init_msg(&priv->mp_id, &mp_res, param->type);
                mp_res.num_fds = 1;
-               mp_res.fds[0] = priv->sh->ctx->cmd_fd;
+               mp_res.fds[0] = ((struct ibv_context *)priv->sh->ctx)->cmd_fd;
                res->result = 0;
                ret = rte_mp_reply(&mp_res, peer);
                break;