Robin Murphy <[email protected]> writes:
> On 2026-02-11 6:00 pm, Michael Kelley wrote:
>> From: Tianyu Lan <[email protected]> Sent: Tuesday, February 10, 2026 8:21
>> AM
>>>
>>> Hyper-V provides Confidential VMBus to communicate between
>>> device model and device guest driver via encrypted/private
>>> memory in Confidential VM. The device model is in OpenHCL
>>> (https://openvmm.dev/guide/user_guide/openhcl.html) that
>>> plays the paravisor rule.
>>>
>>> For a VMBUS device, there are two communication methods to
>>
>> s/VMBUS/VMBus/
>>
>>> talk with Host/Hypervisor. 1) VMBus Ring buffer 2) dynamic
>>> DMA transition.
>>
>> I'm not sure what "dynamic DMA transition" is. Maybe just
>> "DMA transfers"? Also, do the same substitution further
>> down in this commit message.
>>
>>> The Confidential VMBus Ring buffer has been
>>> upstreamed by Roman Kisel(commit 6802d8af).
>>
>> It's customary to use 12 character commit IDs, which would be
>> 6802d8af47d1 in this case.
>>
>>>
>>> The dynamic DMA transition of VMBus device normally goes
>>> through DMA core and it uses SWIOTLB as bounce buffer in
>>> CVM
>>
>> "CVM" is Microsoft-speak. The Linux terminology is "a CoCo VM".
>>
>>> to communicate with Host/Hypervisor. The Confidential
>>> VMBus device may use private/encrypted memory to do DMA
>>> and so the device swiotlb(bounce buffer) isn't necessary.
>>
>> The phrase "isn't necessary" does not capture the real issue
>> here. Saying "isn't necessary" makes it sound like this patch is
>> just avoids unnecessary work, so that it is a performance
>> improvement. But that's not the case.
>>
>> The real issue is that swiotlb memory is decrypted. So bouncing
>> through the swiotlb exposes to the host what is supposed to be
>> confidential data passed on the Confidential VMBus. Disabling
>> the swiotlb bouncing in this case is a hard requirement to preserve
>> confidentially.
>
> Yeah, this really isn't a Hyper-V problem. Indeed as things stand,
> "swiotlb=force" could potentially break confidentiality for any
> environment trying to invent a notion of private DMA, and perhaps we
> could throw a big warning about that, but really the answer there is
> "Don't run your confidential workload with 'swiotlb=force'. Why would
> you even do that? Debug your drivers in a regular VM or bare-metal with
> full debug visibility like a normal person..."
>
> The fact is we do not have a proper notion of trusted/private DMA yet,
> and this is not the way to add it. The current assumption is very much
> that all DMA is untrusted in the CoCo sense, because initially it was
> only virtual devices emulated by a hypervisor, thus had to be bounced
> through shared memory anyway. AMD SEV with a stage 1 IOMMU in the guest
> can allow an assigned physical device to access a suitably-aligned
> encrypted buffer directly, but that's still effectively just putting the
> buffer into a temporarily shared state for that device, it merely skips
> sharing it with the rest of the system. !force_dma_unencrypted() doesn't
> mean "we trust this device's DMA", it just means "we don't have to use
> explicitly-decrypted pages to accommodate untrusted/shared DMA here",
> plus it also serves double-duty for host encryption which doesn't share
> the same trust model anyway.
>
> I assumed this would follow the TDISP stuff, but if Hyper-V has an
> alternative device-trusting mechanism already then there's no need to
> wait. We want some common device property (likely consolidating the
> current PCI external-facing port notion of trustedness plus whatever
> TDISP wants), with which we can then make proper decisions in all the
> right DMA API paths - and if it can end up replacing the horrible
> force_dma_unencrypted() as well then all the better! I'd totally
> forgotten about the previous discussion that Michael referred to (which
> I had to track down[1]), but it looks like all the main points were
> already covered there and we were approaching a consensus, so really I
> guess someone just needs to give it a go.
>
With my device-assignment–related changes, I have made the following
update. It may be a slightly stronger requirement to enforce that
trusted device cannot use SWIOTLB, but it simplifies the overall design.
I also have a prototype, that added two default swiotlb, ie,
static struct io_tlb_mem io_tlb_default_mem;
static struct io_tlb_mem io_tlb_default_shared_mem;
Looking at that change, I would suggest we avoid doing this unless we
are certain that there is a requirement for a trusted device to use
SWIOTLB bouncing.
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index b27de03f2466..07ef149bd9fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -292,6 +292,9 @@ bool swiotlb_free(struct device *dev, struct page *page,
size_t size);
static inline bool is_swiotlb_for_alloc(struct device *dev)
{
+ if (device_cc_accepted(dev))
+ return false;
+
return dev->dma_io_tlb_mem->for_alloc;
}
#else
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 34fe14b987f0..a89a7ac07499 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -159,6 +159,14 @@ static struct page *__dma_direct_alloc_pages(struct device
*dev, size_t size,
*/
static bool dma_direct_use_pool(struct device *dev, gfp_t gfp)
{
+ /*
+ * Atomic pools are marked decrypted and are used if we require require
+ * updation of pfn mem encryption attributes or for DMA non-coherent
+ * device allocation. Both is not true for trusted device.
+ */
+ if (device_cc_accepted(dev))
+ return false;
+
return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev);
}
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index a862712f4dc6..6d9f0c869c6f 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -1643,6 +1643,9 @@ bool is_swiotlb_active(struct device *dev)
{
struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ if (device_cc_accepted(dev))
+ return false;
+
return mem && mem->nslabs;
}