From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id UP/1FFuZcWL8GAQAWB0awg (envelope-from ) for ; Tue, 03 May 2022 17:06:35 -0400 Received: by simark.ca (Postfix, from userid 112) id 530BD1E058; Tue, 3 May 2022 17:06:35 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI, RDNS_DYNAMIC,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 88C6D1E00E for ; Tue, 3 May 2022 17:06:34 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B682C385780F for ; Tue, 3 May 2022 21:06:33 +0000 (GMT) Received: from mail.baldwin.cx (bigwig.baldwin.cx [66.216.25.90]) by sourceware.org (Postfix) with ESMTPS id 3E0723858C51 for ; Tue, 3 May 2022 21:06:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3E0723858C51 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=FreeBSD.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=FreeBSD.org Received: from ralph.com (ralph.baldwin.cx [66.234.199.215]) by mail.baldwin.cx (Postfix) with ESMTPSA id 3C30D1A84C5E; Tue, 3 May 2022 17:06:08 -0400 (EDT) From: John Baldwin To: gdb-patches@sourceware.org Subject: [PATCH v3 01/13] x86: Add an x86_xsave_layout structure to handle variable XSAVE layouts. Date: Tue, 3 May 2022 14:05:03 -0700 Message-Id: <20220503210515.30739-2-jhb@FreeBSD.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220503210515.30739-1-jhb@FreeBSD.org> References: <20220503210515.30739-1-jhb@FreeBSD.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (mail.baldwin.cx [0.0.0.0]); Tue, 03 May 2022 17:06:08 -0400 (EDT) X-Virus-Scanned: clamav-milter 0.103.1 at mail.baldwin.cx X-Virus-Status: Clean X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "George, Jini Susan" , Aleksandar Paunovic Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" The standard layout of the XSAVE extended state area consists of three regions. The first 512 bytes (legacy region) match the layout of the FXSAVE instruction including floating point registers, MMX registers, and SSE registers. The next 64 bytes (XSAVE header) contains a header with a fixed layout. The final region (extended region) contains zero or more optional state components. Examples of these include the upper 128 bits of YMM registers for AVX. These optional state components generally have an architecturally-fixed size, but they are not assigned architectural offsets in the extended region. Instead, processors provide additional CPUID leafs describing the size and offset of each component in the "standard" layout for a given CPU. (There is also a "compact" format which uses an alternate layout, but existing OS's currently export the "standard" layout when exporting XSAVE data via ptrace() and core dumps.) To date, GDB has assumed the layout used on current Intel processors for state components in the extended region and hardcoded those offsets in the tables in i387-tdep.c and i387-fp.cc. However, this fails on recent AMD processors which use a different layout. Specifically, AMD Ryzen 9 processors at least do not leave space for the MPX register set in between the AVX and AVX512 register sets. It is not known if other AMD processors are effected, but seems probable. To rectify this, add an x86_xsave_layout structure which contains the total size of the XSAVE extended state area as well as the offset of each known optional state component. This structure is stored in i386_gdbarch_tdep and is fetched from the current target in i386_gdbarch_init as a TARGET_OBJECT_X86_XSAVE_LAYOUT object. Subsequent commits will modify XSAVE parsing to use x86_xsave_layout. Co-authored-by: Aleksandar Paunovic --- gdb/i386-tdep.c | 36 +++++++++++++++++++++++++- gdb/i386-tdep.h | 3 +++ gdb/target.h | 2 ++ gdbsupport/x86-xstate.h | 57 +++++++++++++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 8501e12e241..be9c4c7e41e 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -8439,6 +8439,21 @@ i386_type_align (struct gdbarch *gdbarch, struct type *type) } +/* Fetch the XSAVE layout for the current target. */ + +static struct x86_xsave_layout +i386_fetch_xsave_layout () +{ + struct x86_xsave_layout layout; + LONGEST len = target_read (current_inferior ()->top_target (), + TARGET_OBJECT_X86_XSAVE_LAYOUT, nullptr, + (gdb_byte *) &layout, 0, sizeof (layout)); + if (len != sizeof (layout)) + return {}; + + return layout; +} + /* Note: This is called for both i386 and amd64. */ static struct gdbarch * @@ -8446,13 +8461,30 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; const struct target_desc *tdesc; + struct x86_xsave_layout xsave_layout; int mm0_regnum; int ymm0_regnum; int bnd0_regnum; int num_bnd_cooked; + xsave_layout = i386_fetch_xsave_layout (); + /* If there is already a candidate, use it. */ - arches = gdbarch_list_lookup_by_info (arches, &info); + for (arches = gdbarch_list_lookup_by_info (arches, &info); + arches != NULL; + arches = gdbarch_list_lookup_by_info (arches->next, &info)) + { + /* Check that the XSAVE layout of ARCHES matches the layout for + the current target. */ + i386_gdbarch_tdep *other_tdep + = (i386_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch); + + if (other_tdep->xsave_layout != xsave_layout) + continue; + + break; + } + if (arches != NULL) return arches->gdbarch; @@ -8705,6 +8737,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdbarch_free (gdbarch); return NULL; } + if (tdep->xcr0 != 0) + tdep->xsave_layout = xsave_layout; num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0); diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index a8067cf6b6c..a2c66ecfed1 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -23,6 +23,7 @@ #include "gdbarch.h" #include "infrun.h" #include "expression.h" +#include "gdbsupport/x86-xstate.h" struct frame_info; struct gdbarch; @@ -145,6 +146,8 @@ struct i386_gdbarch_tdep : gdbarch_tdep /* Offset of XCR0 in XSAVE extended state. */ int xsave_xcr0_offset = 0; + x86_xsave_layout xsave_layout; + /* Register names. */ const char * const *register_names = nullptr; diff --git a/gdb/target.h b/gdb/target.h index f77dbf05113..a5ec3bba496 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -204,6 +204,8 @@ enum target_object TARGET_OBJECT_FREEBSD_VMMAP, /* FreeBSD process strings. */ TARGET_OBJECT_FREEBSD_PS_STRINGS, + /* x86 XSAVE area layout. */ + TARGET_OBJECT_X86_XSAVE_LAYOUT, /* Possible future objects: TARGET_OBJECT_FILE, ... */ }; diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h index d4845243b4b..9e2dd2155be 100644 --- a/gdbsupport/x86-xstate.h +++ b/gdbsupport/x86-xstate.h @@ -20,23 +20,64 @@ #ifndef COMMON_X86_XSTATE_H #define COMMON_X86_XSTATE_H +/* The extended state feature IDs in the state component bitmap. */ +#define X86_XSTATE_X87_ID 0 +#define X86_XSTATE_SSE_ID 1 +#define X86_XSTATE_AVX_ID 2 +#define X86_XSTATE_BNDREGS_ID 3 +#define X86_XSTATE_BNDCFG_ID 4 +#define X86_XSTATE_K_ID 5 +#define X86_XSTATE_ZMM_H_ID 6 +#define X86_XSTATE_ZMM_ID 7 +#define X86_XSTATE_PT_ID 8 +#define X86_XSTATE_PKRU_ID 9 + /* The extended state feature bits. */ -#define X86_XSTATE_X87 (1ULL << 0) -#define X86_XSTATE_SSE (1ULL << 1) -#define X86_XSTATE_AVX (1ULL << 2) -#define X86_XSTATE_BNDREGS (1ULL << 3) -#define X86_XSTATE_BNDCFG (1ULL << 4) +#define X86_XSTATE_X87 (1ULL << X86_XSTATE_X87_ID) +#define X86_XSTATE_SSE (1ULL << X86_XSTATE_SSE_ID) +#define X86_XSTATE_AVX (1ULL << X86_XSTATE_AVX_ID) +#define X86_XSTATE_BNDREGS (1ULL << X86_XSTATE_BNDREGS_ID) +#define X86_XSTATE_BNDCFG (1ULL << X86_XSTATE_BNDCFG_ID) #define X86_XSTATE_MPX (X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG) /* AVX 512 adds three feature bits. All three must be enabled. */ -#define X86_XSTATE_K (1ULL << 5) -#define X86_XSTATE_ZMM_H (1ULL << 6) -#define X86_XSTATE_ZMM (1ULL << 7) +#define X86_XSTATE_K (1ULL << X86_XSTATE_K_ID) +#define X86_XSTATE_ZMM_H (1ULL << X86_XSTATE_ZMM_H_ID) +#define X86_XSTATE_ZMM (1ULL << X86_XSTATE_ZMM_ID) #define X86_XSTATE_AVX512 (X86_XSTATE_K | X86_XSTATE_ZMM_H \ | X86_XSTATE_ZMM) #define X86_XSTATE_PKRU (1ULL << 9) +/* Size and offsets of register states in the XSAVE area extended + region. Offsets are set to 0 to indicate the absence of the + associated registers. */ + +struct x86_xsave_layout +{ + int sizeof_xsave = 0; + int avx_offset = 0; + int bndregs_offset = 0; + int bndcfg_offset = 0; + int k_offset = 0; + int zmm_h_offset = 0; + int zmm_offset = 0; + int pkru_offset = 0; + + bool operator!= (const x86_xsave_layout &other) + { + return sizeof_xsave != other.sizeof_xsave + || avx_offset != other.avx_offset + || bndregs_offset != other.bndregs_offset + || bndcfg_offset != other.bndcfg_offset + || k_offset != other.k_offset + || zmm_h_offset != other.zmm_h_offset + || zmm_offset != other.zmm_offset + || pkru_offset != other.pkru_offset; + } +}; + + /* Supported mask and size of the extended state. */ #define X86_XSTATE_X87_MASK X86_XSTATE_X87 #define X86_XSTATE_SSE_MASK (X86_XSTATE_X87 | X86_XSTATE_SSE) -- 2.34.1