summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0021-x86-altcall-use-a-union-as-register-type-for-functio.patch')
-rw-r--r--0021-x86-altcall-use-a-union-as-register-type-for-functio.patch141
1 files changed, 0 insertions, 141 deletions
diff --git a/0021-x86-altcall-use-a-union-as-register-type-for-functio.patch b/0021-x86-altcall-use-a-union-as-register-type-for-functio.patch
deleted file mode 100644
index ab050dd..0000000
--- a/0021-x86-altcall-use-a-union-as-register-type-for-functio.patch
+++ /dev/null
@@ -1,141 +0,0 @@
-From 1aafe054e7d1efbf8e8482a9cdd4be5753b79e2f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
-Date: Tue, 27 Feb 2024 14:11:04 +0100
-Subject: [PATCH 21/67] x86/altcall: use a union as register type for function
- parameters on clang
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The current code for alternative calls uses the caller parameter types as the
-types for the register variables that serve as function parameters:
-
-uint8_t foo;
-[...]
-alternative_call(myfunc, foo);
-
-Would expand roughly into:
-
-register unint8_t a1_ asm("rdi") = foo;
-register unsigned long a2_ asm("rsi");
-[...]
-asm volatile ("call *%c[addr](%%rip)"...);
-
-However with -O2 clang will generate incorrect code, given the following
-example:
-
-unsigned int func(uint8_t t)
-{
- return t;
-}
-
-static void bar(uint8_t b)
-{
- int ret_;
- register uint8_t di asm("rdi") = b;
- register unsigned long si asm("rsi");
- register unsigned long dx asm("rdx");
- register unsigned long cx asm("rcx");
- register unsigned long r8 asm("r8");
- register unsigned long r9 asm("r9");
- register unsigned long r10 asm("r10");
- register unsigned long r11 asm("r11");
-
- asm volatile ( "call %c[addr]"
- : "+r" (di), "=r" (si), "=r" (dx),
- "=r" (cx), "=r" (r8), "=r" (r9),
- "=r" (r10), "=r" (r11), "=a" (ret_)
- : [addr] "i" (&(func)), "g" (func)
- : "memory" );
-}
-
-void foo(unsigned int a)
-{
- bar(a);
-}
-
-Clang generates the following assembly code:
-
-func: # @func
- movl %edi, %eax
- retq
-foo: # @foo
- callq func
- retq
-
-Note the truncation of the unsigned int parameter 'a' of foo() to uint8_t when
-passed into bar() is lost. clang doesn't zero extend the parameters in the
-callee when required, as the psABI mandates.
-
-The above can be worked around by using a union when defining the register
-variables, so that `di` becomes:
-
-register union {
- uint8_t e;
- unsigned long r;
-} di asm("rdi") = { .e = b };
-
-Which results in following code generated for `foo()`:
-
-foo: # @foo
- movzbl %dil, %edi
- callq func
- retq
-
-So the truncation is not longer lost. Apply such workaround only when built
-with clang.
-
-Reported-by: Matthew Grooms <mgrooms@shrew.net>
-Link: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277200
-Link: https://github.com/llvm/llvm-project/issues/12579
-Link: https://github.com/llvm/llvm-project/issues/82598
-Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
-Acked-by: Jan Beulich <jbeulich@suse.com>
-master commit: 2ce562b2a413cbdb2e1128989ed1722290a27c4e
-master date: 2024-02-26 10:18:01 +0100
----
- xen/arch/x86/include/asm/alternative.h | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
-
-diff --git a/xen/arch/x86/include/asm/alternative.h b/xen/arch/x86/include/asm/alternative.h
-index a7a82c2c03..bcb1dc94f4 100644
---- a/xen/arch/x86/include/asm/alternative.h
-+++ b/xen/arch/x86/include/asm/alternative.h
-@@ -167,9 +167,34 @@ extern void alternative_branches(void);
- #define ALT_CALL_arg5 "r8"
- #define ALT_CALL_arg6 "r9"
-
-+#ifdef CONFIG_CC_IS_CLANG
-+/*
-+ * Use a union with an unsigned long in order to prevent clang from
-+ * skipping a possible truncation of the value. By using the union any
-+ * truncation is carried before the call instruction, in turn covering
-+ * for ABI-non-compliance in that the necessary clipping / extension of
-+ * the value is supposed to be carried out in the callee.
-+ *
-+ * Note this behavior is not mandated by the standard, and hence could
-+ * stop being a viable workaround, or worse, could cause a different set
-+ * of code-generation issues in future clang versions.
-+ *
-+ * This has been reported upstream:
-+ * https://github.com/llvm/llvm-project/issues/12579
-+ * https://github.com/llvm/llvm-project/issues/82598
-+ */
-+#define ALT_CALL_ARG(arg, n) \
-+ register union { \
-+ typeof(arg) e; \
-+ unsigned long r; \
-+ } a ## n ## _ asm ( ALT_CALL_arg ## n ) = { \
-+ .e = ({ BUILD_BUG_ON(sizeof(arg) > sizeof(void *)); (arg); }) \
-+ }
-+#else
- #define ALT_CALL_ARG(arg, n) \
- register typeof(arg) a ## n ## _ asm ( ALT_CALL_arg ## n ) = \
- ({ BUILD_BUG_ON(sizeof(arg) > sizeof(void *)); (arg); })
-+#endif
- #define ALT_CALL_NO_ARG(n) \
- register unsigned long a ## n ## _ asm ( ALT_CALL_arg ## n )
-
---
-2.44.0
-