Re: [PATCH] dma-direct: Force unencrypted DMA under SME for certain DMA masks

From: Robin Murphy
Date: Wed Jul 24 2019 - 13:06:18 EST


On 24/07/2019 17:42, Lendacky, Thomas wrote:
On 7/24/19 10:55 AM, Kirill A. Shutemov wrote:
On Wed, Jul 10, 2019 at 07:01:19PM +0000, Lendacky, Thomas wrote:
@@ -351,6 +355,32 @@ bool sev_active(void)
}
EXPORT_SYMBOL(sev_active);
+/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
+bool force_dma_unencrypted(struct device *dev)
+{
+ /*
+ * For SEV, all DMA must be to unencrypted addresses.
+ */
+ if (sev_active())
+ return true;
+
+ /*
+ * For SME, all DMA must be to unencrypted addresses if the
+ * device does not support DMA to addresses that include the
+ * encryption mask.
+ */
+ if (sme_active()) {
+ u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask));
+ u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask,
+ dev->bus_dma_mask);
+
+ if (dma_dev_mask <= dma_enc_mask)
+ return true;

Hm. What is wrong with the dev mask being equal to enc mask? IIUC, it
means that device mask is wide enough to cover encryption bit, doesn't it?

Not really... it's the way DMA_BIT_MASK works vs bit numbering. Let's say
that sme_me_mask has bit 47 set. __ffs64 returns 47 and DMA_BIT_MASK(47)
will generate a mask without bit 47 set (0x7fffffffffff). So the check
will catch anything that does not support at least 48-bit DMA.

Couldn't that be expressed as just:

if (sme_me_mask & dma_dev_mask == sme_me_mask)

?

Robin.