From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
To: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@intel.com, luto@kernel.org, peterz@infradead.org
Cc: sathyanarayanan.kuppuswamy@linux.intel.com, aarcange@redhat.com,
ak@linux.intel.com, dan.j.williams@intel.com, david@redhat.com,
hpa@zytor.com, jgross@suse.com, jmattson@google.com,
joro@8bytes.org, jpoimboe@redhat.com, knsathya@kernel.org,
pbonzini@redhat.com, sdeep@vmware.com, seanjc@google.com,
tony.luck@intel.com, vkuznets@redhat.com, wanpengli@tencent.com,
thomas.lendacky@amd.com, brijesh.singh@amd.com, x86@kernel.org,
linux-kernel@vger.kernel.org,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Subject: [PATCHv6 26/30] x86/mm/cpa: Add support for TDX shared memory
Date: Wed, 16 Mar 2022 05:08:52 +0300 [thread overview]
Message-ID: <20220316020856.24435-27-kirill.shutemov@linux.intel.com> (raw)
In-Reply-To: <20220316020856.24435-1-kirill.shutemov@linux.intel.com>
Intel TDX protects guest memory from VMM access. Any memory that is
required for communication with the VMM must be explicitly shared.
It is a two-step process: the guest sets the shared bit in the page
table entry and notifies VMM about the change. The notification happens
using MapGPA hypercall.
Conversion back to private memory requires clearing the shared bit,
notifying VMM with MapGPA hypercall following with accepting the memory
with AcceptPage hypercall.
Provide a TDX version of x86_platform.guest.* callbacks. It makes
__set_memory_enc_pgtable() work right in TDX guest.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
arch/x86/coco/core.c | 1 +
arch/x86/coco/tdx/tdx.c | 151 ++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/traps.c | 2 +-
3 files changed, 153 insertions(+), 1 deletion(-)
diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c
index 70956f9d7c7e..9f74125c582d 100644
--- a/arch/x86/coco/core.c
+++ b/arch/x86/coco/core.c
@@ -21,6 +21,7 @@ static bool intel_cc_platform_has(enum cc_attr attr)
switch (attr) {
case CC_ATTR_GUEST_UNROLL_STRING_IO:
case CC_ATTR_HOTPLUG_DISABLED:
+ case CC_ATTR_GUEST_MEM_ENCRYPT:
return true;
default:
return false;
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 09e121619d35..4e404e701170 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -10,10 +10,15 @@
#include <asm/vmx.h>
#include <asm/insn.h>
#include <asm/insn-eval.h>
+#include <asm/x86_init.h>
/* TDX module Call Leaf IDs */
#define TDX_GET_INFO 1
#define TDX_GET_VEINFO 3
+#define TDX_ACCEPT_PAGE 6
+
+/* TDX hypercall Leaf IDs */
+#define TDVMCALL_MAP_GPA 0x10001
/* MMIO direction */
#define EPT_READ 0
@@ -517,6 +522,148 @@ bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve)
return ret;
}
+static bool tdx_tlb_flush_required(bool private)
+{
+ /*
+ * TDX guest is responsible for flushing TLB on private->shared
+ * transition. VMM is responsible for flushing on shared->private.
+ *
+ * The VMM _can't_ flush private addresses as it can't generate PAs
+ * with the guest's HKID. Shared memory isn't subject to integrity
+ * checking, i.e. the VMM doesn't need to flush for its own protection.
+ *
+ * There's no need to flush when converting from shared to private,
+ * as flushing is the VMM's responsibility in this case, e.g. it must
+ * flush to avoid integrity failures in the face of a buggy or
+ * malicious guest.
+ */
+ return !private;
+}
+
+static bool tdx_cache_flush_required(void)
+{
+ /*
+ * AMD SME/SEV can avoid cache flushing if HW enforces cache coherence.
+ * TDX doesn't have such capability.
+ *
+ * Flush cache unconditionally.
+ */
+ return true;
+}
+
+static bool accept_page(phys_addr_t gpa, enum pg_level pg_level)
+{
+ u8 page_size;
+ u64 tdcall_rcx;
+
+ /*
+ * Pass the page physical address to the TDX module to accept the
+ * pending, private page.
+ *
+ * Bits 2:0 of RCX encode page size: 0 - 4K, 1 - 2M, 2 - 1G.
+ */
+ switch (pg_level) {
+ case PG_LEVEL_4K:
+ page_size = 0;
+ break;
+ case PG_LEVEL_2M:
+ page_size = 1;
+ break;
+ case PG_LEVEL_1G:
+ page_size = 2;
+ break;
+ default:
+ return false;
+ }
+
+ tdcall_rcx = gpa | page_size;
+ return !__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL);
+}
+
+static inline enum pg_level size_to_level(unsigned long size)
+{
+ switch (size) {
+ case PUD_SIZE:
+ return PG_LEVEL_1G;
+ case PMD_SIZE:
+ return PG_LEVEL_2M;
+ case PAGE_SIZE:
+ return PG_LEVEL_4K;
+ default:
+ BUILD_BUG();
+ }
+}
+
+static bool try_accept_one(phys_addr_t *start, unsigned long len,
+ unsigned long accept_size)
+{
+ if (!IS_ALIGNED(*start, accept_size))
+ return false;
+
+ if (len < accept_size)
+ return false;
+
+ if (!accept_page(*start, size_to_level(accept_size)))
+ return false;
+
+ *start += accept_size;
+ return true;
+}
+
+/*
+ * Inform the VMM of the guest's intent for this physical page: shared with
+ * the VMM or private to the guest. The VMM is expected to change its mapping
+ * of the page in response.
+ */
+static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc)
+{
+ phys_addr_t start = __pa(vaddr);
+ phys_addr_t end = __pa(vaddr + numpages * PAGE_SIZE);
+
+ if (!enc) {
+ /* Set the shared (decrypted) bits: */
+ start |= cc_mkdec(0);
+ end |= cc_mkdec(0);
+ }
+
+ /*
+ * Notify the VMM about page mapping conversion. More info about ABI
+ * can be found in TDX Guest-Host-Communication Interface (GHCI),
+ * section "TDG.VP.VMCALL<MapGPA>"
+ */
+ if (_tdx_hypercall(TDVMCALL_MAP_GPA, start, end - start, 0, 0))
+ return false;
+
+ /* private->shared conversion requires only MapGPA call */
+ if (!enc)
+ return true;
+
+ /*
+ * For shared->private conversion, accept the page using
+ * TDX_ACCEPT_PAGE TDX module call.
+ */
+ while (start < end) {
+ unsigned long len = end - start;
+
+ /*
+ * Try larger accepts first. It gives chance to VMM to keep
+ * 1G/2M SEPT entries where possible and speeds up process by
+ * cutting number of hypercalls (if successful).
+ */
+
+ if (try_accept_one(&start, len, PUD_SIZE))
+ continue;
+
+ if (try_accept_one(&start, len, PMD_SIZE))
+ continue;
+
+ if (!try_accept_one(&start, len, PAGE_SIZE))
+ return false;
+ }
+
+ return true;
+}
+
void __init tdx_early_init(void)
{
unsigned int gpa_width;
@@ -547,5 +694,9 @@ void __init tdx_early_init(void)
*/
cc_set_mask(BIT_ULL(gpa_width - 1));
+ x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required;
+ x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required;
+ x86_platform.guest.enc_status_change_finish = tdx_enc_status_changed;
+
pr_info("Guest detected\n");
}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 9ab8570c48f5..cabda9d47b06 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -1305,7 +1305,7 @@ static void ve_raise_fault(struct pt_regs *regs, long error_code)
*
* In the settings that Linux will run in, virtualization exceptions are
* never generated on accesses to normal, TD-private memory that has been
- * accepted.
+ * accepted (by BIOS or with tdx_enc_status_changed()).
*
* Syscall entry code has a critical window where the kernel stack is not
* yet set up. Any exception in this window leads to hard to debug issues
--
2.34.1
next prev parent reply other threads:[~2022-03-16 2:11 UTC|newest]
Thread overview: 89+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-16 2:08 [PATCHv6 00/30] TDX Guest: TDX core support Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 01/30] x86/tdx: Detect running as a TDX guest in early boot Kirill A. Shutemov
2022-03-16 23:10 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 02/30] x86/tdx: Provide common base for SEAMCALL and TDCALL C wrappers Kirill A. Shutemov
2022-03-16 23:33 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 03/30] x86/tdx: Add __tdx_module_call() and __tdx_hypercall() helper functions Kirill A. Shutemov
2022-03-16 23:43 ` Thomas Gleixner
2022-03-17 16:03 ` Borislav Petkov
2022-03-16 2:08 ` [PATCHv6 04/30] x86/tdx: Extend the confidential computing API to support TDX guests Kirill A. Shutemov
2022-03-17 0:01 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 05/30] x86/tdx: Exclude shared bit from __PHYSICAL_MASK Kirill A. Shutemov
2022-03-17 0:16 ` Thomas Gleixner
2022-03-17 13:58 ` Kirill A. Shutemov
2022-03-17 14:39 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 06/30] x86/traps: Refactor exc_general_protection() Kirill A. Shutemov
2022-03-17 0:21 ` Thomas Gleixner
2022-03-17 14:05 ` Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 07/30] x86/traps: Add #VE support for TDX guest Kirill A. Shutemov
2022-03-17 0:48 ` Thomas Gleixner
2022-03-17 17:33 ` Kirill A. Shutemov
2022-03-17 18:18 ` Thomas Gleixner
2022-03-17 20:21 ` Peter Zijlstra
2022-03-17 20:32 ` Dave Hansen
2022-03-18 10:55 ` Peter Zijlstra
2022-03-18 13:03 ` Kirill A. Shutemov
2022-03-18 14:19 ` Thomas Gleixner
2022-03-18 15:34 ` Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 08/30] x86/tdx: Add HLT support for TDX guests Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 09/30] x86/tdx: Add MSR " Kirill A. Shutemov
2022-03-17 11:30 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 10/30] x86/tdx: Handle CPUID via #VE Kirill A. Shutemov
2022-03-17 11:32 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 11/30] x86/tdx: Handle in-kernel MMIO Kirill A. Shutemov
2022-03-16 21:53 ` Dave Hansen
2022-03-17 11:48 ` Thomas Gleixner
2022-03-17 11:35 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 12/30] x86/tdx: Detect TDX at early kernel decompression time Kirill A. Shutemov
2022-03-17 11:55 ` Thomas Gleixner
2022-03-17 18:04 ` Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 13/30] x86: Adjust types used in port I/O helpers Kirill A. Shutemov
2022-03-17 11:56 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 14/30] x86: Consolidate " Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 15/30] x86/boot: Port I/O: allow to hook up alternative helpers Kirill A. Shutemov
2022-03-16 22:02 ` Dave Hansen
2022-03-17 12:12 ` Thomas Gleixner
2022-03-17 20:10 ` Kirill A. Shutemov
2022-03-17 20:20 ` Dave Hansen
2022-03-17 20:23 ` Dave Hansen
2022-03-17 22:48 ` Kirill A. Shutemov
2022-03-18 14:20 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 16/30] x86/boot: Port I/O: add decompression-time support for TDX Kirill A. Shutemov
2022-03-17 12:15 ` Thomas Gleixner
2022-03-17 20:15 ` Kirill A. Shutemov
2022-03-18 14:28 ` Thomas Gleixner
2022-03-18 15:36 ` Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 17/30] x86/tdx: Port I/O: add runtime hypercalls Kirill A. Shutemov
2022-03-17 12:25 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 18/30] x86/tdx: Port I/O: add early boot support Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 19/30] x86/tdx: Wire up KVM hypercalls Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 20/30] x86/boot: Add a trampoline for booting APs via firmware handoff Kirill A. Shutemov
2022-03-17 12:32 ` Thomas Gleixner
2022-03-17 12:44 ` Boris Petkov
2022-03-17 20:21 ` Kirill A. Shutemov
2022-03-18 9:55 ` Borislav Petkov
2022-03-16 2:08 ` [PATCHv6 21/30] x86/acpi, x86/boot: Add multiprocessor wake-up support Kirill A. Shutemov
2022-03-16 23:47 ` Dave Hansen
2022-03-17 12:44 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 22/30] x86/boot: Set CR0.NE early and keep it set during the boot Kirill A. Shutemov
2022-03-17 12:46 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 23/30] x86/boot: Avoid #VE during boot for TDX platforms Kirill A. Shutemov
2022-03-17 12:48 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 24/30] x86/topology: Disable CPU online/offline control for TDX guests Kirill A. Shutemov
2022-03-17 12:50 ` Thomas Gleixner
2022-03-17 20:47 ` Kirill A. Shutemov
2022-03-16 2:08 ` [PATCHv6 25/30] x86/tdx: Make pages shared in ioremap() Kirill A. Shutemov
2022-03-16 22:06 ` Dave Hansen
2022-03-17 14:33 ` Thomas Gleixner
2022-03-16 2:08 ` Kirill A. Shutemov [this message]
2022-03-17 14:56 ` [PATCHv6 26/30] x86/mm/cpa: Add support for TDX shared memory Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 27/30] x86/kvm: Make SWIOTLB buffer shared for TD guest Kirill A. Shutemov
2022-03-16 22:24 ` Dave Hansen
2022-03-16 2:08 ` [PATCHv6 28/30] x86/tdx: ioapic: Add shared bit for IOAPIC base address Kirill A. Shutemov
2022-03-17 15:00 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 29/30] ACPICA: Avoid cache flush inside virtual machines Kirill A. Shutemov
2022-03-16 22:13 ` Dave Hansen
2022-03-17 15:32 ` Dan Williams
2022-03-17 23:04 ` Kirill A. Shutemov
2022-03-17 15:23 ` Thomas Gleixner
2022-03-16 2:08 ` [PATCHv6 30/30] Documentation/x86: Document TDX kernel architecture Kirill A. Shutemov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220316020856.24435-27-kirill.shutemov@linux.intel.com \
--to=kirill.shutemov@linux.intel.com \
--cc=aarcange@redhat.com \
--cc=ak@linux.intel.com \
--cc=bp@alien8.de \
--cc=brijesh.singh@amd.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=david@redhat.com \
--cc=hpa@zytor.com \
--cc=jgross@suse.com \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=jpoimboe@redhat.com \
--cc=knsathya@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=sathyanarayanan.kuppuswamy@linux.intel.com \
--cc=sdeep@vmware.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--cc=tony.luck@intel.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®