|
13 | 13 | #include <linux/seq_file.h> |
14 | 14 | #include <linux/proc_fs.h> |
15 | 15 | #include <linux/vmalloc.h> |
| 16 | +#include <linux/coredump.h> |
16 | 17 |
|
17 | 18 | #include <asm/fpu/api.h> |
18 | 19 | #include <asm/fpu/regset.h> |
|
23 | 24 | #include <asm/prctl.h> |
24 | 25 | #include <asm/elf.h> |
25 | 26 |
|
| 27 | +#include <uapi/asm/elf.h> |
| 28 | + |
26 | 29 | #include "context.h" |
27 | 30 | #include "internal.h" |
28 | 31 | #include "legacy.h" |
@@ -1838,3 +1841,89 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns, |
1838 | 1841 | return 0; |
1839 | 1842 | } |
1840 | 1843 | #endif /* CONFIG_PROC_PID_ARCH_STATUS */ |
| 1844 | + |
| 1845 | +#ifdef CONFIG_COREDUMP |
| 1846 | +static const char owner_name[] = "LINUX"; |
| 1847 | + |
| 1848 | +/* |
| 1849 | + * Dump type, size, offset and flag values for every xfeature that is present. |
| 1850 | + */ |
| 1851 | +static int dump_xsave_layout_desc(struct coredump_params *cprm) |
| 1852 | +{ |
| 1853 | + int num_records = 0; |
| 1854 | + int i; |
| 1855 | + |
| 1856 | + for_each_extended_xfeature(i, fpu_user_cfg.max_features) { |
| 1857 | + struct x86_xfeat_component xc = { |
| 1858 | + .type = i, |
| 1859 | + .size = xstate_sizes[i], |
| 1860 | + .offset = xstate_offsets[i], |
| 1861 | + /* reserved for future use */ |
| 1862 | + .flags = 0, |
| 1863 | + }; |
| 1864 | + |
| 1865 | + if (!dump_emit(cprm, &xc, sizeof(xc))) |
| 1866 | + return 0; |
| 1867 | + |
| 1868 | + num_records++; |
| 1869 | + } |
| 1870 | + return num_records; |
| 1871 | +} |
| 1872 | + |
| 1873 | +static u32 get_xsave_desc_size(void) |
| 1874 | +{ |
| 1875 | + u32 cnt = 0; |
| 1876 | + u32 i; |
| 1877 | + |
| 1878 | + for_each_extended_xfeature(i, fpu_user_cfg.max_features) |
| 1879 | + cnt++; |
| 1880 | + |
| 1881 | + return cnt * (sizeof(struct x86_xfeat_component)); |
| 1882 | +} |
| 1883 | + |
| 1884 | +int elf_coredump_extra_notes_write(struct coredump_params *cprm) |
| 1885 | +{ |
| 1886 | + int num_records = 0; |
| 1887 | + struct elf_note en; |
| 1888 | + |
| 1889 | + if (!fpu_user_cfg.max_features) |
| 1890 | + return 0; |
| 1891 | + |
| 1892 | + en.n_namesz = sizeof(owner_name); |
| 1893 | + en.n_descsz = get_xsave_desc_size(); |
| 1894 | + en.n_type = NT_X86_XSAVE_LAYOUT; |
| 1895 | + |
| 1896 | + if (!dump_emit(cprm, &en, sizeof(en))) |
| 1897 | + return 1; |
| 1898 | + if (!dump_emit(cprm, owner_name, en.n_namesz)) |
| 1899 | + return 1; |
| 1900 | + if (!dump_align(cprm, 4)) |
| 1901 | + return 1; |
| 1902 | + |
| 1903 | + num_records = dump_xsave_layout_desc(cprm); |
| 1904 | + if (!num_records) |
| 1905 | + return 1; |
| 1906 | + |
| 1907 | + /* Total size should be equal to the number of records */ |
| 1908 | + if ((sizeof(struct x86_xfeat_component) * num_records) != en.n_descsz) |
| 1909 | + return 1; |
| 1910 | + |
| 1911 | + return 0; |
| 1912 | +} |
| 1913 | + |
| 1914 | +int elf_coredump_extra_notes_size(void) |
| 1915 | +{ |
| 1916 | + int size; |
| 1917 | + |
| 1918 | + if (!fpu_user_cfg.max_features) |
| 1919 | + return 0; |
| 1920 | + |
| 1921 | + /* .note header */ |
| 1922 | + size = sizeof(struct elf_note); |
| 1923 | + /* Name plus alignment to 4 bytes */ |
| 1924 | + size += roundup(sizeof(owner_name), 4); |
| 1925 | + size += get_xsave_desc_size(); |
| 1926 | + |
| 1927 | + return size; |
| 1928 | +} |
| 1929 | +#endif /* CONFIG_COREDUMP */ |
0 commit comments