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.kuppusw...@linux.intel.com>
Reviewed-by: Andi Kleen <a...@linux.intel.com>
---

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

Reply via email to