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