* [PATCH] x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386
@ 2019-08-22 21:11 Sean Christopherson
2019-08-23 7:59 ` Peter Zijlstra
0 siblings, 1 reply; 2+ messages in thread
From: Sean Christopherson @ 2019-08-22 21:11 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86
Cc: H. Peter Anvin, linux-kernel, Peter Zijlstra, Paolo Bonzini, kvm
Use 'lea' instead of 'add' when adjusting %rsp in CALL_NOSPEC so as to
avoid clobbering flags.
KVM's emulator makes indirect calls into a jump table of sorts, where
the destination of the CALL_NOSPEC is a small blob of code that performs
fast emulation by executing the target instruction with fixed operands.
adcb_al_dl:
0x000339f8 <+0>: adc %dl,%al
0x000339fa <+2>: ret
A major motiviation for doing fast emulation is to leverage the CPU to
handle consumption and manipulation of arithmetic flags, i.e. RFLAGS is
both an input and output to the target of CALL_NOSPEC. Clobbering flags
results in all sorts of incorrect emulation, e.g. Jcc instructions often
take the wrong path. Sans the nops...
asm("push %[flags]; popf; " CALL_NOSPEC " ; pushf; pop %[flags]\n"
0x0003595a <+58>: mov 0xc0(%ebx),%eax
0x00035960 <+64>: mov 0x60(%ebx),%edx
0x00035963 <+67>: mov 0x90(%ebx),%ecx
0x00035969 <+73>: push %edi
0x0003596a <+74>: popf
0x0003596b <+75>: call *%esi
0x000359a0 <+128>: pushf
0x000359a1 <+129>: pop %edi
0x000359a2 <+130>: mov %eax,0xc0(%ebx)
0x000359b1 <+145>: mov %edx,0x60(%ebx)
ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
0x000359a8 <+136>: mov -0x10(%ebp),%eax
0x000359ab <+139>: and $0x8d5,%edi
0x000359b4 <+148>: and $0xfffff72a,%eax
0x000359b9 <+153>: or %eax,%edi
0x000359bd <+157>: mov %edi,0x4(%ebx)
For the most part this has gone unnoticed as emulation of guest code
that can trigger fast emulation is effectively limited to MMIO when
running on modern hardware, and MMIO is rarely, if ever, accessed by
instructions that affect or consume flags.
Breakage is almost instantaneous when running with unrestricted guest
disabled, in which case KVM must emulate all instructions when the guest
has invalid state, e.g. when the guest is in Big Real Mode during early
BIOS.
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: <kvm@vger.kernel.org>
Cc: <stable@vger.kernel.org>
Fixes: 1a29b5b7f347a ("KVM: x86: Make indirect calls in emulator speculation safe")
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
arch/x86/include/asm/nospec-branch.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 109f974f9835..80bc209c0708 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -192,7 +192,7 @@
" lfence;\n" \
" jmp 902b;\n" \
" .align 16\n" \
- "903: addl $4, %%esp;\n" \
+ "903: lea 4(%%esp), %%esp;\n" \
" pushl %[thunk_target];\n" \
" ret;\n" \
" .align 16\n" \
--
2.22.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386
2019-08-22 21:11 [PATCH] x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386 Sean Christopherson
@ 2019-08-23 7:59 ` Peter Zijlstra
0 siblings, 0 replies; 2+ messages in thread
From: Peter Zijlstra @ 2019-08-23 7:59 UTC (permalink / raw)
To: Sean Christopherson
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, Paolo Bonzini, kvm
On Thu, Aug 22, 2019 at 02:11:22PM -0700, Sean Christopherson wrote:
> Use 'lea' instead of 'add' when adjusting %rsp in CALL_NOSPEC so as to
> avoid clobbering flags.
>
> KVM's emulator makes indirect calls into a jump table of sorts, where
> the destination of the CALL_NOSPEC is a small blob of code that performs
> fast emulation by executing the target instruction with fixed operands.
>
> adcb_al_dl:
> 0x000339f8 <+0>: adc %dl,%al
> 0x000339fa <+2>: ret
>
> A major motiviation for doing fast emulation is to leverage the CPU to
> handle consumption and manipulation of arithmetic flags, i.e. RFLAGS is
> both an input and output to the target of CALL_NOSPEC. Clobbering flags
> results in all sorts of incorrect emulation, e.g. Jcc instructions often
> take the wrong path. Sans the nops...
>
> asm("push %[flags]; popf; " CALL_NOSPEC " ; pushf; pop %[flags]\n"
> 0x0003595a <+58>: mov 0xc0(%ebx),%eax
> 0x00035960 <+64>: mov 0x60(%ebx),%edx
> 0x00035963 <+67>: mov 0x90(%ebx),%ecx
> 0x00035969 <+73>: push %edi
> 0x0003596a <+74>: popf
> 0x0003596b <+75>: call *%esi
> 0x000359a0 <+128>: pushf
> 0x000359a1 <+129>: pop %edi
> 0x000359a2 <+130>: mov %eax,0xc0(%ebx)
> 0x000359b1 <+145>: mov %edx,0x60(%ebx)
>
> ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
> 0x000359a8 <+136>: mov -0x10(%ebp),%eax
> 0x000359ab <+139>: and $0x8d5,%edi
> 0x000359b4 <+148>: and $0xfffff72a,%eax
> 0x000359b9 <+153>: or %eax,%edi
> 0x000359bd <+157>: mov %edi,0x4(%ebx)
>
> For the most part this has gone unnoticed as emulation of guest code
> that can trigger fast emulation is effectively limited to MMIO when
> running on modern hardware, and MMIO is rarely, if ever, accessed by
> instructions that affect or consume flags.
Also, because nobody every uses 32bit anymore, I suspect ;-)
> Breakage is almost instantaneous when running with unrestricted guest
> disabled, in which case KVM must emulate all instructions when the guest
> has invalid state, e.g. when the guest is in Big Real Mode during early
> BIOS.
>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: <kvm@vger.kernel.org>
> Cc: <stable@vger.kernel.org>
> Fixes: 1a29b5b7f347a ("KVM: x86: Make indirect calls in emulator speculation safe")
Cute; arguably this is a fix for:
776b043848fd2 ("x86/retpoline: Add initial retpoline support")
The patch you quote just happens to trigger it in KVM, but you're right
to note that CALL shouldn't frob EFLAGS, and who knows what possible
other sites care.
Anyway,
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
> arch/x86/include/asm/nospec-branch.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
> index 109f974f9835..80bc209c0708 100644
> --- a/arch/x86/include/asm/nospec-branch.h
> +++ b/arch/x86/include/asm/nospec-branch.h
> @@ -192,7 +192,7 @@
> " lfence;\n" \
> " jmp 902b;\n" \
> " .align 16\n" \
> - "903: addl $4, %%esp;\n" \
> + "903: lea 4(%%esp), %%esp;\n" \
> " pushl %[thunk_target];\n" \
> " ret;\n" \
> " .align 16\n" \
> --
> 2.22.0
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-08-23 7:59 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-22 21:11 [PATCH] x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386 Sean Christopherson
2019-08-23 7:59 ` Peter Zijlstra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).