![Rahul Lakkireddy](/assets/img/avatar_default.png)
The sequence of actions done by device drivers to append their device specific hardware/firmware logs to /proc/vmcore are as follows: 1. During probe (before hardware is initialized), device drivers register to the vmcore module (via vmcore_add_device_dump()), with callback function, along with buffer size and log name needed for firmware/hardware log collection. 2. vmcore module allocates the buffer with requested size. It adds an Elf note and invokes the device driver's registered callback function. 3. Device driver collects all hardware/firmware logs into the buffer and returns control back to vmcore module. Ensure that the device dump buffer size is always aligned to page size so that it can be mmaped. Also, rename alloc_elfnotes_buf() to vmcore_alloc_buf() to make it more generic and reserve NT_VMCOREDD note type to indicate vmcore device dump. Suggested-by: Eric Biederman <ebiederm@xmission.com>. Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
115 lines
3.6 KiB
C
115 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef LINUX_CRASH_DUMP_H
|
|
#define LINUX_CRASH_DUMP_H
|
|
|
|
#include <linux/kexec.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/elf.h>
|
|
#include <uapi/linux/vmcore.h>
|
|
|
|
#include <asm/pgtable.h> /* for pgprot_t */
|
|
|
|
#ifdef CONFIG_CRASH_DUMP
|
|
#define ELFCORE_ADDR_MAX (-1ULL)
|
|
#define ELFCORE_ADDR_ERR (-2ULL)
|
|
|
|
extern unsigned long long elfcorehdr_addr;
|
|
extern unsigned long long elfcorehdr_size;
|
|
|
|
extern int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size);
|
|
extern void elfcorehdr_free(unsigned long long addr);
|
|
extern ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos);
|
|
extern ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos);
|
|
extern int remap_oldmem_pfn_range(struct vm_area_struct *vma,
|
|
unsigned long from, unsigned long pfn,
|
|
unsigned long size, pgprot_t prot);
|
|
|
|
extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
|
|
unsigned long, int);
|
|
void vmcore_cleanup(void);
|
|
|
|
/* Architecture code defines this if there are other possible ELF
|
|
* machine types, e.g. on bi-arch capable hardware. */
|
|
#ifndef vmcore_elf_check_arch_cross
|
|
#define vmcore_elf_check_arch_cross(x) 0
|
|
#endif
|
|
|
|
/*
|
|
* Architecture code can redefine this if there are any special checks
|
|
* needed for 32-bit ELF or 64-bit ELF vmcores. In case of 32-bit
|
|
* only architecture, vmcore_elf64_check_arch can be set to zero.
|
|
*/
|
|
#ifndef vmcore_elf32_check_arch
|
|
#define vmcore_elf32_check_arch(x) elf_check_arch(x)
|
|
#endif
|
|
|
|
#ifndef vmcore_elf64_check_arch
|
|
#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
|
|
#endif
|
|
|
|
/*
|
|
* is_kdump_kernel() checks whether this kernel is booting after a panic of
|
|
* previous kernel or not. This is determined by checking if previous kernel
|
|
* has passed the elf core header address on command line.
|
|
*
|
|
* This is not just a test if CONFIG_CRASH_DUMP is enabled or not. It will
|
|
* return true if CONFIG_CRASH_DUMP=y and if kernel is booting after a panic
|
|
* of previous kernel.
|
|
*/
|
|
|
|
static inline bool is_kdump_kernel(void)
|
|
{
|
|
return elfcorehdr_addr != ELFCORE_ADDR_MAX;
|
|
}
|
|
|
|
/* is_vmcore_usable() checks if the kernel is booting after a panic and
|
|
* the vmcore region is usable.
|
|
*
|
|
* This makes use of the fact that due to alignment -2ULL is not
|
|
* a valid pointer, much in the vain of IS_ERR(), except
|
|
* dealing directly with an unsigned long long rather than a pointer.
|
|
*/
|
|
|
|
static inline int is_vmcore_usable(void)
|
|
{
|
|
return is_kdump_kernel() && elfcorehdr_addr != ELFCORE_ADDR_ERR ? 1 : 0;
|
|
}
|
|
|
|
/* vmcore_unusable() marks the vmcore as unusable,
|
|
* without disturbing the logic of is_kdump_kernel()
|
|
*/
|
|
|
|
static inline void vmcore_unusable(void)
|
|
{
|
|
if (is_kdump_kernel())
|
|
elfcorehdr_addr = ELFCORE_ADDR_ERR;
|
|
}
|
|
|
|
#define HAVE_OLDMEM_PFN_IS_RAM 1
|
|
extern int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn));
|
|
extern void unregister_oldmem_pfn_is_ram(void);
|
|
|
|
#else /* !CONFIG_CRASH_DUMP */
|
|
static inline bool is_kdump_kernel(void) { return 0; }
|
|
#endif /* CONFIG_CRASH_DUMP */
|
|
|
|
extern unsigned long saved_max_pfn;
|
|
|
|
/* Device Dump information to be filled by drivers */
|
|
struct vmcoredd_data {
|
|
char dump_name[VMCOREDD_MAX_NAME_BYTES]; /* Unique name of the dump */
|
|
unsigned int size; /* Size of the dump */
|
|
/* Driver's registered callback to be invoked to collect dump */
|
|
int (*vmcoredd_callback)(struct vmcoredd_data *data, void *buf);
|
|
};
|
|
|
|
#ifdef CONFIG_PROC_VMCORE_DEVICE_DUMP
|
|
int vmcore_add_device_dump(struct vmcoredd_data *data);
|
|
#else
|
|
static inline int vmcore_add_device_dump(struct vmcoredd_data *data)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
#endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
|
|
#endif /* LINUX_CRASHDUMP_H */
|