1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3 *
4 * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved.
5 *
6 * This program is free software and is provided to you under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation, and any use by you of this program is subject to the terms
9 * of such GNU license.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can access it online at
18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 *
20 */
21
22 #include <linux/kernel.h>
23 #include <linux/device.h>
24 #include <linux/list.h>
25 #include <linux/file.h>
26 #include <linux/elf.h>
27 #include <linux/elfcore.h>
28
29 #include "mali_kbase.h"
30 #include "mali_kbase_csf_firmware_core_dump.h"
31 #include "backend/gpu/mali_kbase_pm_internal.h"
32
33 /* Page size in bytes in use by MCU. */
34 #define FW_PAGE_SIZE 4096
35
36 /*
37 * FW image header core dump data format supported.
38 * Currently only version 0.1 is supported.
39 */
40 #define FW_CORE_DUMP_DATA_VERSION_MAJOR 0
41 #define FW_CORE_DUMP_DATA_VERSION_MINOR 1
42
43 /* Full version of the image header core dump data format */
44 #define FW_CORE_DUMP_DATA_VERSION \
45 ((FW_CORE_DUMP_DATA_VERSION_MAJOR << 8) | FW_CORE_DUMP_DATA_VERSION_MINOR)
46
47 /* Validity flag to indicate if the MCU registers in the buffer are valid */
48 #define FW_MCU_STATUS_MASK 0x1
49 #define FW_MCU_STATUS_VALID (1 << 0)
50
51 /* Core dump entry fields */
52 #define FW_CORE_DUMP_VERSION_INDEX 0
53 #define FW_CORE_DUMP_START_ADDR_INDEX 1
54
55 /* MCU registers stored by a firmware core dump */
56 struct fw_core_dump_mcu {
57 u32 r0;
58 u32 r1;
59 u32 r2;
60 u32 r3;
61 u32 r4;
62 u32 r5;
63 u32 r6;
64 u32 r7;
65 u32 r8;
66 u32 r9;
67 u32 r10;
68 u32 r11;
69 u32 r12;
70 u32 sp;
71 u32 lr;
72 u32 pc;
73 };
74
75 /* Any ELF definitions used in this file are from elf.h/elfcore.h except
76 * when specific 32-bit versions are required (mainly for the
77 * ELF_PRSTATUS32 note that is used to contain the MCU registers).
78 */
79
80 /* - 32-bit version of timeval structures used in ELF32 PRSTATUS note. */
81 struct prstatus32_timeval {
82 int tv_sec;
83 int tv_usec;
84 };
85
86 /* - Structure defining ELF32 PRSTATUS note contents, as defined by the
87 * GNU binutils BFD library used by GDB, in bfd/hosts/x86-64linux.h.
88 * Note: GDB checks for the size of this structure to be 0x94.
89 * Modified pr_reg (array containing the Arm 32-bit MCU registers) to
90 * use u32[18] instead of elf_gregset32_t to prevent introducing new typedefs.
91 */
92 struct elf_prstatus32 {
93 struct elf_siginfo pr_info; /* Info associated with signal. */
94 short int pr_cursig; /* Current signal. */
95 unsigned int pr_sigpend; /* Set of pending signals. */
96 unsigned int pr_sighold; /* Set of held signals. */
97 pid_t pr_pid;
98 pid_t pr_ppid;
99 pid_t pr_pgrp;
100 pid_t pr_sid;
101 struct prstatus32_timeval pr_utime; /* User time. */
102 struct prstatus32_timeval pr_stime; /* System time. */
103 struct prstatus32_timeval pr_cutime; /* Cumulative user time. */
104 struct prstatus32_timeval pr_cstime; /* Cumulative system time. */
105 u32 pr_reg[18]; /* GP registers. */
106 int pr_fpvalid; /* True if math copro being used. */
107 };
108
109 /**
110 * struct fw_core_dump_data - Context for seq_file operations used on 'fw_core_dump'
111 * debugfs file.
112 * @kbdev: Instance of a GPU platform device that implements a CSF interface.
113 */
114 struct fw_core_dump_data {
115 struct kbase_device *kbdev;
116 };
117
118 /*
119 * struct fw_core_dump_seq_off - Iterator for seq_file operations used on 'fw_core_dump'
120 * debugfs file.
121 * @interface: current firmware memory interface
122 * @page_num: current page number (0..) within @interface
123 */
124 struct fw_core_dump_seq_off {
125 struct kbase_csf_firmware_interface *interface;
126 u32 page_num;
127 };
128
129 /**
130 * fw_get_core_dump_mcu - Get the MCU registers saved by a firmware core dump
131 *
132 * @kbdev: Instance of a GPU platform device that implements a CSF interface.
133 * @regs: Pointer to a core dump mcu struct where the MCU registers are copied
134 * to. Should be allocated by the called.
135 *
136 * Return: 0 if successfully copied the MCU registers, negative error code otherwise.
137 */
fw_get_core_dump_mcu(struct kbase_device * kbdev,struct fw_core_dump_mcu * regs)138 static int fw_get_core_dump_mcu(struct kbase_device *kbdev, struct fw_core_dump_mcu *regs)
139 {
140 unsigned int i;
141 u32 status = 0;
142 u32 data_addr = kbdev->csf.fw_core_dump.mcu_regs_addr;
143 u32 *data = (u32 *)regs;
144
145 /* Check if the core dump entry exposed the buffer */
146 if (!regs || !kbdev->csf.fw_core_dump.available)
147 return -EPERM;
148
149 /* Check if the data in the buffer is valid, if not, return error */
150 kbase_csf_read_firmware_memory(kbdev, data_addr, &status);
151 if ((status & FW_MCU_STATUS_MASK) != FW_MCU_STATUS_VALID)
152 return -EPERM;
153
154 /* According to image header documentation, the MCU registers core dump
155 * buffer is 32-bit aligned.
156 */
157 for (i = 1; i <= sizeof(struct fw_core_dump_mcu) / sizeof(u32); ++i)
158 kbase_csf_read_firmware_memory(kbdev, data_addr + i * sizeof(u32), &data[i - 1]);
159
160 return 0;
161 }
162
163 /**
164 * fw_core_dump_fill_elf_header - Initializes an ELF32 header
165 * @hdr: ELF32 header to initialize
166 * @sections: Number of entries in the ELF program header table
167 *
168 * Initializes an ELF32 header for an ARM 32-bit little-endian
169 * 'Core file' object file.
170 */
fw_core_dump_fill_elf_header(struct elf32_hdr * hdr,unsigned int sections)171 static void fw_core_dump_fill_elf_header(struct elf32_hdr *hdr, unsigned int sections)
172 {
173 /* Reset all members in header. */
174 memset(hdr, 0, sizeof(*hdr));
175
176 /* Magic number identifying file as an ELF object. */
177 memcpy(hdr->e_ident, ELFMAG, SELFMAG);
178
179 /* Identify file as 32-bit, little-endian, using current
180 * ELF header version, with no OS or ABI specific ELF
181 * extensions used.
182 */
183 hdr->e_ident[EI_CLASS] = ELFCLASS32;
184 hdr->e_ident[EI_DATA] = ELFDATA2LSB;
185 hdr->e_ident[EI_VERSION] = EV_CURRENT;
186 hdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
187
188 /* 'Core file' type of object file. */
189 hdr->e_type = ET_CORE;
190
191 /* ARM 32-bit architecture (AARCH32) */
192 hdr->e_machine = EM_ARM;
193
194 /* Object file version: the original format. */
195 hdr->e_version = EV_CURRENT;
196
197 /* Offset of program header table in file. */
198 hdr->e_phoff = sizeof(struct elf32_hdr);
199
200 /* No processor specific flags. */
201 hdr->e_flags = 0;
202
203 /* Size of the ELF header in bytes. */
204 hdr->e_ehsize = sizeof(struct elf32_hdr);
205
206 /* Size of the ELF program header entry in bytes. */
207 hdr->e_phentsize = sizeof(struct elf32_phdr);
208
209 /* Number of entries in the program header table. */
210 hdr->e_phnum = sections;
211 }
212
213 /**
214 * fw_core_dump_fill_elf_program_header_note - Initializes an ELF32 program header
215 * for holding auxiliary information
216 * @phdr: ELF32 program header
217 * @file_offset: Location of the note in the file in bytes
218 * @size: Size of the note in bytes.
219 *
220 * Initializes an ELF32 program header describing auxiliary information (containing
221 * one or more notes) of @size bytes alltogether located in the file at offset
222 * @file_offset.
223 */
fw_core_dump_fill_elf_program_header_note(struct elf32_phdr * phdr,u32 file_offset,u32 size)224 static void fw_core_dump_fill_elf_program_header_note(struct elf32_phdr *phdr, u32 file_offset,
225 u32 size)
226 {
227 /* Auxiliary information (note) in program header. */
228 phdr->p_type = PT_NOTE;
229
230 /* Location of first note in file in bytes. */
231 phdr->p_offset = file_offset;
232
233 /* Size of all notes combined in bytes. */
234 phdr->p_filesz = size;
235
236 /* Other members not relevant for a note. */
237 phdr->p_vaddr = 0;
238 phdr->p_paddr = 0;
239 phdr->p_memsz = 0;
240 phdr->p_align = 0;
241 phdr->p_flags = 0;
242 }
243
244 /**
245 * fw_core_dump_fill_elf_program_header - Initializes an ELF32 program header for a loadable segment
246 * @phdr: ELF32 program header to initialize.
247 * @file_offset: Location of loadable segment in file in bytes
248 * (aligned to FW_PAGE_SIZE bytes)
249 * @vaddr: 32-bit virtual address where to write the segment
250 * (aligned to FW_PAGE_SIZE bytes)
251 * @size: Size of the segment in bytes.
252 * @flags: CSF_FIRMWARE_ENTRY_* flags describing access permissions.
253 *
254 * Initializes an ELF32 program header describing a loadable segment of
255 * @size bytes located in the file at offset @file_offset to be loaded
256 * at virtual address @vaddr with access permissions as described by
257 * CSF_FIRMWARE_ENTRY_* flags in @flags.
258 */
fw_core_dump_fill_elf_program_header(struct elf32_phdr * phdr,u32 file_offset,u32 vaddr,u32 size,u32 flags)259 static void fw_core_dump_fill_elf_program_header(struct elf32_phdr *phdr, u32 file_offset,
260 u32 vaddr, u32 size, u32 flags)
261 {
262 /* Loadable segment in program header. */
263 phdr->p_type = PT_LOAD;
264
265 /* Location of segment in file in bytes. Aligned to p_align bytes. */
266 phdr->p_offset = file_offset;
267
268 /* Virtual address of segment. Aligned to p_align bytes. */
269 phdr->p_vaddr = vaddr;
270
271 /* Physical address of segment. Not relevant. */
272 phdr->p_paddr = 0;
273
274 /* Size of segment in file and memory. */
275 phdr->p_filesz = size;
276 phdr->p_memsz = size;
277
278 /* Alignment of segment in the file and memory in bytes (integral power of 2). */
279 phdr->p_align = FW_PAGE_SIZE;
280
281 /* Set segment access permissions. */
282 phdr->p_flags = 0;
283 if (flags & CSF_FIRMWARE_ENTRY_READ)
284 phdr->p_flags |= PF_R;
285 if (flags & CSF_FIRMWARE_ENTRY_WRITE)
286 phdr->p_flags |= PF_W;
287 if (flags & CSF_FIRMWARE_ENTRY_EXECUTE)
288 phdr->p_flags |= PF_X;
289 }
290
291 /**
292 * fw_core_dump_get_prstatus_note_size - Calculates size of a ELF32 PRSTATUS note
293 * @name: Name given to the PRSTATUS note.
294 *
295 * Calculates the size of a 32-bit PRSTATUS note (which contains information
296 * about a process like the current MCU registers) taking into account
297 * @name must be padded to a 4-byte multiple.
298 *
299 * Return: size of 32-bit PRSTATUS note in bytes.
300 */
fw_core_dump_get_prstatus_note_size(char * name)301 static unsigned int fw_core_dump_get_prstatus_note_size(char *name)
302 {
303 return sizeof(struct elf32_note) + roundup(strlen(name) + 1, 4) +
304 sizeof(struct elf_prstatus32);
305 }
306
307 /**
308 * fw_core_dump_fill_elf_prstatus - Initializes an ELF32 PRSTATUS structure
309 * @prs: ELF32 PRSTATUS note to initialize
310 * @regs: MCU registers to copy into the PRSTATUS note
311 *
312 * Initializes an ELF32 PRSTATUS structure with MCU registers @regs.
313 * Other process information is N/A for CSF Firmware.
314 */
fw_core_dump_fill_elf_prstatus(struct elf_prstatus32 * prs,struct fw_core_dump_mcu * regs)315 static void fw_core_dump_fill_elf_prstatus(struct elf_prstatus32 *prs,
316 struct fw_core_dump_mcu *regs)
317 {
318 /* Only fill in registers (32-bit) of PRSTATUS note. */
319 memset(prs, 0, sizeof(*prs));
320 prs->pr_reg[0] = regs->r0;
321 prs->pr_reg[1] = regs->r1;
322 prs->pr_reg[2] = regs->r2;
323 prs->pr_reg[3] = regs->r3;
324 prs->pr_reg[4] = regs->r4;
325 prs->pr_reg[5] = regs->r5;
326 prs->pr_reg[6] = regs->r0;
327 prs->pr_reg[7] = regs->r7;
328 prs->pr_reg[8] = regs->r8;
329 prs->pr_reg[9] = regs->r9;
330 prs->pr_reg[10] = regs->r10;
331 prs->pr_reg[11] = regs->r11;
332 prs->pr_reg[12] = regs->r12;
333 prs->pr_reg[13] = regs->sp;
334 prs->pr_reg[14] = regs->lr;
335 prs->pr_reg[15] = regs->pc;
336 }
337
338 /**
339 * fw_core_dump_create_prstatus_note - Creates an ELF32 PRSTATUS note
340 * @name: Name for the PRSTATUS note
341 * @prs: ELF32 PRSTATUS structure to put in the PRSTATUS note
342 * @created_prstatus_note:
343 * Pointer to the allocated ELF32 PRSTATUS note
344 *
345 * Creates an ELF32 note with one PRSTATUS entry containing the
346 * ELF32 PRSTATUS structure @prs. Caller needs to free the created note in
347 * @created_prstatus_note.
348 *
349 * Return: 0 on failure, otherwise size of ELF32 PRSTATUS note in bytes.
350 */
fw_core_dump_create_prstatus_note(char * name,struct elf_prstatus32 * prs,struct elf32_note ** created_prstatus_note)351 static unsigned int fw_core_dump_create_prstatus_note(char *name, struct elf_prstatus32 *prs,
352 struct elf32_note **created_prstatus_note)
353 {
354 struct elf32_note *note;
355 unsigned int note_name_sz;
356 unsigned int note_sz;
357
358 /* Allocate memory for ELF32 note containing a PRSTATUS note. */
359 note_name_sz = strlen(name) + 1;
360 note_sz = sizeof(struct elf32_note) + roundup(note_name_sz, 4) +
361 sizeof(struct elf_prstatus32);
362 note = kmalloc(note_sz, GFP_KERNEL);
363 if (!note)
364 return 0;
365
366 /* Fill in ELF32 note with one entry for a PRSTATUS note. */
367 note->n_namesz = note_name_sz;
368 note->n_descsz = sizeof(struct elf_prstatus32);
369 note->n_type = NT_PRSTATUS;
370 memcpy(note + 1, name, note_name_sz);
371 memcpy((char *)(note + 1) + roundup(note_name_sz, 4), prs, sizeof(*prs));
372
373 /* Return pointer and size of the created ELF32 note. */
374 *created_prstatus_note = note;
375 return note_sz;
376 }
377
378 /**
379 * fw_core_dump_write_elf_header - Writes ELF header for the FW core dump
380 * @m: the seq_file handle
381 *
382 * Writes the ELF header of the core dump including program headers for
383 * memory sections and a note containing the current MCU register
384 * values.
385 *
386 * Excludes memory sections without read access permissions or
387 * are for protected memory.
388 *
389 * The data written is as follows:
390 * - ELF header
391 * - ELF PHDRs for memory sections
392 * - ELF PHDR for program header NOTE
393 * - ELF PRSTATUS note
394 * - 0-bytes padding to multiple of ELF_EXEC_PAGESIZE
395 *
396 * The actual memory section dumps should follow this (not written
397 * by this function).
398 *
399 * Retrieves the necessary information via the struct
400 * fw_core_dump_data stored in the private member of the seq_file
401 * handle.
402 *
403 * Return:
404 * * 0 - success
405 * * -ENOMEM - not enough memory for allocating ELF32 note
406 */
fw_core_dump_write_elf_header(struct seq_file * m)407 static int fw_core_dump_write_elf_header(struct seq_file *m)
408 {
409 struct elf32_hdr hdr;
410 struct elf32_phdr phdr;
411 struct fw_core_dump_data *dump_data = m->private;
412 struct kbase_device *const kbdev = dump_data->kbdev;
413 struct kbase_csf_firmware_interface *interface;
414 struct elf_prstatus32 elf_prs;
415 struct elf32_note *elf_prstatus_note;
416 unsigned int sections = 0;
417 unsigned int elf_prstatus_note_size;
418 u32 elf_prstatus_offset;
419 u32 elf_phdr_note_offset;
420 u32 elf_memory_sections_data_offset;
421 u32 total_pages = 0;
422 u32 padding_size, *padding;
423 struct fw_core_dump_mcu regs = { 0 };
424
425 /* Count number of memory sections. */
426 list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) {
427 /* Skip memory sections that cannot be read or are protected. */
428 if ((interface->flags & CSF_FIRMWARE_ENTRY_PROTECTED) ||
429 (interface->flags & CSF_FIRMWARE_ENTRY_READ) == 0)
430 continue;
431 sections++;
432 }
433
434 /* Prepare ELF header. */
435 fw_core_dump_fill_elf_header(&hdr, sections + 1);
436 seq_write(m, &hdr, sizeof(struct elf32_hdr));
437
438 elf_prstatus_note_size = fw_core_dump_get_prstatus_note_size("CORE");
439 /* PHDRs of PT_LOAD type. */
440 elf_phdr_note_offset = sizeof(struct elf32_hdr) + sections * sizeof(struct elf32_phdr);
441 /* PHDR of PT_NOTE type. */
442 elf_prstatus_offset = elf_phdr_note_offset + sizeof(struct elf32_phdr);
443 elf_memory_sections_data_offset = elf_prstatus_offset + elf_prstatus_note_size;
444
445 /* Calculate padding size to page offset. */
446 padding_size = roundup(elf_memory_sections_data_offset, ELF_EXEC_PAGESIZE) -
447 elf_memory_sections_data_offset;
448 elf_memory_sections_data_offset += padding_size;
449
450 /* Prepare ELF program header table. */
451 list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) {
452 /* Skip memory sections that cannot be read or are protected. */
453 if ((interface->flags & CSF_FIRMWARE_ENTRY_PROTECTED) ||
454 (interface->flags & CSF_FIRMWARE_ENTRY_READ) == 0)
455 continue;
456
457 fw_core_dump_fill_elf_program_header(&phdr, elf_memory_sections_data_offset,
458 interface->virtual,
459 interface->num_pages * FW_PAGE_SIZE,
460 interface->flags);
461
462 seq_write(m, &phdr, sizeof(struct elf32_phdr));
463
464 elf_memory_sections_data_offset += interface->num_pages * FW_PAGE_SIZE;
465 total_pages += interface->num_pages;
466 }
467
468 /* Prepare PHDR of PT_NOTE type. */
469 fw_core_dump_fill_elf_program_header_note(&phdr, elf_prstatus_offset,
470 elf_prstatus_note_size);
471 seq_write(m, &phdr, sizeof(struct elf32_phdr));
472
473 /* Prepare ELF note of PRSTATUS type. */
474 if (fw_get_core_dump_mcu(kbdev, ®s))
475 dev_dbg(kbdev->dev, "MCU Registers not available, all registers set to zero");
476 /* Even if MCU Registers are not available the ELF prstatus is still
477 * filled with the registers equal to zero.
478 */
479 fw_core_dump_fill_elf_prstatus(&elf_prs, ®s);
480 elf_prstatus_note_size =
481 fw_core_dump_create_prstatus_note("CORE", &elf_prs, &elf_prstatus_note);
482 if (elf_prstatus_note_size == 0)
483 return -ENOMEM;
484
485 seq_write(m, elf_prstatus_note, elf_prstatus_note_size);
486 kfree(elf_prstatus_note);
487
488 /* Pad file to page size. */
489 padding = kzalloc(padding_size, GFP_KERNEL);
490 seq_write(m, padding, padding_size);
491 kfree(padding);
492
493 return 0;
494 }
495
496 /**
497 * fw_core_dump_create - Requests firmware to save state for a firmware core dump
498 * @kbdev: Instance of a GPU platform device that implements a CSF interface.
499 *
500 * Return: 0 on success, error code otherwise.
501 */
fw_core_dump_create(struct kbase_device * kbdev)502 static int fw_core_dump_create(struct kbase_device *kbdev)
503 {
504 int err;
505
506 /* Ensure MCU is active before requesting the core dump. */
507 kbase_csf_scheduler_pm_active(kbdev);
508 err = kbase_csf_scheduler_wait_mcu_active(kbdev);
509 if (!err)
510 err = kbase_csf_firmware_req_core_dump(kbdev);
511
512 kbase_csf_scheduler_pm_idle(kbdev);
513
514 return err;
515 }
516
517 /**
518 * fw_core_dump_seq_start - seq_file start operation for firmware core dump file
519 * @m: the seq_file handle
520 * @_pos: holds the current position in pages
521 * (0 or most recent position used in previous session)
522 *
523 * Starts a seq_file session, positioning the iterator for the session to page @_pos - 1
524 * within the firmware interface memory sections. @_pos value 0 is used to indicate the
525 * position of the ELF header at the start of the file.
526 *
527 * Retrieves the necessary information via the struct fw_core_dump_data stored in
528 * the private member of the seq_file handle.
529 *
530 * Return:
531 * * iterator pointer - pointer to iterator struct fw_core_dump_seq_off
532 * * SEQ_START_TOKEN - special iterator pointer indicating its is the start of the file
533 * * NULL - iterator could not be allocated
534 */
fw_core_dump_seq_start(struct seq_file * m,loff_t * _pos)535 static void *fw_core_dump_seq_start(struct seq_file *m, loff_t *_pos)
536 {
537 struct fw_core_dump_data *dump_data = m->private;
538 struct fw_core_dump_seq_off *data;
539 struct kbase_csf_firmware_interface *interface;
540 loff_t pos = *_pos;
541
542 if (pos == 0)
543 return SEQ_START_TOKEN;
544
545 /* Move iterator in the right position based on page number within
546 * available pages of firmware interface memory sections.
547 */
548 pos--; /* ignore start token */
549 list_for_each_entry(interface, &dump_data->kbdev->csf.firmware_interfaces, node) {
550 /* Skip memory sections that cannot be read or are protected. */
551 if ((interface->flags & CSF_FIRMWARE_ENTRY_PROTECTED) ||
552 (interface->flags & CSF_FIRMWARE_ENTRY_READ) == 0)
553 continue;
554
555 if (pos >= interface->num_pages) {
556 pos -= interface->num_pages;
557 } else {
558 data = kmalloc(sizeof(*data), GFP_KERNEL);
559 if (!data)
560 return NULL;
561 data->interface = interface;
562 data->page_num = pos;
563 return data;
564 }
565 }
566
567 return NULL;
568 }
569
570 /**
571 * fw_core_dump_seq_stop - seq_file stop operation for firmware core dump file
572 * @m: the seq_file handle
573 * @v: the current iterator (pointer to struct fw_core_dump_seq_off)
574 *
575 * Closes the current session and frees any memory related.
576 */
fw_core_dump_seq_stop(struct seq_file * m,void * v)577 static void fw_core_dump_seq_stop(struct seq_file *m, void *v)
578 {
579 kfree(v);
580 }
581
582 /**
583 * fw_core_dump_seq_next - seq_file next operation for firmware core dump file
584 * @m: the seq_file handle
585 * @v: the current iterator (pointer to struct fw_core_dump_seq_off)
586 * @pos: holds the current position in pages
587 * (0 or most recent position used in previous session)
588 *
589 * Moves the iterator @v forward to the next page within the firmware interface
590 * memory sections and returns the updated position in @pos.
591 * @v value SEQ_START_TOKEN indicates the ELF header position.
592 *
593 * Return:
594 * * iterator pointer - pointer to iterator struct fw_core_dump_seq_off
595 * * NULL - iterator could not be allocated
596 */
fw_core_dump_seq_next(struct seq_file * m,void * v,loff_t * pos)597 static void *fw_core_dump_seq_next(struct seq_file *m, void *v, loff_t *pos)
598 {
599 struct fw_core_dump_data *dump_data = m->private;
600 struct fw_core_dump_seq_off *data = v;
601 struct kbase_csf_firmware_interface *interface;
602 struct list_head *interfaces = &dump_data->kbdev->csf.firmware_interfaces;
603
604 /* Is current position at the ELF header ? */
605 if (v == SEQ_START_TOKEN) {
606 if (list_empty(interfaces))
607 return NULL;
608
609 /* Prepare iterator for starting at first page in firmware interface
610 * memory sections.
611 */
612 data = kmalloc(sizeof(*data), GFP_KERNEL);
613 if (!data)
614 return NULL;
615 data->interface =
616 list_first_entry(interfaces, struct kbase_csf_firmware_interface, node);
617 data->page_num = 0;
618 ++*pos;
619 return data;
620 }
621
622 /* First attempt to satisfy from current firmware interface memory section. */
623 interface = data->interface;
624 if (data->page_num + 1 < interface->num_pages) {
625 data->page_num++;
626 ++*pos;
627 return data;
628 }
629
630 /* Need next firmware interface memory section. This could be the last one. */
631 if (list_is_last(&interface->node, interfaces)) {
632 kfree(data);
633 return NULL;
634 }
635
636 /* Move to first page in next firmware interface memory section. */
637 data->interface = list_next_entry(interface, node);
638 data->page_num = 0;
639 ++*pos;
640
641 return data;
642 }
643
644 /**
645 * fw_core_dump_seq_show - seq_file show operation for firmware core dump file
646 * @m: the seq_file handle
647 * @v: the current iterator (pointer to struct fw_core_dump_seq_off)
648 *
649 * Writes the current page in a firmware interface memory section indicated
650 * by the iterator @v to the file. If @v is SEQ_START_TOKEN the ELF
651 * header is written.
652 *
653 * Return: 0 on success, error code otherwise.
654 */
fw_core_dump_seq_show(struct seq_file * m,void * v)655 static int fw_core_dump_seq_show(struct seq_file *m, void *v)
656 {
657 struct fw_core_dump_seq_off *data = v;
658 struct page *page;
659 u32 *p;
660
661 /* Either write the ELF header or current page. */
662 if (v == SEQ_START_TOKEN)
663 return fw_core_dump_write_elf_header(m);
664
665 /* Write the current page. */
666 page = as_page(data->interface->phys[data->page_num]);
667 p = kmap_atomic(page);
668 seq_write(m, p, FW_PAGE_SIZE);
669 kunmap_atomic(p);
670
671 return 0;
672 }
673
674 /* Sequence file operations for firmware core dump file. */
675 static const struct seq_operations fw_core_dump_seq_ops = {
676 .start = fw_core_dump_seq_start,
677 .next = fw_core_dump_seq_next,
678 .stop = fw_core_dump_seq_stop,
679 .show = fw_core_dump_seq_show,
680 };
681
682 /**
683 * fw_core_dump_debugfs_open - callback for opening the 'fw_core_dump' debugfs file
684 * @inode: inode of the file
685 * @file: file pointer
686 *
687 * Prepares for servicing a write request to request a core dump from firmware and
688 * a read request to retrieve the core dump.
689 *
690 * Returns an error if the firmware is not initialized yet.
691 *
692 * Return: 0 on success, error code otherwise.
693 */
fw_core_dump_debugfs_open(struct inode * inode,struct file * file)694 static int fw_core_dump_debugfs_open(struct inode *inode, struct file *file)
695 {
696 struct kbase_device *const kbdev = inode->i_private;
697 struct fw_core_dump_data *dump_data;
698 int ret;
699
700 /* Fail if firmware is not initialized yet. */
701 if (!kbdev->csf.firmware_inited) {
702 ret = -ENODEV;
703 goto open_fail;
704 }
705
706 /* Open a sequence file for iterating through the pages in the
707 * firmware interface memory pages. seq_open stores a
708 * struct seq_file * in the private_data field of @file.
709 */
710 ret = seq_open(file, &fw_core_dump_seq_ops);
711 if (ret)
712 goto open_fail;
713
714 /* Allocate a context for sequence file operations. */
715 dump_data = kmalloc(sizeof(*dump_data), GFP_KERNEL);
716 if (!dump_data) {
717 ret = -ENOMEM;
718 goto out;
719 }
720
721 /* Kbase device will be shared with sequence file operations. */
722 dump_data->kbdev = kbdev;
723
724 /* Link our sequence file context. */
725 ((struct seq_file *)file->private_data)->private = dump_data;
726
727 return 0;
728 out:
729 seq_release(inode, file);
730 open_fail:
731 return ret;
732 }
733
734 /**
735 * fw_core_dump_debugfs_write - callback for a write to the 'fw_core_dump' debugfs file
736 * @file: file pointer
737 * @ubuf: user buffer containing data to store
738 * @count: number of bytes in user buffer
739 * @ppos: file position
740 *
741 * Any data written to the file triggers a firmware core dump request which
742 * subsequently can be retrieved by reading from the file.
743 *
744 * Return: @count if the function succeeded. An error code on failure.
745 */
fw_core_dump_debugfs_write(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)746 static ssize_t fw_core_dump_debugfs_write(struct file *file, const char __user *ubuf, size_t count,
747 loff_t *ppos)
748 {
749 int err;
750 struct fw_core_dump_data *dump_data = ((struct seq_file *)file->private_data)->private;
751 struct kbase_device *const kbdev = dump_data->kbdev;
752
753 CSTD_UNUSED(ppos);
754
755 err = fw_core_dump_create(kbdev);
756
757 return err ? err : count;
758 }
759
760 /**
761 * fw_core_dump_debugfs_release - callback for releasing the 'fw_core_dump' debugfs file
762 * @inode: inode of the file
763 * @file: file pointer
764 *
765 * Return: 0 on success, error code otherwise.
766 */
fw_core_dump_debugfs_release(struct inode * inode,struct file * file)767 static int fw_core_dump_debugfs_release(struct inode *inode, struct file *file)
768 {
769 struct fw_core_dump_data *dump_data = ((struct seq_file *)file->private_data)->private;
770
771 seq_release(inode, file);
772
773 kfree(dump_data);
774
775 return 0;
776 }
777 /* Debugfs file operations for firmware core dump file. */
778 static const struct file_operations kbase_csf_fw_core_dump_fops = {
779 .owner = THIS_MODULE,
780 .open = fw_core_dump_debugfs_open,
781 .read = seq_read,
782 .write = fw_core_dump_debugfs_write,
783 .llseek = seq_lseek,
784 .release = fw_core_dump_debugfs_release,
785 };
786
kbase_csf_firmware_core_dump_init(struct kbase_device * const kbdev)787 void kbase_csf_firmware_core_dump_init(struct kbase_device *const kbdev)
788 {
789 #if IS_ENABLED(CONFIG_DEBUG_FS)
790 debugfs_create_file("fw_core_dump", 0600, kbdev->mali_debugfs_directory, kbdev,
791 &kbase_csf_fw_core_dump_fops);
792 #endif /* CONFIG_DEBUG_FS */
793 }
794
kbase_csf_firmware_core_dump_entry_parse(struct kbase_device * kbdev,const u32 * entry)795 int kbase_csf_firmware_core_dump_entry_parse(struct kbase_device *kbdev, const u32 *entry)
796 {
797 /* Casting to u16 as version is defined by bits 15:0 */
798 kbdev->csf.fw_core_dump.version = (u16)entry[FW_CORE_DUMP_VERSION_INDEX];
799
800 if (kbdev->csf.fw_core_dump.version != FW_CORE_DUMP_DATA_VERSION)
801 return -EPERM;
802
803 kbdev->csf.fw_core_dump.mcu_regs_addr = entry[FW_CORE_DUMP_START_ADDR_INDEX];
804 kbdev->csf.fw_core_dump.available = true;
805
806 return 0;
807 }
808