From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: "Andrew Cooper" <andrew.cooper3@citrix.com>,
"Jan Beulich" <JBeulich@suse.com>,
"Roger Pau Monné" <roger.pau@citrix.com>, "Wei Liu" <wl@xen.org>
Subject: [PATCH] x86/nospec: Fix evaluate_nospec() code generation under Clang
Date: Mon, 25 Apr 2022 18:56:03 +0100 [thread overview]
Message-ID: <20220425175603.21086-1-andrew.cooper3@citrix.com> (raw)
It turns out that evaluate_nospec() code generation is not safe under Clang.
Given:
void eval_nospec_test(int x)
{
if ( evaluate_nospec(x) )
asm volatile ("nop #true" ::: "memory");
else
asm volatile ("nop #false" ::: "memory");
}
Clang emits:
<eval_nospec_test>:
0f ae e8 lfence
85 ff test %edi,%edi
74 02 je <eval_nospec_test+0x9>
90 nop
c3 ret
90 nop
c3 ret
which is not safe because the lfence has been hoisted above the conditional
jump. Clang concludes that both barrier_nospec_true()'s have identical side
effects and can safely be merged.
Clang can be persuaded that the side effects are different if there are
different comments in the asm blocks. This is fragile, but no more fragile
that other aspects of this construct.
Introduce barrier_nospec_false() with a separate internal comment to prevent
Clang merging it with barrier_nospec_true() despite the otherwise-identical
content. The generated code now becomes:
<eval_nospec_test>:
85 ff test %edi,%edi
74 05 je <eval_nospec_test+0x9>
0f ae e8 lfence
90 nop
c3 ret
0f ae e8 lfence
90 nop
c3 ret
which has the correct number of lfence's, and in the correct place.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>
---
xen/arch/x86/include/asm/nospec.h | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/include/asm/nospec.h b/xen/arch/x86/include/asm/nospec.h
index 5312ae4c6f31..7150e76b87fb 100644
--- a/xen/arch/x86/include/asm/nospec.h
+++ b/xen/arch/x86/include/asm/nospec.h
@@ -10,15 +10,26 @@
static always_inline bool barrier_nospec_true(void)
{
#ifdef CONFIG_SPECULATIVE_HARDEN_BRANCH
- alternative("lfence", "", X86_FEATURE_SC_NO_BRANCH_HARDEN);
+ alternative("lfence #nospec-true", "", X86_FEATURE_SC_NO_BRANCH_HARDEN);
#endif
return true;
}
+static always_inline bool barrier_nospec_false(void)
+{
+#ifdef CONFIG_SPECULATIVE_HARDEN_BRANCH
+ alternative("lfence #nospec-false", "", X86_FEATURE_SC_NO_BRANCH_HARDEN);
+#endif
+ return false;
+}
+
/* Allow to protect evaluation of conditionals with respect to speculation */
static always_inline bool evaluate_nospec(bool condition)
{
- return condition ? barrier_nospec_true() : !barrier_nospec_true();
+ if ( condition )
+ return barrier_nospec_true();
+ else
+ return barrier_nospec_false();
}
/* Allow to block speculative execution in generic code */
--
2.11.0
next reply other threads:[~2022-04-25 17:56 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-25 17:56 Andrew Cooper [this message]
2022-04-26 6:43 ` [PATCH] x86/nospec: Fix evaluate_nospec() code generation under Clang Jan Beulich
2022-04-26 7:18 ` Roger Pau Monné
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220425175603.21086-1-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=roger.pau@citrix.com \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.