2015-05-14 16:55:56

by Denys Vlasenko

[permalink] [raw]
Subject: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers

"movw %ds,%cx" insn needs a 0x66 prefix, while "movw %ds,%ecx" does not.
The difference is that it overwrite entire %ecx, not only its low half,
but subsequent code doesn't depend on the value of top half of %ecx,
we can safely use the shorter insn.

The new code is also faster than old one - now we don't depend on old value
of %ecx, but this code fragment is not performance-critical.

Signed-off-by: Denys Vlasenko <[email protected]>
CC: Linus Torvalds <[email protected]>
CC: Steven Rostedt <[email protected]>
CC: Ingo Molnar <[email protected]>
CC: Borislav Petkov <[email protected]>
CC: "H. Peter Anvin" <[email protected]>
CC: Andy Lutomirski <[email protected]>
CC: Oleg Nesterov <[email protected]>
CC: Frederic Weisbecker <[email protected]>
CC: Alexei Starovoitov <[email protected]>
CC: Will Drewry <[email protected]>
CC: Kees Cook <[email protected]>
CC: [email protected]
CC: [email protected]
---
arch/x86/kernel/entry_64.S | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 62b4c5f..ef2651d 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1195,19 +1195,19 @@ ENTRY(xen_failsafe_callback)
/*CFI_REL_OFFSET ds,DS*/
CFI_REL_OFFSET r11,8
CFI_REL_OFFSET rcx,0
- movw %ds,%cx
+ movl %ds,%ecx
cmpw %cx,0x10(%rsp)
CFI_REMEMBER_STATE
jne 1f
- movw %es,%cx
+ movl %es,%ecx
cmpw %cx,0x18(%rsp)
jne 1f
- movw %fs,%cx
+ movl %fs,%ecx
cmpw %cx,0x20(%rsp)
jne 1f
- movw %gs,%cx
+ movl %gs,%ecx
cmpw %cx,0x28(%rsp)
jne 1f
/* All segments match their saved values => Category 2 (Bad IRET). */
movq (%rsp),%rcx
CFI_RESTORE rcx
movq 8(%rsp),%r11
--
1.8.1.4


2015-05-14 17:05:16

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers

On Thu, May 14, 2015 at 9:55 AM, Denys Vlasenko <[email protected]> wrote:
> "movw %ds,%cx" insn needs a 0x66 prefix, while "movw %ds,%ecx" does not.
> The difference is that it overwrite entire %ecx, not only its low half,
> but subsequent code doesn't depend on the value of top half of %ecx,
> we can safely use the shorter insn.

I don't object to the patch, but did we actually confirm that it
always overwrites all of %ecx? The segment move instructions are
schizofrenic when it comes to sizes, and sometimes write just 16 bits
even when the instruction size is 32.

Was that just for push and/or move-to-memory?

Linus

2015-05-14 17:08:05

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers

On Thu, May 14, 2015 at 10:05 AM, Linus Torvalds
<[email protected]> wrote:
>
> I don't object to the patch, but did we actually confirm that it
> always overwrites all of %ecx?

Just to clarify: I don't object to the patch because the code doesn't
actually end up *depending* on the high bits anyway, and does
word-sized compares etc. And the instruction size and speed things I
don't doubt. So it's just the commit message I wanted to check wrt
that whole "always overwrites all of %ecx". Because older CPU's didn't
necessarily (things like partial register writes are much less of an
issue when you're in-order and stupid ;)

Linus

2015-05-14 17:41:49

by Denys Vlasenko

[permalink] [raw]
Subject: Re: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers

On 05/14/2015 07:08 PM, Linus Torvalds wrote:
> On Thu, May 14, 2015 at 10:05 AM, Linus Torvalds
> <[email protected]> wrote:
>>
>> I don't object to the patch, but did we actually confirm that it
>> always overwrites all of %ecx?
>
> Just to clarify: I don't object to the patch because the code doesn't
> actually end up *depending* on the high bits anyway, and does
> word-sized compares etc. And the instruction size and speed things I
> don't doubt. So it's just the commit message I wanted to check wrt
> that whole "always overwrites all of %ecx". Because older CPU's didn't
> necessarily (things like partial register writes are much less of an
> issue when you're in-order and stupid ;)

This is 64-bit code, and all 64-bit CPUs zero-extend moves from
segment registers. As you said, in this particular code it wouldn't
matter anyway since subsequent code doesn't care about high bits of %ecx...

2015-05-14 17:46:16

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers


* Denys Vlasenko <[email protected]> wrote:

> On 05/14/2015 07:08 PM, Linus Torvalds wrote:
> > On Thu, May 14, 2015 at 10:05 AM, Linus Torvalds
> > <[email protected]> wrote:
> >>
> >> I don't object to the patch, but did we actually confirm that it
> >> always overwrites all of %ecx?
> >
> > Just to clarify: I don't object to the patch because the code
> > doesn't actually end up *depending* on the high bits anyway, and
> > does word-sized compares etc. And the instruction size and speed
> > things I don't doubt. So it's just the commit message I wanted to
> > check wrt that whole "always overwrites all of %ecx". Because
> > older CPU's didn't necessarily (things like partial register
> > writes are much less of an issue when you're in-order and stupid
> > ;)
>
> This is 64-bit code, and all 64-bit CPUs zero-extend moves from
> segment registers. As you said, in this particular code it wouldn't
> matter anyway since subsequent code doesn't care about high bits of
> %ecx...

Mind updating the changelog with all that information? It wasn't
obvious to me either, as most of the mnemonics 'look' 32-bit.

I'd also say that a changelog is not complete, by definition, if Linus
has to ask about it ;-)

Thanks,

Ingo

2015-05-15 18:17:47

by Thiago Farina

[permalink] [raw]
Subject: Re: [PATCH] x86/asm/entry/64: Use shorter MOVs from segmers registers

On Thu, May 14, 2015 at 1:55 PM, Denys Vlasenko <[email protected]> wrote:
> "movw %ds,%cx" insn needs a 0x66 prefix, while "movw %ds,%ecx" does not.
did you mean 'movl %ds,%ecx' here as is in your patch below?

> Signed-off-by: Denys Vlasenko <[email protected]>
> CC: Linus Torvalds <[email protected]>
> CC: Steven Rostedt <[email protected]>
> CC: Ingo Molnar <[email protected]>
> CC: Borislav Petkov <[email protected]>
> CC: "H. Peter Anvin" <[email protected]>
> CC: Andy Lutomirski <[email protected]>
> CC: Oleg Nesterov <[email protected]>
> CC: Frederic Weisbecker <[email protected]>
> CC: Alexei Starovoitov <[email protected]>
> CC: Will Drewry <[email protected]>
> CC: Kees Cook <[email protected]>
> CC: [email protected]
> CC: [email protected]
> ---
> arch/x86/kernel/entry_64.S | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
> index 62b4c5f..ef2651d 100644
> --- a/arch/x86/kernel/entry_64.S
> +++ b/arch/x86/kernel/entry_64.S
> @@ -1195,19 +1195,19 @@ ENTRY(xen_failsafe_callback)
> /*CFI_REL_OFFSET ds,DS*/
> CFI_REL_OFFSET r11,8
> CFI_REL_OFFSET rcx,0
> - movw %ds,%cx
> + movl %ds,%ecx
> cmpw %cx,0x10(%rsp)
> CFI_REMEMBER_STATE
> jne 1f
> - movw %es,%cx
> + movl %es,%ecx
> cmpw %cx,0x18(%rsp)
> jne 1f
> - movw %fs,%cx
> + movl %fs,%ecx
> cmpw %cx,0x20(%rsp)
> jne 1f
> - movw %gs,%cx
> + movl %gs,%ecx
> cmpw %cx,0x28(%rsp)
> jne 1f
> /* All segments match their saved values => Category 2 (Bad IRET). */
> movq (%rsp),%rcx
> CFI_RESTORE rcx
> movq 8(%rsp),%r11
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/



--
Thiago Farina