diff --git a/CMakeLists.txt b/CMakeLists.txt
index b1467317b68561..e8f4a948ad9610 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,7 +52,7 @@ set(PACKAGE_VERSION "17.0")
 # When this is changed the values in these files need changing too:
 #   debian/libibverbs1.symbols
 #   libibverbs/libibverbs.map
-set(IBVERBS_PABI_VERSION "16")
+set(IBVERBS_PABI_VERSION "17")
 set(IBVERBS_PROVIDER_SUFFIX "-rdmav${IBVERBS_PABI_VERSION}.so")
 
 #-------------------------
diff --git a/debian/libibverbs1.symbols b/debian/libibverbs1.symbols
index 2678fa6e98acf7..7c7659e434bc63 100644
--- a/debian/libibverbs1.symbols
+++ b/debian/libibverbs1.symbols
@@ -1,7 +1,7 @@
 libibverbs.so.1 libibverbs1 #MINVER#
  IBVERBS_1.0@IBVERBS_1.0 1.1.6
  IBVERBS_1.1@IBVERBS_1.1 1.1.6
- (symver)IBVERBS_PRIVATE_16 16
+ (symver)IBVERBS_PRIVATE_17 17
  ibv_ack_async_event@IBVERBS_1.0 1.1.6
  ibv_ack_async_event@IBVERBS_1.1 1.1.6
  ibv_ack_cq_events@IBVERBS_1.0 1.1.6
diff --git a/libibverbs/cmd.c b/libibverbs/cmd.c
index b957550ed6fbdb..bcec94f5b0ce72 100644
--- a/libibverbs/cmd.c
+++ b/libibverbs/cmd.c
@@ -44,22 +44,22 @@
 #include "ibverbs.h"
 #include <ccan/minmax.h>
 
-int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
-			size_t cmd_size, struct ibv_get_context_resp *resp,
-			size_t resp_size)
+int ibv_cmd_get_context(struct verbs_context *context_ex,
+			struct ibv_get_context *cmd, size_t cmd_size,
+			struct ibv_get_context_resp *resp, size_t resp_size)
 {
 	if (abi_ver < IB_USER_VERBS_MIN_ABI_VERSION)
 		return ENOSYS;
 
 	IBV_INIT_CMD_RESP(cmd, cmd_size, GET_CONTEXT, resp, resp_size);
 
-	if (write(context->cmd_fd, cmd, cmd_size) != cmd_size)
+	if (write(context_ex->context.cmd_fd, cmd, cmd_size) != cmd_size)
 		return errno;
 
 	(void) VALGRIND_MAKE_MEM_DEFINED(resp, resp_size);
 
-	context->async_fd         = resp->async_fd;
-	context->num_comp_vectors = resp->num_comp_vectors;
+	context_ex->context.async_fd = resp->async_fd;
+	context_ex->context.num_comp_vectors = resp->num_comp_vectors;
 
 	return 0;
 }
diff --git a/libibverbs/device.c b/libibverbs/device.c
index 4fb759c6474ad7..e42e37bd0a1f8d 100644
--- a/libibverbs/device.c
+++ b/libibverbs/device.c
@@ -162,7 +162,8 @@ static struct ibv_cq_ex *
 __lib_ibv_create_cq_ex(struct ibv_context *context,
 		       struct ibv_cq_init_attr_ex *cq_attr)
 {
-	struct verbs_context *vctx = verbs_get_ctx(context);
+	struct verbs_context *vctx =
+		container_of(context, struct verbs_context, context);
 	struct ibv_cq_ex *cq;
 
 	if (cq_attr->wc_flags & ~IBV_CREATE_CQ_SUP_WC_FLAGS) {
@@ -179,14 +180,115 @@ __lib_ibv_create_cq_ex(struct ibv_context *context,
 	return cq;
 }
 
+/*
+ * Ownership of cmd_fd is transferred into this function, and it will either
+ * be released during the matching call to verbs_uninit_contxt or during the
+ * failure path of this function.
+ */
+int verbs_init_context(struct verbs_context *context_ex,
+		       struct ibv_device *device, int cmd_fd)
+{
+	struct ibv_context *context = &context_ex->context;
+
+	ibverbs_device_hold(device);
+
+	context->device = device;
+	context->cmd_fd = cmd_fd;
+	context->async_fd = -1;
+	pthread_mutex_init(&context->mutex, NULL);
+
+	context_ex->context.abi_compat = __VERBS_ABI_IS_EXTENDED;
+	context_ex->sz = sizeof(*context_ex);
+
+	/*
+	 * In order to maintain backward/forward binary compatibility
+	 * with apps compiled against libibverbs-1.1.8 that use the
+	 * flow steering addition, we need to set the two
+	 * ABI_placeholder entries to match the driver set flow
+	 * entries.  This is because apps compiled against
+	 * libibverbs-1.1.8 use an inline ibv_create_flow and
+	 * ibv_destroy_flow function that looks in the placeholder
+	 * spots for the proper entry points.  For apps compiled
+	 * against libibverbs-1.1.9 and later, the inline functions
+	 * will be looking in the right place.
+	 */
+	context_ex->ABI_placeholder1 =
+		(void (*)(void))context_ex->ibv_create_flow;
+	context_ex->ABI_placeholder2 =
+		(void (*)(void))context_ex->ibv_destroy_flow;
+
+	context_ex->priv = calloc(1, sizeof(context_ex->priv));
+	if (!context_ex->priv) {
+		errno = ENOMEM;
+		close(cmd_fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Allocate and initialize a context structure. This is called to create the
+ * driver wrapper, and context_offset is the number of bytes into the wrapper
+ * structure where the verbs_context starts.
+ */
+void *_verbs_init_and_alloc_context(struct ibv_device *device, int cmd_fd,
+				    size_t alloc_size,
+				    struct verbs_context *context_offset)
+{
+	void *drv_context;
+	struct verbs_context *context;
+
+	drv_context = calloc(1, alloc_size);
+	if (!drv_context) {
+		errno = ENOMEM;
+		close(cmd_fd);
+		return NULL;
+	}
+
+	context = (struct verbs_context *)((uint8_t *)drv_context +
+					   (uintptr_t)context_offset);
+
+	if (verbs_init_context(context, device, cmd_fd))
+		goto err_free;
+
+	return drv_context;
+
+err_free:
+	free(drv_context);
+	return NULL;
+}
+
+/* Use the init_context flow to create a verbs_context */
+static struct verbs_context *alloc_context(struct verbs_device *device,
+					   int cmd_fd)
+{
+	struct verbs_context *context;
+
+	context = _verbs_init_and_alloc_context(
+		&device->device, cmd_fd,
+		sizeof(*context) + device->size_of_context, NULL);
+	if (!context)
+		return NULL;
+
+	if (device->ops->init_context(device, &context->context, cmd_fd))
+		goto err_uninit;
+
+	return context;
+
+err_uninit:
+	verbs_uninit_context(context);
+	free(context);
+	return NULL;
+}
+
 LATEST_SYMVER_FUNC(ibv_open_device, 1_1, "IBVERBS_1.1",
 		   struct ibv_context *,
 		   struct ibv_device *device)
 {
 	struct verbs_device *verbs_device = verbs_get_device(device);
 	char *devpath;
-	int cmd_fd, ret;
-	struct ibv_context *context;
+	int cmd_fd;
 	struct verbs_context *context_ex;
 
 	if (asprintf(&devpath, "/dev/infiniband/%s", device->dev_name) < 0)
@@ -202,96 +304,50 @@ LATEST_SYMVER_FUNC(ibv_open_device, 1_1, "IBVERBS_1.1",
 	if (cmd_fd < 0)
 		return NULL;
 
-	if (!verbs_device->ops->init_context) {
-		context = verbs_device->ops->alloc_context(device, cmd_fd);
-		if (!context)
-			goto err;
-	} else {
-		struct verbs_ex_private *priv;
-
-		/* Library now allocates the context */
-		context_ex = calloc(1, sizeof(*context_ex) +
-				       verbs_device->size_of_context);
-		if (!context_ex) {
-			errno = ENOMEM;
-			goto err;
-		}
-
-		priv = calloc(1, sizeof(*priv));
-		if (!priv) {
-			errno = ENOMEM;
-			free(context_ex);
-			goto err;
-		}
-
-		context_ex->priv = priv;
-		context_ex->context.abi_compat  = __VERBS_ABI_IS_EXTENDED;
-		context_ex->sz = sizeof(*context_ex);
-
-		context = &context_ex->context;
-		ret = verbs_device->ops->init_context(verbs_device, context, cmd_fd);
-		if (ret)
-			goto verbs_err;
-		/*
-		 * In order to maintain backward/forward binary compatibility
-		 * with apps compiled against libibverbs-1.1.8 that use the
-		 * flow steering addition, we need to set the two
-		 * ABI_placeholder entries to match the driver set flow
-		 * entries.  This is because apps compiled against
-		 * libibverbs-1.1.8 use an inline ibv_create_flow and
-		 * ibv_destroy_flow function that looks in the placeholder
-		 * spots for the proper entry points.  For apps compiled
-		 * against libibverbs-1.1.9 and later, the inline functions
-		 * will be looking in the right place.
-		 */
-		context_ex->ABI_placeholder1 = (void (*)(void)) context_ex->ibv_create_flow;
-		context_ex->ABI_placeholder2 = (void (*)(void)) context_ex->ibv_destroy_flow;
-
-		if (context_ex->create_cq_ex) {
-			priv->create_cq_ex = context_ex->create_cq_ex;
-			context_ex->create_cq_ex = __lib_ibv_create_cq_ex;
-		}
-	}
+	if (!verbs_device->ops->init_context)
+		context_ex = verbs_device->ops->alloc_context(device, cmd_fd);
+	else
+		context_ex = alloc_context(verbs_device, cmd_fd);
 
-	context->device = device;
-	context->cmd_fd = cmd_fd;
-	pthread_mutex_init(&context->mutex, NULL);
+	/*
+	 * cmd_fd ownership is transferred into alloc_context, if it fails
+	 * then it closes cmd_fd and returns NULL
+	 */
+	if (context_ex == NULL)
+		return NULL;
 
-	ibverbs_device_hold(device);
+	if (context_ex->create_cq_ex) {
+		context_ex->priv->create_cq_ex = context_ex->create_cq_ex;
+		context_ex->create_cq_ex = __lib_ibv_create_cq_ex;
+	}
 
-	return context;
+	return &context_ex->context;
+}
 
-verbs_err:
+void verbs_uninit_context(struct verbs_context *context_ex)
+{
 	free(context_ex->priv);
-	free(context_ex);
-err:
-	close(cmd_fd);
-	return NULL;
+	close(context_ex->context.cmd_fd);
+	close(context_ex->context.async_fd);
+	ibverbs_device_put(context_ex->context.device);
 }
 
 LATEST_SYMVER_FUNC(ibv_close_device, 1_1, "IBVERBS_1.1",
 		   int,
 		   struct ibv_context *context)
 {
-	int async_fd = context->async_fd;
-	int cmd_fd   = context->cmd_fd;
-	struct verbs_context *context_ex;
 	struct verbs_device *verbs_device = verbs_get_device(context->device);
-	struct ibv_device *device = context->device;
 
-	context_ex = verbs_get_ctx(context);
-	if (context_ex) {
+	if (verbs_device->ops->uninit_context) {
+		struct verbs_context *context_ex =
+			container_of(context, struct verbs_context, context);
+
 		verbs_device->ops->uninit_context(verbs_device, context);
-		free(context_ex->priv);
-		free(context_ex);
+		verbs_uninit_context(context_ex);
 	} else {
 		verbs_device->ops->free_context(context);
 	}
 
-	close(async_fd);
-	close(cmd_fd);
-	ibverbs_device_put(device);
-
 	return 0;
 }
 
diff --git a/libibverbs/driver.h b/libibverbs/driver.h
index 4698ba4e609f34..809c4f5c8cdf39 100644
--- a/libibverbs/driver.h
+++ b/libibverbs/driver.h
@@ -153,8 +153,8 @@ struct verbs_device_ops {
 	bool (*match_device)(struct verbs_sysfs_dev *sysfs_dev);
 
 	/* Old interface, do not use in new code. */
-	struct ibv_context *(*alloc_context)(struct ibv_device *device,
-					     int cmd_fd);
+	struct verbs_context *(*alloc_context)(struct ibv_device *device,
+					       int cmd_fd);
 	void (*free_context)(struct ibv_context *context);
 
 	/* New interface */
@@ -205,13 +205,26 @@ void verbs_register_driver(const struct verbs_device_ops *ops);
 		verbs_register_driver(&drv);                                   \
 	}
 
+void *_verbs_init_and_alloc_context(struct ibv_device *device, int cmd_fd,
+				    size_t alloc_size,
+				    struct verbs_context *context_offset);
+
+#define verbs_init_and_alloc_context(ibdev, cmd_fd, drv_ctx_ptr, ctx_memb)     \
+	((typeof(drv_ctx_ptr))_verbs_init_and_alloc_context(                   \
+		ibdev, cmd_fd, sizeof(*drv_ctx_ptr),                           \
+		&((typeof(drv_ctx_ptr))NULL)->ctx_memb))
+
+int verbs_init_context(struct verbs_context *context_ex,
+		       struct ibv_device *device, int cmd_fd);
+void verbs_uninit_context(struct verbs_context *context);
+
 void verbs_init_cq(struct ibv_cq *cq, struct ibv_context *context,
 		       struct ibv_comp_channel *channel,
 		       void *cq_context);
 
-int ibv_cmd_get_context(struct ibv_context *context, struct ibv_get_context *cmd,
-			size_t cmd_size, struct ibv_get_context_resp *resp,
-			size_t resp_size);
+int ibv_cmd_get_context(struct verbs_context *context,
+			struct ibv_get_context *cmd, size_t cmd_size,
+			struct ibv_get_context_resp *resp, size_t resp_size);
 int ibv_cmd_query_device(struct ibv_context *context,
 			 struct ibv_device_attr *device_attr,
 			 uint64_t *raw_fw_ver,
diff --git a/libibverbs/libibverbs.map.in b/libibverbs/libibverbs.map.in
index 3f635a94b82d58..b787b051b4c381 100644
--- a/libibverbs/libibverbs.map.in
+++ b/libibverbs/libibverbs.map.in
@@ -113,6 +113,7 @@ IBVERBS_1.1 {
 IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
 	global:
 		/* These historical symbols are now private to libibverbs */
+		_verbs_init_and_alloc_context;
 		ibv_cmd_alloc_mw;
 		ibv_cmd_alloc_pd;
 		ibv_cmd_attach_mcast;
@@ -162,6 +163,7 @@ IBVERBS_PRIVATE_@IBVERBS_PABI_VERSION@ {
 		ibv_query_gid_type;
 		ibv_register_driver;
 		verbs_register_driver_@IBVERBS_PABI_VERSION@;
+		verbs_uninit_context;
 		verbs_init_cq;
 		ibv_cmd_modify_cq;
 };
diff --git a/providers/bnxt_re/main.c b/providers/bnxt_re/main.c
index 998c9fe3313389..5e83f9d1c12f35 100644
--- a/providers/bnxt_re/main.c
+++ b/providers/bnxt_re/main.c
@@ -111,14 +111,15 @@ static int bnxt_re_init_context(struct verbs_device *vdev,
 	struct bnxt_re_cntx_resp resp;
 	struct bnxt_re_dev *dev;
 	struct bnxt_re_context *cntx;
+	struct verbs_context *verbs_ctx = verbs_get_ctx(ibvctx);
 
 	dev = to_bnxt_re_dev(&vdev->device);
 	cntx = to_bnxt_re_context(ibvctx);
 
 	memset(&resp, 0, sizeof(resp));
 	ibvctx->cmd_fd = cmd_fd;
-	if (ibv_cmd_get_context(ibvctx, &cmd, sizeof(cmd),
-				&resp.resp, sizeof(resp)))
+	if (ibv_cmd_get_context(verbs_ctx, &cmd, sizeof(cmd), &resp.resp,
+				sizeof(resp)))
 		return errno;
 
 	cntx->dev_id = resp.dev_id;
diff --git a/providers/cxgb3/iwch.c b/providers/cxgb3/iwch.c
index da9179fbbe2a8d..d4d5a96ffd524e 100644
--- a/providers/cxgb3/iwch.c
+++ b/providers/cxgb3/iwch.c
@@ -104,42 +104,38 @@ unsigned long iwch_page_size;
 unsigned long iwch_page_shift;
 unsigned long iwch_page_mask;
 
-static struct ibv_context *iwch_alloc_context(struct ibv_device *ibdev,
-					      int cmd_fd)
+static struct verbs_context *iwch_alloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
 {
 	struct iwch_context *context;
 	struct ibv_get_context cmd;
 	struct iwch_alloc_ucontext_resp resp;
 	struct iwch_device *rhp = to_iwch_dev(ibdev);
 
-	context = malloc(sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	memset(context, 0, sizeof *context);
-	context->ibv_ctx.cmd_fd = cmd_fd;
-
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof cmd,
 				&resp.ibv_resp, sizeof resp))
 		goto err_free;
 
-	context->ibv_ctx.device = ibdev;
-	context->ibv_ctx.ops = iwch_ctx_ops;
+	context->ibv_ctx.context.ops = iwch_ctx_ops;
 
 	switch (rhp->hca_type) {
 	case CHELSIO_T3B:
 		PDBG("%s T3B device\n", __FUNCTION__);
-		context->ibv_ctx.ops.async_event = t3b_async_event;
-		context->ibv_ctx.ops.post_send = t3b_post_send;
-		context->ibv_ctx.ops.post_recv = t3b_post_recv;
-		context->ibv_ctx.ops.poll_cq = t3b_poll_cq;
+		context->ibv_ctx.context.ops.async_event = t3b_async_event;
+		context->ibv_ctx.context.ops.post_send = t3b_post_send;
+		context->ibv_ctx.context.ops.post_recv = t3b_post_recv;
+		context->ibv_ctx.context.ops.poll_cq = t3b_poll_cq;
 		break;
 	case CHELSIO_T3A:
 		PDBG("%s T3A device\n", __FUNCTION__);
-		context->ibv_ctx.ops.async_event = NULL;
-		context->ibv_ctx.ops.post_send = t3a_post_send;
-		context->ibv_ctx.ops.post_recv = t3a_post_recv;
-		context->ibv_ctx.ops.poll_cq = t3a_poll_cq;
+		context->ibv_ctx.context.ops.async_event = NULL;
+		context->ibv_ctx.context.ops.post_send = t3a_post_send;
+		context->ibv_ctx.context.ops.post_recv = t3a_post_recv;
+		context->ibv_ctx.context.ops.poll_cq = t3a_poll_cq;
 		break;
 	default:
 		PDBG("%s unknown hca type %d\n", __FUNCTION__, rhp->hca_type);
@@ -150,6 +146,7 @@ static struct ibv_context *iwch_alloc_context(struct ibv_device *ibdev,
 	return &context->ibv_ctx;
 
 err_free:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -158,6 +155,7 @@ static void iwch_free_context(struct ibv_context *ibctx)
 {
 	struct iwch_context *context = to_iwch_ctx(ibctx);
 
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/cxgb3/iwch.h b/providers/cxgb3/iwch.h
index 1b95fec664ef11..0b8060cf7cfa8f 100644
--- a/providers/cxgb3/iwch.h
+++ b/providers/cxgb3/iwch.h
@@ -71,7 +71,7 @@ static inline int t3a_device(struct iwch_device *dev)
 }
 
 struct iwch_context {
-	struct ibv_context ibv_ctx;
+	struct verbs_context ibv_ctx;
 };
 
 struct iwch_pd {
@@ -111,7 +111,7 @@ static inline struct iwch_device *to_iwch_dev(struct ibv_device *ibdev)
 
 static inline struct iwch_context *to_iwch_ctx(struct ibv_context *ibctx)
 {
-	return to_iwch_xxx(ctx, context);
+	return container_of(ibctx, struct iwch_context, ibv_ctx.context);
 }
 
 static inline struct iwch_pd *to_iwch_pd(struct ibv_pd *ibpd)
diff --git a/providers/cxgb4/dev.c b/providers/cxgb4/dev.c
index b6775da8afeef7..3c309d9f5defb5 100644
--- a/providers/cxgb4/dev.c
+++ b/providers/cxgb4/dev.c
@@ -96,8 +96,8 @@ static struct ibv_context_ops c4iw_ctx_ops = {
 	.req_notify_cq = c4iw_arm_cq,
 };
 
-static struct ibv_context *c4iw_alloc_context(struct ibv_device *ibdev,
-					      int cmd_fd)
+static struct verbs_context *c4iw_alloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
 {
 	struct c4iw_context *context;
 	struct ibv_get_context cmd;
@@ -107,13 +107,10 @@ static struct ibv_context *c4iw_alloc_context(struct ibv_device *ibdev,
 	uint64_t raw_fw_ver;
 	struct ibv_device_attr attr;
 
-	context = malloc(sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	memset(context, 0, sizeof *context);
-	context->ibv_ctx.cmd_fd = cmd_fd;
-
 	resp.status_page_size = 0;
 	resp.reserved = 0;
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof cmd,
@@ -133,8 +130,7 @@ static struct ibv_context *c4iw_alloc_context(struct ibv_device *ibdev,
 			goto err_free;
 	} 
 
-	context->ibv_ctx.device = ibdev;
-	context->ibv_ctx.ops = c4iw_ctx_ops;
+	context->ibv_ctx.context.ops = c4iw_ctx_ops;
 
 	switch (rhp->chip_version) {
 	case CHELSIO_T6:
@@ -143,11 +139,11 @@ static struct ibv_context *c4iw_alloc_context(struct ibv_device *ibdev,
 		PDBG("%s T5/T4 device\n", __FUNCTION__);
 	case CHELSIO_T4:
 		PDBG("%s T4 device\n", __FUNCTION__);
-		context->ibv_ctx.ops.async_event = c4iw_async_event;
-		context->ibv_ctx.ops.post_send = c4iw_post_send;
-		context->ibv_ctx.ops.post_recv = c4iw_post_receive;
-		context->ibv_ctx.ops.poll_cq = c4iw_poll_cq;
-		context->ibv_ctx.ops.req_notify_cq = c4iw_arm_cq;
+		context->ibv_ctx.context.ops.async_event = c4iw_async_event;
+		context->ibv_ctx.context.ops.post_send = c4iw_post_send;
+		context->ibv_ctx.context.ops.post_recv = c4iw_post_receive;
+		context->ibv_ctx.context.ops.poll_cq = c4iw_poll_cq;
+		context->ibv_ctx.context.ops.req_notify_cq = c4iw_arm_cq;
 		break;
 	default:
 		PDBG("%s unknown hca type %d\n", __FUNCTION__,
@@ -159,8 +155,8 @@ static struct ibv_context *c4iw_alloc_context(struct ibv_device *ibdev,
 	if (!rhp->mmid2ptr) {
 		int ret;
 
-		ret = ibv_cmd_query_device(&context->ibv_ctx, &attr, &raw_fw_ver, &qcmd,
-					   sizeof qcmd);
+		ret = ibv_cmd_query_device(&context->ibv_ctx.context, &attr,
+					   &raw_fw_ver, &qcmd, sizeof(qcmd));
 		if (ret)
 			goto err_unmap;
 		rhp->max_mr = attr.max_mr;
@@ -201,6 +197,7 @@ err_free:
 		free(rhp->cqid2ptr);
 	if (rhp->mmid2ptr)
 		free(rhp->cqid2ptr);
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -211,6 +208,8 @@ static void c4iw_free_context(struct ibv_context *ibctx)
 
 	if (context->status_page_size)
 		munmap(context->status_page, context->status_page_size);
+
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/cxgb4/libcxgb4.h b/providers/cxgb4/libcxgb4.h
index a5256f7e081770..893bd85d5f34b2 100644
--- a/providers/cxgb4/libcxgb4.h
+++ b/providers/cxgb4/libcxgb4.h
@@ -80,7 +80,7 @@ static inline int dev_is_t4(struct c4iw_dev *dev)
 }
 
 struct c4iw_context {
-	struct ibv_context ibv_ctx;
+	struct verbs_context ibv_ctx;
 	struct t4_dev_status_page *status_page;
 	int status_page_size;
 };
@@ -129,7 +129,7 @@ static inline struct c4iw_dev *to_c4iw_dev(struct ibv_device *ibdev)
 
 static inline struct c4iw_context *to_c4iw_context(struct ibv_context *ibctx)
 {
-	return to_c4iw_xxx(ctx, context);
+	return container_of(ibctx, struct c4iw_context, ibv_ctx.context);
 }
 
 static inline struct c4iw_pd *to_c4iw_pd(struct ibv_pd *ibpd)
diff --git a/providers/hfi1verbs/hfiverbs.c b/providers/hfi1verbs/hfiverbs.c
index 7f8f5714db1630..6117f99fbc27a2 100644
--- a/providers/hfi1verbs/hfiverbs.c
+++ b/providers/hfi1verbs/hfiverbs.c
@@ -123,41 +123,42 @@ static struct ibv_context_ops hfi1_ctx_ops = {
 	.detach_mcast	= ibv_cmd_detach_mcast
 };
 
-static struct ibv_context *hfi1_alloc_context(struct ibv_device *ibdev,
-					       int cmd_fd)
+static struct verbs_context *hfi1_alloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
 {
 	struct hfi1_context	    *context;
 	struct ibv_get_context       cmd;
 	struct ibv_get_context_resp  resp;
 	struct hfi1_device         *dev;
 
-	context = malloc(sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
-	memset(context, 0, sizeof *context);
-	context->ibv_ctx.cmd_fd = cmd_fd;
+
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd,
 				sizeof cmd, &resp, sizeof resp))
 		goto err_free;
 
-	context->ibv_ctx.ops = hfi1_ctx_ops;
+	context->ibv_ctx.context.ops = hfi1_ctx_ops;
 	dev = to_idev(ibdev);
 	if (dev->abi_version == 1) {
-		context->ibv_ctx.ops.create_cq     = hfi1_create_cq_v1;
-		context->ibv_ctx.ops.poll_cq       = ibv_cmd_poll_cq;
-		context->ibv_ctx.ops.resize_cq     = hfi1_resize_cq_v1;
-		context->ibv_ctx.ops.destroy_cq    = hfi1_destroy_cq_v1;
-		context->ibv_ctx.ops.create_srq    = hfi1_create_srq_v1;
-		context->ibv_ctx.ops.destroy_srq   = hfi1_destroy_srq_v1;
-		context->ibv_ctx.ops.modify_srq    = hfi1_modify_srq_v1;
-		context->ibv_ctx.ops.post_srq_recv = ibv_cmd_post_srq_recv;
-		context->ibv_ctx.ops.create_qp     = hfi1_create_qp_v1;
-		context->ibv_ctx.ops.destroy_qp    = hfi1_destroy_qp_v1;
-		context->ibv_ctx.ops.post_recv     = ibv_cmd_post_recv;
+		context->ibv_ctx.context.ops.create_cq = hfi1_create_cq_v1;
+		context->ibv_ctx.context.ops.poll_cq = ibv_cmd_poll_cq;
+		context->ibv_ctx.context.ops.resize_cq = hfi1_resize_cq_v1;
+		context->ibv_ctx.context.ops.destroy_cq = hfi1_destroy_cq_v1;
+		context->ibv_ctx.context.ops.create_srq = hfi1_create_srq_v1;
+		context->ibv_ctx.context.ops.destroy_srq = hfi1_destroy_srq_v1;
+		context->ibv_ctx.context.ops.modify_srq = hfi1_modify_srq_v1;
+		context->ibv_ctx.context.ops.post_srq_recv =
+			ibv_cmd_post_srq_recv;
+		context->ibv_ctx.context.ops.create_qp = hfi1_create_qp_v1;
+		context->ibv_ctx.context.ops.destroy_qp = hfi1_destroy_qp_v1;
+		context->ibv_ctx.context.ops.post_recv = ibv_cmd_post_recv;
 	}
 	return &context->ibv_ctx;
 
 err_free:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -166,6 +167,7 @@ static void hfi1_free_context(struct ibv_context *ibctx)
 {
 	struct hfi1_context *context = to_ictx(ibctx);
 
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/hfi1verbs/hfiverbs.h b/providers/hfi1verbs/hfiverbs.h
index e672dda4982527..e7a05a0c0a83db 100644
--- a/providers/hfi1verbs/hfiverbs.h
+++ b/providers/hfi1verbs/hfiverbs.h
@@ -74,7 +74,7 @@ struct hfi1_device {
 };
 
 struct hfi1_context {
-	struct ibv_context	ibv_ctx;
+	struct verbs_context	ibv_ctx;
 };
 
 /*
@@ -158,7 +158,7 @@ struct hfi1_srq {
 
 static inline struct hfi1_context *to_ictx(struct ibv_context *ibctx)
 {
-	return to_ixxx(ctx, context);
+	return container_of(ibctx, struct hfi1_context, ibv_ctx.context);
 }
 
 static inline struct hfi1_device *to_idev(struct ibv_device *ibdev)
diff --git a/providers/hns/hns_roce_u.c b/providers/hns/hns_roce_u.c
index 489b71614614fe..781825b3782044 100644
--- a/providers/hns/hns_roce_u.c
+++ b/providers/hns/hns_roce_u.c
@@ -61,8 +61,8 @@ static const struct verbs_match_ent hca_table[] = {
 	{}
 };
 
-static struct ibv_context *hns_roce_alloc_context(struct ibv_device *ibdev,
-						  int cmd_fd)
+static struct verbs_context *hns_roce_alloc_context(struct ibv_device *ibdev,
+						    int cmd_fd)
 {
 	int i;
 	struct ibv_get_context cmd;
@@ -71,11 +71,10 @@ static struct ibv_context *hns_roce_alloc_context(struct ibv_device *ibdev,
 	struct hns_roce_alloc_ucontext_resp resp;
 	struct hns_roce_device *hr_dev = to_hr_dev(ibdev);
 
-	context = calloc(1, sizeof(*context));
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	context->ibv_ctx.cmd_fd = cmd_fd;
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof(cmd),
 				&resp.ibv_resp, sizeof(resp)))
 		goto err_free;
@@ -113,28 +112,28 @@ static struct ibv_context *hns_roce_alloc_context(struct ibv_device *ibdev,
 
 	pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE);
 
-	context->ibv_ctx.ops.query_device  = hns_roce_u_query_device;
-	context->ibv_ctx.ops.query_port    = hns_roce_u_query_port;
-	context->ibv_ctx.ops.alloc_pd	   = hns_roce_u_alloc_pd;
-	context->ibv_ctx.ops.dealloc_pd    = hns_roce_u_free_pd;
-	context->ibv_ctx.ops.reg_mr	   = hns_roce_u_reg_mr;
-	context->ibv_ctx.ops.rereg_mr	   = hns_roce_u_rereg_mr;
-	context->ibv_ctx.ops.dereg_mr	   = hns_roce_u_dereg_mr;
-
-	context->ibv_ctx.ops.create_cq     = hns_roce_u_create_cq;
-	context->ibv_ctx.ops.poll_cq	   = hr_dev->u_hw->poll_cq;
-	context->ibv_ctx.ops.req_notify_cq = hr_dev->u_hw->arm_cq;
-	context->ibv_ctx.ops.cq_event	   = hns_roce_u_cq_event;
-	context->ibv_ctx.ops.destroy_cq    = hns_roce_u_destroy_cq;
-
-	context->ibv_ctx.ops.create_qp     = hns_roce_u_create_qp;
-	context->ibv_ctx.ops.query_qp	   = hns_roce_u_query_qp;
-	context->ibv_ctx.ops.modify_qp     = hr_dev->u_hw->modify_qp;
-	context->ibv_ctx.ops.destroy_qp    = hr_dev->u_hw->destroy_qp;
-	context->ibv_ctx.ops.post_send     = hr_dev->u_hw->post_send;
-	context->ibv_ctx.ops.post_recv     = hr_dev->u_hw->post_recv;
-
-	if (hns_roce_u_query_device(&context->ibv_ctx, &dev_attrs))
+	context->ibv_ctx.context.ops.query_device  = hns_roce_u_query_device;
+	context->ibv_ctx.context.ops.query_port    = hns_roce_u_query_port;
+	context->ibv_ctx.context.ops.alloc_pd	   = hns_roce_u_alloc_pd;
+	context->ibv_ctx.context.ops.dealloc_pd    = hns_roce_u_free_pd;
+	context->ibv_ctx.context.ops.reg_mr	   = hns_roce_u_reg_mr;
+	context->ibv_ctx.context.ops.rereg_mr	   = hns_roce_u_rereg_mr;
+	context->ibv_ctx.context.ops.dereg_mr	   = hns_roce_u_dereg_mr;
+
+	context->ibv_ctx.context.ops.create_cq     = hns_roce_u_create_cq;
+	context->ibv_ctx.context.ops.poll_cq	   = hr_dev->u_hw->poll_cq;
+	context->ibv_ctx.context.ops.req_notify_cq = hr_dev->u_hw->arm_cq;
+	context->ibv_ctx.context.ops.cq_event	   = hns_roce_u_cq_event;
+	context->ibv_ctx.context.ops.destroy_cq    = hns_roce_u_destroy_cq;
+
+	context->ibv_ctx.context.ops.create_qp     = hns_roce_u_create_qp;
+	context->ibv_ctx.context.ops.query_qp	   = hns_roce_u_query_qp;
+	context->ibv_ctx.context.ops.modify_qp     = hr_dev->u_hw->modify_qp;
+	context->ibv_ctx.context.ops.destroy_qp    = hr_dev->u_hw->destroy_qp;
+	context->ibv_ctx.context.ops.post_send     = hr_dev->u_hw->post_send;
+	context->ibv_ctx.context.ops.post_recv     = hr_dev->u_hw->post_recv;
+
+	if (hns_roce_u_query_device(&context->ibv_ctx.context, &dev_attrs))
 		goto tptr_free;
 
 	context->max_qp_wr = dev_attrs.max_qp_wr;
@@ -155,6 +154,7 @@ db_free:
 	context->uar = NULL;
 
 err_free:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -167,6 +167,7 @@ static void hns_roce_free_context(struct ibv_context *ibctx)
 	if (to_hr_dev(ibctx->device)->hw_version == HNS_ROCE_HW_VER1)
 		munmap(context->cq_tptr_base, HNS_ROCE_CQ_DB_BUF_SIZE);
 
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/hns/hns_roce_u.h b/providers/hns/hns_roce_u.h
index 101320b1f8f3ad..02912468e68a65 100644
--- a/providers/hns/hns_roce_u.h
+++ b/providers/hns/hns_roce_u.h
@@ -94,7 +94,7 @@ struct hns_roce_buf {
 };
 
 struct hns_roce_context {
-	struct ibv_context		ibv_ctx;
+	struct verbs_context		ibv_ctx;
 	void				*uar;
 	pthread_spinlock_t		uar_lock;
 
@@ -221,7 +221,7 @@ static inline struct hns_roce_device *to_hr_dev(struct ibv_device *ibv_dev)
 
 static inline struct hns_roce_context *to_hr_ctx(struct ibv_context *ibv_ctx)
 {
-	return container_of(ibv_ctx, struct hns_roce_context, ibv_ctx);
+	return container_of(ibv_ctx, struct hns_roce_context, ibv_ctx.context);
 }
 
 static inline struct hns_roce_pd *to_hr_pd(struct ibv_pd *ibv_pd)
diff --git a/providers/hns/hns_roce_u_verbs.c b/providers/hns/hns_roce_u_verbs.c
index 046f0a4b849712..3def78d25a9a71 100644
--- a/providers/hns/hns_roce_u_verbs.c
+++ b/providers/hns/hns_roce_u_verbs.c
@@ -208,7 +208,8 @@ static void hns_roce_set_sq_sizes(struct hns_roce_qp *qp,
 
 static int hns_roce_verify_cq(int *cqe, struct hns_roce_context *context)
 {
-	struct hns_roce_device *hr_dev = to_hr_dev(context->ibv_ctx.device);
+	struct hns_roce_device *hr_dev =
+		to_hr_dev(context->ibv_ctx.context.device);
 
 	if (hr_dev->hw_version == HNS_ROCE_HW_VER1)
 		if (*cqe < HNS_ROCE_MIN_CQE_NUM) {
@@ -328,7 +329,8 @@ int hns_roce_u_destroy_cq(struct ibv_cq *cq)
 static int hns_roce_verify_qp(struct ibv_qp_init_attr *attr,
 			      struct hns_roce_context *context)
 {
-	struct hns_roce_device *hr_dev = to_hr_dev(context->ibv_ctx.device);
+	struct hns_roce_device *hr_dev =
+		to_hr_dev(context->ibv_ctx.context.device);
 
 	if (hr_dev->hw_version == HNS_ROCE_HW_VER1) {
 		if (attr->cap.max_send_wr < HNS_ROCE_MIN_WQE_NUM) {
diff --git a/providers/i40iw/i40iw_umain.c b/providers/i40iw/i40iw_umain.c
index 77c1ced812499b..6ec40895efcfe0 100644
--- a/providers/i40iw/i40iw_umain.c
+++ b/providers/i40iw/i40iw_umain.c
@@ -131,19 +131,18 @@ static struct ibv_context_ops i40iw_uctx_ops = {
  * context and getting back resource information to return as ibv_context.
  */
 
-static struct ibv_context *i40iw_ualloc_context(struct ibv_device *ibdev, int cmd_fd)
+static struct verbs_context *i40iw_ualloc_context(struct ibv_device *ibdev,
+						  int cmd_fd)
 {
 	struct ibv_pd *ibv_pd;
 	struct i40iw_uvcontext *iwvctx;
 	struct i40iw_get_context cmd;
 	struct i40iw_ualloc_ucontext_resp resp;
 
-	iwvctx = malloc(sizeof(*iwvctx));
+	iwvctx = verbs_init_and_alloc_context(ibdev, cmd_fd, iwvctx, ibv_ctx);
 	if (!iwvctx)
 		return NULL;
 
-	memset(iwvctx, 0, sizeof(*iwvctx));
-	iwvctx->ibv_ctx.cmd_fd = cmd_fd;
 	cmd.userspace_ver = I40IW_ABI_VER;
 	memset(&resp, 0, sizeof(resp));
 	if (ibv_cmd_get_context(&iwvctx->ibv_ctx, (struct ibv_get_context *)&cmd,
@@ -162,24 +161,24 @@ static struct ibv_context *i40iw_ualloc_context(struct ibv_device *ibdev, int cm
 		goto err_free;
 	}
 
-	iwvctx->ibv_ctx.device = ibdev;
-	iwvctx->ibv_ctx.ops = i40iw_uctx_ops;
+	iwvctx->ibv_ctx.context.ops = i40iw_uctx_ops;
 	iwvctx->max_pds = resp.max_pds;
 	iwvctx->max_qps = resp.max_qps;
 	iwvctx->wq_size = resp.wq_size;
 	iwvctx->abi_ver = resp.kernel_ver;
 
 	i40iw_device_init_uk(&iwvctx->dev);
-	ibv_pd = i40iw_ualloc_pd(&iwvctx->ibv_ctx);
+	ibv_pd = i40iw_ualloc_pd(&iwvctx->ibv_ctx.context);
 	if (!ibv_pd)
 		goto err_free;
-	ibv_pd->context = &iwvctx->ibv_ctx;
+	ibv_pd->context = &iwvctx->ibv_ctx.context;
 	iwvctx->iwupd = to_i40iw_upd(ibv_pd);
 
 	return &iwvctx->ibv_ctx;
 
 err_free:
 	fprintf(stderr, PFX "%s: failed to allocate context for device.\n", __func__);
+	verbs_uninit_context(&iwvctx->ibv_ctx);
 	free(iwvctx);
 
 	return NULL;
@@ -195,6 +194,7 @@ static void i40iw_ufree_context(struct ibv_context *ibctx)
 
 	i40iw_ufree_pd(&iwvctx->iwupd->ibv_pd);
 
+	verbs_uninit_context(&iwvctx->ibv_ctx);
 	free(iwvctx);
 }
 
diff --git a/providers/i40iw/i40iw_umain.h b/providers/i40iw/i40iw_umain.h
index 109aba6bd92ef4..a2f4fa8f6b6bd9 100644
--- a/providers/i40iw/i40iw_umain.h
+++ b/providers/i40iw/i40iw_umain.h
@@ -83,7 +83,7 @@ struct i40iw_upd {
 };
 
 struct i40iw_uvcontext {
-	struct ibv_context ibv_ctx;
+	struct verbs_context ibv_ctx;
 	struct i40iw_upd *iwupd;
 	uint32_t max_pds;	/* maximum pds allowed for this user process */
 	uint32_t max_qps;	/* maximum qps allowed for this user process */
@@ -137,7 +137,7 @@ static inline struct i40iw_udevice *to_i40iw_udev(struct ibv_device *ibdev)
 
 static inline struct i40iw_uvcontext *to_i40iw_uctx(struct ibv_context *ibctx)
 {
-	return to_i40iw_uxxx(ctx, vcontext);
+	return container_of(ibctx, struct i40iw_uvcontext, ibv_ctx.context);
 }
 
 static inline struct i40iw_upd *to_i40iw_upd(struct ibv_pd *ibpd)
diff --git a/providers/ipathverbs/ipathverbs.c b/providers/ipathverbs/ipathverbs.c
index 449abb0489955a..3f7f170ed6b986 100644
--- a/providers/ipathverbs/ipathverbs.c
+++ b/providers/ipathverbs/ipathverbs.c
@@ -122,41 +122,42 @@ static struct ibv_context_ops ipath_ctx_ops = {
 	.detach_mcast	= ibv_cmd_detach_mcast
 };
 
-static struct ibv_context *ipath_alloc_context(struct ibv_device *ibdev,
-					       int cmd_fd)
+static struct verbs_context *ipath_alloc_context(struct ibv_device *ibdev,
+						 int cmd_fd)
 {
 	struct ipath_context	    *context;
 	struct ibv_get_context       cmd;
 	struct ibv_get_context_resp  resp;
 	struct ipath_device         *dev;
 
-	context = malloc(sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
-	memset(context, 0, sizeof *context);
-	context->ibv_ctx.cmd_fd = cmd_fd;
+
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd,
 				sizeof cmd, &resp, sizeof resp))
 		goto err_free;
 
-	context->ibv_ctx.ops = ipath_ctx_ops;
+	context->ibv_ctx.context.ops = ipath_ctx_ops;
 	dev = to_idev(ibdev);
 	if (dev->abi_version == 1) {
-		context->ibv_ctx.ops.create_cq     = ipath_create_cq_v1;
-		context->ibv_ctx.ops.poll_cq       = ibv_cmd_poll_cq;
-		context->ibv_ctx.ops.resize_cq     = ipath_resize_cq_v1;
-		context->ibv_ctx.ops.destroy_cq    = ipath_destroy_cq_v1;
-		context->ibv_ctx.ops.create_srq    = ipath_create_srq_v1;
-		context->ibv_ctx.ops.destroy_srq   = ipath_destroy_srq_v1;
-		context->ibv_ctx.ops.modify_srq    = ipath_modify_srq_v1;
-		context->ibv_ctx.ops.post_srq_recv = ibv_cmd_post_srq_recv;
-		context->ibv_ctx.ops.create_qp     = ipath_create_qp_v1;
-		context->ibv_ctx.ops.destroy_qp    = ipath_destroy_qp_v1;
-		context->ibv_ctx.ops.post_recv     = ibv_cmd_post_recv;
+		context->ibv_ctx.context.ops.create_cq = ipath_create_cq_v1;
+		context->ibv_ctx.context.ops.poll_cq = ibv_cmd_poll_cq;
+		context->ibv_ctx.context.ops.resize_cq = ipath_resize_cq_v1;
+		context->ibv_ctx.context.ops.destroy_cq = ipath_destroy_cq_v1;
+		context->ibv_ctx.context.ops.create_srq = ipath_create_srq_v1;
+		context->ibv_ctx.context.ops.destroy_srq = ipath_destroy_srq_v1;
+		context->ibv_ctx.context.ops.modify_srq = ipath_modify_srq_v1;
+		context->ibv_ctx.context.ops.post_srq_recv =
+			ibv_cmd_post_srq_recv;
+		context->ibv_ctx.context.ops.create_qp = ipath_create_qp_v1;
+		context->ibv_ctx.context.ops.destroy_qp = ipath_destroy_qp_v1;
+		context->ibv_ctx.context.ops.post_recv = ibv_cmd_post_recv;
 	}
 	return &context->ibv_ctx;
 
 err_free:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -165,6 +166,7 @@ static void ipath_free_context(struct ibv_context *ibctx)
 {
 	struct ipath_context *context = to_ictx(ibctx);
 
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/ipathverbs/ipathverbs.h b/providers/ipathverbs/ipathverbs.h
index 5f2658e7942c8b..d26a2a1b29009e 100644
--- a/providers/ipathverbs/ipathverbs.h
+++ b/providers/ipathverbs/ipathverbs.h
@@ -54,7 +54,7 @@ struct ipath_device {
 };
 
 struct ipath_context {
-	struct ibv_context	ibv_ctx;
+	struct verbs_context	ibv_ctx;
 };
 
 /*
@@ -137,7 +137,7 @@ struct ipath_srq {
 
 static inline struct ipath_context *to_ictx(struct ibv_context *ibctx)
 {
-	return to_ixxx(ctx, context);
+	return container_of(ibctx, struct ipath_context, ibv_ctx.context);
 }
 
 static inline struct ipath_device *to_idev(struct ibv_device *ibdev)
diff --git a/providers/mlx4/mlx4.c b/providers/mlx4/mlx4.c
index d2ccd328625c80..56bf1298b48734 100644
--- a/providers/mlx4/mlx4.c
+++ b/providers/mlx4/mlx4.c
@@ -167,16 +167,16 @@ static int mlx4_init_context(struct verbs_device *v_device,
 
 	mlx4_read_env();
 	if (dev->abi_version <= MLX4_UVERBS_NO_DEV_CAPS_ABI_VERSION) {
-		if (ibv_cmd_get_context(ibv_ctx, &cmd, sizeof cmd,
-					&resp_v3.ibv_resp, sizeof resp_v3))
+		if (ibv_cmd_get_context(verbs_ctx, &cmd, sizeof(cmd),
+					&resp_v3.ibv_resp, sizeof(resp_v3)))
 			return errno;
 
 		context->num_qps  = resp_v3.qp_tab_size;
 		bf_reg_size	  = resp_v3.bf_reg_size;
 		context->cqe_size = sizeof (struct mlx4_cqe);
 	} else  {
-		if (ibv_cmd_get_context(ibv_ctx, &cmd, sizeof cmd,
-					&resp.ibv_resp, sizeof resp))
+		if (ibv_cmd_get_context(verbs_ctx, &cmd, sizeof(cmd),
+					&resp.ibv_resp, sizeof(resp)))
 			return errno;
 
 		context->num_qps  = resp.qp_tab_size;
diff --git a/providers/mlx5/mlx5.c b/providers/mlx5/mlx5.c
index 36486218e31d81..a829cd5eb26473 100644
--- a/providers/mlx5/mlx5.c
+++ b/providers/mlx5/mlx5.c
@@ -549,7 +549,9 @@ static int mlx5_cmd_get_context(struct mlx5_context *context,
 				struct mlx5_alloc_ucontext_resp *resp,
 				size_t resp_len)
 {
-	if (!ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req,
+	struct verbs_context *verbs_ctx = verbs_get_ctx(&context->ibv_ctx);
+
+	if (!ibv_cmd_get_context(verbs_ctx, &req->ibv_req,
 				 req_len, &resp->ibv_resp, resp_len))
 		return 0;
 
@@ -572,12 +574,12 @@ static int mlx5_cmd_get_context(struct mlx5_context *context,
 	 * to do so. If zero is a valid response, we will add a new
 	 * field that indicates whether the request was handled.
 	 */
-	if (!ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req,
+	if (!ibv_cmd_get_context(verbs_ctx, &req->ibv_req,
 				 offsetof(struct mlx5_alloc_ucontext, lib_caps),
 				 &resp->ibv_resp, resp_len))
 		return 0;
 
-	return ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req,
+	return ibv_cmd_get_context(verbs_ctx, &req->ibv_req,
 				   offsetof(struct mlx5_alloc_ucontext,
 					    cqe_version),
 				   &resp->ibv_resp, resp_len);
diff --git a/providers/mthca/mthca.c b/providers/mthca/mthca.c
index 511b8d5139af9c..15827391986d3a 100644
--- a/providers/mthca/mthca.c
+++ b/providers/mthca/mthca.c
@@ -114,19 +114,18 @@ static struct ibv_context_ops mthca_ctx_ops = {
 	.detach_mcast  = ibv_cmd_detach_mcast
 };
 
-static struct ibv_context *mthca_alloc_context(struct ibv_device *ibdev, int cmd_fd)
+static struct verbs_context *mthca_alloc_context(struct ibv_device *ibdev,
+						 int cmd_fd)
 {
 	struct mthca_context            *context;
 	struct ibv_get_context           cmd;
 	struct mthca_alloc_ucontext_resp resp;
 	int                              i;
 
-	context = calloc(1, sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	context->ibv_ctx.cmd_fd = cmd_fd;
-
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof cmd,
 				&resp.ibv_resp, sizeof resp))
 		goto err_free;
@@ -135,13 +134,7 @@ static struct ibv_context *mthca_alloc_context(struct ibv_device *ibdev, int cmd
 	context->qp_table_shift = ffs(context->num_qps) - 1 - MTHCA_QP_TABLE_BITS;
 	context->qp_table_mask  = (1 << context->qp_table_shift) - 1;
 
-	/*
-	 * Need to set ibv_ctx.device because mthca_is_memfree() will
-	 * look at it to figure out the HCA type.
-	 */
-	context->ibv_ctx.device = ibdev;
-
-	if (mthca_is_memfree(&context->ibv_ctx)) {
+	if (mthca_is_memfree(&context->ibv_ctx.context)) {
 		context->db_tab = mthca_alloc_db_tab(resp.uarc_size);
 		if (!context->db_tab)
 			goto err_free;
@@ -159,26 +152,28 @@ static struct ibv_context *mthca_alloc_context(struct ibv_device *ibdev, int cmd
 
 	pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE);
 
-	context->pd = mthca_alloc_pd(&context->ibv_ctx);
+	context->pd = mthca_alloc_pd(&context->ibv_ctx.context);
 	if (!context->pd)
 		goto err_unmap;
 
-	context->pd->context = &context->ibv_ctx;
+	context->pd->context = &context->ibv_ctx.context;
 
-	context->ibv_ctx.ops = mthca_ctx_ops;
+	context->ibv_ctx.context.ops = mthca_ctx_ops;
 
-	if (mthca_is_memfree(&context->ibv_ctx)) {
-		context->ibv_ctx.ops.req_notify_cq = mthca_arbel_arm_cq;
-		context->ibv_ctx.ops.cq_event      = mthca_arbel_cq_event;
-		context->ibv_ctx.ops.post_send     = mthca_arbel_post_send;
-		context->ibv_ctx.ops.post_recv     = mthca_arbel_post_recv;
-		context->ibv_ctx.ops.post_srq_recv = mthca_arbel_post_srq_recv;
+	if (mthca_is_memfree(&context->ibv_ctx.context)) {
+		context->ibv_ctx.context.ops.req_notify_cq = mthca_arbel_arm_cq;
+		context->ibv_ctx.context.ops.cq_event = mthca_arbel_cq_event;
+		context->ibv_ctx.context.ops.post_send = mthca_arbel_post_send;
+		context->ibv_ctx.context.ops.post_recv = mthca_arbel_post_recv;
+		context->ibv_ctx.context.ops.post_srq_recv =
+			mthca_arbel_post_srq_recv;
 	} else {
-		context->ibv_ctx.ops.req_notify_cq = mthca_tavor_arm_cq;
-		context->ibv_ctx.ops.cq_event      = NULL;
-		context->ibv_ctx.ops.post_send     = mthca_tavor_post_send;
-		context->ibv_ctx.ops.post_recv     = mthca_tavor_post_recv;
-		context->ibv_ctx.ops.post_srq_recv = mthca_tavor_post_srq_recv;
+		context->ibv_ctx.context.ops.req_notify_cq = mthca_tavor_arm_cq;
+		context->ibv_ctx.context.ops.cq_event = NULL;
+		context->ibv_ctx.context.ops.post_send = mthca_tavor_post_send;
+		context->ibv_ctx.context.ops.post_recv = mthca_tavor_post_recv;
+		context->ibv_ctx.context.ops.post_srq_recv =
+			mthca_tavor_post_srq_recv;
 	}
 
 	return &context->ibv_ctx;
@@ -190,6 +185,7 @@ err_db_tab:
 	mthca_free_db_tab(context->db_tab);
 
 err_free:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -201,6 +197,8 @@ static void mthca_free_context(struct ibv_context *ibctx)
 	mthca_free_pd(context->pd);
 	munmap(context->uar, to_mdev(ibctx->device)->page_size);
 	mthca_free_db_tab(context->db_tab);
+
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/mthca/mthca.h b/providers/mthca/mthca.h
index a67acf46c7c56d..d788f7613b439c 100644
--- a/providers/mthca/mthca.h
+++ b/providers/mthca/mthca.h
@@ -97,7 +97,7 @@ struct mthca_device {
 struct mthca_db_table;
 
 struct mthca_context {
-	struct ibv_context     ibv_ctx;
+	struct verbs_context     ibv_ctx;
 	void                  *uar;
 	pthread_spinlock_t     uar_lock;
 	struct mthca_db_table *db_tab;
@@ -229,7 +229,7 @@ static inline struct mthca_device *to_mdev(struct ibv_device *ibdev)
 
 static inline struct mthca_context *to_mctx(struct ibv_context *ibctx)
 {
-	return to_mxxx(ctx, context);
+	return container_of(ibctx, struct mthca_context, ibv_ctx.context);
 }
 
 static inline struct mthca_pd *to_mpd(struct ibv_pd *ibpd)
diff --git a/providers/nes/nes_umain.c b/providers/nes/nes_umain.c
index bd0b6ac68cec40..a5ae678ecfe11c 100644
--- a/providers/nes/nes_umain.c
+++ b/providers/nes/nes_umain.c
@@ -98,7 +98,8 @@ static struct ibv_context_ops nes_uctx_ops = {
 /**
  * nes_ualloc_context
  */
-static struct ibv_context *nes_ualloc_context(struct ibv_device *ibdev, int cmd_fd)
+static struct verbs_context *nes_ualloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
 {
 	struct ibv_pd *ibv_pd;
 	struct nes_uvcontext *nesvctx;
@@ -109,16 +110,14 @@ static struct ibv_context *nes_ualloc_context(struct ibv_device *ibdev, int cmd_
 
 	page_size = sysconf(_SC_PAGESIZE);
 
-	nesvctx = malloc(sizeof *nesvctx);
+	nesvctx = verbs_init_and_alloc_context(ibdev, cmd_fd, nesvctx, ibv_ctx);
 	if (!nesvctx)
 		return NULL;
 
-	memset(nesvctx, 0, sizeof *nesvctx);
-	nesvctx->ibv_ctx.cmd_fd = cmd_fd;
 	cmd.userspace_ver = NES_ABI_USERSPACE_VER;
 
 	if (ibv_cmd_get_context(&nesvctx->ibv_ctx, (struct ibv_get_context *)&cmd, sizeof cmd,
-			&resp.ibv_resp, sizeof(resp)))
+				&resp.ibv_resp, sizeof(resp)))
 		goto err_free;
 
 	if (resp.kernel_ver != NES_ABI_KERNEL_VER) {
@@ -135,12 +134,10 @@ static struct ibv_context *nes_ualloc_context(struct ibv_device *ibdev, int cmd_
 			sscanf(value, "%d", &nes_drv_opt);
 	}
 
-	nesvctx->ibv_ctx.device = ibdev;
-
 	if (nes_drv_opt & NES_DRV_OPT_NO_DB_READ)
 		nes_uctx_ops.poll_cq = nes_upoll_cq_no_db_read;
 
-	nesvctx->ibv_ctx.ops = nes_uctx_ops;
+	nesvctx->ibv_ctx.context.ops = nes_uctx_ops;
 	nesvctx->max_pds = resp.max_pds;
 	nesvctx->max_qps = resp.max_qps;
 	nesvctx->wq_size = resp.wq_size;
@@ -148,16 +145,17 @@ static struct ibv_context *nes_ualloc_context(struct ibv_device *ibdev, int cmd_
 	nesvctx->mcrqf = 0;
 
 	/* Get a doorbell region for the CQs */
-	ibv_pd = nes_ualloc_pd(&nesvctx->ibv_ctx);
+	ibv_pd = nes_ualloc_pd(&nesvctx->ibv_ctx.context);
 	if (!ibv_pd)
 		goto err_free;
-	ibv_pd->context = &nesvctx->ibv_ctx;
+	ibv_pd->context = &nesvctx->ibv_ctx.context;
 	nesvctx->nesupd = to_nes_upd(ibv_pd);
 
 	return &nesvctx->ibv_ctx;
 
 err_free:
  	fprintf(stderr, PFX "%s: Failed to allocate context for device.\n", __FUNCTION__);
+	verbs_uninit_context(&nesvctx->ibv_ctx);
 	free(nesvctx);
 
 	return NULL;
@@ -172,6 +170,7 @@ static void nes_ufree_context(struct ibv_context *ibctx)
 	struct nes_uvcontext *nesvctx = to_nes_uctx(ibctx);
 	nes_ufree_pd(&nesvctx->nesupd->ibv_pd);
 
+	verbs_uninit_context(&nesvctx->ibv_ctx);
 	free(nesvctx);
 }
 
diff --git a/providers/nes/nes_umain.h b/providers/nes/nes_umain.h
index 0a832e7517bea6..2750c128d76ce7 100644
--- a/providers/nes/nes_umain.h
+++ b/providers/nes/nes_umain.h
@@ -261,7 +261,7 @@ struct nes_upd {
 };
 
 struct nes_uvcontext {
-	struct ibv_context ibv_ctx;
+	struct verbs_context ibv_ctx;
 	struct nes_upd *nesupd;
 	uint32_t max_pds; /* maximum pds allowed for this user process */
 	uint32_t max_qps; /* maximum qps allowed for this user process */
@@ -331,7 +331,7 @@ static inline struct nes_udevice *to_nes_udev(struct ibv_device *ibdev)
 
 static inline struct nes_uvcontext *to_nes_uctx(struct ibv_context *ibctx)
 {
-	return to_nes_uxxx(ctx, vcontext);
+	return container_of(ibctx, struct nes_uvcontext, ibv_ctx.context);
 }
 
 static inline struct nes_upd *to_nes_upd(struct ibv_pd *ibpd)
diff --git a/providers/ocrdma/ocrdma_main.c b/providers/ocrdma/ocrdma_main.c
index afd5d79c1884c0..5bb17eb8665bfc 100644
--- a/providers/ocrdma/ocrdma_main.c
+++ b/providers/ocrdma/ocrdma_main.c
@@ -105,27 +105,23 @@ static void ocrdma_uninit_device(struct verbs_device *verbs_device)
 /*
  * ocrdma_alloc_context
  */
-static struct ibv_context *ocrdma_alloc_context(struct ibv_device *ibdev,
-						int cmd_fd)
+static struct verbs_context *ocrdma_alloc_context(struct ibv_device *ibdev,
+						  int cmd_fd)
 {
 	struct ocrdma_devctx *ctx;
 	struct ocrdma_get_context cmd;
 	struct ocrdma_alloc_ucontext_resp resp;
 
-	ctx = calloc(1, sizeof(struct ocrdma_devctx));
+	ctx = verbs_init_and_alloc_context(ibdev, cmd_fd, ctx, ibv_ctx);
 	if (!ctx)
 		return NULL;
-	memset(&resp, 0, sizeof(resp));
-
-	ctx->ibv_ctx.cmd_fd = cmd_fd;
 
 	if (ibv_cmd_get_context(&ctx->ibv_ctx,
 				(struct ibv_get_context *)&cmd, sizeof cmd,
 				&resp.ibv_resp, sizeof(resp)))
 		goto cmd_err;
 
-	ctx->ibv_ctx.device = ibdev;
-	ctx->ibv_ctx.ops = ocrdma_ctx_ops;
+	ctx->ibv_ctx.context.ops = ocrdma_ctx_ops;
 	get_ocrdma_dev(ibdev)->id = resp.dev_id;
 	get_ocrdma_dev(ibdev)->max_inline_data = resp.max_inline_data;
 	get_ocrdma_dev(ibdev)->wqe_size = resp.wqe_size;
@@ -146,6 +142,7 @@ static struct ibv_context *ocrdma_alloc_context(struct ibv_device *ibdev,
 
 cmd_err:
 	ocrdma_err("%s: Failed to allocate context for device.\n", __func__);
+	verbs_uninit_context(&ctx->ibv_ctx);
 	free(ctx);
 	return NULL;
 }
@@ -160,6 +157,7 @@ static void ocrdma_free_context(struct ibv_context *ibctx)
 	if (ctx->ah_tbl)
 		munmap((void *)ctx->ah_tbl, ctx->ah_tbl_len);
 
+	verbs_uninit_context(&ctx->ibv_ctx);
 	free(ctx);
 }
 
diff --git a/providers/ocrdma/ocrdma_main.h b/providers/ocrdma/ocrdma_main.h
index e5b2860f9dc45c..e414223d07cd83 100644
--- a/providers/ocrdma/ocrdma_main.h
+++ b/providers/ocrdma/ocrdma_main.h
@@ -68,7 +68,7 @@ struct ocrdma_device {
 };
 
 struct ocrdma_devctx {
-	struct ibv_context ibv_ctx;
+	struct verbs_context ibv_ctx;
 	uint32_t *ah_tbl;
 	uint32_t ah_tbl_len;
 	pthread_mutex_t tbl_lock;
@@ -231,7 +231,7 @@ struct ocrdma_ah {
 
 static inline struct ocrdma_devctx *get_ocrdma_ctx(struct ibv_context *ibctx)
 {
-	return get_ocrdma_xxx(ctx, devctx);
+	return container_of(ibctx, struct ocrdma_devctx, ibv_ctx.context);
 }
 
 static inline struct ocrdma_device *get_ocrdma_dev(struct ibv_device *ibdev)
diff --git a/providers/qedr/qelr.h b/providers/qedr/qelr.h
index b3faa0044137d8..faa8e99cfa0798 100644
--- a/providers/qedr/qelr.h
+++ b/providers/qedr/qelr.h
@@ -118,7 +118,7 @@ struct qelr_device {
 };
 
 struct qelr_devctx {
-	struct ibv_context	ibv_ctx;
+	struct verbs_context	ibv_ctx;
 	FILE			*dbg_fp;
 	void			*db_addr;
 	uint64_t		db_pa;
@@ -251,7 +251,7 @@ struct qelr_qp {
 
 static inline struct qelr_devctx *get_qelr_ctx(struct ibv_context *ibctx)
 {
-	return container_of(ibctx, struct qelr_devctx, ibv_ctx);
+	return container_of(ibctx, struct qelr_devctx, ibv_ctx.context);
 }
 
 static inline struct qelr_device *get_qelr_dev(struct ibv_device *ibdev)
diff --git a/providers/qedr/qelr_main.c b/providers/qedr/qelr_main.c
index 4d62442a58dcb7..92a635cdcfca94 100644
--- a/providers/qedr/qelr_main.c
+++ b/providers/qedr/qelr_main.c
@@ -155,19 +155,18 @@ static void qelr_set_debug_mask(void)
 		qelr_dp_module = atoi(env);
 }
 
-static struct ibv_context *qelr_alloc_context(struct ibv_device *ibdev,
-					      int cmd_fd)
+static struct verbs_context *qelr_alloc_context(struct ibv_device *ibdev,
+						int cmd_fd)
 {
 	struct qelr_devctx *ctx;
 	struct qelr_get_context cmd;
 	struct qelr_alloc_ucontext_resp resp;
 
-	ctx = calloc(1, sizeof(struct qelr_devctx));
+	ctx = verbs_init_and_alloc_context(ibdev, cmd_fd, ctx, ibv_ctx);
 	if (!ctx)
 		return NULL;
-	memset(&resp, 0, sizeof(resp));
 
-	ctx->ibv_ctx.cmd_fd = cmd_fd;
+	memset(&resp, 0, sizeof(resp));
 
 	qelr_open_debug_file(ctx);
 	qelr_set_debug_mask();
@@ -178,8 +177,7 @@ static struct ibv_context *qelr_alloc_context(struct ibv_device *ibdev,
 		goto cmd_err;
 
 	ctx->kernel_page_size = sysconf(_SC_PAGESIZE);
-	ctx->ibv_ctx.device = ibdev;
-	ctx->ibv_ctx.ops = qelr_ctx_ops;
+	ctx->ibv_ctx.context.ops = qelr_ctx_ops;
 	ctx->db_pa = resp.db_pa;
 	ctx->db_size = resp.db_size;
 	ctx->max_send_wr = resp.max_send_wr;
@@ -205,6 +203,7 @@ static struct ibv_context *qelr_alloc_context(struct ibv_device *ibdev,
 cmd_err:
 	qelr_err("%s: Failed to allocate context for device.\n", __func__);
 	qelr_close_debug_file(ctx);
+	verbs_uninit_context(&ctx->ibv_ctx);
 	free(ctx);
 	return NULL;
 }
@@ -217,6 +216,7 @@ static void qelr_free_context(struct ibv_context *ibctx)
 		munmap(ctx->db_addr, ctx->db_size);
 
 	qelr_close_debug_file(ctx);
+	verbs_uninit_context(&ctx->ibv_ctx);
 	free(ctx);
 }
 
diff --git a/providers/qedr/qelr_verbs.c b/providers/qedr/qelr_verbs.c
index 7db0fb3216dde9..5d7aeb37453c44 100644
--- a/providers/qedr/qelr_verbs.c
+++ b/providers/qedr/qelr_verbs.c
@@ -887,7 +887,7 @@ static inline void qelr_init_dpm_info(struct qelr_devctx *cxt,
 	dpm->is_edpm = 0;
 
 	/* Currently dpm is not supported for iWARP */
-	if (IS_IWARP(cxt->ibv_ctx.device))
+	if (IS_IWARP(cxt->ibv_ctx.context.device))
 		return;
 
 	if (qelr_chain_is_full(&qp->sq.chain) &&
diff --git a/providers/rxe/rxe.c b/providers/rxe/rxe.c
index 683ffaa2a8af9c..5cfdf1aac08a86 100644
--- a/providers/rxe/rxe.c
+++ b/providers/rxe/rxe.c
@@ -858,29 +858,27 @@ static struct ibv_context_ops rxe_ctx_ops = {
 	.detach_mcast = ibv_cmd_detach_mcast
 };
 
-static struct ibv_context *rxe_alloc_context(struct ibv_device *ibdev,
-					     int cmd_fd)
+static struct verbs_context *rxe_alloc_context(struct ibv_device *ibdev,
+					       int cmd_fd)
 {
 	struct rxe_context *context;
 	struct ibv_get_context cmd;
 	struct ibv_get_context_resp resp;
 
-	context = malloc(sizeof *context);
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	memset(context, 0, sizeof *context);
-	context->ibv_ctx.cmd_fd = cmd_fd;
-
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd,
 				sizeof cmd, &resp, sizeof resp))
 		goto out;
 
-	context->ibv_ctx.ops = rxe_ctx_ops;
+	context->ibv_ctx.context.ops = rxe_ctx_ops;
 
 	return &context->ibv_ctx;
 
 out:
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 	return NULL;
 }
@@ -889,6 +887,7 @@ static void rxe_free_context(struct ibv_context *ibctx)
 {
 	struct rxe_context *context = to_rctx(ibctx);
 
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
diff --git a/providers/rxe/rxe.h b/providers/rxe/rxe.h
index 1f331662b2ba2d..3fc0436127e432 100644
--- a/providers/rxe/rxe.h
+++ b/providers/rxe/rxe.h
@@ -54,7 +54,7 @@ struct rxe_device {
 };
 
 struct rxe_context {
-	struct ibv_context	ibv_ctx;
+	struct verbs_context	ibv_ctx;
 };
 
 struct rxe_cq {
@@ -98,7 +98,7 @@ struct rxe_srq {
 
 static inline struct rxe_context *to_rctx(struct ibv_context *ibctx)
 {
-	return to_rxxx(ctx, context);
+	return container_of(ibctx, struct rxe_context, ibv_ctx.context);
 }
 
 static inline struct rxe_device *to_rdev(struct ibv_device *ibdev)
diff --git a/providers/vmw_pvrdma/pvrdma.h b/providers/vmw_pvrdma/pvrdma.h
index 3bcec1cb71d14d..58165cf434b721 100644
--- a/providers/vmw_pvrdma/pvrdma.h
+++ b/providers/vmw_pvrdma/pvrdma.h
@@ -105,7 +105,7 @@ struct pvrdma_device {
 };
 
 struct pvrdma_context {
-	struct ibv_context		ibv_ctx;
+	struct verbs_context		ibv_ctx;
 	void				*uar;
 	pthread_spinlock_t		uar_lock;
 	int				max_qp_wr;
@@ -201,7 +201,7 @@ static inline struct pvrdma_device *to_vdev(struct ibv_device *ibdev)
 
 static inline struct pvrdma_context *to_vctx(struct ibv_context *ibctx)
 {
-	return container_of(ibctx, struct pvrdma_context, ibv_ctx);
+	return container_of(ibctx, struct pvrdma_context, ibv_ctx.context);
 }
 
 static inline struct pvrdma_pd *to_vpd(struct ibv_pd *ibpd)
diff --git a/providers/vmw_pvrdma/pvrdma_main.c b/providers/vmw_pvrdma/pvrdma_main.c
index 17736cd0079036..08b1d4e6d34f07 100644
--- a/providers/vmw_pvrdma/pvrdma_main.c
+++ b/providers/vmw_pvrdma/pvrdma_main.c
@@ -111,7 +111,7 @@ static int pvrdma_init_context_shared(struct pvrdma_context *context,
 	struct ibv_get_context cmd;
 	struct user_pvrdma_alloc_ucontext_resp resp;
 
-	context->ibv_ctx.cmd_fd = cmd_fd;
+	context->ibv_ctx.context.cmd_fd = cmd_fd;
 	if (ibv_cmd_get_context(&context->ibv_ctx, &cmd, sizeof(cmd),
 				&resp.ibv_resp, sizeof(resp)))
 		return errno;
@@ -129,7 +129,7 @@ static int pvrdma_init_context_shared(struct pvrdma_context *context,
 	}
 
 	pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE);
-	context->ibv_ctx.ops = pvrdma_ctx_ops;
+	context->ibv_ctx.context.ops = pvrdma_ctx_ops;
 
 	return 0;
 }
@@ -141,18 +141,17 @@ static void pvrdma_free_context_shared(struct pvrdma_context *context,
 	free(context->qp_tbl);
 }
 
-static struct ibv_context *pvrdma_alloc_context(struct ibv_device *ibdev,
-						int cmd_fd)
+static struct verbs_context *pvrdma_alloc_context(struct ibv_device *ibdev,
+						  int cmd_fd)
 {
 	struct pvrdma_context *context;
 
-	context = malloc(sizeof(*context));
+	context = verbs_init_and_alloc_context(ibdev, cmd_fd, context, ibv_ctx);
 	if (!context)
 		return NULL;
 
-	memset(context, 0, sizeof(*context));
-
 	if (pvrdma_init_context_shared(context, ibdev, cmd_fd)) {
+		verbs_uninit_context(&context->ibv_ctx);
 		free(context);
 		return NULL;
 	}
@@ -165,6 +164,7 @@ static void pvrdma_free_context(struct ibv_context *ibctx)
 	struct pvrdma_context *context = to_vctx(ibctx);
 
 	pvrdma_free_context_shared(context, to_vdev(ibctx->device));
+	verbs_uninit_context(&context->ibv_ctx);
 	free(context);
 }
 
