Re: [PATCH 19/26] x86/tdx: Make pages shared in ioremap()

From: Tom Lendacky
Date: Wed Dec 22 2021 - 12:27:06 EST


On 12/14/21 9:02 AM, Kirill A. Shutemov wrote:
In TDX guests, guest memory is protected from host access. If a guest
performs I/O, it needs to explicitly share the I/O memory with the host.

Make all ioremap()ed pages that are not backed by normal memory
(IORES_DESC_NONE or IORES_DESC_RESERVED) mapped as shared.

Since TDX memory encryption support is similar to AMD SEV architecture,
reuse the infrastructure from AMD SEV code. Introduce CC_ATTR_GUEST_TDX
to add TDX-specific changes to the AMD SEV/SME memory encryption code.

Add tdx_shared_mask() interface to get the TDX guest shared bitmask.

pgprot_decrypted() is used by drivers (i915, virtio_gpu, vfio). Export
both pgprot_encrypted() and pgprot_decrypted().


--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,6 +14,33 @@
#include <linux/mem_encrypt.h>
#include <linux/virtio_config.h>
+#include <asm/tdx.h>
+
+/*
+ * Set or unset encryption attribute in vendor agnostic way.
+ */
+pgprot_t pgprot_cc_encrypted(pgprot_t prot)
+{
+ if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
+ return __pgprot(__sme_set(pgprot_val(prot)));
+ else if (cc_platform_has(CC_ATTR_GUEST_TDX))
+ return __pgprot(pgprot_val(prot) & ~tdx_shared_mask());
+

Hmmm... I believe this breaks SEV guests. __sme_set() uses sme_me_mask which is used for both SME and SEV. With the current checks, an SEV guest will end up never setting an encrypted address through this path. Ditto below on the decrypted path.

Thanks,
Tom

+ return prot;
+}
+EXPORT_SYMBOL_GPL(pgprot_cc_encrypted);
+
+pgprot_t pgprot_cc_decrypted(pgprot_t prot)
+{
+ if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
+ return __pgprot(__sme_clr(pgprot_val(prot)));
+ else if (cc_platform_has(CC_ATTR_GUEST_TDX))
+ return __pgprot(pgprot_val(prot) | tdx_shared_mask());
+
+ return prot;
+}
+EXPORT_SYMBOL_GPL(pgprot_cc_decrypted);
+
/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
bool force_dma_unencrypted(struct device *dev)
{
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
index 63b15108bc85..5fed077cc5f4 100644
--- a/include/linux/cc_platform.h
+++ b/include/linux/cc_platform.h
@@ -82,6 +82,15 @@ enum cc_attr {
* Examples include TDX Guest.
*/
CC_ATTR_HOTPLUG_DISABLED,
+
+ /**
+ * @CC_ATTR_GUEST_TDX: Trust Domain Extension Support
+ *
+ * The platform/OS is running as a TDX guest/virtual machine.
+ *
+ * Examples include Intel TDX.
+ */
+ CC_ATTR_GUEST_TDX = 0x100,
};
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM