]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: s390: pv: add export before import
authorClaudio Imbrenda <imbrenda@linux.ibm.com>
Tue, 28 Jun 2022 13:56:07 +0000 (15:56 +0200)
committerJanosch Frank <frankja@linux.ibm.com>
Wed, 13 Jul 2022 14:42:11 +0000 (14:42 +0000)
Due to upcoming changes, it will be possible to temporarily have
multiple protected VMs in the same address space, although only one
will be actually active.

In that scenario, it is necessary to perform an export of every page
that is to be imported, since the hardware does not allow a page
belonging to a protected guest to be imported into a different
protected guest.

This also applies to pages that are shared, and thus accessible by the
host.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Link: https://lore.kernel.org/r/20220628135619.32410-7-imbrenda@linux.ibm.com
Message-Id: <20220628135619.32410-7-imbrenda@linux.ibm.com>
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
arch/s390/kernel/uv.c

index 4c91a3dbc05b8d7529967eb001a71656e11dd806..f9810d2a267c68b37bcb940e59d3896444ef024e 100644 (file)
@@ -234,6 +234,32 @@ static int make_secure_pte(pte_t *ptep, unsigned long addr,
        return uvcb->rc == 0x10a ? -ENXIO : -EINVAL;
 }
 
+/**
+ * should_export_before_import - Determine whether an export is needed
+ * before an import-like operation
+ * @uvcb: the Ultravisor control block of the UVC to be performed
+ * @mm: the mm of the process
+ *
+ * Returns whether an export is needed before every import-like operation.
+ * This is needed for shared pages, which don't trigger a secure storage
+ * exception when accessed from a different guest.
+ *
+ * Although considered as one, the Unpin Page UVC is not an actual import,
+ * so it is not affected.
+ *
+ * No export is needed also when there is only one protected VM, because the
+ * page cannot belong to the wrong VM in that case (there is no "other VM"
+ * it can belong to).
+ *
+ * Return: true if an export is needed before every import, otherwise false.
+ */
+static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_struct *mm)
+{
+       if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED)
+               return false;
+       return atomic_read(&mm->context.protected_count) > 1;
+}
+
 /*
  * Requests the Ultravisor to make a page accessible to a guest.
  * If it's brought in the first time, it will be cleared. If
@@ -277,6 +303,8 @@ again:
 
        lock_page(page);
        ptep = get_locked_pte(gmap->mm, uaddr, &ptelock);
+       if (should_export_before_import(uvcb, gmap->mm))
+               uv_convert_from_secure(page_to_phys(page));
        rc = make_secure_pte(ptep, uaddr, page, uvcb);
        pte_unmap_unlock(ptep, ptelock);
        unlock_page(page);