drm/ttm: Make sure the mapped tt pages are decrypted when needed
authorjsg <jsg@openbsd.org>
Thu, 4 Apr 2024 07:33:22 +0000 (07:33 +0000)
committerjsg <jsg@openbsd.org>
Thu, 4 Apr 2024 07:33:22 +0000 (07:33 +0000)
From Zack Rusin
de125efb3bae7720d10364a9ab6785466e4e2461 in linux-6.6.y/6.6.24
71ce046327cfd3aef3f93d1c44e091395eb03f8f in mainline linux

sys/dev/pci/drm/include/drm/ttm/ttm_tt.h
sys/dev/pci/drm/ttm/ttm_bo_util.c
sys/dev/pci/drm/ttm/ttm_tt.c

index ce22c3f..c44421a 100644 (file)
@@ -81,6 +81,12 @@ struct ttm_tt {
         *   page_flags = TTM_TT_FLAG_EXTERNAL |
         *                TTM_TT_FLAG_EXTERNAL_MAPPABLE;
         *
+        * TTM_TT_FLAG_DECRYPTED: The mapped ttm pages should be marked as
+        * not encrypted. The framework will try to match what the dma layer
+        * is doing, but note that it is a little fragile because ttm page
+        * fault handling abuses the DMA api a bit and dma_map_attrs can't be
+        * used to assure pgprot always matches.
+        *
         * TTM_TT_FLAG_PRIV_POPULATED: TTM internal only. DO NOT USE. This is
         * set by TTM after ttm_tt_populate() has successfully returned, and is
         * then unset when TTM calls ttm_tt_unpopulate().
@@ -89,8 +95,9 @@ struct ttm_tt {
 #define TTM_TT_FLAG_ZERO_ALLOC         BIT(1)
 #define TTM_TT_FLAG_EXTERNAL           BIT(2)
 #define TTM_TT_FLAG_EXTERNAL_MAPPABLE  BIT(3)
+#define TTM_TT_FLAG_DECRYPTED          BIT(4)
 
-#define TTM_TT_FLAG_PRIV_POPULATED     BIT(4)
+#define TTM_TT_FLAG_PRIV_POPULATED     BIT(5)
        uint32_t page_flags;
        /** @num_pages: Number of pages in the page array. */
        uint32_t num_pages;
index d202b1d..a6cb1a8 100644 (file)
@@ -296,7 +296,13 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res,
        enum ttm_caching caching;
 
        man = ttm_manager_type(bo->bdev, res->mem_type);
-       caching = man->use_tt ? bo->ttm->caching : res->bus.caching;
+       if (man->use_tt) {
+               caching = bo->ttm->caching;
+               if (bo->ttm->page_flags & TTM_TT_FLAG_DECRYPTED)
+                       tmp = pgprot_decrypted(tmp);
+       } else  {
+               caching = res->bus.caching;
+       }
 
        return ttm_prot_from_caching(caching, tmp);
 }
@@ -348,6 +354,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
                .no_wait_gpu = false
        };
        struct ttm_tt *ttm = bo->ttm;
+       struct ttm_resource_manager *man =
+                       ttm_manager_type(bo->bdev, bo->resource->mem_type);
        pgprot_t prot;
        int ret;
 
@@ -357,7 +365,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
        if (ret)
                return ret;
 
-       if (num_pages == 1 && ttm->caching == ttm_cached) {
+       if (num_pages == 1 && ttm->caching == ttm_cached &&
+           !(man->use_tt && (ttm->page_flags & TTM_TT_FLAG_DECRYPTED))) {
                /*
                 * We're mapping a single page, and the desired
                 * page protection is consistent with the bo.
index 21d1d9c..0eee929 100644 (file)
 
 #define pr_fmt(fmt) "[TTM] " fmt
 
+#include <linux/cc_platform.h>
 #include <linux/sched.h>
 #include <linux/shmem_fs.h>
 #include <linux/file.h>
 #include <linux/module.h>
 #include <drm/drm_cache.h>
+#include <drm/drm_device.h>
+#include <drm/drm_util.h>
 #include <drm/ttm/ttm_bo.h>
 #include <drm/ttm/ttm_tt.h>
 
@@ -60,6 +63,7 @@ static atomic_long_t ttm_dma32_pages_allocated;
 int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
 {
        struct ttm_device *bdev = bo->bdev;
+       struct drm_device *ddev = bo->base.dev;
        uint32_t page_flags = 0;
 
        dma_resv_assert_held(bo->base.resv);
@@ -81,6 +85,15 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
                pr_err("Illegal buffer object type\n");
                return -EINVAL;
        }
+       /*
+        * When using dma_alloc_coherent with memory encryption the
+        * mapped TT pages need to be decrypted or otherwise the drivers
+        * will end up sending encrypted mem to the gpu.
+        */
+       if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+               page_flags |= TTM_TT_FLAG_DECRYPTED;
+               drm_info(ddev, "TT memory decryption enabled.");
+       }
 
        bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
        if (unlikely(bo->ttm == NULL))