Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "H.J. Lu" <hongjiu.lu@intel.com>
To: GDB <gdb-patches@sourceware.org>
Subject: PATCH: Add common files for x86 XSAVE extended state
Date: Tue, 02 Mar 2010 15:28:00 -0000	[thread overview]
Message-ID: <20100302152826.GA28158@intel.com> (raw)

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 */


             reply	other threads:[~2010-03-02 15:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-02 15:28 H.J. Lu [this message]
2010-03-02 15:56 ` Mark Kettenis
2010-03-02 16:32   ` H.J. Lu
2010-03-02 19:47 ` H.J. Lu
2010-03-03 23:23   ` Mark Kettenis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100302152826.GA28158@intel.com \
    --to=hongjiu.lu@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=hjl.tools@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox