Introduction
============
This is the second version of the fixes for direct-dma dealing with
memory encryption and restricted-dma.
In this version, one more fix is included and I go a step further
and attempt to clean up the code to consolidate it and make it less
error prone.
Especially with more users coming, such as using decrypted dma-bufs [1]
which also interacts with dma-direct.
Lastly I added a new documentation for memory encryption based on my
conclusion (Documentation/core-api/dma-direct-memory-encryption.rst)
Background
==========
At the moment the following hypervisor guests will need to deal with
memory encryption:
- pKVM (ARM): Documentation/virt/kvm/arm/hypercalls.rst
- ARM CCA: Documentation/arch/arm64/arm-cca.rst
- Intel TDX: Documentation/arch/x86/tdx.rst
- AMD SEV: Documentation/arch/x86/amd-memory-encryption.rst
- PPC SVM: Documentation/arch/powerpc/ultravisor.rst
- Hyper-V: Documentation/virt/hyperv/coco.rst
AFAICT, all (confidential) guests running under those have the memory
encrypted by default and guests will then explicitly share the memory
back if needed.
The main use cases for decrypting(sharing) memory are:
- Sharing memory back to the host through SWIOTLB (for virtio...)
- Hypervisor specific communication (ex: snp_msg, GHCB, VMBUS...)
- Shared/emulated resources: VGARAM (x86-SEV), GIC ITS tables (arm64)
While encrypting memory is typically used for reverting the
set_memory_decrypted() either in error handling or in freeing shared
resources back to the kernel.
Design
======
This series focuses mainly on dma-direct interaction with memory
encryption which is the complicated case.
At the moment memory encryption and dma-direct interacts in 2 ways:
1) force_dma_direct(): if true, memory will be decrypted by default
on allocation.
2) Restricted DMA: where memory is pre-decrypted and managed by
SWIOTLB.
With a third possible usage on the way [1] where the DMA-API allows
an attr for decrypted memory.
Instead of open coding many checks with is_swiotlb_for_alloc() and
force_dma_unencrypted() which doesn’t have the same exact semantics,
add some helpers to abstract that logic into the code:
* dma_external_decryption(dev): Returns true if the pages are decrypted
but managed externally.
* dma_owns_decryption(dev): Returns true if the pages need to be
explicitly decrypted and managed by the `dma-direct` layer (as the
architecture forces unencrypted DMA).
* is_dma_decrypted(dev): Returns true if the memory being used is in
a decrypted state, regardless of who manages it.
Testing
=======
I was able to test this only under pKVM (arm64) as I have no
access to other systems.
Future work
===========
Two other things I am also looking at which are related to restricted
DMA pools, so they should be a different series.
1) Private pools: Currently all restricted DMA pools are decrypted
(shared) by default. Having private pools would be useful for
device assignment when bouncing is needed (as for non-coherent
devices)
2) Optimizations for memory sharing. In some cases, allocations from
restricted dma-pools are page aligned. For CoCo cases, that means
that it will be cheaper to share memory in-place instead of
bouncing.
Both of these add new semantics which need to be done carefully to
avoid regressions, and might be a good candidate for a topic in the
next LPC.
Patches
=======
- 1-3 Fixes
- 4 Refactoring
- 5 Documentation
v1: https://lore.kernel.org/all/20260305170335.963568-1-smostafa@google.com/
[1] https://lore.kernel.org/all/20260305123641.164164-1-jiri@resnulli.us/
Mostafa Saleh (5):
dma-mapping: Avoid double decrypting with DMA_RESTRICTED_POOL
dma-mapping: Use the correct phys_to_dma() for DMA_RESTRICTED_POOL
dma-mapping: Decrypt memory on remap
dma-mapping: Refactor memory encryption usage
dma-mapping: Add doc for memory encryption
.../core-api/dma-direct-memory-encryption.rst | 77 +++++++++++++++++++
kernel/dma/direct.c | 51 ++++++++----
2 files changed, 114 insertions(+), 14 deletions(-)
create mode 100644 Documentation/core-api/dma-direct-memory-encryption.rst
--
2.53.0.1185.g05d4b7b318-goog