$(call as-option-add,CFLAGS,CC,\
".if ((1 > 0) < 0); .error \"\";.endif",,-DHAVE_AS_NEGATIVE_TRUE)
+# Check to see whether the assmbler supports the .nop directive.
+$(call as-option-add,CFLAGS,CC,\
+ ".L1: .L2: .nops (.L2 - .L1)$$(comma)9",-DHAVE_AS_NOPS_DIRECTIVE)
+
CFLAGS += -mno-red-zone -fpic -fno-asynchronous-unwind-tables
# Xen doesn't use SSE interally. If the compiler supports it, also skip the
static const unsigned char * const *ideal_nops init_or_livepatch_data = p6_nops;
+#ifdef HAVE_AS_NOPS_DIRECTIVE
+
+/* Nops in .init.rodata to compare against the runtime ideal nops. */
+asm ( ".pushsection .init.rodata, \"a\", @progbits\n\t"
+ "toolchain_nops: .nops " __stringify(ASM_NOP_MAX) "\n\t"
+ ".popsection\n\t");
+extern char toolchain_nops[ASM_NOP_MAX];
+static bool __read_mostly toolchain_nops_are_ideal;
+
+#else
+# define toolchain_nops_are_ideal false
+#endif
+
static void __init arch_init_ideal_nops(void)
{
switch ( boot_cpu_data.x86_vendor )
ideal_nops = k8_nops;
break;
}
+
+#ifdef HAVE_AS_NOPS_DIRECTIVE
+ if ( memcmp(ideal_nops[ASM_NOP_MAX], toolchain_nops, ASM_NOP_MAX) == 0 )
+ toolchain_nops_are_ideal = true;
+#endif
}
/* Use this to add nops to a buffer, then text_poke the whole buffer. */
base->priv = 1;
/* Nothing useful to do? */
- if ( a->pad_len <= 1 )
+ if ( toolchain_nops_are_ideal || a->pad_len <= 1 )
continue;
add_nops(buf, a->pad_len);
#ifndef _ASM_X86_ALTERNATIVE_ASM_H_
#define _ASM_X86_ALTERNATIVE_ASM_H_
+#include <asm/nops.h>
+
#ifdef __ASSEMBLY__
/*
.byte 0 /* priv */
.endm
+.macro mknops nr_bytes
+#ifdef HAVE_AS_NOPS_DIRECTIVE
+ .nops \nr_bytes, ASM_NOP_MAX
+#else
+ .skip \nr_bytes, 0x90
+#endif
+.endm
+
/* GAS's idea of true is -1, while Clang's idea is 1. */
#ifdef HAVE_AS_NEGATIVE_TRUE
# define as_true(x) (-(x))
#define decl_orig(insn, padding) \
.L\@_orig_s: insn; .L\@_orig_e: \
.L\@_diff = padding; \
- .skip as_true(.L\@_diff > 0) * .L\@_diff, 0x90; \
+ mknops (as_true(.L\@_diff > 0) * .L\@_diff); \
.L\@_orig_p:
#define orig_len (.L\@_orig_e - .L\@_orig_s)
#define __X86_ALTERNATIVE_H__
#include <asm/alternative-asm.h>
-#include <asm/nops.h>
#ifndef __ASSEMBLY__
#include <xen/stringify.h>
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
extern void alternative_instructions(void);
+asm ( ".macro mknops nr_bytes\n\t"
+#ifdef HAVE_AS_NOPS_DIRECTIVE
+ ".nops \\nr_bytes, " __stringify(ASM_NOP_MAX) "\n\t"
+#else
+ ".skip \\nr_bytes, 0x90\n\t"
+#endif
+ ".endm\n\t" );
+
#define alt_orig_len "(.LXEN%=_orig_e - .LXEN%=_orig_s)"
#define alt_pad_len "(.LXEN%=_orig_p - .LXEN%=_orig_e)"
#define alt_total_len "(.LXEN%=_orig_p - .LXEN%=_orig_s)"
#define OLDINSTR(oldinstr, padding) \
".LXEN%=_orig_s:\n\t" oldinstr "\n .LXEN%=_orig_e:\n\t" \
".LXEN%=_diff = " padding "\n\t" \
- ".skip "AS_TRUE"(.LXEN%=_diff > 0) * .LXEN%=_diff, 0x90\n\t" \
+ "mknops ("AS_TRUE"(.LXEN%=_diff > 0) * .LXEN%=_diff)\n\t" \
".LXEN%=_orig_p:\n\t"
#define OLDINSTR_1(oldinstr, n1) \