From: Jiri Pirko <[email protected]>

This is only relevant inside confidential computing (CoCo) virtual
machines, not on the hypervisor side.

Current CoCo designs don't place a vIOMMU in front of untrusted devices.
Instead, the DMA API forces all untrusted device DMA through swiotlb
bounce buffers (is_swiotlb_force_bounce()) which copies data into
decrypted memory on behalf of the device.

When a caller has already arranged for the memory to be decrypted
via set_memory_decrypted(), the DMA API needs to know so it can map
directly using the unencrypted physical address rather than bounce
buffering. Following the pattern of DMA_ATTR_MMIO, add
DMA_ATTR_CC_DECRYPTED for this purpose. Like the MMIO case, only the
caller knows what kind of memory it has and must inform the DMA API
for it to work correctly.

Signed-off-by: Jiri Pirko <[email protected]>
---
 include/linux/dma-mapping.h |  7 +++++++
 include/trace/events/dma.h  |  3 ++-
 kernel/dma/direct.h         | 14 +++++++++++---
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index aa36a0d1d9df..052235feb853 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -78,6 +78,13 @@
  */
 #define DMA_ATTR_MMIO          (1UL << 10)
 
+/*
+ * DMA_ATTR_CC_DECRYPTED: Indicates memory that has been explicitly decrypted
+ * (shared) for confidential computing guests. The caller must have
+ * called set_memory_decrypted(). A struct page is required.
+ */
+#define DMA_ATTR_CC_DECRYPTED  (1UL << 11)
+
 /*
  * A dma_addr_t can hold any valid DMA or bus address for the platform.  It can
  * be given to a device to use as a DMA source or target.  It is specific to a
diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
index b3fef140ae15..b3c2cee8841a 100644
--- a/include/trace/events/dma.h
+++ b/include/trace/events/dma.h
@@ -32,7 +32,8 @@ TRACE_DEFINE_ENUM(DMA_NONE);
                { DMA_ATTR_ALLOC_SINGLE_PAGES, "ALLOC_SINGLE_PAGES" }, \
                { DMA_ATTR_NO_WARN, "NO_WARN" }, \
                { DMA_ATTR_PRIVILEGED, "PRIVILEGED" }, \
-               { DMA_ATTR_MMIO, "MMIO" })
+               { DMA_ATTR_MMIO, "MMIO" }, \
+               { DMA_ATTR_CC_DECRYPTED, "CC_DECRYPTED" })
 
 DECLARE_EVENT_CLASS(dma_map,
        TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
index 62f0d9d0ba02..ae5bc1919e1c 100644
--- a/kernel/dma/direct.h
+++ b/kernel/dma/direct.h
@@ -87,16 +87,24 @@ static inline dma_addr_t dma_direct_map_phys(struct device 
*dev,
        dma_addr_t dma_addr;
 
        if (is_swiotlb_force_bounce(dev)) {
-               if (attrs & DMA_ATTR_MMIO)
-                       return DMA_MAPPING_ERROR;
+               if (!(attrs & DMA_ATTR_CC_DECRYPTED)) {
+                       if (attrs & DMA_ATTR_MMIO)
+                               return DMA_MAPPING_ERROR;
 
-               return swiotlb_map(dev, phys, size, dir, attrs);
+                       return swiotlb_map(dev, phys, size, dir, attrs);
+               }
+       } else if (attrs & DMA_ATTR_CC_DECRYPTED) {
+               return DMA_MAPPING_ERROR;
        }
 
        if (attrs & DMA_ATTR_MMIO) {
                dma_addr = phys;
                if (unlikely(!dma_capable(dev, dma_addr, size, false)))
                        goto err_overflow;
+       } else if (attrs & DMA_ATTR_CC_DECRYPTED) {
+               dma_addr = phys_to_dma_unencrypted(dev, phys);
+               if (unlikely(!dma_capable(dev, dma_addr, size, false)))
+                       goto err_overflow;
        } else {
                dma_addr = phys_to_dma(dev, phys);
                if (unlikely(!dma_capable(dev, dma_addr, size, true)) ||
-- 
2.51.1

Reply via email to