minidump: Parameterize minidumpsys()
The minidump code is written assuming that certain global state will not change, and rightly so, since it executes from a kernel debugger context. In order to support taking minidumps of a live system, we should allow copies of relevant global state that is likely to change to be passed as parameters to the minidumpsys() function. This patch does the work of parameterizing this function, by adding a struct minidumpstate argument. For now, this struct allows for copies of the kernel message buffer, and the bitset that tracks which pages should be dumped (vm_page_dump). Follow-up changes will actually make use of these arguments. Notably, dump_avail[] does not need a snapshot, since it is not expected to change after system initialization. The existing minidumpsys() definitions are renamed, and a thin MI wrapper is added to kern_dump.c, which handles the construction of the state struct. Thus, calling minidumpsys() remains as simple as before. Reviewed by: kib, markj, jhb Sponsored by: Juniper Networks, Inc. Sponsored by: Klara, Inc. MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D31989
This commit is contained in:
parent
840d72371b
commit
1adebe3cd6
@ -160,7 +160,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
|
|||||||
static pd_entry_t fakepd[NPDEPG];
|
static pd_entry_t fakepd[NPDEPG];
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
uint32_t pmapsize;
|
uint32_t pmapsize;
|
||||||
vm_offset_t va;
|
vm_offset_t va;
|
||||||
|
@ -153,7 +153,7 @@ static char dumpbuf[PAGE_SIZE] __aligned(sizeof(uint64_t));
|
|||||||
CTASSERT(sizeof(dumpbuf) % sizeof(pt2_entry_t) == 0);
|
CTASSERT(sizeof(dumpbuf) % sizeof(pt2_entry_t) == 0);
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
struct minidumphdr mdhdr;
|
struct minidumphdr mdhdr;
|
||||||
uint64_t dumpsize, *dump_avail_buf;
|
uint64_t dumpsize, *dump_avail_buf;
|
||||||
|
@ -52,9 +52,10 @@ enum cpu_class {
|
|||||||
extern enum cpu_class cpu_class;
|
extern enum cpu_class cpu_class;
|
||||||
|
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
|
struct minidumpstate;
|
||||||
extern int busdma_swi_pending;
|
extern int busdma_swi_pending;
|
||||||
void busdma_swi(void);
|
void busdma_swi(void);
|
||||||
int minidumpsys(struct dumperinfo *);
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
|
|
||||||
extern uint32_t initial_fpscr;
|
extern uint32_t initial_fpscr;
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
struct minidumphdr mdhdr;
|
struct minidumphdr mdhdr;
|
||||||
pd_entry_t *l0, *l1, *l2;
|
pd_entry_t *l0, *l1, *l2;
|
||||||
|
@ -44,10 +44,11 @@ extern u_long elf32_hwcap2;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
|
struct minidumpstate;
|
||||||
|
|
||||||
extern int busdma_swi_pending;
|
extern int busdma_swi_pending;
|
||||||
void busdma_swi(void);
|
void busdma_swi(void);
|
||||||
int minidumpsys(struct dumperinfo *);
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
void generic_bs_fault(void) __asm(__STRING(generic_bs_fault));
|
void generic_bs_fault(void) __asm(__STRING(generic_bs_fault));
|
||||||
void generic_bs_peek_1(void) __asm(__STRING(generic_bs_peek_1));
|
void generic_bs_peek_1(void) __asm(__STRING(generic_bs_peek_1));
|
||||||
void generic_bs_peek_2(void) __asm(__STRING(generic_bs_peek_2));
|
void generic_bs_peek_2(void) __asm(__STRING(generic_bs_peek_2));
|
||||||
|
@ -50,8 +50,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
CTASSERT(sizeof(struct kerneldumpheader) == 512);
|
CTASSERT(sizeof(struct kerneldumpheader) == 512);
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (pae_mode ? minidumpsys_pae(di) : minidumpsys_nopae(di));
|
return (pae_mode ? cpu_minidumpsys_pae(di, state) :
|
||||||
|
cpu_minidumpsys_nopae(di, state));
|
||||||
}
|
}
|
||||||
|
@ -145,15 +145,15 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
|
|||||||
static pt_entry_t fakept[NPTEPG];
|
static pt_entry_t fakept[NPTEPG];
|
||||||
|
|
||||||
#ifdef PMAP_PAE_COMP
|
#ifdef PMAP_PAE_COMP
|
||||||
#define minidumpsys minidumpsys_pae
|
#define cpu_minidumpsys cpu_minidumpsys_pae
|
||||||
#define IdlePTD IdlePTD_pae
|
#define IdlePTD IdlePTD_pae
|
||||||
#else
|
#else
|
||||||
#define minidumpsys minidumpsys_nopae
|
#define cpu_minidumpsys cpu_minidumpsys_nopae
|
||||||
#define IdlePTD IdlePTD_nopae
|
#define IdlePTD IdlePTD_nopae
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
uint64_t dumpsize;
|
uint64_t dumpsize;
|
||||||
uint32_t ptesize;
|
uint32_t ptesize;
|
||||||
|
@ -68,8 +68,8 @@ void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault));
|
|||||||
void fill_based_sd(struct segment_descriptor *sdp, uint32_t base);
|
void fill_based_sd(struct segment_descriptor *sdp, uint32_t base);
|
||||||
void i686_pagezero(void *addr);
|
void i686_pagezero(void *addr);
|
||||||
void sse2_pagezero(void *addr);
|
void sse2_pagezero(void *addr);
|
||||||
int minidumpsys_nopae(struct dumperinfo *);
|
int cpu_minidumpsys_nopae(struct dumperinfo *, const struct minidumpstate *);
|
||||||
int minidumpsys_pae(struct dumperinfo *);
|
int cpu_minidumpsys_pae(struct dumperinfo *, const struct minidumpstate *);
|
||||||
void init_AMD_Elan_sc520(void);
|
void init_AMD_Elan_sc520(void);
|
||||||
vm_paddr_t kvtop(void *addr);
|
vm_paddr_t kvtop(void *addr);
|
||||||
void panicifcpuunsupported(void);
|
void panicifcpuunsupported(void);
|
||||||
|
@ -32,15 +32,18 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/conf.h>
|
#include <sys/conf.h>
|
||||||
#include <sys/cons.h>
|
#include <sys/cons.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/proc.h>
|
|
||||||
#include <sys/kerneldump.h>
|
#include <sys/kerneldump.h>
|
||||||
|
#include <sys/msgbuf.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
#include <sys/watchdog.h>
|
#include <sys/watchdog.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_param.h>
|
#include <vm/vm_param.h>
|
||||||
#include <vm/vm_page.h>
|
#include <vm/vm_page.h>
|
||||||
#include <vm/vm_phys.h>
|
#include <vm/vm_phys.h>
|
||||||
#include <vm/vm_dumpset.h>
|
#include <vm/vm_dumpset.h>
|
||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <machine/dump.h>
|
#include <machine/dump.h>
|
||||||
#include <machine/elf.h>
|
#include <machine/elf.h>
|
||||||
#include <machine/md_var.h>
|
#include <machine/md_var.h>
|
||||||
@ -386,6 +389,8 @@ dumpsys_generic(struct dumperinfo *di)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MINIDUMP_PAGE_TRACKING == 1
|
||||||
|
|
||||||
/* Minidump progress bar */
|
/* Minidump progress bar */
|
||||||
static struct {
|
static struct {
|
||||||
const int min_per;
|
const int min_per;
|
||||||
@ -454,3 +459,18 @@ dumpsys_pb_progress(size_t delta)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
minidumpsys(struct dumperinfo *di)
|
||||||
|
{
|
||||||
|
struct minidumpstate state;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
state.msgbufp = msgbufp;
|
||||||
|
state.dump_bitset = vm_page_dump;
|
||||||
|
|
||||||
|
error = cpu_minidumpsys(di, &state);
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
#endif /* MINIDUMP_PAGE_TRACKING == 1 */
|
||||||
|
@ -82,6 +82,7 @@ extern int busdma_swi_pending;
|
|||||||
void busdma_swi(void);
|
void busdma_swi(void);
|
||||||
|
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
int minidumpsys(struct dumperinfo *);
|
struct minidumpstate;
|
||||||
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
|
|
||||||
#endif /* !_MACHINE_MD_VAR_H_ */
|
#endif /* !_MACHINE_MD_VAR_H_ */
|
||||||
|
@ -106,7 +106,7 @@ write_buffer(struct dumperinfo *di, char *ptr, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
struct minidumphdr mdhdr;
|
struct minidumphdr mdhdr;
|
||||||
uint64_t *dump_avail_buf;
|
uint64_t *dump_avail_buf;
|
||||||
|
@ -43,7 +43,8 @@ extern char sigcode64[], sigcode64_elfv2[];
|
|||||||
extern int szsigcode64, szsigcode64_elfv2;
|
extern int szsigcode64, szsigcode64_elfv2;
|
||||||
|
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
int minidumpsys(struct dumperinfo *);
|
struct minidumpstate;
|
||||||
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern long Maxmem;
|
extern long Maxmem;
|
||||||
|
@ -189,7 +189,7 @@ dump_pmap(struct dumperinfo *di)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
vm_paddr_t pa;
|
vm_paddr_t pa;
|
||||||
int error, retry_count;
|
int error, retry_count;
|
||||||
|
@ -42,8 +42,9 @@ extern register_t marchid;
|
|||||||
extern register_t mimpid;
|
extern register_t mimpid;
|
||||||
|
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
|
struct minidumpstate;
|
||||||
|
|
||||||
void busdma_swi(void);
|
void busdma_swi(void);
|
||||||
int minidumpsys(struct dumperinfo *);
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
|
|
||||||
#endif /* !_MACHINE_MD_VAR_H_ */
|
#endif /* !_MACHINE_MD_VAR_H_ */
|
||||||
|
@ -153,7 +153,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
minidumpsys(struct dumperinfo *di)
|
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
|
||||||
{
|
{
|
||||||
pd_entry_t *l1, *l2;
|
pd_entry_t *l1, *l2;
|
||||||
pt_entry_t *l3;
|
pt_entry_t *l3;
|
||||||
|
@ -135,6 +135,12 @@ struct dump_pa {
|
|||||||
vm_paddr_t pa_size;
|
vm_paddr_t pa_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct minidumpstate {
|
||||||
|
struct msgbuf *msgbufp;
|
||||||
|
struct bitset *dump_bitset;
|
||||||
|
};
|
||||||
|
|
||||||
|
int minidumpsys(struct dumperinfo *);
|
||||||
int dumpsys_generic(struct dumperinfo *);
|
int dumpsys_generic(struct dumperinfo *);
|
||||||
|
|
||||||
void dumpsys_map_chunk(vm_paddr_t, size_t, void **);
|
void dumpsys_map_chunk(vm_paddr_t, size_t, void **);
|
||||||
|
@ -104,6 +104,7 @@ struct fpreg;
|
|||||||
struct dbreg;
|
struct dbreg;
|
||||||
struct dumperinfo;
|
struct dumperinfo;
|
||||||
struct trapframe;
|
struct trapframe;
|
||||||
|
struct minidumpstate;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The interface type of the interrupt handler entry point cannot be
|
* The interface type of the interrupt handler entry point cannot be
|
||||||
@ -151,7 +152,7 @@ void pagecopy(void *from, void *to);
|
|||||||
void printcpuinfo(void);
|
void printcpuinfo(void);
|
||||||
int pti_get_default(void);
|
int pti_get_default(void);
|
||||||
int user_dbreg_trap(register_t dr6);
|
int user_dbreg_trap(register_t dr6);
|
||||||
int minidumpsys(struct dumperinfo *);
|
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
|
||||||
struct pcb *get_pcb_td(struct thread *td);
|
struct pcb *get_pcb_td(struct thread *td);
|
||||||
void x86_set_fork_retval(struct thread *td);
|
void x86_set_fork_retval(struct thread *td);
|
||||||
uint64_t rdtsc_ordered(void);
|
uint64_t rdtsc_ordered(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user