View | Details | Raw Unified | Return to bug 193873 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/amd64/include/dump.h (+66 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	KERNELDUMP_VERSION	KERNELDUMP_AMD64_VERSION
34
#define	EM_VALUE		EM_X86_64
35
/* 20 phys_avail entry pairs correspond to 10 md_pa's */
36
#define	DUMPSYS_MD_PA_NPAIRS	10
37
38
static inline void
39
dumpsys_md_pa_init(void)
40
{
41
42
	dumpsys_gen_md_pa_init();
43
}
44
45
static inline struct md_pa *
46
dumpsys_md_pa_next(struct md_pa *p)
47
{
48
49
	return dumpsys_gen_md_pa_next(p);
50
}
51
52
static inline void
53
dumpsys_wbinv_all(void)
54
{
55
56
	dumpsys_gen_wbinv_all();
57
}
58
59
static inline void
60
dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
61
{
62
63
	dumpsys_gen_unmap_chunk(pa, s, va);
64
}
65
66
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/arm/arm/dump_machdep.c (-316 / +10 lines)
Lines 40-180 __FBSDID("$FreeBSD$"); Link Here
40
#ifdef SW_WATCHDOG
40
#ifdef SW_WATCHDOG
41
#include <sys/watchdog.h>
41
#include <sys/watchdog.h>
42
#endif
42
#endif
43
#include <vm/vm.h>
43
#include <vm/vm.h>
44
#include <vm/pmap.h>
44
#include <vm/pmap.h>
45
#include <machine/dump.h>
45
#include <machine/elf.h>
46
#include <machine/elf.h>
46
#include <machine/md_var.h>
47
#include <machine/md_var.h>
47
#include <machine/pcb.h>
48
#include <machine/pcb.h>
48
#include <machine/armreg.h>
49
#include <machine/armreg.h>
49
50
50
CTASSERT(sizeof(struct kerneldumpheader) == 512);
51
void
51
52
dumpsys_wbinv_all(void)
52
int do_minidump = 1;
53
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
54
    "Enable mini crash dumps");
55
56
/*
57
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
58
 * is to protect us from metadata and to protect metadata from us.
59
 */
60
#define	SIZEOF_METADATA		(64*1024)
61
62
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
63
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
64
extern struct pcb dumppcb;
65
66
struct md_pa {
67
	vm_paddr_t md_start;
68
	vm_paddr_t md_size;
69
};
70
71
typedef int callback_t(struct md_pa *, int, void *);
72
73
static struct kerneldumpheader kdh;
74
static off_t dumplo, fileofs;
75
76
/* Handle buffered writes. */
77
static char buffer[DEV_BSIZE];
78
static size_t fragsz;
79
80
/* XXX: I suppose 20 should be enough. */
81
static struct md_pa dump_map[20];
82
83
static void
84
md_pa_init(void)
85
{
86
	int n, idx;
87
88
	bzero(dump_map, sizeof(dump_map));
89
	for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
90
		idx = n * 2;
91
		if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
92
			break;
93
		dump_map[n].md_start = dump_avail[idx];
94
		dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
95
	}
96
}
97
98
static struct md_pa *
99
md_pa_first(void)
100
{
101
102
	return (&dump_map[0]);
103
}
104
105
static struct md_pa *
106
md_pa_next(struct md_pa *mdp)
107
{
53
{
108
54
109
	mdp++;
110
	if (mdp->md_size == 0)
111
		mdp = NULL;
112
	return (mdp);
113
}
114
115
static int
116
buf_write(struct dumperinfo *di, char *ptr, size_t sz)
117
{
118
	size_t len;
119
	int error;
120
121
	while (sz) {
122
		len = DEV_BSIZE - fragsz;
123
		if (len > sz)
124
			len = sz;
125
		bcopy(ptr, buffer + fragsz, len);
126
		fragsz += len;
127
		ptr += len;
128
		sz -= len;
129
		if (fragsz == DEV_BSIZE) {
130
			error = dump_write(di, buffer, 0, dumplo,
131
			    DEV_BSIZE);
132
			if (error)
133
				return error;
134
			dumplo += DEV_BSIZE;
135
			fragsz = 0;
136
		}
137
	}
138
139
	return (0);
140
}
141
142
static int
143
buf_flush(struct dumperinfo *di)
144
{
145
	int error;
146
147
	if (fragsz == 0)
148
		return (0);
149
150
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
151
	dumplo += DEV_BSIZE;
152
	fragsz = 0;
153
	return (error);
154
}
155
156
extern vm_offset_t kernel_l1kva;
157
extern char *pouet2;
158
159
static int
160
cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
161
{
162
	struct dumperinfo *di = (struct dumperinfo*)arg;
163
	vm_paddr_t pa;
164
	uint32_t pgs;
165
	size_t counter, sz, chunk;
166
	int c, error;
167
168
	error = 0;	/* catch case in which chunk size is 0 */
169
	counter = 0;
170
	pgs = mdp->md_size / PAGE_SIZE;
171
	pa = mdp->md_start;
172
173
	printf("  chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / (
174
	    1024*1024), pgs);
175
176
	/*
55
	/*
177
	 * Make sure we write coherent data.  Note that in the SMP case this
56
	 * Make sure we write coherent data.  Note that in the SMP case this
178
	 * only operates on the L1 cache of the current CPU, but all other CPUs
57
	 * only operates on the L1 cache of the current CPU, but all other CPUs
179
	 * have already been stopped, and their flush/invalidate was done as
58
	 * have already been stopped, and their flush/invalidate was done as
180
	 * part of stopping.
59
	 * part of stopping.
Lines 182-384 cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) Link Here
182
	cpu_idcache_wbinv_all();
61
	cpu_idcache_wbinv_all();
183
	cpu_l2cache_wbinv_all();
62
	cpu_l2cache_wbinv_all();
184
#ifdef __XSCALE__
63
#ifdef __XSCALE__
185
	xscale_cache_clean_minidata();
64
	xscale_cache_clean_minidata();
186
#endif
65
#endif
187
	while (pgs) {
188
		chunk = pgs;
189
		if (chunk > MAXDUMPPGS)
190
			chunk = MAXDUMPPGS;
191
		sz = chunk << PAGE_SHIFT;
192
		counter += sz;
193
		if (counter >> 24) {
194
			printf(" %d", pgs * PAGE_SIZE);
195
			counter &= (1<<24) - 1;
196
		}
197
		if (pa == (pa & L1_ADDR_BITS)) {
198
			pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
199
			cpu_tlb_flushID_SE(0);
200
			cpu_cpwait();
201
		}
202
#ifdef SW_WATCHDOG
203
		wdog_kern_pat(WD_LASTVAL);
204
#endif
205
		error = dump_write(di,
206
		    (void *)(pa - (pa & L1_ADDR_BITS)),0, dumplo, sz);
207
		if (error)
208
			break;
209
		dumplo += sz;
210
		pgs -= chunk;
211
		pa += sz;
212
213
		/* Check for user abort. */
214
		c = cncheckc();
215
		if (c == 0x03)
216
			return (ECANCELED);
217
		if (c != -1)
218
			printf(" (CTRL-C to abort) ");
219
	}
220
	printf(" ... %s\n", (error) ? "fail" : "ok");
221
	return (error);
222
}
223
224
static int
225
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
226
{
227
	struct dumperinfo *di = (struct dumperinfo*)arg;
228
	Elf_Phdr phdr;
229
	uint64_t size;
230
	int error;
231
232
	size = mdp->md_size;
233
	bzero(&phdr, sizeof(phdr));
234
	phdr.p_type = PT_LOAD;
235
	phdr.p_flags = PF_R;			/* XXX */
236
	phdr.p_offset = fileofs;
237
	phdr.p_vaddr = mdp->md_start;
238
	phdr.p_paddr = mdp->md_start;
239
	phdr.p_filesz = size;
240
	phdr.p_memsz = size;
241
	phdr.p_align = PAGE_SIZE;
242
243
	error = buf_write(di, (char*)&phdr, sizeof(phdr));
244
	fileofs += phdr.p_filesz;
245
	return (error);
246
}
66
}
247
67
248
static int
68
void
249
cb_size(struct md_pa *mdp, int seqnr, void *arg)
69
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
250
{
70
{
251
	uint32_t *sz = (uint32_t*)arg;
252
71
253
	*sz += (uint32_t)mdp->md_size;
72
	if (pa == (pa & L1_ADDR_BITS)) {
254
	return (0);
73
		pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
255
}
74
		cpu_tlb_flushID_SE(0);
256
75
		cpu_cpwait();
257
static int
258
foreach_chunk(callback_t cb, void *arg)
259
{
260
	struct md_pa *mdp;
261
	int error, seqnr;
262
263
	seqnr = 0;
264
	mdp = md_pa_first();
265
	while (mdp != NULL) {
266
		error = (*cb)(mdp, seqnr++, arg);
267
		if (error)
268
			return (-error);
269
		mdp = md_pa_next(mdp);
270
	}
76
	}
271
	return (seqnr);
77
	*va = (void *)(pa - (pa & L1_ADDR_BITS));
272
}
273
274
int
275
dumpsys(struct dumperinfo *di)
276
{
277
	Elf_Ehdr ehdr;
278
	uint32_t dumpsize;
279
	off_t hdrgap;
280
	size_t hdrsz;
281
	int error;
282
283
	if (do_minidump) {
284
		minidumpsys(di);
285
		return (0);
286
	}
287
288
	bzero(&ehdr, sizeof(ehdr));
289
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
290
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
291
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
292
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
293
	ehdr.e_ident[EI_CLASS] = ELF_CLASS;
294
#if BYTE_ORDER == LITTLE_ENDIAN
295
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
296
#else
297
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
298
#endif
299
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
300
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
301
	ehdr.e_type = ET_CORE;
302
	ehdr.e_machine = EM_ARM;
303
	ehdr.e_phoff = sizeof(ehdr);
304
	ehdr.e_flags = 0;
305
	ehdr.e_ehsize = sizeof(ehdr);
306
	ehdr.e_phentsize = sizeof(Elf_Phdr);
307
	ehdr.e_shentsize = sizeof(Elf_Shdr);
308
309
	md_pa_init();
310
311
	/* Calculate dump size. */
312
	dumpsize = 0L;
313
	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
314
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
315
	fileofs = MD_ALIGN(hdrsz);
316
	dumpsize += fileofs;
317
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
318
319
	/* Determine dump offset on device. */
320
	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
321
		error = ENOSPC;
322
		goto fail;
323
	}
324
	dumplo = di->mediaoffset + di->mediasize - dumpsize;
325
	dumplo -= sizeof(kdh) * 2;
326
327
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize, di->blocksize);
328
329
	printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
330
	    ehdr.e_phnum);
331
332
	/* Dump leader */
333
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
334
	if (error)
335
		goto fail;
336
	dumplo += sizeof(kdh);
337
338
	/* Dump ELF header */
339
	error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
340
	if (error)
341
		goto fail;
342
343
	/* Dump program headers */
344
	error = foreach_chunk(cb_dumphdr, di);
345
	if (error < 0)
346
		goto fail;
347
	buf_flush(di);
348
349
	/*
350
	 * All headers are written using blocked I/O, so we know the
351
	 * current offset is (still) block aligned. Skip the alignement
352
	 * in the file to have the segment contents aligned at page
353
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
354
	 * care and may very well be unaligned within the dump device.
355
	 */
356
	dumplo += hdrgap;
357
358
	/* Dump memory chunks (updates dumplo) */
359
	error = foreach_chunk(cb_dumpdata, di);
360
	if (error < 0)
361
		goto fail;
362
363
	/* Dump trailer */
364
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
365
	if (error)
366
		goto fail;
367
368
	/* Signal completion, signoff and exit stage left. */
369
	dump_write(di, NULL, 0, 0, 0);
370
	printf("\nDump complete\n");
371
	return (0);
372
373
 fail:
374
	if (error < 0)
375
		error = -error;
376
377
	if (error == ECANCELED)
378
		printf("\nDump aborted\n");
379
	else if (error == ENOSPC)
380
		printf("\nDump failed. Partition too small.\n");
381
	else
382
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
383
	return (error);
384
}
78
}
(-)b/sys/arm/include/dump.h (+61 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	KERNELDUMP_VERSION	KERNELDUMP_ARM_VERSION
34
#define	EM_VALUE		EM_ARM
35
/* XXX: I suppose 20 should be enough. */
36
#define	DUMPSYS_MD_PA_NPAIRS	20
37
38
void dumpsys_wbinv_all(void);
39
40
static inline void
41
dumpsys_md_pa_init(void)
42
{
43
44
	dumpsys_gen_md_pa_init();
45
}
46
47
static inline struct md_pa *
48
dumpsys_md_pa_next(struct md_pa *p)
49
{
50
51
	return dumpsys_gen_md_pa_next(p);
52
}
53
54
static inline void
55
dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
56
{
57
58
	dumpsys_gen_unmap_chunk(pa, s, va);
59
}
60
61
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/conf/files (+1 lines)
Lines 2929-2938 kern/kern_cons.c standard Link Here
2929
kern/kern_cpu.c			standard
2929
kern/kern_cpu.c			standard
2930
kern/kern_cpuset.c		standard
2930
kern/kern_cpuset.c		standard
2931
kern/kern_context.c		standard
2931
kern/kern_context.c		standard
2932
kern/kern_descrip.c		standard
2932
kern/kern_descrip.c		standard
2933
kern/kern_dtrace.c		optional kdtrace_hooks
2933
kern/kern_dtrace.c		optional kdtrace_hooks
2934
kern/kern_dump.c		standard
2934
kern/kern_environment.c		standard
2935
kern/kern_environment.c		standard
2935
kern/kern_et.c			standard
2936
kern/kern_et.c			standard
2936
kern/kern_event.c		standard
2937
kern/kern_event.c		standard
2937
kern/kern_exec.c		standard
2938
kern/kern_exec.c		standard
2938
kern/kern_exit.c		standard
2939
kern/kern_exit.c		standard
(-)b/sys/conf/files.powerpc (-1 lines)
Lines 181-191 powerpc/powerpc/copystr.c standard Link Here
181
powerpc/powerpc/cpu.c		standard
181
powerpc/powerpc/cpu.c		standard
182
powerpc/powerpc/db_disasm.c	optional	ddb
182
powerpc/powerpc/db_disasm.c	optional	ddb
183
powerpc/powerpc/db_hwwatch.c	optional	ddb
183
powerpc/powerpc/db_hwwatch.c	optional	ddb
184
powerpc/powerpc/db_interface.c	optional	ddb
184
powerpc/powerpc/db_interface.c	optional	ddb
185
powerpc/powerpc/db_trace.c	optional	ddb
185
powerpc/powerpc/db_trace.c	optional	ddb
186
powerpc/powerpc/dump_machdep.c	standard
187
powerpc/powerpc/elf32_machdep.c	optional	powerpc | compat_freebsd32
186
powerpc/powerpc/elf32_machdep.c	optional	powerpc | compat_freebsd32
188
powerpc/powerpc/elf64_machdep.c	optional	powerpc64
187
powerpc/powerpc/elf64_machdep.c	optional	powerpc64
189
powerpc/powerpc/exec_machdep.c	standard
188
powerpc/powerpc/exec_machdep.c	standard
190
powerpc/powerpc/fpu.c		standard
189
powerpc/powerpc/fpu.c		standard
191
powerpc/powerpc/fuswintr.c	standard
190
powerpc/powerpc/fuswintr.c	standard
(-)b/sys/i386/include/dump.h (+66 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	KERNELDUMP_VERSION	KERNELDUMP_I386_VERSION
34
#define	EM_VALUE		EM_386
35
/* 20 phys_avail entry pairs correspond to 10 md_pa's */
36
#define	DUMPSYS_MD_PA_NPAIRS	10
37
38
static inline void
39
dumpsys_md_pa_init(void)
40
{
41
42
	dumpsys_gen_md_pa_init();
43
}
44
45
static inline struct md_pa *
46
dumpsys_md_pa_next(struct md_pa *p)
47
{
48
49
	return dumpsys_gen_md_pa_next(p);
50
}
51
52
static inline void
53
dumpsys_wbinv_all(void)
54
{
55
56
	dumpsys_gen_wbinv_all();
57
}
58
59
static inline void
60
dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
61
{
62
63
	dumpsys_gen_unmap_chunk(pa, s, va);
64
}
65
66
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/kern/kern_dump.c (+397 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2002 Marcel Moolenaar
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <sys/cdefs.h>
28
__FBSDID("$FreeBSD$");
29
30
#include "opt_watchdog.h"
31
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/conf.h>
35
#include <sys/cons.h>
36
#include <sys/sysctl.h>
37
#include <sys/kernel.h>
38
#include <sys/proc.h>
39
#include <sys/kerneldump.h>
40
#ifdef SW_WATCHDOG
41
#include <sys/watchdog.h>
42
#endif
43
#include <vm/vm.h>
44
#include <vm/vm_param.h>
45
#include <vm/pmap.h>
46
#include <machine/dump.h>
47
#include <machine/elf.h>
48
#include <machine/md_var.h>
49
#include <machine/pcb.h>
50
51
CTASSERT(sizeof(struct kerneldumpheader) == 512);
52
53
#ifndef __sparc__
54
int do_minidump = 1;
55
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
56
    "Enable mini crash dumps");
57
#endif
58
59
/*
60
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
61
 * is to protect us from metadata and to protect metadata from us.
62
 */
63
#define	SIZEOF_METADATA		(64*1024)
64
65
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
66
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
67
68
off_t dumplo;
69
70
/* Handle buffered writes. */
71
static char buffer[DEV_BSIZE];
72
static size_t fragsz;
73
74
struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
75
76
#if !defined(__sparc__) && !defined(__powerpc__)
77
void
78
dumpsys_gen_md_pa_init(void)
79
{
80
	int n, idx;
81
82
	bzero(dump_map, sizeof(dump_map));
83
	for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
84
		idx = n * 2;
85
		if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
86
			break;
87
		dump_map[n].md_start = dump_avail[idx];
88
		dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
89
	}
90
}
91
#endif
92
93
struct md_pa *
94
dumpsys_gen_md_pa_next(struct md_pa *mdp)
95
{
96
97
	if (mdp == NULL)
98
		return (&dump_map[0]);
99
100
	mdp++;
101
	if (mdp->md_size == 0)
102
		mdp = NULL;
103
	return (mdp);
104
}
105
106
void
107
dumpsys_gen_wbinv_all(void)
108
{
109
110
	/* nop */;
111
}
112
113
void
114
dumpsys_gen_unmap_chunk(vm_paddr_t pa __unused, size_t chunk __unused,
115
    void *va __unused)
116
{
117
118
	/* nop */;
119
}
120
121
int
122
dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz)
123
{
124
	size_t len;
125
	int error;
126
127
	while (sz) {
128
		len = DEV_BSIZE - fragsz;
129
		if (len > sz)
130
			len = sz;
131
		bcopy(ptr, buffer + fragsz, len);
132
		fragsz += len;
133
		ptr += len;
134
		sz -= len;
135
		if (fragsz == DEV_BSIZE) {
136
			error = dump_write(di, buffer, 0, dumplo,
137
			    DEV_BSIZE);
138
			if (error)
139
				return error;
140
			dumplo += DEV_BSIZE;
141
			fragsz = 0;
142
		}
143
	}
144
145
	return (0);
146
}
147
148
int
149
dumpsys_buf_flush(struct dumperinfo *di)
150
{
151
	int error;
152
153
	if (fragsz == 0)
154
		return (0);
155
156
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
157
	dumplo += DEV_BSIZE;
158
	fragsz = 0;
159
	return (error);
160
}
161
162
CTASSERT(PAGE_SHIFT < 20);
163
#define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT))
164
165
int
166
dumpsys_cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
167
{
168
	struct dumperinfo *di = (struct dumperinfo*)arg;
169
	vm_paddr_t pa;
170
	void *va;
171
	uint64_t pgs;
172
	size_t counter, sz, chunk;
173
	int c, error, twiddle;
174
	u_int maxdumppgs;
175
176
	error = 0;	/* catch case in which chunk size is 0 */
177
	counter = 0;	/* Update twiddle every 16MB */
178
	twiddle = 0;
179
	va = 0;
180
	pgs = mdp->md_size / PAGE_SIZE;
181
	pa = mdp->md_start;
182
	maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS);
183
	if (maxdumppgs == 0)	/* seatbelt */
184
		maxdumppgs = 1;
185
186
	printf("  chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs),
187
	    (uintmax_t)pgs);
188
189
	dumpsys_wbinv_all();
190
	while (pgs) {
191
		chunk = pgs;
192
		if (chunk > maxdumppgs)
193
			chunk = maxdumppgs;
194
		sz = chunk << PAGE_SHIFT;
195
		counter += sz;
196
		if (counter >> 24) {
197
			printf(" %ju", (uintmax_t)PG2MB(pgs));
198
			counter &= (1<<24) - 1;
199
		}
200
201
		dumpsys_map_chunk(pa, chunk, &va);
202
#ifdef SW_WATCHDOG
203
		wdog_kern_pat(WD_LASTVAL);
204
#endif
205
206
		error = dump_write(di, va, 0, dumplo, sz);
207
		dumpsys_unmap_chunk(pa, chunk, va);
208
		if (error)
209
			break;
210
		dumplo += sz;
211
		pgs -= chunk;
212
		pa += sz;
213
214
		/* Check for user abort. */
215
		c = cncheckc();
216
		if (c == 0x03)
217
			return (ECANCELED);
218
		if (c != -1)
219
			printf(" (CTRL-C to abort) ");
220
	}
221
	printf(" ... %s\n", (error) ? "fail" : "ok");
222
	return (error);
223
}
224
225
int
226
dumpsys_foreach_chunk(dumpsys_callback_t cb, void *arg)
227
{
228
	struct md_pa *mdp;
229
	int error, seqnr;
230
231
	seqnr = 0;
232
	mdp = dumpsys_md_pa_next(NULL);
233
	while (mdp != NULL) {
234
		error = (*cb)(mdp, seqnr++, arg);
235
		if (error)
236
			return (-error);
237
		mdp = dumpsys_md_pa_next(mdp);
238
	}
239
	return (seqnr);
240
}
241
242
#ifndef DUMPSYS_HAS_MD_DUMPSYS
243
static off_t fileofs;
244
245
static int
246
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
247
{
248
	struct dumperinfo *di = (struct dumperinfo*)arg;
249
	Elf_Phdr phdr;
250
	uint64_t size;
251
	int error;
252
253
	size = mdp->md_size;
254
	bzero(&phdr, sizeof(phdr));
255
	phdr.p_type = PT_LOAD;
256
	phdr.p_flags = PF_R;			/* XXX */
257
	phdr.p_offset = fileofs;
258
#ifdef __powerpc__
259
	phdr.p_vaddr = (do_minidump? mdp->md_start : ~0L);
260
	phdr.p_paddr = (do_minidump? ~0L : mdp->md_start);
261
#else
262
	phdr.p_vaddr = mdp->md_start;
263
	phdr.p_paddr = mdp->md_start;
264
#endif
265
	phdr.p_filesz = size;
266
	phdr.p_memsz = size;
267
	phdr.p_align = PAGE_SIZE;
268
269
	error = dumpsys_buf_write(di, (char*)&phdr, sizeof(phdr));
270
	fileofs += phdr.p_filesz;
271
	return (error);
272
}
273
274
static int
275
cb_size(struct md_pa *mdp, int seqnr, void *arg)
276
{
277
	uint64_t *sz = (uint64_t*)arg;
278
279
	*sz += (uint64_t)mdp->md_size;
280
	return (0);
281
}
282
283
int
284
dumpsys(struct dumperinfo *di)
285
{
286
	struct kerneldumpheader kdh;
287
	Elf_Ehdr ehdr;
288
	uint64_t dumpsize;
289
	off_t hdrgap;
290
	size_t hdrsz;
291
	int error;
292
293
#ifndef __powerpc__
294
	if (do_minidump) {
295
		minidumpsys(di);
296
		return (0);
297
	}
298
#endif
299
	bzero(&ehdr, sizeof(ehdr));
300
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
301
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
302
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
303
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
304
	ehdr.e_ident[EI_CLASS] = ELF_CLASS;
305
#if BYTE_ORDER == LITTLE_ENDIAN
306
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
307
#else
308
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
309
#endif
310
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
311
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
312
	ehdr.e_type = ET_CORE;
313
	ehdr.e_machine = EM_VALUE;
314
	ehdr.e_phoff = sizeof(ehdr);
315
	ehdr.e_flags = 0;
316
	ehdr.e_ehsize = sizeof(ehdr);
317
	ehdr.e_phentsize = sizeof(Elf_Phdr);
318
	ehdr.e_shentsize = sizeof(Elf_Shdr);
319
320
	dumpsys_md_pa_init();
321
322
	/* Calculate dump size. */
323
	dumpsize = 0L;
324
	ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize);
325
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
326
	fileofs = MD_ALIGN(hdrsz);
327
	dumpsize += fileofs;
328
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
329
330
	/* Determine dump offset on device. */
331
	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
332
		error = ENOSPC;
333
		goto fail;
334
	}
335
	dumplo = di->mediaoffset + di->mediasize - dumpsize;
336
	dumplo -= sizeof(kdh) * 2;
337
338
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize,
339
	    di->blocksize);
340
341
	printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
342
	    ehdr.e_phnum);
343
344
	/* Dump leader */
345
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
346
	if (error)
347
		goto fail;
348
	dumplo += sizeof(kdh);
349
350
	/* Dump ELF header */
351
	error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr));
352
	if (error)
353
		goto fail;
354
355
	/* Dump program headers */
356
	error = dumpsys_foreach_chunk(cb_dumphdr, di);
357
	if (error < 0)
358
		goto fail;
359
	dumpsys_buf_flush(di);
360
361
	/*
362
	 * All headers are written using blocked I/O, so we know the
363
	 * current offset is (still) block aligned. Skip the alignement
364
	 * in the file to have the segment contents aligned at page
365
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
366
	 * care and may very well be unaligned within the dump device.
367
	 */
368
	dumplo += hdrgap;
369
370
	/* Dump memory chunks (updates dumplo) */
371
	error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
372
	if (error < 0)
373
		goto fail;
374
375
	/* Dump trailer */
376
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
377
	if (error)
378
		goto fail;
379
380
	/* Signal completion, signoff and exit stage left. */
381
	dump_write(di, NULL, 0, 0, 0);
382
	printf("\nDump complete\n");
383
	return (0);
384
385
 fail:
386
	if (error < 0)
387
		error = -error;
388
389
	if (error == ECANCELED)
390
		printf("\nDump aborted\n");
391
	else if (error == ENOSPC)
392
		printf("\nDump failed. Partition too small.\n");
393
	else
394
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
395
	return (error);
396
}
397
#endif  /* !DUMPSYS_HAS_MD_DUMPSYS */
(-)b/sys/mips/include/dump.h (+61 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	KERNELDUMP_VERSION	KERNELDUMP_MIPS_VERSION
34
#define	EM_VALUE		EM_MIPS
35
/* XXX: I suppose 20 should be enough. */
36
#define	DUMPSYS_MD_PA_NPAIRS	20
37
38
void dumpsys_wbinv_all(void);
39
40
static inline void
41
dumpsys_md_pa_init(void)
42
{
43
44
	dumpsys_gen_md_pa_init();
45
}
46
47
static inline struct md_pa *
48
dumpsys_md_pa_next(struct md_pa *p)
49
{
50
51
	return dumpsys_gen_md_pa_next(p);
52
}
53
54
static inline void
55
dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
56
{
57
58
	dumpsys_gen_unmap_chunk(pa, s, va);
59
}
60
61
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/mips/include/md_var.h (+1 lines)
Lines 78-83 void busdma_swi(void); Link Here
78
78
79
struct	dumperinfo;
79
struct	dumperinfo;
80
void	dump_add_page(vm_paddr_t);
80
void	dump_add_page(vm_paddr_t);
81
void	dump_drop_page(vm_paddr_t);
81
void	dump_drop_page(vm_paddr_t);
82
void	minidumpsys(struct dumperinfo *);
82
void	minidumpsys(struct dumperinfo *);
83
83
#endif /* !_MACHINE_MD_VAR_H_ */
84
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/mips/mips/dump_machdep.c (-312 / +7 lines)
Lines 40-370 __FBSDID("$FreeBSD$"); Link Here
40
#ifdef SW_WATCHDOG
40
#ifdef SW_WATCHDOG
41
#include <sys/watchdog.h>
41
#include <sys/watchdog.h>
42
#endif
42
#endif
43
#include <vm/vm.h>
43
#include <vm/vm.h>
44
#include <vm/pmap.h>
44
#include <vm/pmap.h>
45
#include <machine/dump.h>
45
#include <machine/elf.h>
46
#include <machine/elf.h>
46
#include <machine/md_var.h>
47
#include <machine/md_var.h>
47
#include <machine/pcb.h>
48
#include <machine/pcb.h>
48
#include <machine/cache.h>
49
#include <machine/cache.h>
49
50
50
CTASSERT(sizeof(struct kerneldumpheader) == 512);
51
void
51
52
dumpsys_wbinv_all(void)
52
int do_minidump = 1;
53
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
54
    "Enable mini crash dumps");
55
56
/*
57
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
58
 * is to protect us from metadata and to protect metadata from us.
59
 */
60
#define	SIZEOF_METADATA		(64*1024)
61
62
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
63
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
64
extern struct pcb dumppcb;
65
66
struct md_pa {
67
	vm_paddr_t md_start;
68
	vm_paddr_t md_size;
69
};
70
71
typedef int callback_t(struct md_pa *, int, void *);
72
73
static struct kerneldumpheader kdh;
74
static off_t dumplo, fileofs;
75
76
/* Handle buffered writes. */
77
static char buffer[DEV_BSIZE];
78
static size_t fragsz;
79
80
/* XXX: I suppose 20 should be enough. */
81
static struct md_pa dump_map[20];
82
83
static void
84
md_pa_init(void)
85
{
86
	int n, idx;
87
88
	bzero(dump_map, sizeof(dump_map));
89
	for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
90
		idx = n * 2;
91
		if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
92
			break;
93
		dump_map[n].md_start = dump_avail[idx];
94
		dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
95
	}
96
}
97
98
static struct md_pa *
99
md_pa_first(void)
100
{
101
102
	return (&dump_map[0]);
103
}
104
105
static struct md_pa *
106
md_pa_next(struct md_pa *mdp)
107
{
108
109
	mdp++;
110
	if (mdp->md_size == 0)
111
		mdp = NULL;
112
	return (mdp);
113
}
114
115
static int
116
buf_write(struct dumperinfo *di, char *ptr, size_t sz)
117
{
53
{
118
	size_t len;
119
	int error;
120
121
	while (sz) {
122
		len = DEV_BSIZE - fragsz;
123
		if (len > sz)
124
			len = sz;
125
		bcopy(ptr, buffer + fragsz, len);
126
		fragsz += len;
127
		ptr += len;
128
		sz -= len;
129
		if (fragsz == DEV_BSIZE) {
130
			error = dump_write(di, buffer, 0, dumplo,
131
			    DEV_BSIZE);
132
			if (error)
133
				return error;
134
			dumplo += DEV_BSIZE;
135
			fragsz = 0;
136
		}
137
	}
138
139
	return (0);
140
}
141
142
static int
143
buf_flush(struct dumperinfo *di)
144
{
145
	int error;
146
147
	if (fragsz == 0)
148
		return (0);
149
150
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
151
	dumplo += DEV_BSIZE;
152
	fragsz = 0;
153
	return (error);
154
}
155
156
extern vm_offset_t kernel_l1kva;
157
extern char *pouet2;
158
159
static int
160
cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
161
{
162
	struct dumperinfo *di = (struct dumperinfo*)arg;
163
	vm_paddr_t pa;
164
	uint32_t pgs;
165
	size_t counter, sz, chunk;
166
	int c, error;
167
168
	error = 0;	/* catch case in which chunk size is 0 */
169
	counter = 0;
170
	pgs = mdp->md_size / PAGE_SIZE;
171
	pa = mdp->md_start;
172
173
	printf("  chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / (
174
	    1024*1024), pgs);
175
54
176
	/* Make sure we write coherent datas. */
55
	/* Make sure we write coherent datas. */
177
	mips_dcache_wbinv_all();
56
	mips_dcache_wbinv_all();
178
	while (pgs) {
179
		chunk = pgs;
180
		if (chunk > MAXDUMPPGS)
181
			chunk = MAXDUMPPGS;
182
		sz = chunk << PAGE_SHIFT;
183
		counter += sz;
184
		if (counter >> 24) {
185
			printf(" %d", pgs * PAGE_SIZE);
186
			counter &= (1<<24) - 1;
187
		}
188
189
#ifdef SW_WATCHDOG
190
		wdog_kern_pat(WD_LASTVAL);
191
#endif
192
		error = dump_write(di, (void *)(intptr_t)(pa),0, dumplo, sz); /* XXX fix PA */
193
		if (error)
194
			break;
195
		dumplo += sz;
196
		pgs -= chunk;
197
		pa += sz;
198
199
		/* Check for user abort. */
200
		c = cncheckc();
201
		if (c == 0x03)
202
			return (ECANCELED);
203
		if (c != -1)
204
			printf(" (CTRL-C to abort) ");
205
	}
206
	printf(" ... %s\n", (error) ? "fail" : "ok");
207
	return (error);
208
}
209
210
static int
211
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
212
{
213
	struct dumperinfo *di = (struct dumperinfo*)arg;
214
	Elf_Phdr phdr;
215
	uint64_t size;
216
	int error;
217
218
	size = mdp->md_size;
219
	bzero(&phdr, sizeof(phdr));
220
	phdr.p_type = PT_LOAD;
221
	phdr.p_flags = PF_R;			/* XXX */
222
	phdr.p_offset = fileofs;
223
	phdr.p_vaddr = mdp->md_start;
224
	phdr.p_paddr = mdp->md_start;
225
	phdr.p_filesz = size;
226
	phdr.p_memsz = size;
227
	phdr.p_align = PAGE_SIZE;
228
229
	error = buf_write(di, (char*)&phdr, sizeof(phdr));
230
	fileofs += phdr.p_filesz;
231
	return (error);
232
}
233
234
static int
235
cb_size(struct md_pa *mdp, int seqnr, void *arg)
236
{
237
	uint32_t *sz = (uint32_t*)arg;
238
239
	*sz += (uint32_t)mdp->md_size;
240
	return (0);
241
}
242
243
static int
244
foreach_chunk(callback_t cb, void *arg)
245
{
246
	struct md_pa *mdp;
247
	int error, seqnr;
248
249
	seqnr = 0;
250
	mdp = md_pa_first();
251
	while (mdp != NULL) {
252
		error = (*cb)(mdp, seqnr++, arg);
253
		if (error)
254
			return (-error);
255
		mdp = md_pa_next(mdp);
256
	}
257
	return (seqnr);
258
}
57
}
259
58
260
int
59
void
261
dumpsys(struct dumperinfo *di)
60
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
262
{
61
{
263
	Elf_Ehdr ehdr;
264
	uint32_t dumpsize;
265
	off_t hdrgap;
266
	size_t hdrsz;
267
	int error;
268
269
	if (do_minidump) {
270
		minidumpsys(di);
271
		return (0);
272
	}
273
274
	bzero(&ehdr, sizeof(ehdr));
275
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
276
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
277
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
278
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
279
	ehdr.e_ident[EI_CLASS] = ELF_CLASS;
280
#if BYTE_ORDER == LITTLE_ENDIAN
281
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
282
#else
283
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
284
#endif
285
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
286
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
287
	ehdr.e_type = ET_CORE;
288
	ehdr.e_machine = EM_MIPS;
289
	ehdr.e_phoff = sizeof(ehdr);
290
	ehdr.e_flags = 0;
291
	ehdr.e_ehsize = sizeof(ehdr);
292
	ehdr.e_phentsize = sizeof(Elf_Phdr);
293
	ehdr.e_shentsize = sizeof(Elf_Shdr);
294
295
	md_pa_init();
296
297
	/* Calculate dump size. */
298
	dumpsize = 0L;
299
	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
300
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
301
	fileofs = MD_ALIGN(hdrsz);
302
	dumpsize += fileofs;
303
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
304
305
	/* Determine dump offset on device. */
306
	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
307
		error = ENOSPC;
308
		goto fail;
309
	}
310
	dumplo = di->mediaoffset + di->mediasize - dumpsize;
311
	dumplo -= sizeof(kdh) * 2;
312
313
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, dumpsize, di->blocksize);
314
315
	printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
316
	    ehdr.e_phnum);
317
318
	/* Dump leader */
319
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
320
	if (error)
321
		goto fail;
322
	dumplo += sizeof(kdh);
323
324
	/* Dump ELF header */
325
	error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
326
	if (error)
327
		goto fail;
328
329
	/* Dump program headers */
330
	error = foreach_chunk(cb_dumphdr, di);
331
	if (error < 0)
332
		goto fail;
333
	buf_flush(di);
334
335
	/*
336
	 * All headers are written using blocked I/O, so we know the
337
	 * current offset is (still) block aligned. Skip the alignement
338
	 * in the file to have the segment contents aligned at page
339
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
340
	 * care and may very well be unaligned within the dump device.
341
	 */
342
	dumplo += hdrgap;
343
344
	/* Dump memory chunks (updates dumplo) */
345
	error = foreach_chunk(cb_dumpdata, di);
346
	if (error < 0)
347
		goto fail;
348
349
	/* Dump trailer */
350
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
351
	if (error)
352
		goto fail;
353
354
	/* Signal completion, signoff and exit stage left. */
355
	dump_write(di, NULL, 0, 0, 0);
356
	printf("\nDump complete\n");
357
	return (0);
358
359
 fail:
360
	if (error < 0)
361
		error = -error;
362
62
363
	if (error == ECANCELED)
63
	/* XXX fix PA */
364
		printf("\nDump aborted\n");
64
	*va = (void*)(intptr_t)pa;
365
	else if (error == ENOSPC)
366
		printf("\nDump failed. Partition too small.\n");
367
	else
368
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
369
	return (error);
370
}
65
}
(-)b/sys/powerpc/aim/mmu_oea.c (-91 / +62 lines)
Lines 104-113 __FBSDID("$FreeBSD$"); Link Here
104
104
105
#include "opt_kstack_pages.h"
105
#include "opt_kstack_pages.h"
106
106
107
#include <sys/param.h>
107
#include <sys/param.h>
108
#include <sys/kernel.h>
108
#include <sys/kernel.h>
109
#include <sys/conf.h>
109
#include <sys/queue.h>
110
#include <sys/queue.h>
110
#include <sys/cpuset.h>
111
#include <sys/cpuset.h>
111
#include <sys/ktr.h>
112
#include <sys/ktr.h>
112
#include <sys/lock.h>
113
#include <sys/lock.h>
113
#include <sys/msgbuf.h>
114
#include <sys/msgbuf.h>
Lines 161-172 struct ofw_map { Link Here
161
};
162
};
162
163
163
extern unsigned char _etext[];
164
extern unsigned char _etext[];
164
extern unsigned char _end[];
165
extern unsigned char _end[];
165
166
166
extern int dumpsys_minidump;
167
168
/*
167
/*
169
 * Map of physical memory regions.
168
 * Map of physical memory regions.
170
 */
169
 */
171
static struct	mem_region *regions;
170
static struct	mem_region *regions;
172
static struct	mem_region *pregions;
171
static struct	mem_region *pregions;
Lines 312-324 vm_paddr_t moea_kextract(mmu_t, vm_offset_t); Link Here
312
void moea_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t);
311
void moea_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t);
313
void moea_kenter(mmu_t, vm_offset_t, vm_paddr_t);
312
void moea_kenter(mmu_t, vm_offset_t, vm_paddr_t);
314
void moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma);
313
void moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma);
315
boolean_t moea_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
314
boolean_t moea_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
316
static void moea_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
315
static void moea_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
317
vm_offset_t moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
316
void moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va);
318
    vm_size_t *sz);
317
void moea_scan_init(mmu_t mmu);
319
struct pmap_md * moea_scan_md(mmu_t mmu, struct pmap_md *prev);
320
318
321
static mmu_method_t moea_methods[] = {
319
static mmu_method_t moea_methods[] = {
322
	MMUMETHOD(mmu_clear_modify,	moea_clear_modify),
320
	MMUMETHOD(mmu_clear_modify,	moea_clear_modify),
323
	MMUMETHOD(mmu_copy_page,	moea_copy_page),
321
	MMUMETHOD(mmu_copy_page,	moea_copy_page),
324
	MMUMETHOD(mmu_copy_pages,	moea_copy_pages),
322
	MMUMETHOD(mmu_copy_pages,	moea_copy_pages),
Lines 361-371 static mmu_method_t moea_methods[] = { Link Here
361
	MMUMETHOD(mmu_unmapdev,		moea_unmapdev),
359
	MMUMETHOD(mmu_unmapdev,		moea_unmapdev),
362
	MMUMETHOD(mmu_kextract,		moea_kextract),
360
	MMUMETHOD(mmu_kextract,		moea_kextract),
363
	MMUMETHOD(mmu_kenter,		moea_kenter),
361
	MMUMETHOD(mmu_kenter,		moea_kenter),
364
	MMUMETHOD(mmu_kenter_attr,	moea_kenter_attr),
362
	MMUMETHOD(mmu_kenter_attr,	moea_kenter_attr),
365
	MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
363
	MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
366
	MMUMETHOD(mmu_scan_md,		moea_scan_md),
364
	MMUMETHOD(mmu_scan_init,	moea_scan_init),
367
	MMUMETHOD(mmu_dumpsys_map,	moea_dumpsys_map),
365
	MMUMETHOD(mmu_dumpsys_map,	moea_dumpsys_map),
368
366
369
	{ 0, 0 }
367
	{ 0, 0 }
370
};
368
};
371
369
Lines 2626-2727 moea_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz) Link Here
2626
		sz -= len;
2624
		sz -= len;
2627
	}
2625
	}
2628
	PMAP_UNLOCK(pm);
2626
	PMAP_UNLOCK(pm);
2629
}
2627
}
2630
2628
2631
vm_offset_t
2629
void
2632
moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2630
moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2633
    vm_size_t *sz)
2634
{
2631
{
2635
	if (md->md_vaddr == ~0UL)
2632
2636
	    return (md->md_paddr + ofs);
2633
	*va = (void *)pa;
2637
	else
2638
	    return (md->md_vaddr + ofs);
2639
}
2634
}
2640
2635
2641
struct pmap_md *
2636
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2642
moea_scan_md(mmu_t mmu, struct pmap_md *prev)
2637
2638
void
2639
moea_scan_init(mmu_t mmu)
2643
{
2640
{
2644
	static struct pmap_md md;
2645
	struct pvo_entry *pvo;
2641
	struct pvo_entry *pvo;
2646
	vm_offset_t va;
2642
	vm_offset_t va;
2647
 
2643
	int i;
2648
	if (dumpsys_minidump) {
2644
2649
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2645
	if (!do_minidump) {
2650
		if (prev == NULL) {
2646
		/* Initialize phys. segments for dumpsys(). */
2651
			/* 1st: kernel .data and .bss. */
2647
		memset(&dump_map, 0, sizeof(dump_map));
2652
			md.md_index = 1;
2648
		mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
2653
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2649
		for (i = 0; i < pregions_sz; i++) {
2654
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2650
			dump_map[i].md_start = pregions[i].mr_start;
2655
			return (&md);
2651
			dump_map[i].md_size = pregions[i].mr_size;
2656
		}
2652
		}
2657
		switch (prev->md_index) {
2653
		return;
2658
		case 1:
2654
	}
2659
			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2655
2660
			md.md_index = 2;
2656
	/* Virtual segments for minidumps: */
2661
			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
2657
	memset(&dump_map, 0, sizeof(dump_map));
2662
			md.md_size = round_page(msgbufp->msg_size);
2658
2659
	/* 1st: kernel .data and .bss. */
2660
	dump_map[0].md_start = trunc_page((uintptr_t)_etext);
2661
	dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
2662
2663
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2664
	dump_map[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
2665
	dump_map[1].md_size = round_page(msgbufp->msg_size);
2666
2667
	/* 3rd: kernel VM. */
2668
	va = dump_map[1].md_start + dump_map[1].md_size;
2669
	/* Find start of next chunk (from va). */
2670
	while (va < virtual_end) {
2671
		/* Don't dump the buffer cache. */
2672
		if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
2673
			va = kmi.buffer_eva;
2674
			continue;
2675
		}
2676
		pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL);
2677
		if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
2663
			break;
2678
			break;
2664
		case 2:
2679
		va += PAGE_SIZE;
2665
			/* 3rd: kernel VM. */
2680
	}
2666
			va = prev->md_vaddr + prev->md_size;
2681
	if (va < virtual_end) {
2667
			/* Find start of next chunk (from va). */
2682
		dump_map[2].md_start = va;
2668
			while (va < virtual_end) {
2683
		va += PAGE_SIZE;
2669
				/* Don't dump the buffer cache. */
2684
		/* Find last page in chunk. */
2670
				if (va >= kmi.buffer_sva &&
2685
		while (va < virtual_end) {
2671
				    va < kmi.buffer_eva) {
2686
			/* Don't run into the buffer cache. */
2672
					va = kmi.buffer_eva;
2687
			if (va == kmi.buffer_sva)
2673
					continue;
2674
				}
2675
				pvo = moea_pvo_find_va(kernel_pmap,
2676
				    va & ~ADDR_POFF, NULL);
2677
				if (pvo != NULL &&
2678
				    (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
2679
					break;
2680
				va += PAGE_SIZE;
2681
			}
2682
			if (va < virtual_end) {
2683
				md.md_vaddr = va;
2684
				va += PAGE_SIZE;
2685
				/* Find last page in chunk. */
2686
				while (va < virtual_end) {
2687
					/* Don't run into the buffer cache. */
2688
					if (va == kmi.buffer_sva)
2689
						break;
2690
					pvo = moea_pvo_find_va(kernel_pmap,
2691
					    va & ~ADDR_POFF, NULL);
2692
					if (pvo == NULL ||
2693
					    !(pvo->pvo_pte.pte.pte_hi & PTE_VALID))
2694
						break;
2695
					va += PAGE_SIZE;
2696
				}
2697
				md.md_size = va - md.md_vaddr;
2698
				break;
2688
				break;
2699
			}
2689
			pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF,
2700
			md.md_index = 3;
2690
			    NULL);
2701
			/* FALLTHROUGH */
2691
			if (pvo == NULL ||
2702
		default:
2692
			    !(pvo->pvo_pte.pte.pte_hi & PTE_VALID))
2703
			return (NULL);
2693
				break;
2704
		}
2694
			va += PAGE_SIZE;
2705
	} else { /* minidumps */
2706
		mem_regions(&pregions, &pregions_sz,
2707
		    &regions, &regions_sz);
2708
2709
		if (prev == NULL) {
2710
			/* first physical chunk. */
2711
			md.md_paddr = pregions[0].mr_start;
2712
			md.md_size = pregions[0].mr_size;
2713
			md.md_vaddr = ~0UL;
2714
			md.md_index = 1;
2715
		} else if (md.md_index < pregions_sz) {
2716
			md.md_paddr = pregions[md.md_index].mr_start;
2717
			md.md_size = pregions[md.md_index].mr_size;
2718
			md.md_vaddr = ~0UL;
2719
			md.md_index++;
2720
		} else {
2721
			/* There's no next physical chunk. */
2722
			return (NULL);
2723
		}
2695
		}
2696
		dump_map[2].md_size = va - dump_map[2].md_start;
2724
	}
2697
	}
2725
2726
	return (&md);
2727
}
2698
}
(-)b/sys/powerpc/aim/mmu_oea64.c (-88 / +62 lines)
Lines 105-114 __FBSDID("$FreeBSD$"); Link Here
105
#include "opt_compat.h"
105
#include "opt_compat.h"
106
#include "opt_kstack_pages.h"
106
#include "opt_kstack_pages.h"
107
107
108
#include <sys/param.h>
108
#include <sys/param.h>
109
#include <sys/kernel.h>
109
#include <sys/kernel.h>
110
#include <sys/conf.h>
110
#include <sys/queue.h>
111
#include <sys/queue.h>
111
#include <sys/cpuset.h>
112
#include <sys/cpuset.h>
112
#include <sys/ktr.h>
113
#include <sys/ktr.h>
113
#include <sys/lock.h>
114
#include <sys/lock.h>
114
#include <sys/msgbuf.h>
115
#include <sys/msgbuf.h>
Lines 185-196 struct ofw_map { Link Here
185
};
186
};
186
187
187
extern unsigned char _etext[];
188
extern unsigned char _etext[];
188
extern unsigned char _end[];
189
extern unsigned char _end[];
189
190
190
extern int dumpsys_minidump;
191
192
/*
191
/*
193
 * Map of physical memory regions.
192
 * Map of physical memory regions.
194
 */
193
 */
195
static struct	mem_region *regions;
194
static struct	mem_region *regions;
196
static struct	mem_region *pregions;
195
static struct	mem_region *pregions;
Lines 325-337 vm_paddr_t moea64_kextract(mmu_t, vm_offset_t); Link Here
325
void moea64_page_set_memattr(mmu_t, vm_page_t m, vm_memattr_t ma);
324
void moea64_page_set_memattr(mmu_t, vm_page_t m, vm_memattr_t ma);
326
void moea64_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t ma);
325
void moea64_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t ma);
327
void moea64_kenter(mmu_t, vm_offset_t, vm_paddr_t);
326
void moea64_kenter(mmu_t, vm_offset_t, vm_paddr_t);
328
boolean_t moea64_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
327
boolean_t moea64_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
329
static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
328
static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
330
vm_offset_t moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
329
void moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz,
331
    vm_size_t *sz);
330
    void **va);
332
struct pmap_md * moea64_scan_md(mmu_t mmu, struct pmap_md *prev);
331
void moea64_scan_init(mmu_t mmu);
333
332
334
static mmu_method_t moea64_methods[] = {
333
static mmu_method_t moea64_methods[] = {
335
	MMUMETHOD(mmu_clear_modify,	moea64_clear_modify),
334
	MMUMETHOD(mmu_clear_modify,	moea64_clear_modify),
336
	MMUMETHOD(mmu_copy_page,	moea64_copy_page),
335
	MMUMETHOD(mmu_copy_page,	moea64_copy_page),
337
	MMUMETHOD(mmu_copy_pages,	moea64_copy_pages),
336
	MMUMETHOD(mmu_copy_pages,	moea64_copy_pages),
Lines 373-383 static mmu_method_t moea64_methods[] = { Link Here
373
	MMUMETHOD(mmu_unmapdev,		moea64_unmapdev),
372
	MMUMETHOD(mmu_unmapdev,		moea64_unmapdev),
374
	MMUMETHOD(mmu_kextract,		moea64_kextract),
373
	MMUMETHOD(mmu_kextract,		moea64_kextract),
375
	MMUMETHOD(mmu_kenter,		moea64_kenter),
374
	MMUMETHOD(mmu_kenter,		moea64_kenter),
376
	MMUMETHOD(mmu_kenter_attr,	moea64_kenter_attr),
375
	MMUMETHOD(mmu_kenter_attr,	moea64_kenter_attr),
377
	MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
376
	MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
378
	MMUMETHOD(mmu_scan_md,		moea64_scan_md),
377
	MMUMETHOD(mmu_scan_init,	moea64_scan_init),
379
	MMUMETHOD(mmu_dumpsys_map,	moea64_dumpsys_map),
378
	MMUMETHOD(mmu_dumpsys_map,	moea64_dumpsys_map),
380
379
381
	{ 0, 0 }
380
	{ 0, 0 }
382
};
381
};
383
382
Lines 2610-2708 moea64_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz) Link Here
2610
		sz -= len;
2609
		sz -= len;
2611
	}
2610
	}
2612
	PMAP_UNLOCK(pm);
2611
	PMAP_UNLOCK(pm);
2613
}
2612
}
2614
2613
2615
vm_offset_t
2614
void
2616
moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2615
moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2617
    vm_size_t *sz)
2618
{
2616
{
2619
	if (md->md_vaddr == ~0UL)
2617
2620
	    return (md->md_paddr + ofs);
2618
	*va = (void *)pa;
2621
	else
2622
	    return (md->md_vaddr + ofs);
2623
}
2619
}
2624
2620
2625
struct pmap_md *
2621
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2626
moea64_scan_md(mmu_t mmu, struct pmap_md *prev)
2622
2623
void
2624
moea64_scan_init(mmu_t mmu)
2627
{
2625
{
2628
	static struct pmap_md md;
2629
	struct pvo_entry *pvo;
2626
	struct pvo_entry *pvo;
2630
	vm_offset_t va;
2627
	vm_offset_t va;
2631
 
2628
	int i;
2632
	if (dumpsys_minidump) {
2629
2633
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2630
	if (!do_minidump) {
2634
		if (prev == NULL) {
2631
		/* Initialize phys. segments for dumpsys(). */
2635
			/* 1st: kernel .data and .bss. */
2632
		memset(&dump_map, 0, sizeof(dump_map));
2636
			md.md_index = 1;
2633
		mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
2637
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2634
		for (i = 0; i < pregions_sz; i++) {
2638
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2635
			dump_map[i].md_start = pregions[i].mr_start;
2639
			return (&md);
2636
			dump_map[i].md_size = pregions[i].mr_size;
2640
		}
2637
		}
2641
		switch (prev->md_index) {
2638
		return;
2642
		case 1:
2639
	}
2643
			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2640
2644
			md.md_index = 2;
2641
	/* Virtual segments for minidumps: */
2645
			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
2642
	memset(&dump_map, 0, sizeof(dump_map));
2646
			md.md_size = round_page(msgbufp->msg_size);
2643
2644
	/* 1st: kernel .data and .bss. */
2645
	dump_map[0].md_start = trunc_page((uintptr_t)_etext);
2646
	dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
2647
2648
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2649
	dump_map[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
2650
	dump_map[1].md_size = round_page(msgbufp->msg_size);
2651
2652
	/* 3rd: kernel VM. */
2653
	va = dump_map[1].md_start + dump_map[1].md_size;
2654
	/* Find start of next chunk (from va). */
2655
	while (va < virtual_end) {
2656
		/* Don't dump the buffer cache. */
2657
		if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
2658
			va = kmi.buffer_eva;
2659
			continue;
2660
		}
2661
		pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF);
2662
		if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
2647
			break;
2663
			break;
2648
		case 2:
2664
		va += PAGE_SIZE;
2649
			/* 3rd: kernel VM. */
2665
	}
2650
			va = prev->md_vaddr + prev->md_size;
2666
	if (va < virtual_end) {
2651
			/* Find start of next chunk (from va). */
2667
		dump_map[2].md_start = va;
2652
			while (va < virtual_end) {
2668
		va += PAGE_SIZE;
2653
				/* Don't dump the buffer cache. */
2669
		/* Find last page in chunk. */
2654
				if (va >= kmi.buffer_sva &&
2670
		while (va < virtual_end) {
2655
				    va < kmi.buffer_eva) {
2671
			/* Don't run into the buffer cache. */
2656
					va = kmi.buffer_eva;
2672
			if (va == kmi.buffer_sva)
2657
					continue;
2658
				}
2659
				pvo = moea64_pvo_find_va(kernel_pmap,
2660
				    va & ~ADDR_POFF);
2661
				if (pvo != NULL &&
2662
				    (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
2663
					break;
2664
				va += PAGE_SIZE;
2665
			}
2666
			if (va < virtual_end) {
2667
				md.md_vaddr = va;
2668
				va += PAGE_SIZE;
2669
				/* Find last page in chunk. */
2670
				while (va < virtual_end) {
2671
					/* Don't run into the buffer cache. */
2672
					if (va == kmi.buffer_sva)
2673
						break;
2674
					pvo = moea64_pvo_find_va(kernel_pmap,
2675
					    va & ~ADDR_POFF);
2676
					if (pvo == NULL ||
2677
					    !(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
2678
						break;
2679
					va += PAGE_SIZE;
2680
				}
2681
				md.md_size = va - md.md_vaddr;
2682
				break;
2673
				break;
2683
			}
2674
			pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF);
2684
			md.md_index = 3;
2675
			if (pvo == NULL ||
2685
			/* FALLTHROUGH */
2676
			    !(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
2686
		default:
2677
				break;
2687
			return (NULL);
2678
			va += PAGE_SIZE;
2688
		}
2689
	} else { /* minidumps */
2690
		if (prev == NULL) {
2691
			/* first physical chunk. */
2692
			md.md_paddr = pregions[0].mr_start;
2693
			md.md_size = pregions[0].mr_size;
2694
			md.md_vaddr = ~0UL;
2695
			md.md_index = 1;
2696
		} else if (md.md_index < pregions_sz) {
2697
			md.md_paddr = pregions[md.md_index].mr_start;
2698
			md.md_size = pregions[md.md_index].mr_size;
2699
			md.md_vaddr = ~0UL;
2700
			md.md_index++;
2701
		} else {
2702
			/* There's no next physical chunk. */
2703
			return (NULL);
2704
		}
2679
		}
2680
		dump_map[2].md_size = va - dump_map[2].md_start;
2705
	}
2681
	}
2706
2707
	return (&md);
2708
}
2682
}
(-)b/sys/powerpc/booke/pmap.c (-115 / +99 lines)
Lines 50-59 Link Here
50
50
51
#include <sys/cdefs.h>
51
#include <sys/cdefs.h>
52
__FBSDID("$FreeBSD$");
52
__FBSDID("$FreeBSD$");
53
53
54
#include <sys/param.h>
54
#include <sys/param.h>
55
#include <sys/conf.h>
55
#include <sys/malloc.h>
56
#include <sys/malloc.h>
56
#include <sys/ktr.h>
57
#include <sys/ktr.h>
57
#include <sys/proc.h>
58
#include <sys/proc.h>
58
#include <sys/user.h>
59
#include <sys/user.h>
59
#include <sys/queue.h>
60
#include <sys/queue.h>
Lines 98-109 __FBSDID("$FreeBSD$"); Link Here
98
#define debugf(fmt, args...)
99
#define debugf(fmt, args...)
99
#endif
100
#endif
100
101
101
#define TODO			panic("%s: not implemented", __func__);
102
#define TODO			panic("%s: not implemented", __func__);
102
103
103
extern int dumpsys_minidump;
104
105
extern unsigned char _etext[];
104
extern unsigned char _etext[];
106
extern unsigned char _end[];
105
extern unsigned char _end[];
107
106
108
extern uint32_t *bootinfo;
107
extern uint32_t *bootinfo;
109
108
Lines 320-334 static void mmu_booke_kenter(mmu_t, vm_offset_t, vm_paddr_t); Link Here
320
static void		mmu_booke_kenter_attr(mmu_t, vm_offset_t, vm_paddr_t, vm_memattr_t);
319
static void		mmu_booke_kenter_attr(mmu_t, vm_offset_t, vm_paddr_t, vm_memattr_t);
321
static void		mmu_booke_kremove(mmu_t, vm_offset_t);
320
static void		mmu_booke_kremove(mmu_t, vm_offset_t);
322
static boolean_t	mmu_booke_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
321
static boolean_t	mmu_booke_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
323
static void		mmu_booke_sync_icache(mmu_t, pmap_t, vm_offset_t,
322
static void		mmu_booke_sync_icache(mmu_t, pmap_t, vm_offset_t,
324
    vm_size_t);
323
    vm_size_t);
325
static vm_offset_t	mmu_booke_dumpsys_map(mmu_t, struct pmap_md *,
324
static void		mmu_booke_dumpsys_map(mmu_t, vm_paddr_t pa, size_t,
326
    vm_size_t, vm_size_t *);
325
    void **);
327
static void		mmu_booke_dumpsys_unmap(mmu_t, struct pmap_md *,
326
static void		mmu_booke_dumpsys_unmap(mmu_t, vm_paddr_t pa, size_t,
328
    vm_size_t, vm_offset_t);
327
    void *);
329
static struct pmap_md	*mmu_booke_scan_md(mmu_t, struct pmap_md *);
328
static void		mmu_booke_scan_init(mmu_t);
330
329
331
static mmu_method_t mmu_booke_methods[] = {
330
static mmu_method_t mmu_booke_methods[] = {
332
	/* pmap dispatcher interface */
331
	/* pmap dispatcher interface */
333
	MMUMETHOD(mmu_clear_modify,	mmu_booke_clear_modify),
332
	MMUMETHOD(mmu_clear_modify,	mmu_booke_clear_modify),
334
	MMUMETHOD(mmu_copy,		mmu_booke_copy),
333
	MMUMETHOD(mmu_copy,		mmu_booke_copy),
Lines 379-389 static mmu_method_t mmu_booke_methods[] = { Link Here
379
	MMUMETHOD(mmu_unmapdev,		mmu_booke_unmapdev),
378
	MMUMETHOD(mmu_unmapdev,		mmu_booke_unmapdev),
380
379
381
	/* dumpsys() support */
380
	/* dumpsys() support */
382
	MMUMETHOD(mmu_dumpsys_map,	mmu_booke_dumpsys_map),
381
	MMUMETHOD(mmu_dumpsys_map,	mmu_booke_dumpsys_map),
383
	MMUMETHOD(mmu_dumpsys_unmap,	mmu_booke_dumpsys_unmap),
382
	MMUMETHOD(mmu_dumpsys_unmap,	mmu_booke_dumpsys_unmap),
384
	MMUMETHOD(mmu_scan_md,		mmu_booke_scan_md),
383
	MMUMETHOD(mmu_scan_init,	mmu_booke_scan_init),
385
384
386
	{ 0, 0 }
385
	{ 0, 0 }
387
};
386
};
388
387
389
MMU_DEF(booke_mmu, MMU_TYPE_BOOKE, mmu_booke_methods, 0);
388
MMU_DEF(booke_mmu, MMU_TYPE_BOOKE, mmu_booke_methods, 0);
Lines 2532-2674 mmu_booke_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size) Link Here
2532
	}
2531
	}
2533
2532
2534
	return (EFAULT);
2533
	return (EFAULT);
2535
}
2534
}
2536
2535
2537
vm_offset_t
2536
void
2538
mmu_booke_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2537
mmu_booke_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2539
    vm_size_t *sz)
2540
{
2538
{
2541
	vm_paddr_t pa, ppa;
2539
	vm_paddr_t ppa;
2542
	vm_offset_t va;
2540
	vm_offset_t ofs;
2543
	vm_size_t gran;
2541
	vm_size_t gran;
2544
2542
2545
	/* Raw physical memory dumps don't have a virtual address. */
2546
	if (md->md_vaddr == ~0UL) {
2547
		/* We always map a 256MB page at 256M. */
2548
		gran = 256 * 1024 * 1024;
2549
		pa = md->md_paddr + ofs;
2550
		ppa = pa & ~(gran - 1);
2551
		ofs = pa - ppa;
2552
		va = gran;
2553
		tlb1_set_entry(va, ppa, gran, _TLB_ENTRY_IO);
2554
		if (*sz > (gran - ofs))
2555
			*sz = gran - ofs;
2556
		return (va + ofs);
2557
	}
2558
2559
	/* Minidumps are based on virtual memory addresses. */
2543
	/* Minidumps are based on virtual memory addresses. */
2560
	va = md->md_vaddr + ofs;
2544
	if (do_minidump) {
2561
	if (va >= kernstart + kernsize) {
2545
		*va = (void *)pa;
2562
		gran = PAGE_SIZE - (va & PAGE_MASK);
2546
		return;
2563
		if (*sz > gran)
2564
			*sz = gran;
2565
	}
2547
	}
2566
	return (va);
2548
2549
	/* Raw physical memory dumps don't have a virtual address. */
2550
	/* We always map a 256MB page at 256M. */
2551
	gran = 256 * 1024 * 1024;
2552
	ppa = pa & ~(gran - 1);
2553
	ofs = pa - ppa;
2554
	*va = (void *)gran;
2555
	tlb1_set_entry((vm_offset_t)va, ppa, gran, _TLB_ENTRY_IO);
2556
2557
	if (sz > (gran - ofs))
2558
		tlb1_set_entry((vm_offset_t)(va + gran), ppa + gran, gran,
2559
		    _TLB_ENTRY_IO);
2567
}
2560
}
2568
2561
2569
void
2562
void
2570
mmu_booke_dumpsys_unmap(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2563
mmu_booke_dumpsys_unmap(mmu_t mmu, vm_paddr_t pa, size_t sz, void *va)
2571
    vm_offset_t va)
2572
{
2564
{
2565
	vm_paddr_t ppa;
2566
	vm_offset_t ofs;
2567
	vm_size_t gran;
2568
2569
	/* Minidumps are based on virtual memory addresses. */
2570
	/* Nothing to do... */
2571
	if (do_minidump)
2572
		return;
2573
2573
2574
	/* Raw physical memory dumps don't have a virtual address. */
2574
	/* Raw physical memory dumps don't have a virtual address. */
2575
	if (md->md_vaddr == ~0UL) {
2575
	tlb1_idx--;
2576
	tlb1[tlb1_idx].mas1 = 0;
2577
	tlb1[tlb1_idx].mas2 = 0;
2578
	tlb1[tlb1_idx].mas3 = 0;
2579
	tlb1_write_entry(tlb1_idx);
2580
2581
	gran = 256 * 1024 * 1024;
2582
	ppa = pa & ~(gran - 1);
2583
	ofs = pa - ppa;
2584
	if (sz > (gran - ofs)) {
2576
		tlb1_idx--;
2585
		tlb1_idx--;
2577
		tlb1[tlb1_idx].mas1 = 0;
2586
		tlb1[tlb1_idx].mas1 = 0;
2578
		tlb1[tlb1_idx].mas2 = 0;
2587
		tlb1[tlb1_idx].mas2 = 0;
2579
		tlb1[tlb1_idx].mas3 = 0;
2588
		tlb1[tlb1_idx].mas3 = 0;
2580
		tlb1_write_entry(tlb1_idx);
2589
		tlb1_write_entry(tlb1_idx);
2581
		return;
2582
	}
2590
	}
2583
 
2584
	/* Minidumps are based on virtual memory addresses. */
2585
	/* Nothing to do... */
2586
}
2591
}
2587
2592
2588
struct pmap_md *
2593
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2589
mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
2594
2595
void
2596
mmu_booke_scan_init(mmu_t mmu)
2590
{
2597
{
2591
	static struct pmap_md md;
2592
	pte_t *pte;
2593
	vm_offset_t va;
2598
	vm_offset_t va;
2594
 
2599
	pte_t *pte;
2595
	if (dumpsys_minidump) {
2600
	int i;
2596
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2601
2597
		if (prev == NULL) {
2602
	if (!do_minidump) {
2598
			/* 1st: kernel .data and .bss. */
2603
		/* Initialize phys. segments for dumpsys(). */
2599
			md.md_index = 1;
2604
		memset(&dump_map, 0, sizeof(dump_map));
2600
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2605
		mem_regions(&physmem_regions, &physmem_regions_sz, &availmem_regions,
2601
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2606
		    &availmem_regions_sz);
2602
			return (&md);
2607
		for (i = 0; i < physmem_regions_sz; i++) {
2608
			dump_map[i].md_start = physmem_regions[i].mr_start;
2609
			dump_map[i].md_size = physmem_regions[i].mr_size;
2610
		}
2611
		return;
2612
	}
2613
2614
	/* Virtual segments for minidumps: */
2615
	memset(&dump_map, 0, sizeof(dump_map));
2616
2617
	/* 1st: kernel .data and .bss. */
2618
	dump_map[0].md_start = trunc_page((uintptr_t)_etext);
2619
	dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
2620
2621
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2622
	dump_map[1].md_start = data_start;
2623
	dump_map[1].md_size = data_end - data_start;
2624
2625
	/* 3rd: kernel VM. */
2626
	va = dump_map[1].md_start + dump_map[1].md_size;
2627
	/* Find start of next chunk (from va). */
2628
	while (va < virtual_end) {
2629
		/* Don't dump the buffer cache. */
2630
		if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
2631
			va = kmi.buffer_eva;
2632
			continue;
2603
		}
2633
		}
2604
		switch (prev->md_index) {
2634
		pte = pte_find(mmu, kernel_pmap, va);
2605
		case 1:
2635
		if (pte != NULL && PTE_ISVALID(pte))
2606
			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2607
			md.md_index = 2;
2608
			md.md_vaddr = data_start;
2609
			md.md_size = data_end - data_start;
2610
			break;
2636
			break;
2611
		case 2:
2637
		va += PAGE_SIZE;
2612
			/* 3rd: kernel VM. */
2638
	}
2613
			va = prev->md_vaddr + prev->md_size;
2639
	if (va < virtual_end) {
2614
			/* Find start of next chunk (from va). */
2640
		dump_map[2].md_start = va;
2615
			while (va < virtual_end) {
2641
		va += PAGE_SIZE;
2616
				/* Don't dump the buffer cache. */
2642
		/* Find last page in chunk. */
2617
				if (va >= kmi.buffer_sva &&
2643
		while (va < virtual_end) {
2618
				    va < kmi.buffer_eva) {
2644
			/* Don't run into the buffer cache. */
2619
					va = kmi.buffer_eva;
2645
			if (va == kmi.buffer_sva)
2620
					continue;
2621
				}
2622
				pte = pte_find(mmu, kernel_pmap, va);
2623
				if (pte != NULL && PTE_ISVALID(pte))
2624
					break;
2625
				va += PAGE_SIZE;
2626
			}
2627
			if (va < virtual_end) {
2628
				md.md_vaddr = va;
2629
				va += PAGE_SIZE;
2630
				/* Find last page in chunk. */
2631
				while (va < virtual_end) {
2632
					/* Don't run into the buffer cache. */
2633
					if (va == kmi.buffer_sva)
2634
						break;
2635
					pte = pte_find(mmu, kernel_pmap, va);
2636
					if (pte == NULL || !PTE_ISVALID(pte))
2637
						break;
2638
					va += PAGE_SIZE;
2639
				}
2640
				md.md_size = va - md.md_vaddr;
2641
				break;
2646
				break;
2642
			}
2647
			pte = pte_find(mmu, kernel_pmap, va);
2643
			md.md_index = 3;
2648
			if (pte == NULL || !PTE_ISVALID(pte))
2644
			/* FALLTHROUGH */
2649
				break;
2645
		default:
2650
			va += PAGE_SIZE;
2646
			return (NULL);
2647
		}
2648
	} else { /* minidumps */
2649
		mem_regions(&physmem_regions, &physmem_regions_sz,
2650
		    &availmem_regions, &availmem_regions_sz);
2651
2652
		if (prev == NULL) {
2653
			/* first physical chunk. */
2654
			md.md_paddr = physmem_regions[0].mr_start;
2655
			md.md_size = physmem_regions[0].mr_size;
2656
			md.md_vaddr = ~0UL;
2657
			md.md_index = 1;
2658
		} else if (md.md_index < physmem_regions_sz) {
2659
			md.md_paddr = physmem_regions[md.md_index].mr_start;
2660
			md.md_size = physmem_regions[md.md_index].mr_size;
2661
			md.md_vaddr = ~0UL;
2662
			md.md_index++;
2663
		} else {
2664
			/* There's no next physical chunk. */
2665
			return (NULL);
2666
		}
2651
		}
2652
		dump_map[2].md_size = va - dump_map[2].md_start;
2667
	}
2653
	}
2668
2669
	return (&md);
2670
}
2654
}
2671
2655
2672
/*
2656
/*
2673
 * Map a set of physical memory pages into the kernel virtual address space.
2657
 * Map a set of physical memory pages into the kernel virtual address space.
2674
 * Return a pointer to where it is mapped. This routine is intended to be used
2658
 * Return a pointer to where it is mapped. This routine is intended to be used
(-)b/sys/powerpc/include/dump.h (+54 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	KERNELDUMP_VERSION	KERNELDUMP_POWERPC_VERSION
34
#define	EM_VALUE		ELF_ARCH /* Defined in powerpc/include/elf.h */
35
#define	DUMPSYS_MD_PA_NPAIRS	(PHYS_AVAIL_SZ + 1)
36
37
void dumpsys_md_pa_init(void);
38
void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *);
39
40
static inline struct md_pa *
41
dumpsys_md_pa_next(struct md_pa *p)
42
{
43
44
	return dumpsys_gen_md_pa_next(p);
45
}
46
47
static inline void
48
dumpsys_wbinv_all(void)
49
{
50
51
	dumpsys_gen_wbinv_all();
52
}
53
54
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/powerpc/include/pmap.h (-12 lines)
Lines 72-88 Link Here
72
#include <machine/sr.h>
72
#include <machine/sr.h>
73
#include <machine/pte.h>
73
#include <machine/pte.h>
74
#include <machine/slb.h>
74
#include <machine/slb.h>
75
#include <machine/tlb.h>
75
#include <machine/tlb.h>
76
76
77
struct pmap_md {
78
	u_int		md_index;
79
	vm_paddr_t      md_paddr;
80
	vm_offset_t     md_vaddr;
81
	vm_size_t       md_size;
82
};
83
84
#if defined(AIM)
77
#if defined(AIM)
85
78
86
#if !defined(NPMAPS)
79
#if !defined(NPMAPS)
87
#define	NPMAPS		32768
80
#define	NPMAPS		32768
88
#endif /* !defined(NPMAPS) */
81
#endif /* !defined(NPMAPS) */
Lines 250-264 extern vm_offset_t virtual_end; Link Here
250
243
251
extern	vm_offset_t msgbuf_phys;
244
extern	vm_offset_t msgbuf_phys;
252
245
253
extern	int pmap_bootstrapped;
246
extern	int pmap_bootstrapped;
254
247
255
extern vm_offset_t pmap_dumpsys_map(struct pmap_md *, vm_size_t, vm_size_t *);
256
extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t);
257
258
extern struct pmap_md *pmap_scan_md(struct pmap_md *);
259
260
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
248
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
261
249
262
#endif
250
#endif
263
251
264
#endif /* !_MACHINE_PMAP_H_ */
252
#endif /* !_MACHINE_PMAP_H_ */
(-)a/sys/powerpc/powerpc/dump_machdep.c (-315 lines)
Removed Link Here
1
/*-
2
 * Copyright (c) 2002 Marcel Moolenaar
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <sys/cdefs.h>
28
__FBSDID("$FreeBSD$");
29
30
#include "opt_watchdog.h"
31
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/conf.h>
35
#include <sys/cons.h>
36
#include <sys/kernel.h>
37
#include <sys/kerneldump.h>
38
#include <sys/sysctl.h>
39
#ifdef SW_WATCHDOG
40
#include <sys/watchdog.h>
41
#endif
42
#include <vm/vm.h>
43
#include <vm/pmap.h>
44
#include <machine/elf.h>
45
#include <machine/md_var.h>
46
47
CTASSERT(sizeof(struct kerneldumpheader) == 512);
48
49
/*
50
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
51
 * is to protect us from metadata and to protect metadata from us.
52
 */
53
#define	SIZEOF_METADATA		(64*1024)
54
55
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
56
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
57
58
typedef int callback_t(struct pmap_md *, int, void *);
59
60
static struct kerneldumpheader kdh;
61
static off_t dumplo, fileofs;
62
63
/* Handle buffered writes. */
64
static char buffer[DEV_BSIZE];
65
static size_t fragsz;
66
67
int dumpsys_minidump = 1;
68
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RD, &dumpsys_minidump, 0,
69
    "Kernel makes compressed crash dumps");
70
71
static int
72
buf_write(struct dumperinfo *di, char *ptr, size_t sz)
73
{
74
	size_t len;
75
	int error;
76
77
	while (sz) {
78
		len = DEV_BSIZE - fragsz;
79
		if (len > sz)
80
			len = sz;
81
		bcopy(ptr, buffer + fragsz, len);
82
		fragsz += len;
83
		ptr += len;
84
		sz -= len;
85
		if (fragsz == DEV_BSIZE) {
86
			error = di->dumper(di->priv, buffer, 0, dumplo,
87
			    DEV_BSIZE);
88
			if (error)
89
				return error;
90
			dumplo += DEV_BSIZE;
91
			fragsz = 0;
92
		}
93
	}
94
95
	return (0);
96
}
97
98
static int
99
buf_flush(struct dumperinfo *di)
100
{
101
	int error;
102
103
	if (fragsz == 0)
104
		return (0);
105
106
	error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
107
	dumplo += DEV_BSIZE;
108
	fragsz = 0;
109
	return (error);
110
}
111
112
static int
113
cb_dumpdata(struct pmap_md *md, int seqnr, void *arg)
114
{
115
	struct dumperinfo *di = (struct dumperinfo*)arg;
116
	vm_offset_t va;
117
	size_t counter, ofs, resid, sz, maxsz;
118
	int c, error, twiddle;
119
120
	error = 0;
121
	counter = 0;	/* Update twiddle every 16MB */
122
	twiddle = 0;
123
124
	ofs = 0;	/* Logical offset within the chunk */
125
	resid = md->md_size;
126
	maxsz = min(DFLTPHYS, di->maxiosize);
127
128
	printf("  chunk %d: %lu bytes ", seqnr, (u_long)resid);
129
130
	while (resid) {
131
		sz = min(resid, maxsz);
132
		va = pmap_dumpsys_map(md, ofs, &sz);
133
		counter += sz;
134
		if (counter >> 24) {
135
			printf("%c\b", "|/-\\"[twiddle++ & 3]);
136
			counter &= (1<<24) - 1;
137
		}
138
#ifdef SW_WATCHDOG
139
		wdog_kern_pat(WD_LASTVAL);
140
#endif
141
		error = di->dumper(di->priv, (void*)va, 0, dumplo, sz);
142
		pmap_dumpsys_unmap(md, ofs, va);
143
		if (error)
144
			break;
145
		dumplo += sz;
146
		resid -= sz;
147
		ofs += sz;
148
149
		/* Check for user abort. */
150
		c = cncheckc();
151
		if (c == 0x03)
152
			return (ECANCELED);
153
		if (c != -1)
154
			printf("(CTRL-C to abort)  ");
155
	}
156
	printf("... %s\n", (error) ? "fail" : "ok");
157
	return (error);
158
}
159
160
static int
161
cb_dumphdr(struct pmap_md *md, int seqnr, void *arg)
162
{
163
	struct dumperinfo *di = (struct dumperinfo*)arg;
164
	Elf_Phdr phdr;
165
	int error;
166
167
	bzero(&phdr, sizeof(phdr));
168
	phdr.p_type = PT_LOAD;
169
	phdr.p_flags = PF_R;			/* XXX */
170
	phdr.p_offset = fileofs;
171
	phdr.p_vaddr = md->md_vaddr;
172
	phdr.p_paddr = md->md_paddr;
173
	phdr.p_filesz = md->md_size;
174
	phdr.p_memsz = md->md_size;
175
	phdr.p_align = PAGE_SIZE;
176
177
	error = buf_write(di, (char*)&phdr, sizeof(phdr));
178
	fileofs += phdr.p_filesz;
179
	return (error);
180
}
181
182
static int
183
cb_size(struct pmap_md *md, int seqnr, void *arg)
184
{
185
	uint32_t *sz = (uint32_t*)arg;
186
187
	*sz += md->md_size;
188
	return (0);
189
}
190
191
static int
192
foreach_chunk(callback_t cb, void *arg)
193
{
194
	struct pmap_md *md;
195
	int error, seqnr;
196
197
	seqnr = 0;
198
	md = pmap_scan_md(NULL);
199
	while (md != NULL) {
200
		error = (*cb)(md, seqnr++, arg);
201
		if (error)
202
			return (-error);
203
		md = pmap_scan_md(md);
204
	}
205
	return (seqnr);
206
}
207
208
int
209
dumpsys(struct dumperinfo *di)
210
{
211
	Elf_Ehdr ehdr;
212
	uint32_t dumpsize;
213
	off_t hdrgap;
214
	size_t hdrsz;
215
	int error;
216
217
	bzero(&ehdr, sizeof(ehdr));
218
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
219
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
220
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
221
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
222
	ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS;
223
#if BYTE_ORDER == LITTLE_ENDIAN
224
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
225
#else
226
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
227
#endif
228
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
229
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
230
	ehdr.e_type = ET_CORE;
231
	ehdr.e_machine = ELF_ARCH;      /* Defined in powerpc/include/elf.h */
232
	ehdr.e_phoff = sizeof(ehdr);
233
	ehdr.e_ehsize = sizeof(ehdr);
234
	ehdr.e_phentsize = sizeof(Elf_Phdr);
235
	ehdr.e_shentsize = sizeof(Elf_Shdr);
236
237
	/* Calculate dump size. */
238
	dumpsize = 0L;
239
	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
240
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
241
	fileofs = MD_ALIGN(hdrsz);
242
	dumpsize += fileofs;
243
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
244
245
	/* For block devices, determine the dump offset on the device. */
246
	if (di->mediasize > 0) {
247
		if (di->mediasize <
248
		    SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
249
			error = ENOSPC;
250
			goto fail;
251
		}
252
		dumplo = di->mediaoffset + di->mediasize - dumpsize;
253
		dumplo -= sizeof(kdh) * 2;
254
	} else
255
		dumplo = 0;
256
257
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_POWERPC_VERSION, dumpsize,
258
	    di->blocksize);
259
260
	printf("Dumping %u MB (%d chunks)\n", dumpsize >> 20,
261
	    ehdr.e_phnum);
262
263
	/* Dump leader */
264
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
265
	if (error)
266
		goto fail;
267
	dumplo += sizeof(kdh);
268
269
	/* Dump ELF header */
270
	error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
271
	if (error)
272
		goto fail;
273
274
	/* Dump program headers */
275
	error = foreach_chunk(cb_dumphdr, di);
276
	if (error < 0)
277
		goto fail;
278
	buf_flush(di);
279
280
	/*
281
	 * All headers are written using blocked I/O, so we know the
282
	 * current offset is (still) block aligned. Skip the alignement
283
	 * in the file to have the segment contents aligned at page
284
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
285
	 * care and may very well be unaligned within the dump device.
286
	 */
287
	dumplo += hdrgap;
288
289
	/* Dump memory chunks (updates dumplo) */
290
	error = foreach_chunk(cb_dumpdata, di);
291
	if (error < 0)
292
		goto fail;
293
294
	/* Dump trailer */
295
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
296
	if (error)
297
		goto fail;
298
299
	/* Signal completion, signoff and exit stage left. */
300
	dump_write(di, NULL, 0, 0, 0);
301
	printf("\nDump complete\n");
302
	return (0);
303
304
 fail:
305
	if (error < 0)
306
		error = -error;
307
308
	if (error == ECANCELED)
309
		printf("\nDump aborted\n");
310
	else if (error == ENOSPC)
311
		printf("\nDump failed. Partition too small.\n");
312
	else
313
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
314
	return (error);
315
}
(-)b/sys/powerpc/powerpc/mmu_if.m (-29 / +14 lines)
Lines 105-119 CODE { Link Here
105
	    vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
105
	    vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
106
	{
106
	{
107
		return;
107
		return;
108
	}
108
	}
109
109
110
	static struct pmap_md *mmu_null_scan_md(mmu_t mmu, struct pmap_md *p)
111
	{
112
		return (NULL);
113
	}
114
115
	static void *mmu_null_mapdev_attr(mmu_t mmu, vm_offset_t pa,
110
	static void *mmu_null_mapdev_attr(mmu_t mmu, vm_offset_t pa,
116
	    vm_size_t size, vm_memattr_t ma)
111
	    vm_size_t size, vm_memattr_t ma)
117
	{
112
	{
118
		return MMU_MAPDEV(mmu, pa, size);
113
		return MMU_MAPDEV(mmu, pa, size);
119
	}
114
	}
Lines 903-950 METHOD void sync_icache { Link Here
903
898
904
899
905
/**
900
/**
906
 * @brief Create temporary memory mapping for use by dumpsys().
901
 * @brief Create temporary memory mapping for use by dumpsys().
907
 *
902
 *
908
 * @param _md		The memory chunk in which the mapping lies.
903
 * @param _pa		The physical page to map.
909
 * @param _ofs		The offset within the chunk of the mapping.
910
 * @param _sz		The requested size of the mapping.
904
 * @param _sz		The requested size of the mapping.
911
 *
905
 * @param _va		The virtual address of the mapping.
912
 * @retval vm_offset_t	The virtual address of the mapping.
913
 *			
914
 * The sz argument is modified to reflect the actual size of the
915
 * mapping.
916
 */
906
 */
917
METHOD vm_offset_t dumpsys_map {
907
METHOD void dumpsys_map {
918
	mmu_t		_mmu;
908
	mmu_t		_mmu;
919
	struct pmap_md	*_md;
909
	vm_paddr_t	_pa;
920
	vm_size_t	_ofs;
910
	size_t		_sz;
921
	vm_size_t	*_sz;
911
	void		**_va;
922
};
912
};
923
913
924
914
925
/**
915
/**
926
 * @brief Remove temporary dumpsys() mapping.
916
 * @brief Remove temporary dumpsys() mapping.
927
 *
917
 *
928
 * @param _md		The memory chunk in which the mapping lies.
918
 * @param _pa		The physical page to map.
929
 * @param _ofs		The offset within the chunk of the mapping.
919
 * @param _sz		The requested size of the mapping.
930
 * @param _va		The virtual address of the mapping.
920
 * @param _va		The virtual address of the mapping.
931
 */
921
 */
932
METHOD void dumpsys_unmap {
922
METHOD void dumpsys_unmap {
933
	mmu_t		_mmu;
923
	mmu_t		_mmu;
934
	struct pmap_md	*_md;
924
	vm_paddr_t	_pa;
935
	vm_size_t	_ofs;
925
	size_t		_sz;
936
	vm_offset_t	_va;
926
	void		*_va;
937
};
927
};
938
928
939
929
940
/**
930
/**
941
 * @brief Scan/iterate memory chunks.
931
 * @brief Initialize memory chunks for dumpsys.
942
 *
943
 * @param _prev		The previously returned chunk or NULL.
944
 *
945
 * @retval		The next (or first when _prev is NULL) chunk.
946
 */
932
 */
947
METHOD struct pmap_md * scan_md {
933
METHOD void scan_init {
948
	mmu_t		_mmu;
934
	mmu_t		_mmu;
949
	struct pmap_md	*_prev;
935
};
950
} DEFAULT mmu_null_scan_md;
(-)b/sys/powerpc/powerpc/pmap_dispatch.c (-11 / +14 lines)
Lines 41-58 __FBSDID("$FreeBSD$"); Link Here
41
 * as the PMAP layer makes extensive use of mutexes.
41
 * as the PMAP layer makes extensive use of mutexes.
42
 */
42
 */
43
43
44
#include <sys/param.h>
44
#include <sys/param.h>
45
#include <sys/kernel.h>
45
#include <sys/kernel.h>
46
#include <sys/conf.h>
46
#include <sys/lock.h>
47
#include <sys/lock.h>
47
#include <sys/ktr.h>
48
#include <sys/ktr.h>
48
#include <sys/mutex.h>
49
#include <sys/mutex.h>
49
#include <sys/systm.h>
50
#include <sys/systm.h>
50
51
51
#include <vm/vm.h>
52
#include <vm/vm.h>
52
#include <vm/vm_page.h>
53
#include <vm/vm_page.h>
53
54
55
#include <machine/dump.h>
56
#include <machine/md_var.h>
54
#include <machine/mmuvar.h>
57
#include <machine/mmuvar.h>
55
#include <machine/smp.h>
58
#include <machine/smp.h>
56
59
57
#include "mmu_if.h"
60
#include "mmu_if.h"
58
61
Lines 520-551 pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) Link Here
520
 
523
 
521
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz);
524
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz);
522
	return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
525
	return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
523
}
526
}
524
527
525
vm_offset_t
528
void
526
pmap_dumpsys_map(struct pmap_md *md, vm_size_t ofs, vm_size_t *sz)
529
dumpsys_map_chunk(vm_paddr_t pa, size_t sz, void **va)
527
{
530
{
528
531
529
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, *sz);
532
	CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
530
	return (MMU_DUMPSYS_MAP(mmu_obj, md, ofs, sz));
533
	return (MMU_DUMPSYS_MAP(mmu_obj, pa, sz, va));
531
}
534
}
532
535
533
void
536
void
534
pmap_dumpsys_unmap(struct pmap_md *md, vm_size_t ofs, vm_offset_t va)
537
dumpsys_unmap_chunk(vm_paddr_t pa, size_t sz, void *va)
535
{
538
{
536
539
537
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, va);
540
	CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
538
	return (MMU_DUMPSYS_UNMAP(mmu_obj, md, ofs, va));
541
	return (MMU_DUMPSYS_UNMAP(mmu_obj, pa, sz, va));
539
}
542
}
540
543
541
struct pmap_md *
544
void
542
pmap_scan_md(struct pmap_md *prev)
545
dumpsys_md_pa_init(void)
543
{
546
{
544
547
545
	CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
548
	CTR1(KTR_PMAP, "%s()", __func__);
546
	return (MMU_SCAN_MD(mmu_obj, prev));
549
	return (MMU_SCAN_INIT(mmu_obj));
547
}
550
}
548
551
549
/*
552
/*
550
 * MMU install routines. Highest priority wins, equal priority also
553
 * MMU install routines. Highest priority wins, equal priority also
551
 * overrides allowing last-set to win.
554
 * overrides allowing last-set to win.
(-)b/sys/sparc64/include/dump.h (+59 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2014 EMC Corp.
3
 * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#ifndef _MACHINE_DUMP_H_
31
#define	_MACHINE_DUMP_H_
32
33
#define	DUMPSYS_MD_PA_NPAIRS	128
34
#define	DUMPSYS_HAS_MD_DUMPSYS	1
35
36
void dumpsys_md_pa_init(void);
37
38
static inline struct md_pa *
39
dumpsys_md_pa_next(struct md_pa *p)
40
{
41
42
	return dumpsys_gen_md_pa_next(p);
43
}
44
45
static inline void
46
dumpsys_wbinv_all(void)
47
{
48
49
	dumpsys_gen_wbinv_all();
50
}
51
52
static inline void
53
dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
54
{
55
56
	dumpsys_gen_unmap_chunk(pa, s, va);
57
}
58
59
#endif  /* !_MACHINE_DUMP_H_ */
(-)b/sys/sparc64/sparc64/dump_machdep.c (-87 / +29 lines)
Lines 37-152 __FBSDID("$FreeBSD$"); Link Here
37
37
38
#include <vm/vm.h>
38
#include <vm/vm.h>
39
#include <vm/vm_param.h>
39
#include <vm/vm_param.h>
40
#include <vm/pmap.h>
40
#include <vm/pmap.h>
41
41
42
#include <machine/dump.h>
42
#include <machine/metadata.h>
43
#include <machine/metadata.h>
44
#include <machine/md_var.h>
43
#include <machine/kerneldump.h>
45
#include <machine/kerneldump.h>
44
#include <machine/ofw_mem.h>
46
#include <machine/ofw_mem.h>
45
#include <machine/tsb.h>
47
#include <machine/tsb.h>
46
#include <machine/tlb.h>
48
#include <machine/tlb.h>
47
49
48
CTASSERT(sizeof(struct kerneldumpheader) == DEV_BSIZE);
50
static off_t fileofs;
49
51
50
static struct kerneldumpheader kdh;
52
extern off_t dumplo;
51
static off_t dumplo, dumppos;
53
extern struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
52
54
53
/* Handle buffered writes. */
55
void
54
static char buffer[DEV_BSIZE];
56
dumpsys_md_pa_init(void)
55
static vm_size_t fragsz;
56
57
#define	MAXDUMPSZ	(MAXDUMPPGS << PAGE_SHIFT)
58
59
static int
60
buf_write(struct dumperinfo *di, char *ptr, size_t sz)
61
{
57
{
62
	size_t len;
58
	int i;
63
	int error;
64
65
	while (sz) {
66
		len = DEV_BSIZE - fragsz;
67
		if (len > sz)
68
			len = sz;
69
		bcopy(ptr, buffer + fragsz, len);
70
		fragsz += len;
71
		ptr += len;
72
		sz -= len;
73
		if (fragsz == DEV_BSIZE) {
74
			error = dump_write(di, buffer, 0, dumplo,
75
			    DEV_BSIZE);
76
			if (error)
77
				return error;
78
			dumplo += DEV_BSIZE;
79
			fragsz = 0;
80
		}
81
	}
82
59
83
	return (0);
60
	memset(dump_map, 0, sizeof(dump_map));
61
	for (i = 0; i < sparc64_nmemreg; i++) {
62
		dump_map[i].md_start = sparc64_memreg[i].mr_start;
63
		dump_map[i].md_size = sparc64_memreg[i].mr_size;
64
	}
84
}
65
}
85
66
86
static int
67
void
87
buf_flush(struct dumperinfo *di)
68
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
88
{
69
{
89
	int error;
90
91
	if (fragsz == 0)
92
		return (0);
93
70
94
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
71
	*va = (void*)TLB_PHYS_TO_DIRECT(pa);
95
	dumplo += DEV_BSIZE;
96
	fragsz = 0;
97
	return (error);
98
}
72
}
99
73
100
static int
74
static int
101
reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
75
reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
102
{
76
{
103
	struct sparc64_dump_reg r;
77
	struct sparc64_dump_reg r;
104
78
105
	r.dr_pa = pa;
79
	r.dr_pa = pa;
106
	r.dr_size = size;
80
	r.dr_size = size;
107
	r.dr_offs = dumppos;
81
	r.dr_offs = fileofs;
108
	dumppos += size;
82
	fileofs += size;
109
	return (buf_write(di, (char *)&r, sizeof(r)));
83
	return (dumpsys_buf_write(di, (char *)&r, sizeof(r)));
110
}
111
112
static int
113
blk_dump(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
114
{
115
	vm_size_t pos, rsz;
116
	vm_offset_t va;
117
	int c, counter, error, twiddle;
118
119
	printf("  chunk at %#lx: %ld bytes ", (u_long)pa, (long)size);
120
121
	va = 0L;
122
	error = counter = twiddle = 0;
123
	for (pos = 0; pos < size; pos += MAXDUMPSZ, counter++) {
124
		if (counter % 128 == 0)
125
			printf("%c\b", "|/-\\"[twiddle++ & 3]);
126
		rsz = size - pos;
127
		rsz = (rsz > MAXDUMPSZ) ? MAXDUMPSZ : rsz;
128
		va = TLB_PHYS_TO_DIRECT(pa + pos);
129
		error = dump_write(di, (void *)va, 0, dumplo, rsz);
130
		if (error)
131
			break;
132
		dumplo += rsz;
133
134
		/* Check for user abort. */
135
		c = cncheckc();
136
		if (c == 0x03)
137
			return (ECANCELED);
138
		if (c != -1)
139
			printf("(CTRL-C to abort)  ");
140
	}
141
	printf("... %s\n", (error) ? "fail" : "ok");
142
	return (error);
143
}
84
}
144
85
145
int
86
int
146
dumpsys(struct dumperinfo *di)
87
dumpsys(struct dumperinfo *di)
147
{
88
{
89
	struct kerneldumpheader kdh;
148
	struct sparc64_dump_hdr hdr;
90
	struct sparc64_dump_hdr hdr;
149
	vm_size_t size, totsize, hdrsize;
91
	vm_size_t size, totsize, hdrsize;
150
	int error, i, nreg;
92
	int error, i, nreg;
151
93
152
	/* Calculate dump size. */
94
	/* Calculate dump size. */
Lines 187-216 dumpsys(struct dumperinfo *di) Link Here
187
	hdr.dh_tsb_pa = tsb_kernel_phys;
129
	hdr.dh_tsb_pa = tsb_kernel_phys;
188
	hdr.dh_tsb_size = tsb_kernel_size;
130
	hdr.dh_tsb_size = tsb_kernel_size;
189
	hdr.dh_tsb_mask = tsb_kernel_mask;
131
	hdr.dh_tsb_mask = tsb_kernel_mask;
190
	hdr.dh_nregions = nreg;
132
	hdr.dh_nregions = nreg;
191
133
192
	if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
134
	if (dumpsys_buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
193
		goto fail;
135
		goto fail;
194
136
195
	dumppos = hdrsize;
137
	fileofs = hdrsize;
196
	/* Now, write out the region descriptors. */
138
	/* Now, write out the region descriptors. */
197
	for (i = 0; i < sparc64_nmemreg; i++) {
139
	for (i = 0; i < sparc64_nmemreg; i++) {
198
		error = reg_write(di, sparc64_memreg[i].mr_start,
140
		error = reg_write(di, sparc64_memreg[i].mr_start,
199
		    sparc64_memreg[i].mr_size);
141
		    sparc64_memreg[i].mr_size);
200
		if (error != 0)
142
		if (error != 0)
201
			goto fail;
143
			goto fail;
202
	}
144
	}
203
	buf_flush(di);
145
	dumpsys_buf_flush(di);
204
146
205
	/* Dump memory chunks. */
147
	/* Dump memory chunks. */
206
	for (i = 0; i < sparc64_nmemreg; i++) {
148
	error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
207
		error = blk_dump(di, sparc64_memreg[i].mr_start,
149
	if (error < 0)
208
		    sparc64_memreg[i].mr_size);
150
		goto fail;
209
		if (error != 0)
210
			goto fail;
211
	}
212
151
213
	/* Dump trailer */
152
	/* Dump trailer */
214
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
153
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
215
	if (error)
154
	if (error)
216
		goto fail;
155
		goto fail;
Lines 219-227 dumpsys(struct dumperinfo *di) Link Here
219
	dump_write(di, NULL, 0, 0, 0);
158
	dump_write(di, NULL, 0, 0, 0);
220
	printf("\nDump complete\n");
159
	printf("\nDump complete\n");
221
	return (0);
160
	return (0);
222
161
223
 fail:
162
 fail:
163
	if (error < 0)
164
		error = -error;
165
224
	/* XXX It should look more like VMS :-) */
166
	/* XXX It should look more like VMS :-) */
225
	printf("** DUMP FAILED (ERROR %d) **\n", error);
167
	printf("** DUMP FAILED (ERROR %d) **\n", error);
226
	return (error);
168
	return (error);
227
}
169
}
(-)b/sys/sys/conf.h (+19 lines)
Lines 332-345 struct dumperinfo { Link Here
332
	u_int	maxiosize;	/* Max size allowed for an individual I/O */
332
	u_int	maxiosize;	/* Max size allowed for an individual I/O */
333
	off_t   mediaoffset;	/* Initial offset in bytes. */
333
	off_t   mediaoffset;	/* Initial offset in bytes. */
334
	off_t   mediasize;	/* Space available in bytes. */
334
	off_t   mediasize;	/* Space available in bytes. */
335
};
335
};
336
336
337
struct md_pa {
338
	vm_paddr_t md_start;
339
	vm_paddr_t md_size;
340
};
341
337
int set_dumper(struct dumperinfo *, const char *_devname);
342
int set_dumper(struct dumperinfo *, const char *_devname);
338
int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
343
int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
339
int dumpsys(struct dumperinfo *);
344
int dumpsys(struct dumperinfo *);
340
int doadump(boolean_t);
345
int doadump(boolean_t);
346
void dumpsys_map_chunk(vm_paddr_t, size_t, void **);
347
typedef int dumpsys_callback_t(struct md_pa *, int, void *);
348
int dumpsys_foreach_chunk(dumpsys_callback_t, void *);
349
int dumpsys_cb_dumpdata(struct md_pa *, int, void *);
350
int dumpsys_buf_write(struct dumperinfo *, char *, size_t);
351
int dumpsys_buf_flush(struct dumperinfo *);
341
extern int dumping;		/* system is dumping */
352
extern int dumping;		/* system is dumping */
353
extern int do_minidump;
354
355
#if !defined(__sparc__) && !defined(__powerpc__)
356
void dumpsys_gen_md_pa_init(void);
357
#endif
358
struct md_pa *dumpsys_gen_md_pa_next(struct md_pa *);
359
void dumpsys_gen_wbinv_all(void);
360
void dumpsys_gen_unmap_chunk(vm_paddr_t, size_t, void *);
342
361
343
#endif /* _KERNEL */
362
#endif /* _KERNEL */
344
363
345
#endif /* !_SYS_CONF_H_ */
364
#endif /* !_SYS_CONF_H_ */
(-)b/sys/x86/x86/dump_machdep.c (-340 / +8 lines)
Lines 28-379 Link Here
28
__FBSDID("$FreeBSD$");
28
__FBSDID("$FreeBSD$");
29
29
30
#include "opt_watchdog.h"
30
#include "opt_watchdog.h"
31
31
32
#include <sys/param.h>
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/conf.h>
33
#include <sys/conf.h>
35
#include <sys/cons.h>
34
#include <sys/systm.h>
36
#include <sys/sysctl.h>
37
#include <sys/kernel.h>
38
#include <sys/kerneldump.h>
39
#include <sys/watchdog.h>
40
#include <vm/vm.h>
35
#include <vm/vm.h>
41
#include <vm/pmap.h>
36
#include <vm/pmap.h>
42
#include <machine/elf.h>
43
#include <machine/md_var.h>
44
45
#ifdef __amd64__
46
#define	KERNELDUMP_VERSION	KERNELDUMP_AMD64_VERSION
47
#define	EM_VALUE		EM_X86_64
48
#else
49
#define	KERNELDUMP_VERSION	KERNELDUMP_I386_VERSION
50
#define	EM_VALUE		EM_386
51
#endif
52
53
CTASSERT(sizeof(struct kerneldumpheader) == 512);
54
55
int do_minidump = 1;
56
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
57
    "Enable mini crash dumps");
58
59
/*
60
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
61
 * is to protect us from metadata and to protect metadata from us.
62
 */
63
#define	SIZEOF_METADATA		(64*1024)
64
65
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
66
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
67
68
struct md_pa {
69
	vm_paddr_t md_start;
70
	vm_paddr_t md_size;
71
};
72
73
typedef int callback_t(struct md_pa *, int, void *);
74
37
75
static struct kerneldumpheader kdh;
38
void
76
static off_t dumplo, fileofs;
39
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk, void **va)
77
78
/* Handle buffered writes. */
79
static char buffer[DEV_BSIZE];
80
static size_t fragsz;
81
82
/* 20 phys_avail entry pairs correspond to 10 md_pa's */
83
static struct md_pa dump_map[10];
84
85
static void
86
md_pa_init(void)
87
{
40
{
88
	int n, idx;
41
	int i;
42
	vm_paddr_t a;
89
43
90
	bzero(dump_map, sizeof(dump_map));
44
	for (i = 0; i < chunk; i++) {
91
	for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
45
		a = pa + i * PAGE_SIZE;
92
		idx = n * 2;
46
		*va = pmap_kenter_temporary(trunc_page(a), i);
93
		if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
94
			break;
95
		dump_map[n].md_start = dump_avail[idx];
96
		dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
97
	}
47
	}
98
}
48
}
99
100
static struct md_pa *
101
md_pa_first(void)
102
{
103
104
	return (&dump_map[0]);
105
}
106
107
static struct md_pa *
108
md_pa_next(struct md_pa *mdp)
109
{
110
111
	mdp++;
112
	if (mdp->md_size == 0)
113
		mdp = NULL;
114
	return (mdp);
115
}
116
117
static int
118
buf_write(struct dumperinfo *di, char *ptr, size_t sz)
119
{
120
	size_t len;
121
	int error;
122
123
	while (sz) {
124
		len = DEV_BSIZE - fragsz;
125
		if (len > sz)
126
			len = sz;
127
		bcopy(ptr, buffer + fragsz, len);
128
		fragsz += len;
129
		ptr += len;
130
		sz -= len;
131
		if (fragsz == DEV_BSIZE) {
132
			error = dump_write(di, buffer, 0, dumplo,
133
			    DEV_BSIZE);
134
			if (error)
135
				return error;
136
			dumplo += DEV_BSIZE;
137
			fragsz = 0;
138
		}
139
	}
140
141
	return (0);
142
}
143
144
static int
145
buf_flush(struct dumperinfo *di)
146
{
147
	int error;
148
149
	if (fragsz == 0)
150
		return (0);
151
152
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
153
	dumplo += DEV_BSIZE;
154
	fragsz = 0;
155
	return (error);
156
}
157
158
#define PG2MB(pgs) ((pgs + (1 << 8) - 1) >> 8)
159
160
static int
161
cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
162
{
163
	struct dumperinfo *di = (struct dumperinfo*)arg;
164
	vm_paddr_t a, pa;
165
	void *va;
166
	uint64_t pgs;
167
	size_t counter, sz, chunk;
168
	int i, c, error, twiddle;
169
	u_int maxdumppgs;
170
171
	error = 0;	/* catch case in which chunk size is 0 */
172
	counter = 0;	/* Update twiddle every 16MB */
173
	twiddle = 0;
174
	va = 0;
175
	pgs = mdp->md_size / PAGE_SIZE;
176
	pa = mdp->md_start;
177
	maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS);
178
	if (maxdumppgs == 0)	/* seatbelt */
179
		maxdumppgs = 1;
180
181
	printf("  chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs),
182
	    (uintmax_t)pgs);
183
184
	while (pgs) {
185
		chunk = pgs;
186
		if (chunk > maxdumppgs)
187
			chunk = maxdumppgs;
188
		sz = chunk << PAGE_SHIFT;
189
		counter += sz;
190
		if (counter >> 24) {
191
			printf(" %ju", (uintmax_t)PG2MB(pgs));
192
			counter &= (1<<24) - 1;
193
		}
194
		for (i = 0; i < chunk; i++) {
195
			a = pa + i * PAGE_SIZE;
196
			va = pmap_kenter_temporary(trunc_page(a), i);
197
		}
198
199
		wdog_kern_pat(WD_LASTVAL);
200
201
		error = dump_write(di, va, 0, dumplo, sz);
202
		if (error)
203
			break;
204
		dumplo += sz;
205
		pgs -= chunk;
206
		pa += sz;
207
208
		/* Check for user abort. */
209
		c = cncheckc();
210
		if (c == 0x03)
211
			return (ECANCELED);
212
		if (c != -1)
213
			printf(" (CTRL-C to abort) ");
214
	}
215
	printf(" ... %s\n", (error) ? "fail" : "ok");
216
	return (error);
217
}
218
219
static int
220
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
221
{
222
	struct dumperinfo *di = (struct dumperinfo*)arg;
223
	Elf_Phdr phdr;
224
	uint64_t size;
225
	int error;
226
227
	size = mdp->md_size;
228
	bzero(&phdr, sizeof(phdr));
229
	phdr.p_type = PT_LOAD;
230
	phdr.p_flags = PF_R;			/* XXX */
231
	phdr.p_offset = fileofs;
232
	phdr.p_vaddr = mdp->md_start;
233
	phdr.p_paddr = mdp->md_start;
234
	phdr.p_filesz = size;
235
	phdr.p_memsz = size;
236
	phdr.p_align = PAGE_SIZE;
237
238
	error = buf_write(di, (char*)&phdr, sizeof(phdr));
239
	fileofs += phdr.p_filesz;
240
	return (error);
241
}
242
243
static int
244
cb_size(struct md_pa *mdp, int seqnr, void *arg)
245
{
246
	uint64_t *sz = (uint64_t*)arg;
247
248
	*sz += (uint64_t)mdp->md_size;
249
	return (0);
250
}
251
252
static int
253
foreach_chunk(callback_t cb, void *arg)
254
{
255
	struct md_pa *mdp;
256
	int error, seqnr;
257
258
	seqnr = 0;
259
	mdp = md_pa_first();
260
	while (mdp != NULL) {
261
		error = (*cb)(mdp, seqnr++, arg);
262
		if (error)
263
			return (-error);
264
		mdp = md_pa_next(mdp);
265
	}
266
	return (seqnr);
267
}
268
269
int
270
dumpsys(struct dumperinfo *di)
271
{
272
	Elf_Ehdr ehdr;
273
	uint64_t dumpsize;
274
	off_t hdrgap;
275
	size_t hdrsz;
276
	int error;
277
278
	if (do_minidump) {
279
		minidumpsys(di);
280
		return (0);
281
	}
282
	bzero(&ehdr, sizeof(ehdr));
283
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
284
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
285
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
286
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
287
	ehdr.e_ident[EI_CLASS] = ELF_CLASS;
288
#if BYTE_ORDER == LITTLE_ENDIAN
289
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
290
#else
291
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
292
#endif
293
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
294
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
295
	ehdr.e_type = ET_CORE;
296
	ehdr.e_machine = EM_VALUE;
297
	ehdr.e_phoff = sizeof(ehdr);
298
	ehdr.e_flags = 0;
299
	ehdr.e_ehsize = sizeof(ehdr);
300
	ehdr.e_phentsize = sizeof(Elf_Phdr);
301
	ehdr.e_shentsize = sizeof(Elf_Shdr);
302
303
	md_pa_init();
304
305
	/* Calculate dump size. */
306
	dumpsize = 0L;
307
	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
308
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
309
	fileofs = MD_ALIGN(hdrsz);
310
	dumpsize += fileofs;
311
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
312
313
	/* Determine dump offset on device. */
314
	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
315
		error = ENOSPC;
316
		goto fail;
317
	}
318
	dumplo = di->mediaoffset + di->mediasize - dumpsize;
319
	dumplo -= sizeof(kdh) * 2;
320
321
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize,
322
	    di->blocksize);
323
324
	printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
325
	    ehdr.e_phnum);
326
327
	/* Dump leader */
328
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
329
	if (error)
330
		goto fail;
331
	dumplo += sizeof(kdh);
332
333
	/* Dump ELF header */
334
	error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
335
	if (error)
336
		goto fail;
337
338
	/* Dump program headers */
339
	error = foreach_chunk(cb_dumphdr, di);
340
	if (error < 0)
341
		goto fail;
342
	buf_flush(di);
343
344
	/*
345
	 * All headers are written using blocked I/O, so we know the
346
	 * current offset is (still) block aligned. Skip the alignement
347
	 * in the file to have the segment contents aligned at page
348
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
349
	 * care and may very well be unaligned within the dump device.
350
	 */
351
	dumplo += hdrgap;
352
353
	/* Dump memory chunks (updates dumplo) */
354
	error = foreach_chunk(cb_dumpdata, di);
355
	if (error < 0)
356
		goto fail;
357
358
	/* Dump trailer */
359
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
360
	if (error)
361
		goto fail;
362
363
	/* Signal completion, signoff and exit stage left. */
364
	dump_write(di, NULL, 0, 0, 0);
365
	printf("\nDump complete\n");
366
	return (0);
367
368
 fail:
369
	if (error < 0)
370
		error = -error;
371
372
	if (error == ECANCELED)
373
		printf("\nDump aborted\n");
374
	else if (error == ENOSPC)
375
		printf("\nDump failed. Partition too small.\n");
376
	else
377
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
378
	return (error);
379
}
380
- 

Return to bug 193873