[librm] Preserve CR0 across virt_call() Clearing the CR0.EM and CR0.TS flags is a prerequisite for using the AES-NI instructions for AES hardware acceleration: if CR0.EM is set then the CPU will raise an undefined-instruction exception, and if CR0.TS is set then the CPU will raise a device-not-available exception (expecting the OS to have installed an exception handler that would perform a deferred context switch of the FPU/MMX/SSE registers). Preserve CR0 across virt_call(), to allow the CR0.EM and CR0.TS flags to be modified as needed. Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S index faa5c51..c08d544 100644 --- a/src/arch/x86/transitions/librm.S +++ b/src/arch/x86/transitions/librm.S
@@ -205,10 +205,11 @@ /* Temporary static buffer usage by virt_call */ .struct 0 VC_TMP_GDTR_IDTR: .space 12 /* must match rm_default_gdtr_idtr layout */ -VC_TMP_PAD: .space 4 /* for alignment */ +VC_TMP_CR0: .space 4 VC_TMP_CR3: .space 4 VC_TMP_CR4: .space 4 VC_TMP_EMER: .space 8 + .balign 16 VC_TMP_FXSAVE: .space 512 VC_TMP_END: .previous @@ -1021,6 +1022,10 @@ movl %cr4, %eax movl %eax, ( rm_tmpbuf + VC_TMP_CR4 ) 1: + /* Preserve CR0 in temporary static buffer */ + movl %cr0, %eax + movl %eax, ( rm_tmpbuf + VC_TMP_CR0 ) + /* Preserve GDTR and IDTR in temporary static buffer */ sidt ( rm_tmpbuf + VC_TMP_GDTR_IDTR + 6 ) sgdt ( rm_tmpbuf + VC_TMP_GDTR_IDTR + 0 ) @@ -1082,6 +1087,9 @@ movl $MSR_EFER, %ecx wrmsr .endif + /* Restore CR0 from temporary static buffer */ + movl ( rm_tmpbuf + VC_TMP_CR0 ), %eax + movl %eax, %cr0 /* Restore FPU/MMX/SSE state and CR4 from temporary static buffer */ .if32 ; testb $0xff, fxsr_supported ; jz 1f ; .endif