/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef CPU_X86_MSR_ACCESS_H #define CPU_X86_MSR_ACCESS_H #ifndef __ASSEMBLER__ #include <types.h> typedef union msr_union { struct { unsigned int lo; unsigned int hi; }; uint64_t raw; } msr_t; _Static_assert(sizeof(msr_t) == sizeof(uint64_t), "Incorrect size for msr_t"); #if CONFIG(SOC_SETS_MSRS) msr_t soc_msr_read(unsigned int index); void soc_msr_write(unsigned int index, msr_t msr); /* Handle MSR references in the other source code */ static __always_inline msr_t rdmsr(unsigned int index) { return soc_msr_read(index); } static __always_inline void wrmsr(unsigned int index, msr_t msr) { soc_msr_write(index, msr); } #else /* CONFIG_SOC_SETS_MSRS */ /* The following functions require the __always_inline due to AMD * function STOP_CAR_AND_CPU that disables cache as * RAM, the cache as RAM stack can no longer be used. Called * functions must be inlined to avoid stack usage. Also, the * compiler must keep local variables register based and not * allocated them from the stack. With gcc 4.5.0, some functions * declared as inline are not being inlined. This patch forces * these functions to always be inlined by adding the qualifier * __always_inline to their declaration. */ static __always_inline msr_t rdmsr(unsigned int index) { msr_t result; __asm__ __volatile__ ( "rdmsr" : "=a" (result.lo), "=d" (result.hi) : "c" (index) ); return result; } static __always_inline void wrmsr(unsigned int index, msr_t msr) { __asm__ __volatile__ ( "wrmsr" : /* No outputs */ : "c" (index), "a" (msr.lo), "d" (msr.hi) ); } #endif /* CONFIG_SOC_SETS_MSRS */ #endif /* __ASSEMBLER__ */ #endif /* CPU_X86_MSR_ACCESS_H */