linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
@ 2025-02-27 14:41 Suzuki K Poulose
  2025-02-27 14:41 ` [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys Suzuki K Poulose
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Suzuki K Poulose @ 2025-02-27 14:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Suzuki K Poulose,
	Jean-Philippe Brucker, Christoph Hellwig, Marek Szyprowski,
	Tom Lendacky

Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
half and shared top half. In Linux we treat the "top" bit of the IPA space as
an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
and are managed by RMM. The "top" bit as attribute is only a software construct.

At present any device passed through to a Realm is treated as untrusted and the
Realm uses bounce buffering for any DMA, using the "decrypted" (shared) DMA
buffers (i.e., IPA with top bit set). In Linux, we only send the "DMA" address
masking the "top" bit. In Arm CCA, SMMU for untrusted devices are managed by the
non-secure Host and thus it can be confusing for the host/device when an unmasked
address is provided. Given there could be other hypervisors than Linux/KVM
running Arm CCA guests, the Realm Guest must adhere to a single convention for
the DMA address. This gets further complicated when we add support for trusted
devices, which can DMA into the full Realm memory space, once accepted. Thus,
a DMA masked address (with "top" bit lost) will prevent a trusted device from
accessing a shared buffer.

To resolve this Arm has decided to standardise the DMA address used by the Realm
to include the full IPA address bits (including the "top" bit, which Linux uses
as an attribute). This implies, any DMA to a shared buffer must have the top bit
of the IPA space set.

There is already a provision to do this in phys_to_dma* and dma_to_phys(), but
that is specific to AMD SME and is quite the opposite of what we need for Arm CCA.
i.e., For Arm CCA we need to set the bit for "decrypted" DMA and clear the bit
for "encrypted".

This series converts the existing __sme_* helpers to a bit more generalised versions :
dma_addr_decrypted() and dma_encrypted(). Also, while converting a DMA address back
to CPU physical address requires clearing off any "encryption/decryption" bits.
I have named this "dma_addr_canonical()". (The other options are :
  * dma_addr_clear_encryption - Well, not just for encryption, but we clear decryption
    too, so not ideal.
  * dma_addr_normal
  * dma_addr_clear
  * dma_addr_default

This also implies that the VMMs must take care to :

 1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
 2. Always mask the "top" bit off any IPA it receives from the Realm for DMA.
    KVM already does that today and no changes are required.

A kvmtool branch with the changes above is available here [1]. There are two
patches [2] & [3], that are really required on top of the Arm CCA support.

Ideally it would be good to get this backported to v6.13 stable kernel releases
to make sure that they are compliant with this change.

Changes since v2:
 Link: https://lkml.kernel.org/r/20250219220751.1276854-1-suzuki.poulose@arm.com
  - Collect Acks & Reviews for Patch 1
  - Rename helpers
  	dma_encrypted		=> dma_addr_encrypted
	dma_decrypted		=> dma_addr_unencrypted
	dma_clear_encryption	=> dma_addr_canonical
  - For Arm CCA, use PROT_NS_SHARED, set/clear only the top IPA bit.
  - Drop dma_addr_encrypted() helper for Arm CCA as it is a NOP

Changes since v1
 Link: https://lkml.kernel.org/r/20250212171411.951874-1-suzuki.poulose@arm.com
 - Follow Robin's suggestion to generalise the DMA address conversion helpers
   to provide dma_{encrypte,decrypted,clear_encryption}. See PATCH 2 for more
   details.
 - Add a fix to the ordering of "__sme_clr" for dma_to_phys (PATCH 1)

[1] git@git.gitlab.arm.com:linux-arm/kvmtool-cca.git cca/guest-dma-alias/v1
[2] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/ea37a6eb968abe4c75be4a8a90808714657c2ef7
[3] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/8afd0d5e6a7ee444dd0c1565fe94ecd831054a29

Cc: Will Deacon <will@kernel.org>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Gavin Shan <gshan@redhat.com>

Suzuki K Poulose (3):
  dma: Fix encryption bit clearing for dma_to_phys
  dma: Introduce generic dma_addr_*crypted helpers
  arm64: realm: Use aliased addresses for device DMA to shared buffers

 arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
 include/linux/dma-direct.h           | 13 +++++++++----
 include/linux/mem_encrypt.h          | 23 +++++++++++++++++++++++
 3 files changed, 43 insertions(+), 4 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys
  2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
@ 2025-02-27 14:41 ` Suzuki K Poulose
  2025-02-28  2:08   ` Gavin Shan
  2025-02-27 14:41 ` [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers Suzuki K Poulose
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Suzuki K Poulose @ 2025-02-27 14:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Suzuki K Poulose,
	Jean-Philippe Brucker, Christoph Hellwig, Marek Szyprowski,
	Tom Lendacky

phys_to_dma() sets the encryption bit on the translated DMA address. But
dma_to_phys() clears the encryption bit after it has been translated back
to the physical address, which could fail if the device uses DMA ranges.

AMD SME doesn't use the DMA ranges and thus this is harmless. But as we
are about to add support for other architectures, let us fix this.

Reported-by: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Link: https://lkml.kernel.org/r/yq5amsen9stc.fsf@kernel.org
Cc: Will Deacon <will@kernel.org>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 include/linux/dma-direct.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index d7e30d4f7503..d20ecc24cb0f 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -101,12 +101,13 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr)
 {
 	phys_addr_t paddr;
 
+	dma_addr = __sme_clr(dma_addr);
 	if (dev->dma_range_map)
 		paddr = translate_dma_to_phys(dev, dma_addr);
 	else
 		paddr = dma_addr;
 
-	return __sme_clr(paddr);
+	return paddr;
 }
 #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers
  2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
  2025-02-27 14:41 ` [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys Suzuki K Poulose
@ 2025-02-27 14:41 ` Suzuki K Poulose
  2025-02-28  2:09   ` Gavin Shan
  2025-02-28 18:23   ` Robin Murphy
  2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 17+ messages in thread
From: Suzuki K Poulose @ 2025-02-27 14:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Suzuki K Poulose,
	Jean-Philippe Brucker, Christoph Hellwig, Marek Szyprowski,
	Tom Lendacky

AMD SME added __sme_set/__sme_clr primitives to modify the DMA address for
encrypted/decrypted traffic. However this doesn't fit in with other models,
e.g., Arm CCA where the meanings are the opposite. i.e., "decrypted" traffic
has a bit set and "encrypted" traffic has the top bit cleared.

In preparation for adding the support for Arm CCA DMA conversions, convert the
existing primitives to more generic ones that can be provided by the backends.
i.e., add helpers to
 1. dma_addr_encrypted - Convert a DMA address to "encrypted" [ == __sme_set() ]
 2. dma_addr_unencrypted - Convert a DMA address to "decrypted" [ None exists today ]
 3. dma_addr_canonical - Clear any "encryption"/"decryption" bits from DMA
    address [ SME uses __sme_clr() ] and convert to a canonical DMA address.

Since the original __sme_xxx helpers come from linux/mem_encrypt.h, use that
as the home for the new definitions and provide dummy ones when none is provided
by the architectures.

With the above, phys_to_dma_unencrypted() uses the newly added dma_addr_unencrypted()
helper and to make it a bit more easier to read and avoid double conversion,
provide __phys_to_dma().

Suggested-by: Robin Murphy <robin.murphy@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Changes since v2:
 - Rename helpers- s/dma_*crypted/dma_addr_*crypted (Robin)
---
 include/linux/dma-direct.h  | 12 ++++++++----
 include/linux/mem_encrypt.h | 23 +++++++++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index d20ecc24cb0f..f3bc0bcd7098 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -78,14 +78,18 @@ static inline dma_addr_t dma_range_map_max(const struct bus_dma_region *map)
 #define phys_to_dma_unencrypted		phys_to_dma
 #endif
 #else
-static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
-		phys_addr_t paddr)
+static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
 	if (dev->dma_range_map)
 		return translate_phys_to_dma(dev, paddr);
 	return paddr;
 }
 
+static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
+						phys_addr_t paddr)
+{
+	return dma_addr_unencrypted(__phys_to_dma(dev, paddr));
+}
 /*
  * If memory encryption is supported, phys_to_dma will set the memory encryption
  * bit in the DMA address, and dma_to_phys will clear it.
@@ -94,14 +98,14 @@ static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
  */
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return __sme_set(phys_to_dma_unencrypted(dev, paddr));
+	return dma_addr_encrypted(__phys_to_dma(dev, paddr));
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr)
 {
 	phys_addr_t paddr;
 
-	dma_addr = __sme_clr(dma_addr);
+	dma_addr = dma_addr_canonical(dma_addr);
 	if (dev->dma_range_map)
 		paddr = translate_dma_to_phys(dev, dma_addr);
 	else
diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
index ae4526389261..07584c5e36fb 100644
--- a/include/linux/mem_encrypt.h
+++ b/include/linux/mem_encrypt.h
@@ -26,11 +26,34 @@
  */
 #define __sme_set(x)		((x) | sme_me_mask)
 #define __sme_clr(x)		((x) & ~sme_me_mask)
+
+#define dma_addr_encrypted(x)	__sme_set(x)
+#define dma_addr_canonical(x)	__sme_clr(x)
+
 #else
 #define __sme_set(x)		(x)
 #define __sme_clr(x)		(x)
 #endif
 
+/*
+ * dma_addr_encrypted() and dma_addr_unencrypted() are for converting a given DMA
+ * address to the respective type of addressing.
+ *
+ * dma_addr_canonical() is used to reverse any conversions for encrypted/decrypted
+ * back to the canonical address.
+ */
+#ifndef dma_addr_encrypted
+#define dma_addr_encrypted(x)		(x)
+#endif
+
+#ifndef dma_addr_unencrypted
+#define dma_addr_unencrypted(x)		(x)
+#endif
+
+#ifndef dma_addr_canonical
+#define dma_addr_canonical(x)		(x)
+#endif
+
 #endif	/* __ASSEMBLY__ */
 
 #endif	/* __MEM_ENCRYPT_H__ */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
  2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
  2025-02-27 14:41 ` [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys Suzuki K Poulose
  2025-02-27 14:41 ` [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers Suzuki K Poulose
@ 2025-02-27 14:41 ` Suzuki K Poulose
  2025-02-27 16:05   ` Catalin Marinas
                     ` (2 more replies)
  2025-03-03 11:35 ` [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
  2025-03-11 17:15 ` Catalin Marinas
  4 siblings, 3 replies; 17+ messages in thread
From: Suzuki K Poulose @ 2025-02-27 14:41 UTC (permalink / raw)
  To: linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Suzuki K Poulose,
	Jean-Philippe Brucker, Christoph Hellwig, Marek Szyprowski,
	Tom Lendacky

When a device performs DMA to a shared buffer using physical addresses,
(without Stage1 translation), the device must use the "{I}PA address" with the
top bit set in Realm. This is to make sure that a trusted device will be able
to write to shared buffers as well as the protected buffers. Thus, a Realm must
always program the full address including the "protection" bit, like AMD SME
encryption bits.

Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
helpers for Realms. Please note that the VMM needs to similarly make sure that
the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
unprotected alias.

Cc: Will Deacon <will@kernel.org>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Changes since v2:
 - Drop dma_addr_encrypted() helper, which is a NOP for CCA ( Aneesh )
 - Only mask the "top" IPA bit and not all the bits beyond top bit. ( Robin )
 - Use PROT_NS_SHARED, now that we only set/clear top bit. (Gavin)
---
 arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h
index f8f78f622dd2..a2a1eeb36d4b 100644
--- a/arch/arm64/include/asm/mem_encrypt.h
+++ b/arch/arm64/include/asm/mem_encrypt.h
@@ -21,4 +21,15 @@ static inline bool force_dma_unencrypted(struct device *dev)
 	return is_realm_world();
 }
 
+/*
+ * For Arm CCA guests, canonical addresses are "encrypted", so no changes
+ * required for dma_addr_encrypted().
+ * The unencrypted DMA buffers must be accessed via the unprotected IPA,
+ * "top IPA bit" set.
+ */
+#define dma_addr_unencrypted(x)		((x) | PROT_NS_SHARED)
+
+/* Clear the "top" IPA bit while converting back */
+#define dma_addr_canonical(x)		((x) & ~PROT_NS_SHARED)
+
 #endif	/* __ASM_MEM_ENCRYPT_H */
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
  2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
@ 2025-02-27 16:05   ` Catalin Marinas
  2025-02-27 17:03     ` Suzuki K Poulose
  2025-02-28  2:08   ` Gavin Shan
  2025-03-03 14:16   ` Robin Murphy
  2 siblings, 1 reply; 17+ messages in thread
From: Catalin Marinas @ 2025-02-27 16:05 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: linux-kernel, will, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky

On Thu, Feb 27, 2025 at 02:41:50PM +0000, Suzuki K Poulose wrote:
> When a device performs DMA to a shared buffer using physical addresses,
> (without Stage1 translation), the device must use the "{I}PA address" with the
> top bit set in Realm. This is to make sure that a trusted device will be able
> to write to shared buffers as well as the protected buffers. Thus, a Realm must
> always program the full address including the "protection" bit, like AMD SME
> encryption bits.
> 
> Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
> helpers for Realms. Please note that the VMM needs to similarly make sure that
> the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
> unprotected alias.
> 
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

In case this goes in via the DMA API tree:

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

(we could bikeshed on the names like unencrypted vs decrypted but I'm
not fussed about)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
  2025-02-27 16:05   ` Catalin Marinas
@ 2025-02-27 17:03     ` Suzuki K Poulose
  0 siblings, 0 replies; 17+ messages in thread
From: Suzuki K Poulose @ 2025-02-27 17:03 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: linux-kernel, will, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky

On 27/02/2025 16:05, Catalin Marinas wrote:
> On Thu, Feb 27, 2025 at 02:41:50PM +0000, Suzuki K Poulose wrote:
>> When a device performs DMA to a shared buffer using physical addresses,
>> (without Stage1 translation), the device must use the "{I}PA address" with the
>> top bit set in Realm. This is to make sure that a trusted device will be able
>> to write to shared buffers as well as the protected buffers. Thus, a Realm must
>> always program the full address including the "protection" bit, like AMD SME
>> encryption bits.
>>
>> Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
>> helpers for Realms. Please note that the VMM needs to similarly make sure that
>> the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
>> unprotected alias.
>>
>> Cc: Will Deacon <will@kernel.org>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Steven Price <steven.price@arm.com>
>> Cc: Christoph Hellwig <hch@lst.de>
>> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> 
> In case this goes in via the DMA API tree:
> 
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>

Thanks Catalin.

> 
> (we could bikeshed on the names like unencrypted vs decrypted but I'm
> not fussed about)

It was initially decrypted, but Robin suggested that the DMA layer 
already uses "encrypted" and "unencrypted" (e.g., 
force_dma_unencrypted(), phys_to_dma_unencrypted() etc)

Cheers
Suzuki





^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
  2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
  2025-02-27 16:05   ` Catalin Marinas
@ 2025-02-28  2:08   ` Gavin Shan
  2025-03-03 14:16   ` Robin Murphy
  2 siblings, 0 replies; 17+ messages in thread
From: Gavin Shan @ 2025-02-28  2:08 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky



On 2/28/25 12:41 AM, Suzuki K Poulose wrote:
> When a device performs DMA to a shared buffer using physical addresses,
> (without Stage1 translation), the device must use the "{I}PA address" with the
> top bit set in Realm. This is to make sure that a trusted device will be able
> to write to shared buffers as well as the protected buffers. Thus, a Realm must
> always program the full address including the "protection" bit, like AMD SME
> encryption bits.
> 
> Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
> helpers for Realms. Please note that the VMM needs to similarly make sure that
> the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
> unprotected alias.
> 
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> Changes since v2:
>   - Drop dma_addr_encrypted() helper, which is a NOP for CCA ( Aneesh )
>   - Only mask the "top" IPA bit and not all the bits beyond top bit. ( Robin )
>   - Use PROT_NS_SHARED, now that we only set/clear top bit. (Gavin)
> ---
>   arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 

Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys
  2025-02-27 14:41 ` [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys Suzuki K Poulose
@ 2025-02-28  2:08   ` Gavin Shan
  0 siblings, 0 replies; 17+ messages in thread
From: Gavin Shan @ 2025-02-28  2:08 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky

On 2/28/25 12:41 AM, Suzuki K Poulose wrote:
> phys_to_dma() sets the encryption bit on the translated DMA address. But
> dma_to_phys() clears the encryption bit after it has been translated back
> to the physical address, which could fail if the device uses DMA ranges.
> 
> AMD SME doesn't use the DMA ranges and thus this is harmless. But as we
> are about to add support for other architectures, let us fix this.
> 
> Reported-by: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Link: https://lkml.kernel.org/r/yq5amsen9stc.fsf@kernel.org
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>   include/linux/dma-direct.h | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers
  2025-02-27 14:41 ` [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers Suzuki K Poulose
@ 2025-02-28  2:09   ` Gavin Shan
  2025-02-28 18:23   ` Robin Murphy
  1 sibling, 0 replies; 17+ messages in thread
From: Gavin Shan @ 2025-02-28  2:09 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky

On 2/28/25 12:41 AM, Suzuki K Poulose wrote:
> AMD SME added __sme_set/__sme_clr primitives to modify the DMA address for
> encrypted/decrypted traffic. However this doesn't fit in with other models,
> e.g., Arm CCA where the meanings are the opposite. i.e., "decrypted" traffic
> has a bit set and "encrypted" traffic has the top bit cleared.
> 
> In preparation for adding the support for Arm CCA DMA conversions, convert the
> existing primitives to more generic ones that can be provided by the backends.
> i.e., add helpers to
>   1. dma_addr_encrypted - Convert a DMA address to "encrypted" [ == __sme_set() ]
>   2. dma_addr_unencrypted - Convert a DMA address to "decrypted" [ None exists today ]
>   3. dma_addr_canonical - Clear any "encryption"/"decryption" bits from DMA
>      address [ SME uses __sme_clr() ] and convert to a canonical DMA address.
> 
> Since the original __sme_xxx helpers come from linux/mem_encrypt.h, use that
> as the home for the new definitions and provide dummy ones when none is provided
> by the architectures.
> 
> With the above, phys_to_dma_unencrypted() uses the newly added dma_addr_unencrypted()
> helper and to make it a bit more easier to read and avoid double conversion,
> provide __phys_to_dma().
> 
> Suggested-by: Robin Murphy <robin.murphy@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> Changes since v2:
>   - Rename helpers- s/dma_*crypted/dma_addr_*crypted (Robin)
> ---
>   include/linux/dma-direct.h  | 12 ++++++++----
>   include/linux/mem_encrypt.h | 23 +++++++++++++++++++++++
>   2 files changed, 31 insertions(+), 4 deletions(-)
> 

Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers
  2025-02-27 14:41 ` [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers Suzuki K Poulose
  2025-02-28  2:09   ` Gavin Shan
@ 2025-02-28 18:23   ` Robin Murphy
  1 sibling, 0 replies; 17+ messages in thread
From: Robin Murphy @ 2025-02-28 18:23 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	linux-arm-kernel, Jean-Philippe Brucker, Christoph Hellwig,
	Marek Szyprowski, Tom Lendacky

On 27/02/2025 2:41 pm, Suzuki K Poulose wrote:
> AMD SME added __sme_set/__sme_clr primitives to modify the DMA address for
> encrypted/decrypted traffic. However this doesn't fit in with other models,
> e.g., Arm CCA where the meanings are the opposite. i.e., "decrypted" traffic
> has a bit set and "encrypted" traffic has the top bit cleared.
> 
> In preparation for adding the support for Arm CCA DMA conversions, convert the
> existing primitives to more generic ones that can be provided by the backends.
> i.e., add helpers to
>   1. dma_addr_encrypted - Convert a DMA address to "encrypted" [ == __sme_set() ]
>   2. dma_addr_unencrypted - Convert a DMA address to "decrypted" [ None exists today ]
>   3. dma_addr_canonical - Clear any "encryption"/"decryption" bits from DMA
>      address [ SME uses __sme_clr() ] and convert to a canonical DMA address.
> 
> Since the original __sme_xxx helpers come from linux/mem_encrypt.h, use that
> as the home for the new definitions and provide dummy ones when none is provided
> by the architectures.
> 
> With the above, phys_to_dma_unencrypted() uses the newly added dma_addr_unencrypted()
> helper and to make it a bit more easier to read and avoid double conversion,
> provide __phys_to_dma().

Yeah, I'm happy with "canonical" being the least-worst option for now; I 
certainly can't think of anything snappier yet still sufficiently clear.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> Suggested-by: Robin Murphy <robin.murphy@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> Changes since v2:
>   - Rename helpers- s/dma_*crypted/dma_addr_*crypted (Robin)
> ---
>   include/linux/dma-direct.h  | 12 ++++++++----
>   include/linux/mem_encrypt.h | 23 +++++++++++++++++++++++
>   2 files changed, 31 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
> index d20ecc24cb0f..f3bc0bcd7098 100644
> --- a/include/linux/dma-direct.h
> +++ b/include/linux/dma-direct.h
> @@ -78,14 +78,18 @@ static inline dma_addr_t dma_range_map_max(const struct bus_dma_region *map)
>   #define phys_to_dma_unencrypted		phys_to_dma
>   #endif
>   #else
> -static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
> -		phys_addr_t paddr)
> +static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
>   {
>   	if (dev->dma_range_map)
>   		return translate_phys_to_dma(dev, paddr);
>   	return paddr;
>   }
>   
> +static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
> +						phys_addr_t paddr)
> +{
> +	return dma_addr_unencrypted(__phys_to_dma(dev, paddr));
> +}
>   /*
>    * If memory encryption is supported, phys_to_dma will set the memory encryption
>    * bit in the DMA address, and dma_to_phys will clear it.
> @@ -94,14 +98,14 @@ static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
>    */
>   static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
>   {
> -	return __sme_set(phys_to_dma_unencrypted(dev, paddr));
> +	return dma_addr_encrypted(__phys_to_dma(dev, paddr));
>   }
>   
>   static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr)
>   {
>   	phys_addr_t paddr;
>   
> -	dma_addr = __sme_clr(dma_addr);
> +	dma_addr = dma_addr_canonical(dma_addr);
>   	if (dev->dma_range_map)
>   		paddr = translate_dma_to_phys(dev, dma_addr);
>   	else
> diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h
> index ae4526389261..07584c5e36fb 100644
> --- a/include/linux/mem_encrypt.h
> +++ b/include/linux/mem_encrypt.h
> @@ -26,11 +26,34 @@
>    */
>   #define __sme_set(x)		((x) | sme_me_mask)
>   #define __sme_clr(x)		((x) & ~sme_me_mask)
> +
> +#define dma_addr_encrypted(x)	__sme_set(x)
> +#define dma_addr_canonical(x)	__sme_clr(x)
> +
>   #else
>   #define __sme_set(x)		(x)
>   #define __sme_clr(x)		(x)
>   #endif
>   
> +/*
> + * dma_addr_encrypted() and dma_addr_unencrypted() are for converting a given DMA
> + * address to the respective type of addressing.
> + *
> + * dma_addr_canonical() is used to reverse any conversions for encrypted/decrypted
> + * back to the canonical address.
> + */
> +#ifndef dma_addr_encrypted
> +#define dma_addr_encrypted(x)		(x)
> +#endif
> +
> +#ifndef dma_addr_unencrypted
> +#define dma_addr_unencrypted(x)		(x)
> +#endif
> +
> +#ifndef dma_addr_canonical
> +#define dma_addr_canonical(x)		(x)
> +#endif
> +
>   #endif	/* __ASSEMBLY__ */
>   
>   #endif	/* __MEM_ENCRYPT_H__ */


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
                   ` (2 preceding siblings ...)
  2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
@ 2025-03-03 11:35 ` Suzuki K Poulose
  2025-03-04 13:40   ` Marek Szyprowski
  2025-03-11 17:15 ` Catalin Marinas
  4 siblings, 1 reply; 17+ messages in thread
From: Suzuki K Poulose @ 2025-03-03 11:35 UTC (permalink / raw)
  To: linux-kernel, Marek Szyprowski
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Marek Szyprowski, Tom Lendacky

Hi Marek,


On 27/02/2025 14:41, Suzuki K Poulose wrote:
> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> half and shared top half. In Linux we treat the "top" bit of the IPA space as
> an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> and are managed by RMM. The "top" bit as attribute is only a software construct.
> 
> At present any device passed through to a Realm is treated as untrusted and the
> Realm uses bounce buffering for any DMA, using the "decrypted" (shared) DMA
> buffers (i.e., IPA with top bit set). In Linux, we only send the "DMA" address
> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are managed by the
> non-secure Host and thus it can be confusing for the host/device when an unmasked
> address is provided. Given there could be other hypervisors than Linux/KVM
> running Arm CCA guests, the Realm Guest must adhere to a single convention for
> the DMA address. This gets further complicated when we add support for trusted
> devices, which can DMA into the full Realm memory space, once accepted. Thus,
> a DMA masked address (with "top" bit lost) will prevent a trusted device from
> accessing a shared buffer.
> 
> To resolve this Arm has decided to standardise the DMA address used by the Realm
> to include the full IPA address bits (including the "top" bit, which Linux uses
> as an attribute). This implies, any DMA to a shared buffer must have the top bit
> of the IPA space set.
> 
> There is already a provision to do this in phys_to_dma* and dma_to_phys(), but
> that is specific to AMD SME and is quite the opposite of what we need for Arm CCA.
> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and clear the bit
> for "encrypted".
> 
> This series converts the existing __sme_* helpers to a bit more generalised versions :
> dma_addr_decrypted() and dma_encrypted(). Also, while converting a DMA address back
> to CPU physical address requires clearing off any "encryption/decryption" bits.
> I have named this "dma_addr_canonical()". (The other options are :
>    * dma_addr_clear_encryption - Well, not just for encryption, but we clear decryption
>      too, so not ideal.
>    * dma_addr_normal
>    * dma_addr_clear
>    * dma_addr_default
> 
> This also implies that the VMMs must take care to :
> 
>   1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>   2. Always mask the "top" bit off any IPA it receives from the Realm for DMA.
>      KVM already does that today and no changes are required.
> 
> A kvmtool branch with the changes above is available here [1]. There are two
> patches [2] & [3], that are really required on top of the Arm CCA support.
> 
> Ideally it would be good to get this backported to v6.13 stable kernel releases
> to make sure that they are compliant with this change.
> 

Please could you take a look at this series and let us know your
thoughts ? If you are happy with the changes, are you happy to pull
this through the DMA MAP tree ? The relevant bits have been reviewed/
acked by people (arm64 and AMD bits).

Kind regards
Suzuki


> Changes since v2:
>   Link: https://lkml.kernel.org/r/20250219220751.1276854-1-suzuki.poulose@arm.com
>    - Collect Acks & Reviews for Patch 1
>    - Rename helpers
>    	dma_encrypted		=> dma_addr_encrypted
> 	dma_decrypted		=> dma_addr_unencrypted
> 	dma_clear_encryption	=> dma_addr_canonical
>    - For Arm CCA, use PROT_NS_SHARED, set/clear only the top IPA bit.
>    - Drop dma_addr_encrypted() helper for Arm CCA as it is a NOP
> 
> Changes since v1
>   Link: https://lkml.kernel.org/r/20250212171411.951874-1-suzuki.poulose@arm.com
>   - Follow Robin's suggestion to generalise the DMA address conversion helpers
>     to provide dma_{encrypte,decrypted,clear_encryption}. See PATCH 2 for more
>     details.
>   - Add a fix to the ordering of "__sme_clr" for dma_to_phys (PATCH 1)
> 
> [1] git@git.gitlab.arm.com:linux-arm/kvmtool-cca.git cca/guest-dma-alias/v1
> [2] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/ea37a6eb968abe4c75be4a8a90808714657c2ef7
> [3] https://gitlab.arm.com/linux-arm/kvmtool-cca/-/commit/8afd0d5e6a7ee444dd0c1565fe94ecd831054a29
> 
> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Gavin Shan <gshan@redhat.com>
> 
> Suzuki K Poulose (3):
>    dma: Fix encryption bit clearing for dma_to_phys
>    dma: Introduce generic dma_addr_*crypted helpers
>    arm64: realm: Use aliased addresses for device DMA to shared buffers
> 
>   arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
>   include/linux/dma-direct.h           | 13 +++++++++----
>   include/linux/mem_encrypt.h          | 23 +++++++++++++++++++++++
>   3 files changed, 43 insertions(+), 4 deletions(-)
> 



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
  2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
  2025-02-27 16:05   ` Catalin Marinas
  2025-02-28  2:08   ` Gavin Shan
@ 2025-03-03 14:16   ` Robin Murphy
  2 siblings, 0 replies; 17+ messages in thread
From: Robin Murphy @ 2025-03-03 14:16 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	linux-arm-kernel, Jean-Philippe Brucker, Christoph Hellwig,
	Marek Szyprowski, Tom Lendacky

On 27/02/2025 2:41 pm, Suzuki K Poulose wrote:
> When a device performs DMA to a shared buffer using physical addresses,
> (without Stage1 translation), the device must use the "{I}PA address" with the
> top bit set in Realm. This is to make sure that a trusted device will be able
> to write to shared buffers as well as the protected buffers. Thus, a Realm must
> always program the full address including the "protection" bit, like AMD SME
> encryption bits.
> 
> Enable this by providing arm64 specific dma_addr_{encrypted, canonical}
> helpers for Realms. Please note that the VMM needs to similarly make sure that
> the SMMU Stage2 in the Non-secure world is setup accordingly to map IPA at the
> unprotected alias.

FWIW,

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

> Cc: Will Deacon <will@kernel.org>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> Changes since v2:
>   - Drop dma_addr_encrypted() helper, which is a NOP for CCA ( Aneesh )
>   - Only mask the "top" IPA bit and not all the bits beyond top bit. ( Robin )
>   - Use PROT_NS_SHARED, now that we only set/clear top bit. (Gavin)
> ---
>   arch/arm64/include/asm/mem_encrypt.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h
> index f8f78f622dd2..a2a1eeb36d4b 100644
> --- a/arch/arm64/include/asm/mem_encrypt.h
> +++ b/arch/arm64/include/asm/mem_encrypt.h
> @@ -21,4 +21,15 @@ static inline bool force_dma_unencrypted(struct device *dev)
>   	return is_realm_world();
>   }
>   
> +/*
> + * For Arm CCA guests, canonical addresses are "encrypted", so no changes
> + * required for dma_addr_encrypted().
> + * The unencrypted DMA buffers must be accessed via the unprotected IPA,
> + * "top IPA bit" set.
> + */
> +#define dma_addr_unencrypted(x)		((x) | PROT_NS_SHARED)
> +
> +/* Clear the "top" IPA bit while converting back */
> +#define dma_addr_canonical(x)		((x) & ~PROT_NS_SHARED)
> +
>   #endif	/* __ASM_MEM_ENCRYPT_H */


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-03-03 11:35 ` [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
@ 2025-03-04 13:40   ` Marek Szyprowski
  2025-03-06 11:39     ` Suzuki K Poulose
  0 siblings, 1 reply; 17+ messages in thread
From: Marek Szyprowski @ 2025-03-04 13:40 UTC (permalink / raw)
  To: Suzuki K Poulose, linux-kernel
  Cc: will, catalin.marinas, maz, steven.price, aneesh.kumar, gshan,
	robin.murphy, linux-arm-kernel, Jean-Philippe Brucker,
	Christoph Hellwig, Tom Lendacky

Hi,

On 03.03.2025 12:35, Suzuki K Poulose wrote:
> On 27/02/2025 14:41, Suzuki K Poulose wrote:
>> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. 
>> The address
>> space (GPA or IPA) of a Realm VM is split into two halves, with 
>> private bottom
>> half and shared top half. In Linux we treat the "top" bit of the IPA 
>> space as
>> an attribute, to indicate whether it is shared or not (MSB == 1 
>> implies shared).
>> Stage2 (GPA to PA) translations used by the CPU accesses, cover the 
>> full IPA space,
>> and are managed by RMM. The "top" bit as attribute is only a software 
>> construct.
>>
>> At present any device passed through to a Realm is treated as 
>> untrusted and the
>> Realm uses bounce buffering for any DMA, using the "decrypted" 
>> (shared) DMA
>> buffers (i.e., IPA with top bit set). In Linux, we only send the 
>> "DMA" address
>> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are 
>> managed by the
>> non-secure Host and thus it can be confusing for the host/device when 
>> an unmasked
>> address is provided. Given there could be other hypervisors than 
>> Linux/KVM
>> running Arm CCA guests, the Realm Guest must adhere to a single 
>> convention for
>> the DMA address. This gets further complicated when we add support 
>> for trusted
>> devices, which can DMA into the full Realm memory space, once 
>> accepted. Thus,
>> a DMA masked address (with "top" bit lost) will prevent a trusted 
>> device from
>> accessing a shared buffer.
>>
>> To resolve this Arm has decided to standardise the DMA address used 
>> by the Realm
>> to include the full IPA address bits (including the "top" bit, which 
>> Linux uses
>> as an attribute). This implies, any DMA to a shared buffer must have 
>> the top bit
>> of the IPA space set.
>>
>> There is already a provision to do this in phys_to_dma* and 
>> dma_to_phys(), but
>> that is specific to AMD SME and is quite the opposite of what we need 
>> for Arm CCA.
>> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and 
>> clear the bit
>> for "encrypted".
>>
>> This series converts the existing __sme_* helpers to a bit more 
>> generalised versions :
>> dma_addr_decrypted() and dma_encrypted(). Also, while converting a 
>> DMA address back
>> to CPU physical address requires clearing off any 
>> "encryption/decryption" bits.
>> I have named this "dma_addr_canonical()". (The other options are :
>>    * dma_addr_clear_encryption - Well, not just for encryption, but 
>> we clear decryption
>>      too, so not ideal.
>>    * dma_addr_normal
>>    * dma_addr_clear
>>    * dma_addr_default
>>
>> This also implies that the VMMs must take care to :
>>
>>   1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>>   2. Always mask the "top" bit off any IPA it receives from the Realm 
>> for DMA.
>>      KVM already does that today and no changes are required.
>>
>> A kvmtool branch with the changes above is available here [1]. There 
>> are two
>> patches [2] & [3], that are really required on top of the Arm CCA 
>> support.
>>
>> Ideally it would be good to get this backported to v6.13 stable 
>> kernel releases
>> to make sure that they are compliant with this change.
>>
>
> Please could you take a look at this series and let us know your
> thoughts ? If you are happy with the changes, are you happy to pull
> this through the DMA MAP tree ? The relevant bits have been reviewed/
> acked by people (arm64 and AMD bits).

The changes look fine. However I won't be able to setup new dma-mapping 
git tree this week because I got really sick has to stay in bed. :/ If 
You don't want such delay, please merge it via ARM64 tree. Here is my:

Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>


Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-03-04 13:40   ` Marek Szyprowski
@ 2025-03-06 11:39     ` Suzuki K Poulose
  2025-03-06 18:06       ` Catalin Marinas
  0 siblings, 1 reply; 17+ messages in thread
From: Suzuki K Poulose @ 2025-03-06 11:39 UTC (permalink / raw)
  To: Marek Szyprowski, linux-kernel, Catalin Marinas, Will Deacon
  Cc: maz, steven.price, aneesh.kumar, gshan, robin.murphy,
	linux-arm-kernel, Jean-Philippe Brucker, Christoph Hellwig,
	Tom Lendacky

On 04/03/2025 13:40, Marek Szyprowski wrote:
> Hi,
> 
> On 03.03.2025 12:35, Suzuki K Poulose wrote:
>> On 27/02/2025 14:41, Suzuki K Poulose wrote:
>>> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13.
>>> The address
>>> space (GPA or IPA) of a Realm VM is split into two halves, with
>>> private bottom
>>> half and shared top half. In Linux we treat the "top" bit of the IPA
>>> space as
>>> an attribute, to indicate whether it is shared or not (MSB == 1
>>> implies shared).
>>> Stage2 (GPA to PA) translations used by the CPU accesses, cover the
>>> full IPA space,
>>> and are managed by RMM. The "top" bit as attribute is only a software
>>> construct.
>>>
>>> At present any device passed through to a Realm is treated as
>>> untrusted and the
>>> Realm uses bounce buffering for any DMA, using the "decrypted"
>>> (shared) DMA
>>> buffers (i.e., IPA with top bit set). In Linux, we only send the
>>> "DMA" address
>>> masking the "top" bit. In Arm CCA, SMMU for untrusted devices are
>>> managed by the
>>> non-secure Host and thus it can be confusing for the host/device when
>>> an unmasked
>>> address is provided. Given there could be other hypervisors than
>>> Linux/KVM
>>> running Arm CCA guests, the Realm Guest must adhere to a single
>>> convention for
>>> the DMA address. This gets further complicated when we add support
>>> for trusted
>>> devices, which can DMA into the full Realm memory space, once
>>> accepted. Thus,
>>> a DMA masked address (with "top" bit lost) will prevent a trusted
>>> device from
>>> accessing a shared buffer.
>>>
>>> To resolve this Arm has decided to standardise the DMA address used
>>> by the Realm
>>> to include the full IPA address bits (including the "top" bit, which
>>> Linux uses
>>> as an attribute). This implies, any DMA to a shared buffer must have
>>> the top bit
>>> of the IPA space set.
>>>
>>> There is already a provision to do this in phys_to_dma* and
>>> dma_to_phys(), but
>>> that is specific to AMD SME and is quite the opposite of what we need
>>> for Arm CCA.
>>> i.e., For Arm CCA we need to set the bit for "decrypted" DMA and
>>> clear the bit
>>> for "encrypted".
>>>
>>> This series converts the existing __sme_* helpers to a bit more
>>> generalised versions :
>>> dma_addr_decrypted() and dma_encrypted(). Also, while converting a
>>> DMA address back
>>> to CPU physical address requires clearing off any
>>> "encryption/decryption" bits.
>>> I have named this "dma_addr_canonical()". (The other options are :
>>>     * dma_addr_clear_encryption - Well, not just for encryption, but
>>> we clear decryption
>>>       too, so not ideal.
>>>     * dma_addr_normal
>>>     * dma_addr_clear
>>>     * dma_addr_default
>>>
>>> This also implies that the VMMs must take care to :
>>>
>>>    1. Create the S2-SMMU mappings for VFIO at the "unprotected" alias.
>>>    2. Always mask the "top" bit off any IPA it receives from the Realm
>>> for DMA.
>>>       KVM already does that today and no changes are required.
>>>
>>> A kvmtool branch with the changes above is available here [1]. There
>>> are two
>>> patches [2] & [3], that are really required on top of the Arm CCA
>>> support.
>>>
>>> Ideally it would be good to get this backported to v6.13 stable
>>> kernel releases
>>> to make sure that they are compliant with this change.
>>>
>>
>> Please could you take a look at this series and let us know your
>> thoughts ? If you are happy with the changes, are you happy to pull
>> this through the DMA MAP tree ? The relevant bits have been reviewed/
>> acked by people (arm64 and AMD bits).
> 
> The changes look fine. However I won't be able to setup new dma-mapping
> git tree this week because I got really sick has to stay in bed. :/ If
> You don't want such delay, please merge it via ARM64 tree. Here is my:

Sorry to hear that. Hope you feel better soon.

> 
> Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>

Thanks Marek.

Btw, this series fixes the "Realm Guest" support for Linux, which was 
merged in v6.13. To be precise, this should have :

Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")

Will/Catalin,

Please let me know if you would like me to send the series with
all the Acks, Reviews and mainly the Fixes tag added ?

Kind regards
Suzuki

> 
> 
> Best regards



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-03-06 11:39     ` Suzuki K Poulose
@ 2025-03-06 18:06       ` Catalin Marinas
  2025-03-11 11:45         ` Will Deacon
  0 siblings, 1 reply; 17+ messages in thread
From: Catalin Marinas @ 2025-03-06 18:06 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: Marek Szyprowski, linux-kernel, Will Deacon, maz, steven.price,
	aneesh.kumar, gshan, robin.murphy, linux-arm-kernel,
	Jean-Philippe Brucker, Christoph Hellwig, Tom Lendacky

On Thu, Mar 06, 2025 at 11:39:14AM +0000, Suzuki K Poulose wrote:
> On 04/03/2025 13:40, Marek Szyprowski wrote:
> > > On 27/02/2025 14:41, Suzuki K Poulose wrote:
> > > > Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> > > > space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> > > > half and shared top half. In Linux we treat the "top" bit of the IPA space as
> > > > an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> > > > Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> > > > and are managed by RMM. The "top" bit as attribute is only a software construct.
[...]
> > The changes look fine. However I won't be able to setup new dma-mapping
> > git tree this week because I got really sick has to stay in bed. :/ If
> > You don't want such delay, please merge it via ARM64 tree. Here is my:
> 
> Sorry to hear that. Hope you feel better soon.
> 
> > Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Thanks Marek.
> 
> Btw, this series fixes the "Realm Guest" support for Linux, which was merged
> in v6.13. To be precise, this should have :
> 
> Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")
> 
> Will/Catalin,
> 
> Please let me know if you would like me to send the series with
> all the Acks, Reviews and mainly the Fixes tag added ?

We can add the acks and fixes tag, no worries. I can queue them for 6.15
unless Will takes them as fixes for 6.14 (I'll wait for a bit).

-- 
Catalin


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-03-06 18:06       ` Catalin Marinas
@ 2025-03-11 11:45         ` Will Deacon
  0 siblings, 0 replies; 17+ messages in thread
From: Will Deacon @ 2025-03-11 11:45 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Suzuki K Poulose, Marek Szyprowski, linux-kernel, maz,
	steven.price, aneesh.kumar, gshan, robin.murphy, linux-arm-kernel,
	Jean-Philippe Brucker, Christoph Hellwig, Tom Lendacky

On Thu, Mar 06, 2025 at 06:06:44PM +0000, Catalin Marinas wrote:
> On Thu, Mar 06, 2025 at 11:39:14AM +0000, Suzuki K Poulose wrote:
> > On 04/03/2025 13:40, Marek Szyprowski wrote:
> > > > On 27/02/2025 14:41, Suzuki K Poulose wrote:
> > > > > Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> > > > > space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> > > > > half and shared top half. In Linux we treat the "top" bit of the IPA space as
> > > > > an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> > > > > Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> > > > > and are managed by RMM. The "top" bit as attribute is only a software construct.
> [...]
> > > The changes look fine. However I won't be able to setup new dma-mapping
> > > git tree this week because I got really sick has to stay in bed. :/ If
> > > You don't want such delay, please merge it via ARM64 tree. Here is my:
> > 
> > Sorry to hear that. Hope you feel better soon.
> > 
> > > Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > 
> > Thanks Marek.
> > 
> > Btw, this series fixes the "Realm Guest" support for Linux, which was merged
> > in v6.13. To be precise, this should have :
> > 
> > Fixes: 42be24a4178f ("arm64: Enable memory encrypt for Realms")
> > 
> > Will/Catalin,
> > 
> > Please let me know if you would like me to send the series with
> > all the Acks, Reviews and mainly the Fixes tag added ?
> 
> We can add the acks and fixes tag, no worries. I can queue them for 6.15
> unless Will takes them as fixes for 6.14 (I'll wait for a bit).

For the series:

Acked-by: Will Deacon <will@kernel.org>

but I'd prefer this to land in 6.15 at this stage given that (a) it's
always been broken and (b) we're not exactly tripping over CCA-capable
hardware.

Cheers,

Will


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/3] arm64: realm: Fix DMA address for devices
  2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
                   ` (3 preceding siblings ...)
  2025-03-03 11:35 ` [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
@ 2025-03-11 17:15 ` Catalin Marinas
  4 siblings, 0 replies; 17+ messages in thread
From: Catalin Marinas @ 2025-03-11 17:15 UTC (permalink / raw)
  To: linux-kernel, Suzuki K Poulose
  Cc: Will Deacon, maz, steven.price, aneesh.kumar, gshan, robin.murphy,
	linux-arm-kernel, Jean-Philippe Brucker, Christoph Hellwig,
	Marek Szyprowski, Tom Lendacky

On Thu, 27 Feb 2025 14:41:47 +0000, Suzuki K Poulose wrote:
> Linux can be run as a Confidential Guest in Arm CCA from Linux v6.13. The address
> space (GPA or IPA) of a Realm VM is split into two halves, with private bottom
> half and shared top half. In Linux we treat the "top" bit of the IPA space as
> an attribute, to indicate whether it is shared or not (MSB == 1 implies shared).
> Stage2 (GPA to PA) translations used by the CPU accesses, cover the full IPA space,
> and are managed by RMM. The "top" bit as attribute is only a software construct.
> 
> [...]

Applied to arm64 (for-next/cca-dma-address), thanks!

[1/3] dma: Fix encryption bit clearing for dma_to_phys
      https://git.kernel.org/arm64/c/c380931712d1
[2/3] dma: Introduce generic dma_addr_*crypted helpers
      https://git.kernel.org/arm64/c/b66e2ee7b6c8
[3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers
      https://git.kernel.org/arm64/c/7d953a062416

-- 
Catalin



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2025-03-11 17:25 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-27 14:41 [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
2025-02-27 14:41 ` [PATCH v3 1/3] dma: Fix encryption bit clearing for dma_to_phys Suzuki K Poulose
2025-02-28  2:08   ` Gavin Shan
2025-02-27 14:41 ` [PATCH v3 2/3] dma: Introduce generic dma_addr_*crypted helpers Suzuki K Poulose
2025-02-28  2:09   ` Gavin Shan
2025-02-28 18:23   ` Robin Murphy
2025-02-27 14:41 ` [PATCH v3 3/3] arm64: realm: Use aliased addresses for device DMA to shared buffers Suzuki K Poulose
2025-02-27 16:05   ` Catalin Marinas
2025-02-27 17:03     ` Suzuki K Poulose
2025-02-28  2:08   ` Gavin Shan
2025-03-03 14:16   ` Robin Murphy
2025-03-03 11:35 ` [PATCH v3 0/3] arm64: realm: Fix DMA address for devices Suzuki K Poulose
2025-03-04 13:40   ` Marek Szyprowski
2025-03-06 11:39     ` Suzuki K Poulose
2025-03-06 18:06       ` Catalin Marinas
2025-03-11 11:45         ` Will Deacon
2025-03-11 17:15 ` Catalin Marinas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).