Unlike the WRMSR side, we can't use asm goto() unconditionally, because our
toolchain baseline doesn't support asm goto with outputs.

Detect support, and use asm goto() when available.

Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com>
---
CC: Jan Beulich <jbeul...@suse.com>
CC: Roger Pau Monné <roger....@citrix.com>

Condensing these two to a single Kconfig symbol is prohibitively difficult.

Also, there's a different errata workaround we'll need if we want to use asm
goto() with "+" constraints:

config CC_HAS_ASM_GOTO_TIED_OUTPUT
        depends on CC_HAS_ASM_GOTO_OUTPUT
        # Detect buggy gcc and clang, fixed in gcc-11 clang-14.
        def_bool $(success,echo 'int foo(int *x) { asm goto (".long (%l[bar]) - 
.": "+m"(*x) ::: bar); return *x; bar: return 0; }' | $CC -x c - -c -o 
/dev/null)

I'm tempted to put it in straight away, lest we forget about it.
---
 xen/Kconfig            | 14 ++++++++++++++
 xen/arch/x86/cpu/amd.c | 13 +++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/xen/Kconfig b/xen/Kconfig
index 2128f0ccfc0b..a367337cafa5 100644
--- a/xen/Kconfig
+++ b/xen/Kconfig
@@ -41,6 +41,20 @@ config CC_SPLIT_SECTIONS
 config CC_HAS_UBSAN
        def_bool $(cc-option,-fsanitize=undefined)
 
+# Fixed in GCC 14, 13.3, 12.4 and 11.5
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
+config GCC_ASM_GOTO_OUTPUT_BROKEN
+       bool
+       depends on CC_IS_GCC
+       default y if GCC_VERSION < 110500
+       default y if GCC_VERSION >= 120000 && GCC_VERSION < 120400
+       default y if GCC_VERSION >= 130000 && GCC_VERSION < 130300
+
+config CC_HAS_ASM_GOTO_OUTPUT
+       def_bool y
+       depends on !GCC_ASM_GOTO_OUTPUT_BROKEN
+       depends on $(success,echo 'int foo(int x) { asm goto ("": "=r"(x) ::: 
bar); return x; bar: return 0; }' | $(CC) -x c - -c -o /dev/null)
+
 # Set code alignment.
 #
 # Allow setting on a boolean basis, and then convert such selection to an
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index ce4e1df71064..37d67dd15c89 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -59,6 +59,18 @@ static bool __read_mostly fam17_c6_disabled;
 static inline int rdmsr_amd_safe(unsigned int msr, unsigned int *lo,
                                 unsigned int *hi)
 {
+#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+    asm goto ( "1: rdmsr\n\t"
+               _ASM_EXTABLE(1b, %l[fault])
+               : "=a" (*lo), "=d" (*hi)
+               : "c" (msr), "D" (0x9c5a203a)
+               :
+               : fault );
+    return 0;
+
+ fault:
+    return -EFAULT;
+#else
        int err;
 
        asm volatile("1: rdmsr\n2:\n"
@@ -71,6 +83,7 @@ static inline int rdmsr_amd_safe(unsigned int msr, unsigned 
int *lo,
                     : "c" (msr), "D" (0x9c5a203a), "2" (0), "i" (-EFAULT));
 
        return err;
+#endif
 }
 
 static inline int wrmsr_amd_safe(unsigned int msr, unsigned int lo,

base-commit: a235f856e4bbd270b085590e1f5fc9599234dcdf
prerequisite-patch-id: 2874d23382cbbc2ec8eaad596b6f49f14b990b8a
prerequisite-patch-id: fdc7cdec843e4d24fc64006c977fa83a55d98910
-- 
2.39.5


Reply via email to