summaryrefslogtreecommitdiff
path: root/arch/x86/include/asm/insn.h
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2020-11-13 19:09:54 +0300
committerJosh Poimboeuf <jpoimboe@redhat.com>2021-01-14 03:13:17 +0300
commit5ed934e57e712b676ca62e1904ad672a9fa1505a (patch)
tree648beb17a7469cda7287483554316a66bc6dcf93 /arch/x86/include/asm/insn.h
parent7786032e52cb02982a7154993b5d88c9c7a31ba5 (diff)
downloadlinux-5ed934e57e712b676ca62e1904ad672a9fa1505a.tar.xz
x86/insn: Fix vector instruction decoding on big endian cross-compiles
Running instruction decoder posttest on an s390 host with an x86 target with allyesconfig shows errors. Instructions used in a couple of kernel objects could not be correctly decoded on big endian system. insn_decoder_test: warning: objdump says 6 bytes, but insn_get_length() says 5 insn_decoder_test: warning: Found an x86 instruction decoder bug, please report this. insn_decoder_test: warning: ffffffff831eb4e1: 62 d1 fd 48 7f 04 24 vmovdqa64 %zmm0,(%r12) insn_decoder_test: warning: objdump says 7 bytes, but insn_get_length() says 6 insn_decoder_test: warning: Found an x86 instruction decoder bug, please report this. insn_decoder_test: warning: ffffffff831eb4e8: 62 51 fd 48 7f 44 24 01 vmovdqa64 %zmm8,0x40(%r12) insn_decoder_test: warning: objdump says 8 bytes, but insn_get_length() says 6 This is because in a few places instruction field bytes are set directly with further usage of "value". To address that introduce and use a insn_set_byte() helper, which correctly updates "value" on big endian systems. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Diffstat (limited to 'arch/x86/include/asm/insn.h')
-rw-r--r--arch/x86/include/asm/insn.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h
index 090863cfb7f3..95a448fbb44c 100644
--- a/arch/x86/include/asm/insn.h
+++ b/arch/x86/include/asm/insn.h
@@ -30,6 +30,12 @@ static inline void insn_field_set(struct insn_field *p, insn_value_t v,
p->nbytes = n;
}
+static inline void insn_set_byte(struct insn_field *p, unsigned char n,
+ insn_byte_t v)
+{
+ p->bytes[n] = v;
+}
+
#else
struct insn_field {
@@ -51,6 +57,12 @@ static inline void insn_field_set(struct insn_field *p, insn_value_t v,
p->nbytes = n;
}
+static inline void insn_set_byte(struct insn_field *p, unsigned char n,
+ insn_byte_t v)
+{
+ p->bytes[n] = v;
+ p->value = __le32_to_cpu(p->little);
+}
#endif
struct insn {