diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 9258902d9f70..675aa97612f6 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -52,6 +52,12 @@ static int vfio_ap_mdev_remove(struct mdev_device *mdev)
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 
 	mutex_lock(&matrix_dev.lock);
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: mdev remove failed: mdev %s is activated",
+			VFIO_AP_MODULE_NAME, __func__, matrix_mdev->name);
+		mutex_unlock(&matrix_dev.lock);
+		return -EBUSY;
+	}
 	list_del(&matrix_mdev->list);
 	mutex_unlock(&matrix_dev.lock);
 	kfree(matrix_mdev);
@@ -125,6 +131,15 @@ static ssize_t assign_adapter_store(struct device *dev,
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 	unsigned long max_apid = matrix_mdev->matrix.apm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: assign adapter '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &apid);
 	if (ret || (apid > max_apid)) {
 		pr_warn("%s: %s: adapter id '%s' not a value from 0 to %02lu(%#04lx)\n",
@@ -133,17 +148,17 @@ static ssize_t assign_adapter_store(struct device *dev,
 		if (!ret)
 			ret = -EINVAL;
 
-		return ret;
+		goto done;
 	}
 
 	/* Set the bit in the AP mask (APM) corresponding to the AP adapter
 	 * number (APID). The bits in the mask, from most significant to least
 	 * significant bit, correspond to APIDs 0-255.
 	 */
-	mutex_lock(&matrix_dev.lock);
 	set_bit_inv(apid, matrix_mdev->matrix.apm);
 	ret = count;
 
+done:
 	mutex_unlock(&matrix_dev.lock);
 
 	return ret;
@@ -175,6 +190,15 @@ static ssize_t unassign_adapter_store(struct device *dev,
 
 	unsigned long max_apid = matrix_mdev->matrix.apm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: unassign adapter '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &apid);
 	if (ret || (apid > max_apid)) {
 		pr_warn("%s: %s: adapter id '%s' must be a value from 0 to %02lu(%#04lx)\n",
@@ -183,10 +207,9 @@ static ssize_t unassign_adapter_store(struct device *dev,
 		if (!ret)
 			ret = -EINVAL;
 
-		return ret;
+		goto done;
 	}
 
-	mutex_lock(&matrix_dev.lock);
 	if (!test_bit_inv(apid, matrix_mdev->matrix.apm)) {
 		pr_warn("%s: %s: adapter id %02lu(%#04lx) not assigned\n",
 		       VFIO_AP_MODULE_NAME, __func__, apid, apid);
@@ -214,6 +237,15 @@ static ssize_t assign_domain_store(struct device *dev,
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 	unsigned long max_apqi = matrix_mdev->matrix.aqm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: assign domain '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &apqi);
 	if (ret || (apqi > max_apqi)) {
 		pr_warn("%s: %s: domain id '%s' not a value from 0 to %02lu(%#04lx)\n",
@@ -222,17 +254,17 @@ static ssize_t assign_domain_store(struct device *dev,
 		if (!ret)
 			ret = -EINVAL;
 
-		return ret;
+		goto done;
 	}
 
 	/* Set the bit in the AQM (bitmask) corresponding to the AP domain
 	 * number (APQI). The bits in the mask, from most significant to least
 	 * significant, correspond to numbers 0-255.
 	 */
-	mutex_lock(&matrix_dev.lock);
 	set_bit_inv(apqi, matrix_mdev->matrix.aqm);
 	ret = count;
 
+done:
 	mutex_unlock(&matrix_dev.lock);
 
 	return ret;
@@ -249,15 +281,23 @@ static ssize_t unassign_domain_store(struct device *dev,
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 	unsigned long max_apqi = matrix_mdev->matrix.aqm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: unassign domain '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &apqi);
 	if (ret || (apqi > max_apqi)) {
 		pr_warn("%s: %s: domain id '%s' not a value from 0 to %02lu(%#04lx)\n",
 		       VFIO_AP_MODULE_NAME, __func__, buf, max_apqi, max_apqi);
 		ret = -EINVAL;
-		return ret;
+		goto done;
 	}
 
-	mutex_lock(&matrix_dev.lock);
 	if (!test_bit_inv(apqi, matrix_mdev->matrix.aqm)) {
 		pr_warn("%s: %s: domain %02lu(%#04lx) not assigned\n",
 		       VFIO_AP_MODULE_NAME, __func__, apqi, apqi);
@@ -301,6 +341,15 @@ static ssize_t assign_control_domain_store(struct device *dev,
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 	unsigned long maxid = matrix_mdev->matrix.adm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: assign control domain '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &id);
 	if (ret || (id > maxid)) {
 		pr_warn("%s: %s: control domain id '%s' not a value from 0 to %02lu(%#04lx)\n",
@@ -309,7 +358,7 @@ static ssize_t assign_control_domain_store(struct device *dev,
 		if (!ret)
 			ret = -EINVAL;
 
-		return ret;
+		goto done;
 	}
 
 	/* Set the bit in the ADM (bitmask) corresponding to the AP control
@@ -317,10 +366,10 @@ static ssize_t assign_control_domain_store(struct device *dev,
 	 * least significant, correspond to IDs 0 up to the one less than the
 	 * number of control domains that can be assigned.
 	 */
-	mutex_lock(&matrix_dev.lock);
 	set_bit_inv(id, matrix_mdev->matrix.adm);
 	ret = count;
 
+done:
 	mutex_unlock(&matrix_dev.lock);
 
 	return ret;
@@ -351,16 +400,24 @@ static ssize_t unassign_control_domain_store(struct device *dev,
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 	unsigned long max_domid =  matrix_mdev->matrix.adm_max;
 
+	mutex_lock(&matrix_dev.lock);
+
+	if (matrix_mdev->activated) {
+		pr_warn("%s: %s: unassign control domain '%s' failed: mdev %s is activated\n",
+			VFIO_AP_MODULE_NAME, __func__, buf, matrix_mdev->name);
+		ret = -EBUSY;
+		goto done;
+	}
+
 	ret = kstrtoul(buf, 0, &domid);
 	if (ret || (domid > max_domid)) {
 		pr_warn("%s: %s: control domain id '%s' not a value from 0 to %02lu(%#04lx)\n",
 		       VFIO_AP_MODULE_NAME, __func__, buf,
 		       max_domid, max_domid);
 		ret = -EINVAL;
-		return ret;
+		goto done;
 	}
 
-	mutex_lock(&matrix_dev.lock);
 	if (!test_bit_inv(domid, matrix_mdev->matrix.adm)) {
 		pr_warn("%s: %s: control domain id %02lu(%#04lx) is not assigned\n",
 		       VFIO_AP_MODULE_NAME, __func__, domid, domid);
@@ -434,6 +491,168 @@ static ssize_t matrix_show(struct device *dev, struct device_attribute *attr,
 }
 DEVICE_ATTR_RO(matrix);
 
+static int vfio_ap_verify_queues_reserved(struct ap_matrix_mdev *matrix_mdev)
+{
+	unsigned long apid, apqi;
+	int ret = 0;
+
+	for_each_set_bit_inv(apid, matrix_mdev->matrix.apm,
+			     matrix_mdev->matrix.apm_max + 1) {
+		for_each_set_bit_inv(apqi, matrix_mdev->matrix.aqm,
+				     matrix_mdev->matrix.aqm_max + 1) {
+			if (!ap_owned_by_def_drv((int)apid, (int)apqi))
+				continue;
+
+			/*
+			 * We want to log every APQN that is not reserved by
+			 * the driver, so record the return code, log a message
+			 * and allow the loop to continue
+			 */
+			ret = -EPERM;
+			pr_warn("%s: activate for %s failed: queue %02lx.%04lx owned by default driver\n",
+				VFIO_AP_MODULE_NAME, matrix_mdev->name, apid,
+				apqi);
+		}
+	}
+
+	return ret;
+}
+
+static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *matrix_mdev,
+					 unsigned long apid, unsigned long apqi)
+{
+	pr_warn("%s: AP queue %02lx.%04lx is assigned to %s device\n", __func__,
+		apid, apqi, matrix_mdev->name);
+}
+
+/**
+ * vfio_ap_mdev_verify_no_sharing
+ *
+ * Verifies that the APQNs derived from the cross product of the AP adapter IDs
+ * and AP queue indexes comprising the AP matrix are not configured for another
+ * activated mediated device. AP queue sharing is not allowed.
+ *
+ * @kvm: the KVM guest
+ * @matrix: the AP matrix
+ *
+ * Returns 0 if the APQNs are valid, otherwise; returns -EBUSY.
+ */
+static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *matrix_mdev)
+{
+	int nbits;
+	struct ap_matrix_mdev *lstdev;
+	unsigned long apid, apqi;
+	unsigned long apm[BITS_TO_LONGS(matrix_mdev->matrix.apm_max + 1)];
+	unsigned long aqm[BITS_TO_LONGS(matrix_mdev->matrix.aqm_max + 1)];
+
+	list_for_each_entry(lstdev, &matrix_dev.mdev_list, list) {
+		if ((matrix_mdev == lstdev) || !lstdev->activated)
+			continue;
+
+		memset(apm, 0, sizeof(apm));
+		memset(aqm, 0, sizeof(aqm));
+
+		/*
+		 * We work on full longs, as we can only exclude the leftover
+		 * bits in non-inverse order. The leftover is all zeros.
+		 */
+		nbits = sizeof(apm) * BITS_PER_BYTE;
+		if (!bitmap_and(apm, matrix_mdev->matrix.apm,
+				lstdev->matrix.apm, nbits))
+			continue;
+
+		nbits = sizeof(aqm) * BITS_PER_BYTE;
+		if (!bitmap_and(aqm, matrix_mdev->matrix.aqm,
+				lstdev->matrix.aqm, nbits))
+			continue;
+
+		goto sharing_err;
+	}
+	return 0;
+
+sharing_err:
+
+	for_each_set_bit_inv(apid, apm, matrix_mdev->matrix.apm_max + 1)
+		for_each_set_bit_inv(apqi, aqm,
+				     matrix_mdev->matrix.aqm_max + 1)
+			vfio_ap_mdev_log_sharing_err(lstdev, apid, apqi);
+
+	return -EPERM;
+}
+
+static int vfio_ap_mdev_activate(struct ap_matrix_mdev *matrix_mdev)
+{
+	int ret = 0;
+
+	if (matrix_mdev->activated)
+		return 0;
+
+	ret = vfio_ap_verify_queues_reserved(matrix_mdev);
+	if (ret)
+		return ret;
+
+	ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev);
+	if (ret)
+		return ret;
+
+	matrix_mdev->activated = 1;
+
+	return 0;
+}
+
+static int vfio_ap_mdev_deactivate(struct ap_matrix_mdev *matrix_mdev)
+{
+	if (!matrix_mdev->activated)
+		return 0;
+
+	matrix_mdev->activated = false;
+
+	return 0;
+}
+
+static ssize_t activate_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int ret;
+	unsigned int activate;
+	struct mdev_device *mdev = mdev_from_dev(dev);
+	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+	ret = kstrtouint(buf, 0, &activate);
+	if (ret || ((activate != 0) && (activate != 1))) {
+		pr_warn("%s: %s: input to activate '%s' not 0 or 1\n",
+			VFIO_AP_MODULE_NAME, __func__, buf);
+
+		if (!ret)
+			ret = -EINVAL;
+
+		return ret;
+	}
+
+	mutex_lock(&matrix_dev.lock);
+
+	ret = (activate) ? vfio_ap_mdev_activate(matrix_mdev) :
+			   vfio_ap_mdev_deactivate(matrix_mdev);
+	if (ret)
+		goto done;
+
+	ret = count;
+
+done:
+	mutex_unlock(&matrix_dev.lock);
+
+	return ret;
+}
+
+static ssize_t activate_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct mdev_device *mdev = mdev_from_dev(dev);
+	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
+
+	return sprintf(buf, "%d\n", matrix_mdev->activated);
+}
+DEVICE_ATTR_RW(activate);
 
 static struct attribute *vfio_ap_mdev_attrs[] = {
 	&dev_attr_assign_adapter.attr,
@@ -444,6 +663,7 @@ static struct attribute *vfio_ap_mdev_attrs[] = {
 	&dev_attr_unassign_control_domain.attr,
 	&dev_attr_control_domains.attr,
 	&dev_attr_matrix.attr,
+	&dev_attr_activate.attr,
 	NULL,
 };
 
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index c2fd4a3e0ae3..df1996e6fce3 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -63,6 +63,7 @@ struct ap_matrix_mdev {
 	const char *name;
 	struct list_head list;
 	struct ap_matrix matrix;
+	bool activated;
 };
 
 static inline struct device *to_device(struct ap_matrix_dev *matrix_dev)
