1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Coredump functionality for Remoteproc framework. 4 * 5 * Copyright (c) 2020, The Linux Foundation. All rights reserved. 6 */ 7 8 #include <linux/completion.h> 9 #include <linux/devcoredump.h> 10 #include <linux/device.h> 11 #include <linux/kernel.h> 12 #include <linux/remoteproc.h> 13 #include "remoteproc_internal.h" 14 #include "remoteproc_elf_helpers.h" 15 16 struct rproc_coredump_state { 17 struct rproc *rproc; 18 void *header; 19 struct completion dump_done; 20 }; 21 22 /** 23 * rproc_coredump_cleanup() - clean up dump_segments list 24 * @rproc: the remote processor handle 25 */ 26 void rproc_coredump_cleanup(struct rproc *rproc) 27 { 28 struct rproc_dump_segment *entry, *tmp; 29 30 list_for_each_entry_safe(entry, tmp, &rproc->dump_segments, node) { 31 list_del(&entry->node); 32 kfree(entry); 33 } 34 } 35 36 /** 37 * rproc_coredump_add_segment() - add segment of device memory to coredump 38 * @rproc: handle of a remote processor 39 * @da: device address 40 * @size: size of segment 41 * 42 * Add device memory to the list of segments to be included in a coredump for 43 * the remoteproc. 44 * 45 * Return: 0 on success, negative errno on error. 46 */ 47 int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size) 48 { 49 struct rproc_dump_segment *segment; 50 51 segment = kzalloc(sizeof(*segment), GFP_KERNEL); 52 if (!segment) 53 return -ENOMEM; 54 55 segment->da = da; 56 segment->size = size; 57 58 list_add_tail(&segment->node, &rproc->dump_segments); 59 60 return 0; 61 } 62 EXPORT_SYMBOL(rproc_coredump_add_segment); 63 64 /** 65 * rproc_coredump_add_custom_segment() - add custom coredump segment 66 * @rproc: handle of a remote processor 67 * @da: device address 68 * @size: size of segment 69 * @dumpfn: custom dump function called for each segment during coredump 70 * @priv: private data 71 * 72 * Add device memory to the list of segments to be included in the coredump 73 * and associate the segment with the given custom dump function and private 74 * data. 75 * 76 * Return: 0 on success, negative errno on error. 77 */ 78 int rproc_coredump_add_custom_segment(struct rproc *rproc, 79 dma_addr_t da, size_t size, 80 void (*dumpfn)(struct rproc *rproc, 81 struct rproc_dump_segment *segment, 82 void *dest, size_t offset, 83 size_t size), 84 void *priv) 85 { 86 struct rproc_dump_segment *segment; 87 88 segment = kzalloc(sizeof(*segment), GFP_KERNEL); 89 if (!segment) 90 return -ENOMEM; 91 92 segment->da = da; 93 segment->size = size; 94 segment->priv = priv; 95 segment->dump = dumpfn; 96 97 list_add_tail(&segment->node, &rproc->dump_segments); 98 99 return 0; 100 } 101 EXPORT_SYMBOL(rproc_coredump_add_custom_segment); 102 103 /** 104 * rproc_coredump_set_elf_info() - set coredump elf information 105 * @rproc: handle of a remote processor 106 * @class: elf class for coredump elf file 107 * @machine: elf machine for coredump elf file 108 * 109 * Set elf information which will be used for coredump elf file. 110 * 111 * Return: 0 on success, negative errno on error. 112 */ 113 int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine) 114 { 115 if (class != ELFCLASS64 && class != ELFCLASS32) 116 return -EINVAL; 117 118 rproc->elf_class = class; 119 rproc->elf_machine = machine; 120 121 return 0; 122 } 123 EXPORT_SYMBOL(rproc_coredump_set_elf_info); 124 125 static void rproc_coredump_free(void *data) 126 { 127 struct rproc_coredump_state *dump_state = data; 128 129 vfree(dump_state->header); 130 complete(&dump_state->dump_done); 131 } 132 133 static void *rproc_coredump_find_segment(loff_t user_offset, 134 struct list_head *segments, 135 size_t *data_left) 136 { 137 struct rproc_dump_segment *segment; 138 139 list_for_each_entry(segment, segments, node) { 140 if (user_offset < segment->size) { 141 *data_left = segment->size - user_offset; 142 return segment; 143 } 144 user_offset -= segment->size; 145 } 146 147 *data_left = 0; 148 return NULL; 149 } 150 151 static void rproc_copy_segment(struct rproc *rproc, void *dest, 152 struct rproc_dump_segment *segment, 153 size_t offset, size_t size) 154 { 155 void *ptr; 156 157 if (segment->dump) { 158 segment->dump(rproc, segment, dest, offset, size); 159 } else { 160 ptr = rproc_da_to_va(rproc, segment->da + offset, size); 161 if (!ptr) { 162 dev_err(&rproc->dev, 163 "invalid copy request for segment %pad with offset %zu and size %zu)\n", 164 &segment->da, offset, size); 165 memset(dest, 0xff, size); 166 } else { 167 memcpy(dest, ptr, size); 168 } 169 } 170 } 171 172 static ssize_t rproc_coredump_read(char *buffer, loff_t offset, size_t count, 173 void *data, size_t header_sz) 174 { 175 size_t seg_data, bytes_left = count; 176 ssize_t copy_sz; 177 struct rproc_dump_segment *seg; 178 struct rproc_coredump_state *dump_state = data; 179 struct rproc *rproc = dump_state->rproc; 180 void *elfcore = dump_state->header; 181 182 /* Copy the vmalloc'ed header first. */ 183 if (offset < header_sz) { 184 copy_sz = memory_read_from_buffer(buffer, count, &offset, 185 elfcore, header_sz); 186 187 return copy_sz; 188 } 189 190 /* 191 * Find out the segment memory chunk to be copied based on offset. 192 * Keep copying data until count bytes are read. 193 */ 194 while (bytes_left) { 195 seg = rproc_coredump_find_segment(offset - header_sz, 196 &rproc->dump_segments, 197 &seg_data); 198 /* EOF check */ 199 if (!seg) { 200 dev_info(&rproc->dev, "Ramdump done, %lld bytes read", 201 offset); 202 break; 203 } 204 205 copy_sz = min_t(size_t, bytes_left, seg_data); 206 207 rproc_copy_segment(rproc, buffer, seg, seg->size - seg_data, 208 copy_sz); 209 210 offset += copy_sz; 211 buffer += copy_sz; 212 bytes_left -= copy_sz; 213 } 214 215 return count - bytes_left; 216 } 217 218 /** 219 * rproc_coredump() - perform coredump 220 * @rproc: rproc handle 221 * 222 * This function will generate an ELF header for the registered segments 223 * and create a devcoredump device associated with rproc. Based on the 224 * coredump configuration this function will directly copy the segments 225 * from device memory to userspace or copy segments from device memory to 226 * a separate buffer, which can then be read by userspace. 227 * The first approach avoids using extra vmalloc memory. But it will stall 228 * recovery flow until dump is read by userspace. 229 */ 230 void rproc_coredump(struct rproc *rproc) 231 { 232 struct rproc_dump_segment *segment; 233 void *phdr; 234 void *ehdr; 235 size_t data_size; 236 size_t offset; 237 void *data; 238 u8 class = rproc->elf_class; 239 int phnum = 0; 240 struct rproc_coredump_state dump_state; 241 enum rproc_dump_mechanism dump_conf = rproc->dump_conf; 242 243 if (list_empty(&rproc->dump_segments) || 244 dump_conf == RPROC_COREDUMP_DISABLED) 245 return; 246 247 if (class == ELFCLASSNONE) { 248 dev_err(&rproc->dev, "Elf class is not set\n"); 249 return; 250 } 251 252 data_size = elf_size_of_hdr(class); 253 list_for_each_entry(segment, &rproc->dump_segments, node) { 254 /* 255 * For default configuration buffer includes headers & segments. 256 * For inline dump buffer just includes headers as segments are 257 * directly read from device memory. 258 */ 259 data_size += elf_size_of_phdr(class); 260 if (dump_conf == RPROC_COREDUMP_ENABLED) 261 data_size += segment->size; 262 263 phnum++; 264 } 265 266 data = vmalloc(data_size); 267 if (!data) 268 return; 269 270 ehdr = data; 271 272 memset(ehdr, 0, elf_size_of_hdr(class)); 273 /* e_ident field is common for both elf32 and elf64 */ 274 elf_hdr_init_ident(ehdr, class); 275 276 elf_hdr_set_e_type(class, ehdr, ET_CORE); 277 elf_hdr_set_e_machine(class, ehdr, rproc->elf_machine); 278 elf_hdr_set_e_version(class, ehdr, EV_CURRENT); 279 elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr); 280 elf_hdr_set_e_phoff(class, ehdr, elf_size_of_hdr(class)); 281 elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class)); 282 elf_hdr_set_e_phentsize(class, ehdr, elf_size_of_phdr(class)); 283 elf_hdr_set_e_phnum(class, ehdr, phnum); 284 285 phdr = data + elf_hdr_get_e_phoff(class, ehdr); 286 offset = elf_hdr_get_e_phoff(class, ehdr); 287 offset += elf_size_of_phdr(class) * elf_hdr_get_e_phnum(class, ehdr); 288 289 list_for_each_entry(segment, &rproc->dump_segments, node) { 290 memset(phdr, 0, elf_size_of_phdr(class)); 291 elf_phdr_set_p_type(class, phdr, PT_LOAD); 292 elf_phdr_set_p_offset(class, phdr, offset); 293 elf_phdr_set_p_vaddr(class, phdr, segment->da); 294 elf_phdr_set_p_paddr(class, phdr, segment->da); 295 elf_phdr_set_p_filesz(class, phdr, segment->size); 296 elf_phdr_set_p_memsz(class, phdr, segment->size); 297 elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X); 298 elf_phdr_set_p_align(class, phdr, 0); 299 300 if (dump_conf == RPROC_COREDUMP_ENABLED) 301 rproc_copy_segment(rproc, data + offset, segment, 0, 302 segment->size); 303 304 offset += elf_phdr_get_p_filesz(class, phdr); 305 phdr += elf_size_of_phdr(class); 306 } 307 if (dump_conf == RPROC_COREDUMP_ENABLED) { 308 dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL); 309 return; 310 } 311 312 /* Initialize the dump state struct to be used by rproc_coredump_read */ 313 dump_state.rproc = rproc; 314 dump_state.header = data; 315 init_completion(&dump_state.dump_done); 316 317 dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size, GFP_KERNEL, 318 rproc_coredump_read, rproc_coredump_free); 319 320 /* 321 * Wait until the dump is read and free is called. Data is freed 322 * by devcoredump framework automatically after 5 minutes. 323 */ 324 wait_for_completion(&dump_state.dump_done); 325 } 326 327 /** 328 * rproc_coredump_using_sections() - perform coredump using section headers 329 * @rproc: rproc handle 330 * 331 * This function will generate an ELF header for the registered sections of 332 * segments and create a devcoredump device associated with rproc. Based on 333 * the coredump configuration this function will directly copy the segments 334 * from device memory to userspace or copy segments from device memory to 335 * a separate buffer, which can then be read by userspace. 336 * The first approach avoids using extra vmalloc memory. But it will stall 337 * recovery flow until dump is read by userspace. 338 */ 339 void rproc_coredump_using_sections(struct rproc *rproc) 340 { 341 struct rproc_dump_segment *segment; 342 void *shdr; 343 void *ehdr; 344 size_t data_size; 345 size_t strtbl_size = 0; 346 size_t strtbl_index = 1; 347 size_t offset; 348 void *data; 349 u8 class = rproc->elf_class; 350 int shnum; 351 struct rproc_coredump_state dump_state; 352 unsigned int dump_conf = rproc->dump_conf; 353 char *str_tbl = "STR_TBL"; 354 355 if (list_empty(&rproc->dump_segments) || 356 dump_conf == RPROC_COREDUMP_DISABLED) 357 return; 358 359 if (class == ELFCLASSNONE) { 360 dev_err(&rproc->dev, "Elf class is not set\n"); 361 return; 362 } 363 364 /* 365 * We allocate two extra section headers. The first one is null. 366 * Second section header is for the string table. Also space is 367 * allocated for string table. 368 */ 369 data_size = elf_size_of_hdr(class) + 2 * elf_size_of_shdr(class); 370 shnum = 2; 371 372 /* the extra byte is for the null character at index 0 */ 373 strtbl_size += strlen(str_tbl) + 2; 374 375 list_for_each_entry(segment, &rproc->dump_segments, node) { 376 data_size += elf_size_of_shdr(class); 377 strtbl_size += strlen(segment->priv) + 1; 378 if (dump_conf == RPROC_COREDUMP_ENABLED) 379 data_size += segment->size; 380 shnum++; 381 } 382 383 data_size += strtbl_size; 384 385 data = vmalloc(data_size); 386 if (!data) 387 return; 388 389 ehdr = data; 390 memset(ehdr, 0, elf_size_of_hdr(class)); 391 /* e_ident field is common for both elf32 and elf64 */ 392 elf_hdr_init_ident(ehdr, class); 393 394 elf_hdr_set_e_type(class, ehdr, ET_CORE); 395 elf_hdr_set_e_machine(class, ehdr, rproc->elf_machine); 396 elf_hdr_set_e_version(class, ehdr, EV_CURRENT); 397 elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr); 398 elf_hdr_set_e_shoff(class, ehdr, elf_size_of_hdr(class)); 399 elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class)); 400 elf_hdr_set_e_shentsize(class, ehdr, elf_size_of_shdr(class)); 401 elf_hdr_set_e_shnum(class, ehdr, shnum); 402 elf_hdr_set_e_shstrndx(class, ehdr, 1); 403 404 /* 405 * The zeroth index of the section header is reserved and is rarely used. 406 * Set the section header as null (SHN_UNDEF) and move to the next one. 407 */ 408 shdr = data + elf_hdr_get_e_shoff(class, ehdr); 409 memset(shdr, 0, elf_size_of_shdr(class)); 410 shdr += elf_size_of_shdr(class); 411 412 /* Initialize the string table. */ 413 offset = elf_hdr_get_e_shoff(class, ehdr) + 414 elf_size_of_shdr(class) * elf_hdr_get_e_shnum(class, ehdr); 415 memset(data + offset, 0, strtbl_size); 416 417 /* Fill in the string table section header. */ 418 memset(shdr, 0, elf_size_of_shdr(class)); 419 elf_shdr_set_sh_type(class, shdr, SHT_STRTAB); 420 elf_shdr_set_sh_offset(class, shdr, offset); 421 elf_shdr_set_sh_size(class, shdr, strtbl_size); 422 elf_shdr_set_sh_entsize(class, shdr, 0); 423 elf_shdr_set_sh_flags(class, shdr, 0); 424 elf_shdr_set_sh_name(class, shdr, elf_strtbl_add(str_tbl, ehdr, class, &strtbl_index)); 425 offset += elf_shdr_get_sh_size(class, shdr); 426 shdr += elf_size_of_shdr(class); 427 428 list_for_each_entry(segment, &rproc->dump_segments, node) { 429 memset(shdr, 0, elf_size_of_shdr(class)); 430 elf_shdr_set_sh_type(class, shdr, SHT_PROGBITS); 431 elf_shdr_set_sh_offset(class, shdr, offset); 432 elf_shdr_set_sh_addr(class, shdr, segment->da); 433 elf_shdr_set_sh_size(class, shdr, segment->size); 434 elf_shdr_set_sh_entsize(class, shdr, 0); 435 elf_shdr_set_sh_flags(class, shdr, SHF_WRITE); 436 elf_shdr_set_sh_name(class, shdr, 437 elf_strtbl_add(segment->priv, ehdr, class, &strtbl_index)); 438 439 /* No need to copy segments for inline dumps */ 440 if (dump_conf == RPROC_COREDUMP_ENABLED) 441 rproc_copy_segment(rproc, data + offset, segment, 0, 442 segment->size); 443 offset += elf_shdr_get_sh_size(class, shdr); 444 shdr += elf_size_of_shdr(class); 445 } 446 447 if (dump_conf == RPROC_COREDUMP_ENABLED) { 448 dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL); 449 return; 450 } 451 452 /* Initialize the dump state struct to be used by rproc_coredump_read */ 453 dump_state.rproc = rproc; 454 dump_state.header = data; 455 init_completion(&dump_state.dump_done); 456 457 dev_coredumpm(&rproc->dev, NULL, &dump_state, data_size, GFP_KERNEL, 458 rproc_coredump_read, rproc_coredump_free); 459 460 /* Wait until the dump is read and free is called. Data is freed 461 * by devcoredump framework automatically after 5 minutes. 462 */ 463 wait_for_completion(&dump_state.dump_done); 464 } 465 EXPORT_SYMBOL(rproc_coredump_using_sections); 466