[OE-core] [PATCH 2/2] binutils: fix CVE-2020-0551

Khem Raj raj.khem at gmail.com
Fri Mar 13 14:42:21 UTC 2020


Please backport the tests patch [1] as well along with this

[1] 
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=97b4a8f744f437fa35afbe20f53e657e9de957cd

On 3/12/20 6:09 PM, Anuj Mittal wrote:
> Signed-off-by: Anuj Mittal <anuj.mittal at intel.com>
> ---
>   .../binutils/binutils-2.34.inc                |   1 +
>   .../binutils/binutils/CVE-2020-0551.patch     | 549 ++++++++++++++++++
>   2 files changed, 550 insertions(+)
>   create mode 100644 meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
> 
> diff --git a/meta/recipes-devtools/binutils/binutils-2.34.inc b/meta/recipes-devtools/binutils/binutils-2.34.inc
> index eaaa5ed2ac..ed9f902fd2 100644
> --- a/meta/recipes-devtools/binutils/binutils-2.34.inc
> +++ b/meta/recipes-devtools/binutils/binutils-2.34.inc
> @@ -40,6 +40,7 @@ SRC_URI = "\
>        file://0013-fix-the-incorrect-assembling-for-ppc-wait-mnemonic.patch \
>        file://0014-Detect-64-bit-MIPS-targets.patch \
>        file://0015-sync-with-OE-libtool-changes.patch \
> +     file://CVE-2020-0551.patch \
>   "
>   S  = "${WORKDIR}/git"
>   
> diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch b/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
> new file mode 100644
> index 0000000000..53e3caf445
> --- /dev/null
> +++ b/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
> @@ -0,0 +1,549 @@
> +From ae531041c7c5956672342f89c486a011c84f027f Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools at gmail.com>
> +Date: Wed, 11 Mar 2020 09:46:19 -0700
> +Subject: [PATCH 1/1] i386: Generate lfence with load/indirect branch/ret
> + [CVE-2020-0551]
> +
> +Add 3 command-line options to generate lfence for load, indirect near
> +branch and ret to help mitigate:
> +
> +https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00334.html
> +http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0551
> +
> +1. -mlfence-after-load=[no|yes]:
> +  -mlfence-after-load=yes generates lfence after load instructions.
> +2. -mlfence-before-indirect-branch=[none|all|memory|register]:
> +  a. -mlfence-before-indirect-branch=all generates lfence before indirect
> +  near branches via register and a warning before indirect near branches
> +  via memory.
> +  b. -mlfence-before-indirect-branch=memory issue a warning before
> +  indirect near branches via memory.
> +  c. -mlfence-before-indirect-branch=register generates lfence before
> +  indirect near branches via register.
> +Note that lfence won't be generated before indirect near branches via
> +register with -mlfence-after-load=yes since lfence will be generated
> +after loading branch target register.
> +3. -mlfence-before-ret=[none|or|not]
> +  a. -mlfence-before-ret=or generates or with lfence before ret.
> +  b. -mlfence-before-ret=not generates not with lfence before ret.
> +
> +A warning will be issued and lfence won't be generated before indirect
> +near branch and ret if the previous item is a prefix or a constant
> +directive, which may be used to hardcode an instruction, since there
> +is no clear instruction boundary.
> +
> +	* config/tc-i386.c (lfence_after_load): New.
> +	(lfence_before_indirect_branch_kind): New.
> +	(lfence_before_indirect_branch): New.
> +	(lfence_before_ret_kind): New.
> +	(lfence_before_ret): New.
> +	(last_insn): New.
> +	(load_insn_p): New.
> +	(insert_lfence_after): New.
> +	(insert_lfence_before): New.
> +	(md_assemble): Call insert_lfence_before and insert_lfence_after.
> +	Set last_insn.
> +	(OPTION_MLFENCE_AFTER_LOAD): New.
> +	(OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH): New.
> +	(OPTION_MLFENCE_BEFORE_RET): New.
> +	(md_longopts): Add -mlfence-after-load=,
> +	-mlfence-before-indirect-branch= and -mlfence-before-ret=.
> +	(md_parse_option): Handle -mlfence-after-load=,
> +	-mlfence-before-indirect-branch= and -mlfence-before-ret=.
> +	(md_show_usage): Display -mlfence-after-load=,
> +	-mlfence-before-indirect-branch= and -mlfence-before-ret=.
> +	(i386_cons_align): New.
> +	* config/tc-i386.h (i386_cons_align): New.
> +	(md_cons_align): New.
> +	* doc/c-i386.texi: Document -mlfence-after-load=,
> +	-mlfence-before-indirect-branch= and -mlfence-before-ret=.
> +
> +Signed-off-by: Anuj Mittal <anuj.mittal at intel.com>
> +Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=ae531041c7c5956672342f89c486a011c84f027f]
> +CVE: CVE-2020-0551
> +---
> +diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
> +index b020f39c863..09063f784b7 100644
> +--- a/gas/config/tc-i386.c
> ++++ b/gas/config/tc-i386.c
> +@@ -629,7 +629,29 @@ static int omit_lock_prefix = 0;
> +    "lock addl $0, (%{re}sp)".  */
> + static int avoid_fence = 0;
> +
> +-/* Type of the previous instruction.  */
> ++/* 1 if lfence should be inserted after every load.  */
> ++static int lfence_after_load = 0;
> ++
> ++/* Non-zero if lfence should be inserted before indirect branch.  */
> ++static enum lfence_before_indirect_branch_kind
> ++  {
> ++    lfence_branch_none = 0,
> ++    lfence_branch_register,
> ++    lfence_branch_memory,
> ++    lfence_branch_all
> ++  }
> ++lfence_before_indirect_branch;
> ++
> ++/* Non-zero if lfence should be inserted before ret.  */
> ++static enum lfence_before_ret_kind
> ++  {
> ++    lfence_before_ret_none = 0,
> ++    lfence_before_ret_not,
> ++    lfence_before_ret_or
> ++  }
> ++lfence_before_ret;
> ++
> ++/* Types of previous instruction is .byte or prefix.  */
> + static struct
> +   {
> +     segT seg;
> +@@ -4311,6 +4333,283 @@ optimize_encoding (void)
> +     }
> + }
> +
> ++/* Return non-zero for load instruction.  */
> ++
> ++static int
> ++load_insn_p (void)
> ++{
> ++  unsigned int dest;
> ++  int any_vex_p = is_any_vex_encoding (&i.tm);
> ++  unsigned int base_opcode = i.tm.base_opcode | 1;
> ++
> ++  if (!any_vex_p)
> ++    {
> ++      /* lea  */
> ++      if (i.tm.base_opcode == 0x8d)
> ++	return 0;
> ++
> ++      /* pop  */
> ++      if ((i.tm.base_opcode & ~7) == 0x58
> ++	  || (i.tm.base_opcode == 0x8f && i.tm.extension_opcode == 0))
> ++	return 1;
> ++
> ++      /* movs, cmps, lods, scas.  */
> ++      if ((i.tm.base_opcode | 0xb) == 0xaf)
> ++	return 1;
> ++
> ++      /* outs */
> ++      if (base_opcode == 0x6f)
> ++	return 1;
> ++    }
> ++
> ++  /* No memory operand.  */
> ++  if (!i.mem_operands)
> ++    return 0;
> ++
> ++  if (any_vex_p)
> ++    {
> ++      /* vldmxcsr.  */
> ++      if (i.tm.base_opcode == 0xae
> ++	  && i.tm.opcode_modifier.vex
> ++	  && i.tm.opcode_modifier.vexopcode == VEX0F
> ++	  && i.tm.extension_opcode == 2)
> ++	return 1;
> ++    }
> ++  else
> ++    {
> ++      /* test, not, neg, mul, imul, div, idiv.  */
> ++      if ((i.tm.base_opcode == 0xf6 || i.tm.base_opcode == 0xf7)
> ++	  && i.tm.extension_opcode != 1)
> ++	return 1;
> ++
> ++      /* inc, dec.  */
> ++      if (base_opcode == 0xff && i.tm.extension_opcode <= 1)
> ++	return 1;
> ++
> ++      /* add, or, adc, sbb, and, sub, xor, cmp.  */
> ++      if (i.tm.base_opcode >= 0x80 && i.tm.base_opcode <= 0x83)
> ++	return 1;
> ++
> ++      /* bt, bts, btr, btc.  */
> ++      if (i.tm.base_opcode == 0xfba
> ++	  && (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
> ++	return 1;
> ++
> ++      /* rol, ror, rcl, rcr, shl/sal, shr, sar. */
> ++      if ((base_opcode == 0xc1
> ++	   || (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
> ++	  && i.tm.extension_opcode != 6)
> ++	return 1;
> ++
> ++      /* cmpxchg8b, cmpxchg16b, xrstors.  */
> ++      if (i.tm.base_opcode == 0xfc7
> ++	  && (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3))
> ++	return 1;
> ++
> ++      /* fxrstor, ldmxcsr, xrstor.  */
> ++      if (i.tm.base_opcode == 0xfae
> ++	  && (i.tm.extension_opcode == 1
> ++	      || i.tm.extension_opcode == 2
> ++	      || i.tm.extension_opcode == 5))
> ++	return 1;
> ++
> ++      /* lgdt, lidt, lmsw.  */
> ++      if (i.tm.base_opcode == 0xf01
> ++	  && (i.tm.extension_opcode == 2
> ++	      || i.tm.extension_opcode == 3
> ++	      || i.tm.extension_opcode == 6))
> ++	return 1;
> ++
> ++      /* vmptrld */
> ++      if (i.tm.base_opcode == 0xfc7
> ++	  && i.tm.extension_opcode == 6)
> ++	return 1;
> ++
> ++      /* Check for x87 instructions.  */
> ++      if (i.tm.base_opcode >= 0xd8 && i.tm.base_opcode <= 0xdf)
> ++	{
> ++	  /* Skip fst, fstp, fstenv, fstcw.  */
> ++	  if (i.tm.base_opcode == 0xd9
> ++	      && (i.tm.extension_opcode == 2
> ++		  || i.tm.extension_opcode == 3
> ++		  || i.tm.extension_opcode == 6
> ++		  || i.tm.extension_opcode == 7))
> ++	    return 0;
> ++
> ++	  /* Skip fisttp, fist, fistp, fstp.  */
> ++	  if (i.tm.base_opcode == 0xdb
> ++	      && (i.tm.extension_opcode == 1
> ++		  || i.tm.extension_opcode == 2
> ++		  || i.tm.extension_opcode == 3
> ++		  || i.tm.extension_opcode == 7))
> ++	    return 0;
> ++
> ++	  /* Skip fisttp, fst, fstp, fsave, fstsw.  */
> ++	  if (i.tm.base_opcode == 0xdd
> ++	      && (i.tm.extension_opcode == 1
> ++		  || i.tm.extension_opcode == 2
> ++		  || i.tm.extension_opcode == 3
> ++		  || i.tm.extension_opcode == 6
> ++		  || i.tm.extension_opcode == 7))
> ++	    return 0;
> ++
> ++	  /* Skip fisttp, fist, fistp, fbstp, fistp.  */
> ++	  if (i.tm.base_opcode == 0xdf
> ++	      && (i.tm.extension_opcode == 1
> ++		  || i.tm.extension_opcode == 2
> ++		  || i.tm.extension_opcode == 3
> ++		  || i.tm.extension_opcode == 6
> ++		  || i.tm.extension_opcode == 7))
> ++	    return 0;
> ++
> ++	  return 1;
> ++	}
> ++    }
> ++
> ++  dest = i.operands - 1;
> ++
> ++  /* Check fake imm8 operand and 3 source operands.  */
> ++  if ((i.tm.opcode_modifier.immext
> ++       || i.tm.opcode_modifier.vexsources == VEX3SOURCES)
> ++      && i.types[dest].bitfield.imm8)
> ++    dest--;
> ++
> ++  /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg, xadd  */
> ++  if (!any_vex_p
> ++      && (base_opcode == 0x1
> ++	  || base_opcode == 0x9
> ++	  || base_opcode == 0x11
> ++	  || base_opcode == 0x19
> ++	  || base_opcode == 0x21
> ++	  || base_opcode == 0x29
> ++	  || base_opcode == 0x31
> ++	  || base_opcode == 0x39
> ++	  || (i.tm.base_opcode >= 0x84 && i.tm.base_opcode <= 0x87)
> ++	  || base_opcode == 0xfc1))
> ++    return 1;
> ++
> ++  /* Check for load instruction.  */
> ++  return (i.types[dest].bitfield.class != ClassNone
> ++	  || i.types[dest].bitfield.instance == Accum);
> ++}
> ++
> ++/* Output lfence, 0xfaee8, after instruction.  */
> ++
> ++static void
> ++insert_lfence_after (void)
> ++{
> ++  if (lfence_after_load && load_insn_p ())
> ++    {
> ++      char *p = frag_more (3);
> ++      *p++ = 0xf;
> ++      *p++ = 0xae;
> ++      *p = 0xe8;
> ++    }
> ++}
> ++
> ++/* Output lfence, 0xfaee8, before instruction.  */
> ++
> ++static void
> ++insert_lfence_before (void)
> ++{
> ++  char *p;
> ++
> ++  if (is_any_vex_encoding (&i.tm))
> ++    return;
> ++
> ++  if (i.tm.base_opcode == 0xff
> ++      && (i.tm.extension_opcode == 2 || i.tm.extension_opcode == 4))
> ++    {
> ++      /* Insert lfence before indirect branch if needed.  */
> ++
> ++      if (lfence_before_indirect_branch == lfence_branch_none)
> ++	return;
> ++
> ++      if (i.operands != 1)
> ++	abort ();
> ++
> ++      if (i.reg_operands == 1)
> ++	{
> ++	  /* Indirect branch via register.  Don't insert lfence with
> ++	     -mlfence-after-load=yes.  */
> ++	  if (lfence_after_load
> ++	      || lfence_before_indirect_branch == lfence_branch_memory)
> ++	    return;
> ++	}
> ++      else if (i.mem_operands == 1
> ++	       && lfence_before_indirect_branch != lfence_branch_register)
> ++	{
> ++	  as_warn (_("indirect `%s` with memory operand should be avoided"),
> ++		   i.tm.name);
> ++	  return;
> ++	}
> ++      else
> ++	return;
> ++
> ++      if (last_insn.kind != last_insn_other
> ++	  && last_insn.seg == now_seg)
> ++	{
> ++	  as_warn_where (last_insn.file, last_insn.line,
> ++			 _("`%s` skips -mlfence-before-indirect-branch on `%s`"),
> ++			 last_insn.name, i.tm.name);
> ++	  return;
> ++	}
> ++
> ++      p = frag_more (3);
> ++      *p++ = 0xf;
> ++      *p++ = 0xae;
> ++      *p = 0xe8;
> ++      return;
> ++    }
> ++
> ++  /* Output or/not and lfence before ret.  */
> ++  if (lfence_before_ret != lfence_before_ret_none
> ++      && (i.tm.base_opcode == 0xc2
> ++	  || i.tm.base_opcode == 0xc3
> ++	  || i.tm.base_opcode == 0xca
> ++	  || i.tm.base_opcode == 0xcb))
> ++    {
> ++      if (last_insn.kind != last_insn_other
> ++	  && last_insn.seg == now_seg)
> ++	{
> ++	  as_warn_where (last_insn.file, last_insn.line,
> ++			 _("`%s` skips -mlfence-before-ret on `%s`"),
> ++			 last_insn.name, i.tm.name);
> ++	  return;
> ++	}
> ++      if (lfence_before_ret == lfence_before_ret_or)
> ++	{
> ++	  /* orl: 0x830c2400.  */
> ++	  p = frag_more ((flag_code == CODE_64BIT ? 1 : 0) + 4 + 3);
> ++	  if (flag_code == CODE_64BIT)
> ++	    *p++ = 0x48;
> ++	  *p++ = 0x83;
> ++	  *p++ = 0xc;
> ++	  *p++ = 0x24;
> ++	  *p++ = 0x0;
> ++	}
> ++      else
> ++	{
> ++	  p = frag_more ((flag_code == CODE_64BIT ? 2 : 0) + 6 + 3);
> ++	  /* notl: 0xf71424.  */
> ++	  if (flag_code == CODE_64BIT)
> ++	    *p++ = 0x48;
> ++	  *p++ = 0xf7;
> ++	  *p++ = 0x14;
> ++	  *p++ = 0x24;
> ++	  /* notl: 0xf71424.  */
> ++	  if (flag_code == CODE_64BIT)
> ++	    *p++ = 0x48;
> ++	  *p++ = 0xf7;
> ++	  *p++ = 0x14;
> ++	  *p++ = 0x24;
> ++	}
> ++      *p++ = 0xf;
> ++      *p++ = 0xae;
> ++      *p = 0xe8;
> ++    }
> ++}
> ++
> + /* This is the guts of the machine-dependent assembler.  LINE points to a
> +    machine dependent instruction.  This function is supposed to emit
> +    the frags/bytes it assembles to.  */
> +@@ -4628,9 +4927,13 @@ md_assemble (char *line)
> +   if (i.rex != 0)
> +     add_prefix (REX_OPCODE | i.rex);
> +
> ++  insert_lfence_before ();
> ++
> +   /* We are ready to output the insn.  */
> +   output_insn ();
> +
> ++  insert_lfence_after ();
> ++
> +   last_insn.seg = now_seg;
> +
> +   if (i.tm.opcode_modifier.isprefix)
> +@@ -12250,6 +12553,9 @@ const char *md_shortopts = "qnO::";
> + #define OPTION_MALIGN_BRANCH_PREFIX_SIZE (OPTION_MD_BASE + 28)
> + #define OPTION_MALIGN_BRANCH (OPTION_MD_BASE + 29)
> + #define OPTION_MBRANCHES_WITH_32B_BOUNDARIES (OPTION_MD_BASE + 30)
> ++#define OPTION_MLFENCE_AFTER_LOAD (OPTION_MD_BASE + 31)
> ++#define OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH (OPTION_MD_BASE + 32)
> ++#define OPTION_MLFENCE_BEFORE_RET (OPTION_MD_BASE + 33)
> +
> + struct option md_longopts[] =
> + {
> +@@ -12289,6 +12595,10 @@ struct option md_longopts[] =
> +   {"malign-branch-prefix-size", required_argument, NULL, OPTION_MALIGN_BRANCH_PREFIX_SIZE},
> +   {"malign-branch", required_argument, NULL, OPTION_MALIGN_BRANCH},
> +   {"mbranches-within-32B-boundaries", no_argument, NULL, OPTION_MBRANCHES_WITH_32B_BOUNDARIES},
> ++  {"mlfence-after-load", required_argument, NULL, OPTION_MLFENCE_AFTER_LOAD},
> ++  {"mlfence-before-indirect-branch", required_argument, NULL,
> ++   OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH},
> ++  {"mlfence-before-ret", required_argument, NULL, OPTION_MLFENCE_BEFORE_RET},
> +   {"mamd64", no_argument, NULL, OPTION_MAMD64},
> +   {"mintel64", no_argument, NULL, OPTION_MINTEL64},
> +   {NULL, no_argument, NULL, 0}
> +@@ -12668,6 +12978,41 @@ md_parse_option (int c, const char *arg)
> +         as_fatal (_("invalid -mfence-as-lock-add= option: `%s'"), arg);
> +       break;
> +
> ++    case OPTION_MLFENCE_AFTER_LOAD:
> ++      if (strcasecmp (arg, "yes") == 0)
> ++	lfence_after_load = 1;
> ++      else if (strcasecmp (arg, "no") == 0)
> ++	lfence_after_load = 0;
> ++      else
> ++        as_fatal (_("invalid -mlfence-after-load= option: `%s'"), arg);
> ++      break;
> ++
> ++    case OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH:
> ++      if (strcasecmp (arg, "all") == 0)
> ++	lfence_before_indirect_branch = lfence_branch_all;
> ++      else if (strcasecmp (arg, "memory") == 0)
> ++	lfence_before_indirect_branch = lfence_branch_memory;
> ++      else if (strcasecmp (arg, "register") == 0)
> ++	lfence_before_indirect_branch = lfence_branch_register;
> ++      else if (strcasecmp (arg, "none") == 0)
> ++	lfence_before_indirect_branch = lfence_branch_none;
> ++      else
> ++        as_fatal (_("invalid -mlfence-before-indirect-branch= option: `%s'"),
> ++		  arg);
> ++      break;
> ++
> ++    case OPTION_MLFENCE_BEFORE_RET:
> ++      if (strcasecmp (arg, "or") == 0)
> ++	lfence_before_ret = lfence_before_ret_or;
> ++      else if (strcasecmp (arg, "not") == 0)
> ++	lfence_before_ret = lfence_before_ret_not;
> ++      else if (strcasecmp (arg, "none") == 0)
> ++	lfence_before_ret = lfence_before_ret_none;
> ++      else
> ++        as_fatal (_("invalid -mlfence-before-ret= option: `%s'"),
> ++		  arg);
> ++      break;
> ++
> +     case OPTION_MRELAX_RELOCATIONS:
> +       if (strcasecmp (arg, "yes") == 0)
> +         generate_relax_relocations = 1;
> +@@ -13025,6 +13370,15 @@ md_show_usage (FILE *stream)
> +   -mbranches-within-32B-boundaries\n\
> +                           align branches within 32 byte boundary\n"));
> +   fprintf (stream, _("\
> ++  -mlfence-after-load=[no|yes] (default: no)\n\
> ++                          generate lfence after load\n"));
> ++  fprintf (stream, _("\
> ++  -mlfence-before-indirect-branch=[none|all|register|memory] (default: none)\n\
> ++                          generate lfence before indirect near branch\n"));
> ++  fprintf (stream, _("\
> ++  -mlfence-before-ret=[none|or|not] (default: none)\n\
> ++                          generate lfence before ret\n"));
> ++  fprintf (stream, _("\
> +   -mamd64                 accept only AMD64 ISA [default]\n"));
> +   fprintf (stream, _("\
> +   -mintel64               accept only Intel64 ISA\n"));
> +@@ -13254,6 +13608,16 @@ i386_cons_align (int ignore ATTRIBUTE_UNUSED)
> +       last_insn.kind = last_insn_directive;
> +       last_insn.name = "constant directive";
> +       last_insn.file = as_where (&last_insn.line);
> ++      if (lfence_before_ret != lfence_before_ret_none)
> ++	{
> ++	  if (lfence_before_indirect_branch != lfence_branch_none)
> ++	    as_warn (_("constant directive skips -mlfence-before-ret "
> ++		       "and -mlfence-before-indirect-branch"));
> ++	  else
> ++	    as_warn (_("constant directive skips -mlfence-before-ret"));
> ++	}
> ++      else if (lfence_before_indirect_branch != lfence_branch_none)
> ++	as_warn (_("constant directive skips -mlfence-before-indirect-branch"));
> +     }
> + }
> +
> +diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
> +index c536759cb38..1dd99f91bb0 100644
> +--- a/gas/doc/c-i386.texi
> ++++ b/gas/doc/c-i386.texi
> +@@ -464,6 +464,49 @@ on an instruction.  It is equivalent to
> + @option{-malign-branch-prefix-size=5}.
> + The default doesn't align branches.
> +
> ++ at cindex @samp{-mlfence-after-load=} option, i386
> ++ at cindex @samp{-mlfence-after-load=} option, x86-64
> ++ at item -mlfence-after-load=@var{no}
> ++ at itemx -mlfence-after-load=@var{yes}
> ++These options control whether the assembler should generate lfence
> ++after load instructions.  @option{-mlfence-after-load=@var{yes}} will
> ++generate lfence.  @option{-mlfence-after-load=@var{no}} will not generate
> ++lfence, which is the default.
> ++
> ++ at cindex @samp{-mlfence-before-indirect-branch=} option, i386
> ++ at cindex @samp{-mlfence-before-indirect-branch=} option, x86-64
> ++ at item -mlfence-before-indirect-branch=@var{none}
> ++ at item -mlfence-before-indirect-branch=@var{all}
> ++ at item -mlfence-before-indirect-branch=@var{register}
> ++ at itemx -mlfence-before-indirect-branch=@var{memory}
> ++These options control whether the assembler should generate lfence
> ++after indirect near branch instructions.
> ++ at option{-mlfence-before-indirect-branch=@var{all}} will generate lfence
> ++after indirect near branch via register and issue a warning before
> ++indirect near branch via memory.
> ++ at option{-mlfence-before-indirect-branch=@var{register}} will generate
> ++lfence after indirect near branch via register.
> ++ at option{-mlfence-before-indirect-branch=@var{memory}} will issue a
> ++warning before indirect near branch via memory.
> ++ at option{-mlfence-before-indirect-branch=@var{none}} will not generate
> ++lfence nor issue warning, which is the default.  Note that lfence won't
> ++be generated before indirect near branch via register with
> ++ at option{-mlfence-after-load=@var{yes}} since lfence will be generated
> ++after loading branch target register.
> ++
> ++ at cindex @samp{-mlfence-before-ret=} option, i386
> ++ at cindex @samp{-mlfence-before-ret=} option, x86-64
> ++ at item -mlfence-before-ret=@var{none}
> ++ at item -mlfence-before-ret=@var{or}
> ++ at itemx -mlfence-before-ret=@var{not}
> ++These options control whether the assembler should generate lfence
> ++before ret.  @option{-mlfence-before-ret=@var{or}} will generate
> ++generate or instruction with lfence.
> ++ at option{-mlfence-before-ret=@var{not}} will generate not instruction
> ++with lfence.
> ++ at option{-mlfence-before-ret=@var{none}} will not generate lfence,
> ++which is the default.
> ++
> + @cindex @samp{-mx86-used-note=} option, i386
> + @cindex @samp{-mx86-used-note=} option, x86-64
> + @item -mx86-used-note=@var{no}
> +--
> +2.18.2
> 


More information about the Openembedded-core mailing list