2019-11-15 20:50:44

by Ram Pai

[permalink] [raw]
Subject: [v3 0/2] Enable IOMMU support for pseries Secure VMs

This patch series enables IOMMU support for pseries Secure VMs.

Tested using QEMU command line option:

"-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x4,
iommu_platform=on,disable-modern=off,disable-legacy=on"

and

"-device virtio-blk-pci,scsi=off,bus=pci.0,
addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,
iommu_platform=on,disable-modern=off,disable-legacy=on"

changelog:
v3: Better description of 2/2 patch.
Suggested by David Gibson.
v2: added comments describing the changes.
Suggested by Alexey and Michael Ellermen.


Ram Pai (2):
powerpc/pseries/iommu: Share the per-cpu TCE page with the hypervisor.
powerpc/pseries/iommu: Use dma_iommu_ops for Secure VMs aswell.

arch/powerpc/platforms/pseries/iommu.c | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)

--
1.8.3.1


2019-11-15 20:50:50

by Ram Pai

[permalink] [raw]
Subject: [v3 1/2] powerpc/pseries/iommu: Share the per-cpu TCE page with the hypervisor.

H_PUT_TCE_INDIRECT hcall uses a page filled with TCE entries, as one of
its parameters. One page is dedicated per cpu, for the lifetime of the
kernel for this purpose. On secure VMs, contents of this page, when
accessed by the hypervisor, retrieves encrypted TCE entries. Hypervisor
needs to know the unencrypted entries, to update the TCE table
accordingly. There is nothing secret or sensitive about these entries.
Hence share the page with the hypervisor.

Signed-off-by: Ram Pai <[email protected]>
---
arch/powerpc/platforms/pseries/iommu.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 6ba081d..0720831 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -37,6 +37,7 @@
#include <asm/mmzone.h>
#include <asm/plpar_wrappers.h>
#include <asm/svm.h>
+#include <asm/ultravisor.h>

#include "pseries.h"

@@ -179,6 +180,23 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,

static DEFINE_PER_CPU(__be64 *, tce_page);

+/*
+ * Allocate a tce page. If secure VM, share the page with the hypervisor.
+ *
+ * NOTE: the TCE page is shared with the hypervisor explicitly and remains
+ * shared for the lifetime of the kernel. It is implicitly unshared at kernel
+ * shutdown through a UV_UNSHARE_ALL_PAGES ucall.
+ */
+static __be64 *alloc_tce_page(void)
+{
+ __be64 *tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
+
+ if (tcep && is_secure_guest())
+ uv_share_page(PHYS_PFN(__pa(tcep)), 1);
+
+ return tcep;
+}
+
static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
@@ -206,8 +224,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
* from iommu_alloc{,_sg}()
*/
if (!tcep) {
- tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
- /* If allocation fails, fall back to the loop implementation */
+ tcep = alloc_tce_page();
if (!tcep) {
local_irq_restore(flags);
return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
@@ -405,7 +422,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
tcep = __this_cpu_read(tce_page);

if (!tcep) {
- tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
+ tcep = alloc_tce_page();
if (!tcep) {
local_irq_enable();
return -ENOMEM;
--
1.8.3.1

2019-11-15 20:51:59

by Ram Pai

[permalink] [raw]
Subject: [v3 2/2] powerpc/pseries/iommu: Use dma_iommu_ops for Secure VMs aswell.

Commit edea902c1c1e ("powerpc/pseries/iommu: Don't use dma_iommu_ops on
secure guests")
disabled dma_iommu_ops path, for secure VMs. The rationale for disabling
the dma_iommu_ops path, was to use the dma_direct path, since it had
inbuilt support for bounce-buffering through SWIOTLB.

However dma_iommu_ops is functionally much richer. Depending on the
capabilities of the platform, it can handle direct DMA; with or without
bounce buffering, and it can handle indirect DMA. Hence its better to
leverage the richer functionality supported by dma_iommu_ops.

Renable dma_iommu_ops path for pseries Secure VMs.

Signed-off-by: Ram Pai <[email protected]>
---
arch/powerpc/platforms/pseries/iommu.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 0720831..6adf4d3 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -36,7 +36,6 @@
#include <asm/udbg.h>
#include <asm/mmzone.h>
#include <asm/plpar_wrappers.h>
-#include <asm/svm.h>
#include <asm/ultravisor.h>

#include "pseries.h"
@@ -1337,15 +1336,7 @@ void iommu_init_early_pSeries(void)
of_reconfig_notifier_register(&iommu_reconfig_nb);
register_memory_notifier(&iommu_mem_nb);

- /*
- * Secure guest memory is inacessible to devices so regular DMA isn't
- * possible.
- *
- * In that case keep devices' dma_map_ops as NULL so that the generic
- * DMA code path will use SWIOTLB to bounce buffers for DMA.
- */
- if (!is_secure_guest())
- set_pci_dma_ops(&dma_iommu_ops);
+ set_pci_dma_ops(&dma_iommu_ops);
}

static int __init disable_multitce(char *str)
--
1.8.3.1