From: Sean Christopherson <sean.j.christopher...@intel.com>

Skip writing EFER during secondary_startup_64() if the current value is
also the desired value. This avoids a #VE when running as a TDX guest,
as the TDX-Module does not allow writes to EFER (even when writing the
current, fixed value).

Also, preserve CR4.MCE instead of clearing it during boot to avoid a #VE
when running as a TDX guest. The TDX-Module (effectively part of the
hypervisor) requires CR4.MCE to be set at all times and injects a #VE
if the guest attempts to clear CR4.MCE.

Signed-off-by: Sean Christopherson <sean.j.christopher...@intel.com>
Reviewed-by: Andi Kleen <a...@linux.intel.com>
Signed-off-by: Kuppuswamy Sathyanarayanan 
<sathyanarayanan.kuppusw...@linux.intel.com>
---
 arch/x86/boot/compressed/head_64.S |  5 ++++-
 arch/x86/kernel/head_64.S          | 13 +++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/compressed/head_64.S 
b/arch/x86/boot/compressed/head_64.S
index 37c2f37d4a0d..2d79e5f97360 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -622,7 +622,10 @@ SYM_CODE_START(trampoline_32bit_src)
        popl    %ecx
 
        /* Enable PAE and LA57 (if required) paging modes */
-       movl    $X86_CR4_PAE, %eax
+       movl    %cr4, %eax
+       /* Clearing CR4.MCE will #VE on TDX guests.  Leave it alone. */
+       andl    $X86_CR4_MCE, %eax
+       orl     $X86_CR4_PAE, %eax
        testl   %edx, %edx
        jz      1f
        orl     $X86_CR4_LA57, %eax
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 04bddaaba8e2..92c77cf75542 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -141,7 +141,10 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, 
SYM_L_GLOBAL)
 1:
 
        /* Enable PAE mode, PGE and LA57 */
-       movl    $(X86_CR4_PAE | X86_CR4_PGE), %ecx
+       movq    %cr4, %rcx
+       /* Clearing CR4.MCE will #VE on TDX guests.  Leave it alone. */
+       andl    $X86_CR4_MCE, %ecx
+       orl     $(X86_CR4_PAE | X86_CR4_PGE), %ecx
 #ifdef CONFIG_X86_5LEVEL
        testl   $1, __pgtable_l5_enabled(%rip)
        jz      1f
@@ -229,13 +232,19 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, 
SYM_L_GLOBAL)
        /* Setup EFER (Extended Feature Enable Register) */
        movl    $MSR_EFER, %ecx
        rdmsr
+       movl    %eax, %edx
        btsl    $_EFER_SCE, %eax        /* Enable System Call */
        btl     $20,%edi                /* No Execute supported? */
        jnc     1f
        btsl    $_EFER_NX, %eax
        btsq    $_PAGE_BIT_NX,early_pmd_flags(%rip)
-1:     wrmsr                           /* Make changes effective */
 
+       /* Skip the WRMSR if the current value matches the desired value. */
+1:     cmpl    %edx, %eax
+       je      1f
+       xor     %edx, %edx
+       wrmsr                           /* Make changes effective */
+1:
        /* Setup cr0 */
        movl    $CR0_STATE, %eax
        /* Make changes effective */
-- 
2.25.1

Reply via email to