1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * crash.c - kernel crash support code. 4 * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com> 5 */ 6 7 #include <linux/buildid.h> 8 #include <linux/init.h> 9 #include <linux/utsname.h> 10 #include <linux/vmalloc.h> 11 #include <linux/sizes.h> 12 #include <linux/kexec.h> 13 #include <linux/memory.h> 14 #include <linux/cpuhotplug.h> 15 #include <linux/memblock.h> 16 #include <linux/kmemleak.h> 17 18 #include <asm/page.h> 19 #include <asm/sections.h> 20 21 #include <crypto/sha1.h> 22 23 #include "kallsyms_internal.h" 24 #include "kexec_internal.h" 25 26 /* vmcoreinfo stuff */ 27 unsigned char *vmcoreinfo_data; 28 size_t vmcoreinfo_size; 29 u32 *vmcoreinfo_note; 30 31 /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */ 32 static unsigned char *vmcoreinfo_data_safecopy; 33 34 struct hwerr_info { 35 atomic_t count; 36 time64_t timestamp; 37 }; 38 39 /* 40 * The hwerr_data[] array is declared with global scope so that it remains 41 * accessible to vmcoreinfo even when Link Time Optimization (LTO) is enabled. 42 */ 43 struct hwerr_info hwerr_data[HWERR_RECOV_MAX]; 44 45 Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type, 46 void *data, size_t data_len) 47 { 48 struct elf_note *note = (struct elf_note *)buf; 49 50 note->n_namesz = strlen(name) + 1; 51 note->n_descsz = data_len; 52 note->n_type = type; 53 buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf_Word)); 54 memcpy(buf, name, note->n_namesz); 55 buf += DIV_ROUND_UP(note->n_namesz, sizeof(Elf_Word)); 56 memcpy(buf, data, data_len); 57 buf += DIV_ROUND_UP(data_len, sizeof(Elf_Word)); 58 59 return buf; 60 } 61 62 void final_note(Elf_Word *buf) 63 { 64 memset(buf, 0, sizeof(struct elf_note)); 65 } 66 67 static void update_vmcoreinfo_note(void) 68 { 69 u32 *buf = vmcoreinfo_note; 70 71 if (!vmcoreinfo_size) 72 return; 73 buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data, 74 vmcoreinfo_size); 75 final_note(buf); 76 } 77 78 void crash_update_vmcoreinfo_safecopy(void *ptr) 79 { 80 if (ptr) 81 memcpy(ptr, vmcoreinfo_data, vmcoreinfo_size); 82 83 vmcoreinfo_data_safecopy = ptr; 84 } 85 86 void crash_save_vmcoreinfo(void) 87 { 88 if (!vmcoreinfo_note) 89 return; 90 91 /* Use the safe copy to generate vmcoreinfo note if have */ 92 if (vmcoreinfo_data_safecopy) 93 vmcoreinfo_data = vmcoreinfo_data_safecopy; 94 95 vmcoreinfo_append_str("CRASHTIME=%lld\n", ktime_get_real_seconds()); 96 update_vmcoreinfo_note(); 97 } 98 99 void vmcoreinfo_append_str(const char *fmt, ...) 100 { 101 va_list args; 102 char buf[0x50]; 103 size_t r; 104 105 va_start(args, fmt); 106 r = vscnprintf(buf, sizeof(buf), fmt, args); 107 va_end(args); 108 109 r = min(r, (size_t)VMCOREINFO_BYTES - vmcoreinfo_size); 110 111 memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r); 112 113 vmcoreinfo_size += r; 114 115 WARN_ONCE(vmcoreinfo_size == VMCOREINFO_BYTES, 116 "vmcoreinfo data exceeds allocated size, truncating"); 117 } 118 119 /* 120 * provide an empty default implementation here -- architecture 121 * code may override this 122 */ 123 void __weak arch_crash_save_vmcoreinfo(void) 124 {} 125 126 phys_addr_t __weak paddr_vmcoreinfo_note(void) 127 { 128 return __pa(vmcoreinfo_note); 129 } 130 EXPORT_SYMBOL(paddr_vmcoreinfo_note); 131 132 void hwerr_log_error_type(enum hwerr_error_type src) 133 { 134 if (src < 0 || src >= HWERR_RECOV_MAX) 135 return; 136 137 atomic_inc(&hwerr_data[src].count); 138 WRITE_ONCE(hwerr_data[src].timestamp, ktime_get_real_seconds()); 139 } 140 EXPORT_SYMBOL_GPL(hwerr_log_error_type); 141 142 static int __init crash_save_vmcoreinfo_init(void) 143 { 144 int order; 145 order = get_order(VMCOREINFO_BYTES); 146 vmcoreinfo_data = (unsigned char *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order); 147 if (!vmcoreinfo_data) { 148 pr_warn("Memory allocation for vmcoreinfo_data failed\n"); 149 return -ENOMEM; 150 } 151 152 vmcoreinfo_note = alloc_pages_exact(VMCOREINFO_NOTE_SIZE, 153 GFP_KERNEL | __GFP_ZERO); 154 if (!vmcoreinfo_note) { 155 free_pages((unsigned long)vmcoreinfo_data, order); 156 vmcoreinfo_data = NULL; 157 pr_warn("Memory allocation for vmcoreinfo_note failed\n"); 158 return -ENOMEM; 159 } 160 161 VMCOREINFO_OSRELEASE(init_uts_ns.name.release); 162 VMCOREINFO_BUILD_ID(); 163 VMCOREINFO_PAGESIZE(PAGE_SIZE); 164 165 VMCOREINFO_SYMBOL(init_uts_ns); 166 VMCOREINFO_OFFSET(uts_namespace, name); 167 VMCOREINFO_SYMBOL(node_online_map); 168 #ifdef CONFIG_MMU 169 VMCOREINFO_SYMBOL_ARRAY(swapper_pg_dir); 170 #endif 171 VMCOREINFO_SYMBOL(_stext); 172 vmcoreinfo_append_str("NUMBER(VMALLOC_START)=0x%lx\n", (unsigned long) VMALLOC_START); 173 174 #ifndef CONFIG_NUMA 175 VMCOREINFO_SYMBOL(mem_map); 176 VMCOREINFO_SYMBOL(contig_page_data); 177 #endif 178 #ifdef CONFIG_SPARSEMEM_VMEMMAP 179 VMCOREINFO_SYMBOL_ARRAY(vmemmap); 180 #endif 181 #ifdef CONFIG_SPARSEMEM 182 VMCOREINFO_SYMBOL_ARRAY(mem_section); 183 VMCOREINFO_LENGTH(mem_section, NR_SECTION_ROOTS); 184 VMCOREINFO_STRUCT_SIZE(mem_section); 185 VMCOREINFO_OFFSET(mem_section, section_mem_map); 186 VMCOREINFO_NUMBER(SECTION_SIZE_BITS); 187 VMCOREINFO_NUMBER(MAX_PHYSMEM_BITS); 188 #endif 189 VMCOREINFO_STRUCT_SIZE(page); 190 VMCOREINFO_STRUCT_SIZE(pglist_data); 191 VMCOREINFO_STRUCT_SIZE(zone); 192 VMCOREINFO_STRUCT_SIZE(free_area); 193 VMCOREINFO_STRUCT_SIZE(list_head); 194 VMCOREINFO_SIZE(nodemask_t); 195 VMCOREINFO_OFFSET(page, flags); 196 VMCOREINFO_OFFSET(page, _refcount); 197 VMCOREINFO_OFFSET(page, mapping); 198 VMCOREINFO_OFFSET(page, lru); 199 VMCOREINFO_OFFSET(page, _mapcount); 200 VMCOREINFO_OFFSET(page, private); 201 VMCOREINFO_OFFSET(page, compound_head); 202 VMCOREINFO_OFFSET(pglist_data, node_zones); 203 VMCOREINFO_OFFSET(pglist_data, nr_zones); 204 #ifdef CONFIG_FLATMEM 205 VMCOREINFO_OFFSET(pglist_data, node_mem_map); 206 #endif 207 VMCOREINFO_OFFSET(pglist_data, node_start_pfn); 208 VMCOREINFO_OFFSET(pglist_data, node_spanned_pages); 209 VMCOREINFO_OFFSET(pglist_data, node_id); 210 VMCOREINFO_OFFSET(zone, free_area); 211 VMCOREINFO_OFFSET(zone, vm_stat); 212 VMCOREINFO_OFFSET(zone, spanned_pages); 213 VMCOREINFO_OFFSET(free_area, free_list); 214 VMCOREINFO_OFFSET(list_head, next); 215 VMCOREINFO_OFFSET(list_head, prev); 216 VMCOREINFO_LENGTH(zone.free_area, NR_PAGE_ORDERS); 217 log_buf_vmcoreinfo_setup(); 218 VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES); 219 VMCOREINFO_NUMBER(NR_FREE_PAGES); 220 VMCOREINFO_NUMBER(PG_lru); 221 VMCOREINFO_NUMBER(PG_private); 222 VMCOREINFO_NUMBER(PG_swapcache); 223 VMCOREINFO_NUMBER(PG_swapbacked); 224 #define PAGE_SLAB_MAPCOUNT_VALUE (PGTY_slab << 24) 225 VMCOREINFO_NUMBER(PAGE_SLAB_MAPCOUNT_VALUE); 226 #ifdef CONFIG_MEMORY_FAILURE 227 VMCOREINFO_NUMBER(PG_hwpoison); 228 #endif 229 VMCOREINFO_NUMBER(PG_head_mask); 230 #define PAGE_BUDDY_MAPCOUNT_VALUE (PGTY_buddy << 24) 231 VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); 232 #define PAGE_HUGETLB_MAPCOUNT_VALUE (PGTY_hugetlb << 24) 233 VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE); 234 #define PAGE_OFFLINE_MAPCOUNT_VALUE (PGTY_offline << 24) 235 VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE); 236 #ifdef CONFIG_UNACCEPTED_MEMORY 237 #define PAGE_UNACCEPTED_MAPCOUNT_VALUE (PGTY_unaccepted << 24) 238 VMCOREINFO_NUMBER(PAGE_UNACCEPTED_MAPCOUNT_VALUE); 239 #endif 240 241 #ifdef CONFIG_KALLSYMS 242 VMCOREINFO_SYMBOL(kallsyms_names); 243 VMCOREINFO_SYMBOL(kallsyms_num_syms); 244 VMCOREINFO_SYMBOL(kallsyms_token_table); 245 VMCOREINFO_SYMBOL(kallsyms_token_index); 246 VMCOREINFO_SYMBOL(kallsyms_offsets); 247 #endif /* CONFIG_KALLSYMS */ 248 249 arch_crash_save_vmcoreinfo(); 250 update_vmcoreinfo_note(); 251 252 return 0; 253 } 254 255 subsys_initcall(crash_save_vmcoreinfo_init); 256