This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Add common files for x86 XSAVE extended state


Hi,

This patch adds common files for x86 XSAVE extended state. They
are used by native x86 gdb and gdbserver to discover x86 XSAVE
extended state support. You can see IA32/Intel64 SDM at

http://developer.intel.com/products/processor/manuals/index.htm

for details. OK to install?

Thanks.


H.J.
---
2010-03-02  H.J. Lu  <hongjiu.lu@intel.com>

	* common/i386-cpuid.h: New.
	* common/i386-xstate.c: Likewise.
	* common/i386-xstate.h: Likewise.

diff --git a/gdb/common/i386-cpuid.h b/gdb/common/i386-cpuid.h
new file mode 100644
index 0000000..3228414
--- /dev/null
+++ b/gdb/common/i386-cpuid.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3, or (at your option) any
+ * later version.
+ * 
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ * 
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/* %ecx */
+#define bit_SSE3	(1 << 0)
+#define bit_PCLMUL	(1 << 1)
+#define bit_SSSE3	(1 << 9)
+#define bit_FMA		(1 << 12)
+#define bit_CMPXCHG16B	(1 << 13)
+#define bit_SSE4_1	(1 << 19)
+#define bit_SSE4_2	(1 << 20)
+#define bit_MOVBE	(1 << 22)
+#define bit_POPCNT	(1 << 23)
+#define bit_AES		(1 << 25)
+#define bit_XSAVE	(1 << 26)
+#define bit_OSXSAVE	(1 << 27)
+#define bit_AVX		(1 << 28)
+
+/* %edx */
+#define bit_CMPXCHG8B	(1 << 8)
+#define bit_CMOV	(1 << 15)
+#define bit_MMX		(1 << 23)
+#define bit_FXSAVE	(1 << 24)
+#define bit_SSE		(1 << 25)
+#define bit_SSE2	(1 << 26)
+
+/* Extended Features */
+/* %ecx */
+#define bit_LAHF_LM	(1 << 0)
+#define bit_ABM		(1 << 5)
+#define bit_SSE4a	(1 << 6)
+#define bit_XOP         (1 << 11)
+#define bit_LWP 	(1 << 15)
+#define bit_FMA4        (1 << 16)
+
+/* %edx */
+#define bit_LM		(1 << 29)
+#define bit_3DNOWP	(1 << 30)
+#define bit_3DNOW	(1 << 31)
+
+
+#if defined(__i386__) && defined(__PIC__)
+/* %ebx may be the PIC register.  */
+#if __GNUC__ >= 3
+#define __cpuid(level, a, b, c, d)			\
+  __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"			\
+	   "cpuid\n\t"					\
+	   "xchg{l}\t{%%}ebx, %1\n\t"			\
+	   : "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level))
+
+#define __cpuid_count(level, count, a, b, c, d)		\
+  __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"			\
+	   "cpuid\n\t"					\
+	   "xchg{l}\t{%%}ebx, %1\n\t"			\
+	   : "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level), "2" (count))
+#else
+/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
+   nor alternatives in i386 code.  */
+#define __cpuid(level, a, b, c, d)			\
+  __asm__ ("xchgl\t%%ebx, %1\n\t"			\
+	   "cpuid\n\t"					\
+	   "xchgl\t%%ebx, %1\n\t"			\
+	   : "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level))
+
+#define __cpuid_count(level, count, a, b, c, d)		\
+  __asm__ ("xchgl\t%%ebx, %1\n\t"			\
+	   "cpuid\n\t"					\
+	   "xchgl\t%%ebx, %1\n\t"			\
+	   : "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level), "2" (count))
+#endif
+#else
+#define __cpuid(level, a, b, c, d)			\
+  __asm__ ("cpuid\n\t"					\
+	   : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level))
+
+#define __cpuid_count(level, count, a, b, c, d)		\
+  __asm__ ("cpuid\n\t"					\
+	   : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level), "2" (count))
+#endif
+
+/* Return highest supported input value for cpuid instruction.  ext can
+   be either 0x0 or 0x8000000 to return highest supported value for
+   basic or extended cpuid information.  Function returns 0 if cpuid
+   is not supported or whatever cpuid returns in eax register.  If sig
+   pointer is non-null, then first four bytes of the signature
+   (as found in ebx register) are returned in location pointed by sig.  */
+
+static __inline unsigned int
+__get_cpuid_max (unsigned int __ext, unsigned int *__sig)
+{
+  unsigned int __eax, __ebx, __ecx, __edx;
+
+#ifndef __x86_64__
+#if __GNUC__ >= 3
+  /* See if we can use cpuid.  On AMD64 we always can.  */
+  __asm__ ("pushf{l|d}\n\t"
+	   "pushf{l|d}\n\t"
+	   "pop{l}\t%0\n\t"
+	   "mov{l}\t{%0, %1|%1, %0}\n\t"
+	   "xor{l}\t{%2, %0|%0, %2}\n\t"
+	   "push{l}\t%0\n\t"
+	   "popf{l|d}\n\t"
+	   "pushf{l|d}\n\t"
+	   "pop{l}\t%0\n\t"
+	   "popf{l|d}\n\t"
+	   : "=&r" (__eax), "=&r" (__ebx)
+	   : "i" (0x00200000));
+#else
+/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
+   nor alternatives in i386 code.  */
+  __asm__ ("pushfl\n\t"
+	   "pushfl\n\t"
+	   "popl\t%0\n\t"
+	   "movl\t%0, %1\n\t"
+	   "xorl\t%2, %0\n\t"
+	   "pushl\t%0\n\t"
+	   "popfl\n\t"
+	   "pushfl\n\t"
+	   "popl\t%0\n\t"
+	   "popfl\n\t"
+	   : "=&r" (__eax), "=&r" (__ebx)
+	   : "i" (0x00200000));
+#endif
+
+  if (!((__eax ^ __ebx) & 0x00200000))
+    return 0;
+#endif
+
+  /* Host supports cpuid.  Return highest supported cpuid input value.  */
+  __cpuid (__ext, __eax, __ebx, __ecx, __edx);
+
+  if (__sig)
+    *__sig = __ebx;
+
+  return __eax;
+}
+
+/* Return cpuid data for requested cpuid level, as found in returned
+   eax, ebx, ecx and edx registers.  The function checks if cpuid is
+   supported and returns 1 for valid cpuid information or 0 for
+   unsupported cpuid level.  All pointers are required to be non-null.  */
+
+static __inline int
+__get_cpuid (unsigned int __level,
+	     unsigned int *__eax, unsigned int *__ebx,
+	     unsigned int *__ecx, unsigned int *__edx)
+{
+  unsigned int __ext = __level & 0x80000000;
+
+  if (__get_cpuid_max (__ext, 0) < __level)
+    return 0;
+
+  __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
+  return 1;
+}
diff --git a/gdb/common/i386-xstate.c b/gdb/common/i386-xstate.c
new file mode 100644
index 0000000..a4d17e7
--- /dev/null
+++ b/gdb/common/i386-xstate.c
@@ -0,0 +1,92 @@
+/* Common code for i386 XSAVE extended state.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef XSTATE_MAIN
+#include <stdio.h>
+#else
+#include "config.h"
+#endif
+
+#ifdef HAVE_CPUID_H
+#include <cpuid.h>
+#else
+#include "i386-cpuid.h"
+#endif
+
+#include "i386-xstate.h"
+
+struct i386_xstate_type i386_xstate;
+
+void
+i386_xstate_init (void)
+{
+  unsigned int eax, ebx, ecx, edx, eax_mask, edx_mask, size;
+
+  if (i386_xstate.status != XSTATE_UNKNOWN)
+    return;
+
+  i386_xstate.status = XSTATE_UNSUPPORTED;
+
+  if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+    return;
+
+  if (!(ecx & bit_OSXSAVE))
+    return;
+
+  i386_xstate.status = XSTATE_INITIALIZED;
+
+  /* Get enabled extended state save area size.  */
+  __cpuid_count (0xd, 0, eax_mask, size, ecx, edx_mask);
+  i386_xstate.size = size;
+  i386_xstate.n_of_int64
+    = (size + sizeof (long long) - 1) / sizeof (long long);
+
+  /* Get XCR0, the XFEATURE_ENABLED_MASK register.  */
+  __asm__ ("xgetbv\n\t" : "=a" (eax), "=d" (edx) : "c" (0));
+  i386_xstate.xcr0 = (((unsigned long long) (edx & edx_mask) << 32)
+		      | (eax & eax_mask));
+}
+
+#ifdef XSTATE_MAIN
+
+int
+main ()
+{
+  i386_xstate_init ();
+
+  if (i386_xstate.status == XSTATE_UNSUPPORTED)
+    {
+      printf ("XSAVE extended state is unsupported\n");
+      return 0;
+    }
+
+  printf ("XSAVE extended state size: %d bytes\n", i386_xstate.size);
+  printf ("XSAVE extended state enabled:");
+  if ((i386_xstate.xcr0 & bit_XSTATE_X87))
+    fputs (" X87", stdout);
+  if ((i386_xstate.xcr0 & bit_XSTATE_SSE))
+    fputs (" SSE", stdout);
+  if ((i386_xstate.xcr0 & bit_XSTATE_AVX))
+    fputs (" AVX", stdout);
+  fputs ("\n", stdout);
+
+  return 0;
+}
+
+#endif /* XSTATE_MAIN */
diff --git a/gdb/common/i386-xstate.h b/gdb/common/i386-xstate.h
new file mode 100644
index 0000000..75cdc1e
--- /dev/null
+++ b/gdb/common/i386-xstate.h
@@ -0,0 +1,73 @@
+/* Common code for i386 XSAVE extended state.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef I386_XSTATE_H
+#define I386_XSTATE_H 1
+
+/* XSAVE extended state information.  */
+
+/* The extended state status.  */
+enum xstate_status
+{
+  XSTATE_UNKNOWN = 0,
+  XSTATE_UNSUPPORTED,
+  XSTATE_INITIALIZED
+};
+
+/* The extended state feature bits.  */
+#define bit_XSTATE_X87		(1ULL << 0)
+#define bit_XSTATE_SSE		(1ULL << 1)
+#define bit_XSTATE_AVX		(1ULL << 2)
+
+/* Supported mask and size of the extended state.  */
+#define XSTATE_SSE_MASK		(bit_XSTATE_X87 | bit_XSTATE_SSE)
+#define XSTATE_AVX_MASK		(XSTATE_SSE_MASK | bit_XSTATE_AVX)
+#define XSTATE_MAX_MASK		XSTATE_AVX_MASK
+
+#define XSTATE_SSE_MASK_STRING	"0x3"
+#define XSTATE_AVX_MASK_STRING	"0x7"
+#define XSTATE_MAX_MASK_STRING	"0x7"
+
+#define XSTATE_SSE_SIZE		576
+#define XSTATE_AVX_SIZE		832
+#define XSTATE_MAX_SIZE		832
+
+#define XSTATE_SSE_SIZE_STRING	"576"
+#define XSTATE_AVX_SIZE_STRING	"832"
+#define XSTATE_MAX_SIZE_STRING	"832"
+
+struct i386_xstate_type
+  {
+    /* The extended state status.  */
+    enum xstate_status status;
+    /* The extended control register 0 (the XFEATURE_ENABLED_MASK
+       register).  */
+    unsigned long long xcr0;
+    /* The extended state size in bytes.  */
+    unsigned int size;
+    /* The extended state size in unit of int64.  We use array of
+       int64 for better alignment.  */
+    unsigned int n_of_int64;
+  };
+
+extern struct i386_xstate_type i386_xstate;
+
+extern void i386_xstate_init (void);
+
+#endif /* I386_XSTATE_H */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]