Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Jan 2012 07:30:37 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r230262 - head/sys/amd64/include
Message-ID:  <201201170730.q0H7UbGJ073270@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Jan 17 07:30:36 2012
New Revision: 230262
URL: http://svn.freebsd.org/changeset/base/230262

Log:
  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

Modified:
  head/sys/amd64/include/cpufunc.h

Modified: head/sys/amd64/include/cpufunc.h
==============================================================================
--- head/sys/amd64/include/cpufunc.h	Tue Jan 17 07:23:43 2012	(r230261)
+++ head/sys/amd64/include/cpufunc.h	Tue Jan 17 07:30:36 2012	(r230262)
@@ -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 */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201170730.q0H7UbGJ073270>