[PATCH v3 1/1] x86/tdx: Handle MWAIT, MONITOR and WBINVD

From: Kuppuswamy Sathyanarayanan
Date: Mon Mar 29 2021 - 19:23:09 EST


In non-root TDX guest mode, MWAIT, MONITOR and WBINVD instructions
are not supported. So handle #VE due to these instructions
appropriately.

Since the impact of executing WBINVD instruction in non ring-0 mode
can be heavy, use BUG() to report it. For others, raise a WARNING
message.

Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@xxxxxxxxxxxxxxx>
Reviewed-by: Andi Kleen <ak@xxxxxxxxxxxxxxx>
---

Changes since v2:
* Added BUG() for WBINVD, WARN for MONITOR instructions.
* Fixed comments as per Dave's review.

Changes since v1:
* Added WARN() for MWAIT #VE exception.

Changes since previous series:
* Suppressed MWAIT feature as per Andi's comment.
* Added warning debug log for MWAIT #VE exception.

arch/x86/kernel/tdx.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
index e936b2f88bf6..4c6336a055a3 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c
@@ -308,6 +308,9 @@ void __init tdx_early_init(void)

setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);

+ /* MWAIT is not supported in TDX platform, so suppress it */
+ setup_clear_cpu_cap(X86_FEATURE_MWAIT);
+
tdg_get_info();

pv_ops.irq.safe_halt = tdg_safe_halt;
@@ -362,6 +365,32 @@ int tdg_handle_virtualization_exception(struct pt_regs *regs,
case EXIT_REASON_EPT_VIOLATION:
ve->instr_len = tdg_handle_mmio(regs, ve);
break;
+ case EXIT_REASON_WBINVD:
+ /*
+ * WBINVD is a privileged instruction, can only be executed
+ * in ring 0. Since we reached here, the kernel is in buggy
+ * state.
+ */
+ pr_err("WBINVD #VE Exception\n");
+ BUG();
+ break;
+ case EXIT_REASON_MONITOR_INSTRUCTION:
+ /*
+ * MONITOR is a privileged instruction, can only be executed
+ * in ring 0. So we are not supposed to reach here. Raise a
+ * warning message.
+ */
+ WARN(1, "MONITOR unexpected #VE Exception\n");
+ break;
+ case EXIT_REASON_MWAIT_INSTRUCTION:
+ /*
+ * MWAIT feature is suppressed in firmware and in
+ * tdx_early_init() by clearing X86_FEATURE_MWAIT CPU feature
+ * flag. Since we are not supposed to reach here, raise a
+ * warning message and return -EFAULT.
+ */
+ WARN(1, "MWAIT unexpected #VE Exception\n");
+ return -EFAULT;
default:
pr_warn("Unexpected #VE: %d\n", ve->exit_reason);
return -EFAULT;
--
2.25.1