On 18/08/2025 12:27 pm, Jan Beulich wrote: > On 15.08.2025 22:41, Andrew Cooper wrote: >> ... on capable toolchains. >> >> This avoids needing to hold rc in a register across the RDMSR, and in most >> cases removes direct testing and branching based on rc, as the fault label >> can >> be rearranged to directly land on the out-of-line block. >> >> There is a subtle difference in behaviour. The old behaviour would, on >> fault, >> still produce 0's and write to val. >> >> The new behaviour only writes val on success, and write_msr() is the only >> place where this matters. Move temp out of switch() scope and initialise it >> to 0. > But what's the motivation behind making this behavioral change? At least in > the cases where the return value isn't checked, it would feel safer if we > continued clearing the value. Even if in all cases where this could matter > (besides the one you cover here) one can prove correctness by looking at > surrounding code.
I didn't realise I'd made a change at first, but it's a consequence of the compiler's ability to rearrange basic blocks. It can be fixed with ... > >> --- a/xen/arch/x86/include/asm/msr.h >> +++ b/xen/arch/x86/include/asm/msr.h >> @@ -55,6 +55,24 @@ static inline void wrmsrns(uint32_t msr, uint64_t val) >> /* rdmsr with exception handling */ >> static inline int rdmsr_safe(unsigned int msr, uint64_t *val) >> { >> +#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT >> + uint64_t lo, hi; >> + asm_inline goto ( >> + "1: rdmsr\n\t" >> + _ASM_EXTABLE(1b, %l[fault]) >> + : "=a" (lo), "=d" (hi) >> + : "c" (msr) >> + : >> + : fault ); >> + >> + *val = lo | (hi << 32); >> + >> + return 0; >> + >> + fault: *val = 0; here, but I don't want to do this. Because val is by pointer and generally spilled to the stack, the compiler can't optimise away the store. I'd far rather get a real compiler error, than to have logic relying on the result of a faulting MSR read. >> + return -EFAULT; >> +#else >> int rc; >> uint64_t lo, hi; > ... the same being needed here? Fixed. ~Andrew