From 6a34de7c5a0e59d6349ce628792e19d793eeb2b4 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 17 Jan 2012 07:30:36 +0000 Subject: [PATCH] Implement xsetbv(), xsave() and xrstor() providing C access to the similarly named CPU instructions. Since our in-tree binutils gas is not aware of the instructions, and I have to use the byte-sequence to encode them, hardcode the r/m operand as (%rdi). This way, first argument of the pseudo-function is already placed into proper register. MFC after: 1 week --- sys/amd64/include/cpufunc.h | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index c07e09b1061b..9b147c70b62a 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -669,6 +669,41 @@ intr_restore(register_t rflags) write_rflags(rflags); } +static __inline void +xsetbv(uint32_t reg, uint64_t val) +{ + uint32_t low, hi; + + low = val; + hi = val >> 32; + __asm __volatile(".byte 0x0f,0x01,0xd1" : : + "c" (reg), "a" (low), "d" (hi)); +} + +static __inline void +xsave(char *addr, uint64_t mask) +{ + uint32_t low, hi; + + low = mask; + hi = mask >> 32; + /* xsave (%rdi) */ + __asm __volatile(".byte 0x0f,0xae,0x27" : : + "a" (low), "d" (hi), "D" (addr) : "memory"); +} + +static __inline void +xrstor(char *addr, uint64_t mask) +{ + uint32_t low, hi; + + low = mask; + hi = mask >> 32; + /* xrstor (%rdi) */ + __asm __volatile(".byte 0x0f,0xae,0x2f" : : + "a" (low), "d" (hi), "D" (addr)); +} + #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ int breakpoint(void); @@ -733,6 +768,9 @@ u_int rgs(void); void wbinvd(void); void write_rflags(u_int rf); void wrmsr(u_int msr, uint64_t newval); +void xsetbv(uint32_t reg, uint64_t val); +void xsave(char *addr, uint64_t mask); +void xrstor(char *addr, uint64_t mask); #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */