2012-09-21 19:43:09 +00:00
|
|
|
#ifndef _ASM_X86_ALTERNATIVE_ASM_H
|
|
|
|
#define _ASM_X86_ALTERNATIVE_ASM_H
|
|
|
|
|
2007-10-17 16:04:38 +00:00
|
|
|
#ifdef __ASSEMBLY__
|
|
|
|
|
2009-11-27 15:06:16 +00:00
|
|
|
#include <asm/asm.h>
|
2007-10-17 16:04:38 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
.macro LOCK_PREFIX
|
2012-01-03 16:35:40 +00:00
|
|
|
672: lock
|
2012-09-21 19:43:08 +00:00
|
|
|
.pushsection .smp_locks,"a"
|
2010-04-21 15:08:14 +00:00
|
|
|
.balign 4
|
2012-01-03 16:35:40 +00:00
|
|
|
.long 672b - .
|
2012-09-21 19:43:08 +00:00
|
|
|
.popsection
|
2007-10-17 16:04:38 +00:00
|
|
|
.endm
|
|
|
|
#else
|
|
|
|
.macro LOCK_PREFIX
|
|
|
|
.endm
|
|
|
|
#endif
|
|
|
|
|
2015-04-04 14:40:45 +00:00
|
|
|
/*
|
|
|
|
* Issue one struct alt_instr descriptor entry (need to put it into
|
|
|
|
* the section .altinstructions, see below). This entry contains
|
|
|
|
* enough information for the alternatives patching code to patch an
|
|
|
|
* instruction. See apply_alternatives().
|
|
|
|
*/
|
2014-12-27 09:41:52 +00:00
|
|
|
.macro altinstruction_entry orig alt feature orig_len alt_len pad_len
|
2011-07-13 13:24:10 +00:00
|
|
|
.long \orig - .
|
|
|
|
.long \alt - .
|
2011-05-17 22:29:13 +00:00
|
|
|
.word \feature
|
|
|
|
.byte \orig_len
|
|
|
|
.byte \alt_len
|
2014-12-27 09:41:52 +00:00
|
|
|
.byte \pad_len
|
|
|
|
.endm
|
|
|
|
|
2015-04-04 14:40:45 +00:00
|
|
|
/*
|
|
|
|
* Define an alternative between two instructions. If @feature is
|
|
|
|
* present, early code in apply_alternatives() replaces @oldinstr with
|
|
|
|
* @newinstr. ".skip" directive takes care of proper instruction padding
|
|
|
|
* in case @newinstr is longer than @oldinstr.
|
|
|
|
*/
|
2014-12-27 09:41:52 +00:00
|
|
|
.macro ALTERNATIVE oldinstr, newinstr, feature
|
|
|
|
140:
|
|
|
|
\oldinstr
|
|
|
|
141:
|
|
|
|
.skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90
|
|
|
|
142:
|
|
|
|
|
|
|
|
.pushsection .altinstructions,"a"
|
|
|
|
altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b
|
|
|
|
.popsection
|
|
|
|
|
|
|
|
.pushsection .altinstr_replacement,"ax"
|
|
|
|
143:
|
|
|
|
\newinstr
|
|
|
|
144:
|
|
|
|
.popsection
|
|
|
|
.endm
|
|
|
|
|
x86/alternatives: Fix ALTERNATIVE_2 padding generation properly
Quentin caught a corner case with the generation of instruction
padding in the ALTERNATIVE_2 macro: if len(orig_insn) <
len(alt1) < len(alt2), then not enough padding gets added and
that is not good(tm) as we could overwrite the beginning of the
next instruction.
Luckily, at the time of this writing, we don't have
ALTERNATIVE_2() invocations which have that problem and even if
we did, a simple fix would be to prepend the instructions with
enough prefixes so that that corner case doesn't happen.
However, best it would be if we fixed it properly. See below for
a simple, abstracted example of what we're doing.
So what we ended up doing is, we compute the
max(len(alt1), len(alt2)) - len(orig_insn)
and feed that value to the .skip gas directive. The max() cannot
have conditionals due to gas limitations, thus the fancy integer
math.
With this patch, all ALTERNATIVE_2 sites get padded correctly;
generating obscure test cases pass too:
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
#define gen_skip(orig, alt1, alt2, marker) \
.skip -((alt_max_short(alt1, alt2) - (orig)) > 0) * \
(alt_max_short(alt1, alt2) - (orig)),marker
.pushsection .text, "ax"
.globl main
main:
gen_skip(1, 2, 4, 0x09)
gen_skip(4, 1, 2, 0x10)
...
.popsection
Thanks to Quentin for catching it and double-checking the fix!
Reported-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150404133443.GE21152@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-04-04 13:34:43 +00:00
|
|
|
#define old_len 141b-140b
|
|
|
|
#define new_len1 144f-143f
|
|
|
|
#define new_len2 145f-144f
|
|
|
|
|
|
|
|
/*
|
x86/alternatives: Fix alt_max_short macro to really be a max()
The alt_max_short() macro in asm/alternative.h does not work as
intended, leading to nasty bugs. E.g. alt_max_short("1", "3")
evaluates to 3, but alt_max_short("3", "1") evaluates to 1 -- not
exactly the maximum of 1 and 3.
In fact, I had to learn it the hard way by crashing my kernel in not
so funny ways by attempting to make use of the ALTENATIVE_2 macro
with alternatives where the first one was larger than the second
one.
According to [1] and commit dbe4058a6a44 ("x86/alternatives: Fix
ALTERNATIVE_2 padding generation properly") the right handed side
should read "-(-(a < b))" not "-(-(a - b))". Fix that, to make the
macro work as intended.
While at it, fix up the comments regarding the additional "-", too.
It's not about gas' usage of s32 but brain dead logic of having a
"true" value of -1 for the < operator ... *sigh*
Btw., the one in asm/alternative-asm.h is correct. And, apparently,
all current users of ALTERNATIVE_2() pass same sized alternatives,
avoiding to hit the bug.
[1] http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
Reviewed-and-tested-by: Borislav Petkov <bp@suse.de>
Fixes: dbe4058a6a44 ("x86/alternatives: Fix ALTERNATIVE_2 padding generation properly")
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/1507228213-13095-1-git-send-email-minipli@googlemail.com
2017-10-05 18:30:12 +00:00
|
|
|
* gas compatible max based on the idea from:
|
x86/alternatives: Fix ALTERNATIVE_2 padding generation properly
Quentin caught a corner case with the generation of instruction
padding in the ALTERNATIVE_2 macro: if len(orig_insn) <
len(alt1) < len(alt2), then not enough padding gets added and
that is not good(tm) as we could overwrite the beginning of the
next instruction.
Luckily, at the time of this writing, we don't have
ALTERNATIVE_2() invocations which have that problem and even if
we did, a simple fix would be to prepend the instructions with
enough prefixes so that that corner case doesn't happen.
However, best it would be if we fixed it properly. See below for
a simple, abstracted example of what we're doing.
So what we ended up doing is, we compute the
max(len(alt1), len(alt2)) - len(orig_insn)
and feed that value to the .skip gas directive. The max() cannot
have conditionals due to gas limitations, thus the fancy integer
math.
With this patch, all ALTERNATIVE_2 sites get padded correctly;
generating obscure test cases pass too:
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
#define gen_skip(orig, alt1, alt2, marker) \
.skip -((alt_max_short(alt1, alt2) - (orig)) > 0) * \
(alt_max_short(alt1, alt2) - (orig)),marker
.pushsection .text, "ax"
.globl main
main:
gen_skip(1, 2, 4, 0x09)
gen_skip(4, 1, 2, 0x10)
...
.popsection
Thanks to Quentin for catching it and double-checking the fix!
Reported-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150404133443.GE21152@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-04-04 13:34:43 +00:00
|
|
|
* http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
|
x86/alternatives: Fix alt_max_short macro to really be a max()
The alt_max_short() macro in asm/alternative.h does not work as
intended, leading to nasty bugs. E.g. alt_max_short("1", "3")
evaluates to 3, but alt_max_short("3", "1") evaluates to 1 -- not
exactly the maximum of 1 and 3.
In fact, I had to learn it the hard way by crashing my kernel in not
so funny ways by attempting to make use of the ALTENATIVE_2 macro
with alternatives where the first one was larger than the second
one.
According to [1] and commit dbe4058a6a44 ("x86/alternatives: Fix
ALTERNATIVE_2 padding generation properly") the right handed side
should read "-(-(a < b))" not "-(-(a - b))". Fix that, to make the
macro work as intended.
While at it, fix up the comments regarding the additional "-", too.
It's not about gas' usage of s32 but brain dead logic of having a
"true" value of -1 for the < operator ... *sigh*
Btw., the one in asm/alternative-asm.h is correct. And, apparently,
all current users of ALTERNATIVE_2() pass same sized alternatives,
avoiding to hit the bug.
[1] http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
Reviewed-and-tested-by: Borislav Petkov <bp@suse.de>
Fixes: dbe4058a6a44 ("x86/alternatives: Fix ALTERNATIVE_2 padding generation properly")
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/1507228213-13095-1-git-send-email-minipli@googlemail.com
2017-10-05 18:30:12 +00:00
|
|
|
*
|
|
|
|
* The additional "-" is needed because gas uses a "true" value of -1.
|
x86/alternatives: Fix ALTERNATIVE_2 padding generation properly
Quentin caught a corner case with the generation of instruction
padding in the ALTERNATIVE_2 macro: if len(orig_insn) <
len(alt1) < len(alt2), then not enough padding gets added and
that is not good(tm) as we could overwrite the beginning of the
next instruction.
Luckily, at the time of this writing, we don't have
ALTERNATIVE_2() invocations which have that problem and even if
we did, a simple fix would be to prepend the instructions with
enough prefixes so that that corner case doesn't happen.
However, best it would be if we fixed it properly. See below for
a simple, abstracted example of what we're doing.
So what we ended up doing is, we compute the
max(len(alt1), len(alt2)) - len(orig_insn)
and feed that value to the .skip gas directive. The max() cannot
have conditionals due to gas limitations, thus the fancy integer
math.
With this patch, all ALTERNATIVE_2 sites get padded correctly;
generating obscure test cases pass too:
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
#define gen_skip(orig, alt1, alt2, marker) \
.skip -((alt_max_short(alt1, alt2) - (orig)) > 0) * \
(alt_max_short(alt1, alt2) - (orig)),marker
.pushsection .text, "ax"
.globl main
main:
gen_skip(1, 2, 4, 0x09)
gen_skip(4, 1, 2, 0x10)
...
.popsection
Thanks to Quentin for catching it and double-checking the fix!
Reported-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150404133443.GE21152@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-04-04 13:34:43 +00:00
|
|
|
*/
|
|
|
|
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
|
|
|
|
|
2015-04-04 14:40:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Same as ALTERNATIVE macro above but for two alternatives. If CPU
|
|
|
|
* has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
|
|
|
|
* @feature2, it replaces @oldinstr with @feature2.
|
|
|
|
*/
|
2014-12-27 09:41:52 +00:00
|
|
|
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
|
|
|
140:
|
|
|
|
\oldinstr
|
|
|
|
141:
|
x86/alternatives: Fix ALTERNATIVE_2 padding generation properly
Quentin caught a corner case with the generation of instruction
padding in the ALTERNATIVE_2 macro: if len(orig_insn) <
len(alt1) < len(alt2), then not enough padding gets added and
that is not good(tm) as we could overwrite the beginning of the
next instruction.
Luckily, at the time of this writing, we don't have
ALTERNATIVE_2() invocations which have that problem and even if
we did, a simple fix would be to prepend the instructions with
enough prefixes so that that corner case doesn't happen.
However, best it would be if we fixed it properly. See below for
a simple, abstracted example of what we're doing.
So what we ended up doing is, we compute the
max(len(alt1), len(alt2)) - len(orig_insn)
and feed that value to the .skip gas directive. The max() cannot
have conditionals due to gas limitations, thus the fancy integer
math.
With this patch, all ALTERNATIVE_2 sites get padded correctly;
generating obscure test cases pass too:
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
#define gen_skip(orig, alt1, alt2, marker) \
.skip -((alt_max_short(alt1, alt2) - (orig)) > 0) * \
(alt_max_short(alt1, alt2) - (orig)),marker
.pushsection .text, "ax"
.globl main
main:
gen_skip(1, 2, 4, 0x09)
gen_skip(4, 1, 2, 0x10)
...
.popsection
Thanks to Quentin for catching it and double-checking the fix!
Reported-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20150404133443.GE21152@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2015-04-04 13:34:43 +00:00
|
|
|
.skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
|
|
|
|
(alt_max_short(new_len1, new_len2) - (old_len)),0x90
|
2014-12-27 09:41:52 +00:00
|
|
|
142:
|
|
|
|
|
|
|
|
.pushsection .altinstructions,"a"
|
|
|
|
altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b
|
|
|
|
altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b
|
|
|
|
.popsection
|
|
|
|
|
|
|
|
.pushsection .altinstr_replacement,"ax"
|
|
|
|
143:
|
|
|
|
\newinstr1
|
|
|
|
144:
|
|
|
|
\newinstr2
|
|
|
|
145:
|
|
|
|
.popsection
|
2011-05-17 22:29:13 +00:00
|
|
|
.endm
|
|
|
|
|
2007-10-17 16:04:38 +00:00
|
|
|
#endif /* __ASSEMBLY__ */
|
2012-09-21 19:43:09 +00:00
|
|
|
|
|
|
|
#endif /* _ASM_X86_ALTERNATIVE_ASM_H */
|