Commit c3056a7d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86-fpu-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fpu updates from Thomas Gleixner:
 "Provide FPU buffer layout in core dumps:

  Debuggers have guess the FPU buffer layout in core dumps, which is
  error prone. This is because AMD and Intel layouts differ.

  To avoid buggy heuristics add a ELF section which describes the buffer
  layout which can be retrieved by tools"

* tag 'x86-fpu-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/elf: Add a new FPU buffer layout info to x86 core files
parents dea435d3 ba386777
...@@ -107,6 +107,7 @@ config X86 ...@@ -107,6 +107,7 @@ config X86
select ARCH_HAS_DEBUG_WX select ARCH_HAS_DEBUG_WX
select ARCH_HAS_ZONE_DMA_SET if EXPERT select ARCH_HAS_ZONE_DMA_SET if EXPERT
select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_HAVE_EXTRA_ELF_NOTES
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_PARPORT
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_X86_ELF_H
#define _UAPI_ASM_X86_ELF_H
#include <linux/types.h>
struct x86_xfeat_component {
__u32 type;
__u32 size;
__u32 offset;
__u32 flags;
} __packed;
_Static_assert(sizeof(struct x86_xfeat_component) % 4 == 0, "x86_xfeat_component is not aligned");
#endif /* _UAPI_ASM_X86_ELF_H */
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/coredump.h>
#include <asm/fpu/api.h> #include <asm/fpu/api.h>
#include <asm/fpu/regset.h> #include <asm/fpu/regset.h>
...@@ -23,6 +24,8 @@ ...@@ -23,6 +24,8 @@
#include <asm/prctl.h> #include <asm/prctl.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <uapi/asm/elf.h>
#include "context.h" #include "context.h"
#include "internal.h" #include "internal.h"
#include "legacy.h" #include "legacy.h"
...@@ -1841,3 +1844,89 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns, ...@@ -1841,3 +1844,89 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
return 0; return 0;
} }
#endif /* CONFIG_PROC_PID_ARCH_STATUS */ #endif /* CONFIG_PROC_PID_ARCH_STATUS */
#ifdef CONFIG_COREDUMP
static const char owner_name[] = "LINUX";
/*
* Dump type, size, offset and flag values for every xfeature that is present.
*/
static int dump_xsave_layout_desc(struct coredump_params *cprm)
{
int num_records = 0;
int i;
for_each_extended_xfeature(i, fpu_user_cfg.max_features) {
struct x86_xfeat_component xc = {
.type = i,
.size = xstate_sizes[i],
.offset = xstate_offsets[i],
/* reserved for future use */
.flags = 0,
};
if (!dump_emit(cprm, &xc, sizeof(xc)))
return 0;
num_records++;
}
return num_records;
}
static u32 get_xsave_desc_size(void)
{
u32 cnt = 0;
u32 i;
for_each_extended_xfeature(i, fpu_user_cfg.max_features)
cnt++;
return cnt * (sizeof(struct x86_xfeat_component));
}
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
{
int num_records = 0;
struct elf_note en;
if (!fpu_user_cfg.max_features)
return 0;
en.n_namesz = sizeof(owner_name);
en.n_descsz = get_xsave_desc_size();
en.n_type = NT_X86_XSAVE_LAYOUT;
if (!dump_emit(cprm, &en, sizeof(en)))
return 1;
if (!dump_emit(cprm, owner_name, en.n_namesz))
return 1;
if (!dump_align(cprm, 4))
return 1;
num_records = dump_xsave_layout_desc(cprm);
if (!num_records)
return 1;
/* Total size should be equal to the number of records */
if ((sizeof(struct x86_xfeat_component) * num_records) != en.n_descsz)
return 1;
return 0;
}
int elf_coredump_extra_notes_size(void)
{
int size;
if (!fpu_user_cfg.max_features)
return 0;
/* .note header */
size = sizeof(struct elf_note);
/* Name plus alignment to 4 bytes */
size += roundup(sizeof(owner_name), 4);
size += get_xsave_desc_size();
return size;
}
#endif /* CONFIG_COREDUMP */
...@@ -2039,7 +2039,7 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2039,7 +2039,7 @@ static int elf_core_dump(struct coredump_params *cprm)
{ {
size_t sz = info.size; size_t sz = info.size;
/* For cell spufs */ /* For cell spufs and x86 xstate */
sz += elf_coredump_extra_notes_size(); sz += elf_coredump_extra_notes_size();
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
...@@ -2103,7 +2103,7 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2103,7 +2103,7 @@ static int elf_core_dump(struct coredump_params *cprm)
if (!write_note_info(&info, cprm)) if (!write_note_info(&info, cprm))
goto end_coredump; goto end_coredump;
/* For cell spufs */ /* For cell spufs and x86 xstate */
if (elf_coredump_extra_notes_write(cprm)) if (elf_coredump_extra_notes_write(cprm))
goto end_coredump; goto end_coredump;
......
...@@ -411,6 +411,7 @@ typedef struct elf64_shdr { ...@@ -411,6 +411,7 @@ typedef struct elf64_shdr {
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
/* Old binutils treats 0x203 as a CET state */ /* Old binutils treats 0x203 as a CET state */
#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */ #define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
#define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description */
#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ #define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
#define NT_S390_TIMER 0x301 /* s390 timer register */ #define NT_S390_TIMER 0x301 /* s390 timer register */
#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ #define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment