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

(cherry picked from commit 1adebe3cd6)
This commit is contained in:
Mitchell Horne 2021-11-17 11:26:59 -04:00
parent a6172e6353
commit eb2ea57ef1
17 changed files with 55 additions and 22 deletions

View File

@ -160,7 +160,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
static pd_entry_t fakepd[NPDEPG];
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
uint32_t pmapsize;
vm_offset_t va;

View File

@ -153,7 +153,7 @@ static char dumpbuf[PAGE_SIZE] __aligned(sizeof(uint64_t));
CTASSERT(sizeof(dumpbuf) % sizeof(pt2_entry_t) == 0);
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
struct minidumphdr mdhdr;
uint64_t dumpsize, *dump_avail_buf;

View File

@ -62,9 +62,10 @@ enum cpu_class {
extern enum cpu_class cpu_class;
struct dumperinfo;
struct minidumpstate;
extern int busdma_swi_pending;
void busdma_swi(void);
int minidumpsys(struct dumperinfo *);
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
extern uint32_t initial_fpscr;

View File

@ -147,7 +147,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
}
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
struct minidumphdr mdhdr;
pd_entry_t *l0, *l1, *l2;

View File

@ -44,10 +44,11 @@ extern u_long elf32_hwcap2;
#endif
struct dumperinfo;
struct minidumpstate;
extern int busdma_swi_pending;
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_peek_1(void) __asm(__STRING(generic_bs_peek_1));
void generic_bs_peek_2(void) __asm(__STRING(generic_bs_peek_2));

View File

@ -50,8 +50,9 @@ __FBSDID("$FreeBSD$");
CTASSERT(sizeof(struct kerneldumpheader) == 512);
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));
}

View File

@ -145,15 +145,15 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
static pt_entry_t fakept[NPTEPG];
#ifdef PMAP_PAE_COMP
#define minidumpsys minidumpsys_pae
#define IdlePTD IdlePTD_pae
#define cpu_minidumpsys cpu_minidumpsys_pae
#define IdlePTD IdlePTD_pae
#else
#define minidumpsys minidumpsys_nopae
#define IdlePTD IdlePTD_nopae
#define cpu_minidumpsys cpu_minidumpsys_nopae
#define IdlePTD IdlePTD_nopae
#endif
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
uint64_t dumpsize;
uint32_t ptesize;

View File

@ -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 i686_pagezero(void *addr);
void sse2_pagezero(void *addr);
int minidumpsys_nopae(struct dumperinfo *);
int minidumpsys_pae(struct dumperinfo *);
int cpu_minidumpsys_nopae(struct dumperinfo *, const struct minidumpstate *);
int cpu_minidumpsys_pae(struct dumperinfo *, const struct minidumpstate *);
void init_AMD_Elan_sc520(void);
vm_paddr_t kvtop(void *addr);
void panicifcpuunsupported(void);

View File

@ -32,15 +32,18 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/kerneldump.h>
#include <sys/msgbuf.h>
#include <sys/proc.h>
#include <sys/watchdog.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_phys.h>
#include <vm/vm_dumpset.h>
#include <vm/pmap.h>
#include <machine/dump.h>
#include <machine/elf.h>
#include <machine/md_var.h>
@ -386,6 +389,8 @@ dumpsys_generic(struct dumperinfo *di)
return (error);
}
#if MINIDUMP_PAGE_TRACKING == 1
/* Minidump progress bar */
static struct {
const int min_per;
@ -454,3 +459,18 @@ dumpsys_pb_progress(size_t delta)
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 */

View File

@ -82,6 +82,7 @@ extern int busdma_swi_pending;
void busdma_swi(void);
struct dumperinfo;
int minidumpsys(struct dumperinfo *);
struct minidumpstate;
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
#endif /* !_MACHINE_MD_VAR_H_ */

View File

@ -106,7 +106,7 @@ write_buffer(struct dumperinfo *di, char *ptr, size_t sz)
}
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
struct minidumphdr mdhdr;
uint64_t *dump_avail_buf;

View File

@ -43,7 +43,8 @@ extern char sigcode64[], sigcode64_elfv2[];
extern int szsigcode64, szsigcode64_elfv2;
struct dumperinfo;
int minidumpsys(struct dumperinfo *);
struct minidumpstate;
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
#endif
extern long Maxmem;

View File

@ -189,7 +189,7 @@ dump_pmap(struct dumperinfo *di)
}
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
vm_paddr_t pa;
int error, retry_count;

View File

@ -42,8 +42,9 @@ extern register_t marchid;
extern register_t mimpid;
struct dumperinfo;
struct minidumpstate;
void busdma_swi(void);
int minidumpsys(struct dumperinfo *);
int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
#endif /* !_MACHINE_MD_VAR_H_ */

View File

@ -153,7 +153,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
}
int
minidumpsys(struct dumperinfo *di)
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
{
pd_entry_t *l1, *l2;
pt_entry_t *l3;

View File

@ -135,6 +135,12 @@ struct dump_pa {
vm_paddr_t pa_size;
};
struct minidumpstate {
struct msgbuf *msgbufp;
struct bitset *dump_bitset;
};
int minidumpsys(struct dumperinfo *);
int dumpsys_generic(struct dumperinfo *);
void dumpsys_map_chunk(vm_paddr_t, size_t, void **);

View File

@ -103,6 +103,7 @@ struct fpreg;
struct dbreg;
struct dumperinfo;
struct trapframe;
struct minidumpstate;
/*
* The interface type of the interrupt handler entry point cannot be
@ -150,7 +151,7 @@ void pagecopy(void *from, void *to);
void printcpuinfo(void);
int pti_get_default(void);
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);
uint64_t rdtsc_ordered(void);