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

Collapse All | Expand All

(-)b/sys/amd64/include/md_var.h (+5 lines)
Lines 122-127 void minidumpsys(struct dumperinfo *); Link Here
122
struct savefpu *get_pcb_user_save_td(struct thread *td);
122
struct savefpu *get_pcb_user_save_td(struct thread *td);
123
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
123
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
124
struct pcb *get_pcb_td(struct thread *td);
124
struct pcb *get_pcb_td(struct thread *td);
125
void	amd64_db_resume_dbreg(void);
125
void	amd64_db_resume_dbreg(void);
126
126
127
#define	KERNELDUMP_VERSION	KERNELDUMP_AMD64_VERSION
128
#define	EM_VALUE		EM_X86_64
129
/* 20 phys_avail entry pairs correspond to 10 md_pa's */
130
#define	DUMPSYS_MD_PA_NPAIRS	10
131
127
#endif /* !_MACHINE_MD_VAR_H_ */
132
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/arm/arm/dump_machdep.c (-316 / +9 lines)
Lines 45-180 __FBSDID("$FreeBSD$"); Link Here
45
#include <machine/elf.h>
45
#include <machine/elf.h>
46
#include <machine/md_var.h>
46
#include <machine/md_var.h>
47
#include <machine/pcb.h>
47
#include <machine/pcb.h>
48
#include <machine/armreg.h>
48
#include <machine/armreg.h>
49
49
50
CTASSERT(sizeof(struct kerneldumpheader) == 512);
50
void
51
51
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
{
52
{
108
53
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
	/*
54
	/*
177
	 * Make sure we write coherent data.  Note that in the SMP case this
55
	 * 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
56
	 * 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
57
	 * have already been stopped, and their flush/invalidate was done as
180
	 * part of stopping.
58
	 * part of stopping.
Lines 182-384 cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) Link Here
182
	cpu_idcache_wbinv_all();
60
	cpu_idcache_wbinv_all();
183
	cpu_l2cache_wbinv_all();
61
	cpu_l2cache_wbinv_all();
184
#ifdef __XSCALE__
62
#ifdef __XSCALE__
185
	xscale_cache_clean_minidata();
63
	xscale_cache_clean_minidata();
186
#endif
64
#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
}
65
}
247
66
248
static int
67
void
249
cb_size(struct md_pa *mdp, int seqnr, void *arg)
68
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
250
{
69
{
251
	uint32_t *sz = (uint32_t*)arg;
252
70
253
	*sz += (uint32_t)mdp->md_size;
71
	if (pa == (pa & L1_ADDR_BITS)) {
254
	return (0);
72
		pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
255
}
73
		cpu_tlb_flushID_SE(0);
256
74
		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
	}
75
	}
271
	return (seqnr);
76
	*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
}
77
}
(-)b/sys/arm/include/md_var.h (+7 lines)
Lines 68-73 extern int busdma_swi_pending; Link Here
68
void busdma_swi(void);
68
void busdma_swi(void);
69
void dump_add_page(vm_paddr_t);
69
void dump_add_page(vm_paddr_t);
70
void dump_drop_page(vm_paddr_t);
70
void dump_drop_page(vm_paddr_t);
71
void minidumpsys(struct dumperinfo *);
71
void minidumpsys(struct dumperinfo *);
72
72
73
#define	KERNELDUMP_VERSION	KERNELDUMP_ARM_VERSION
74
#define	EM_VALUE		EM_ARM
75
/* XXX: I suppose 20 should be enough. */
76
#define	DUMPSYS_MD_PA_NPAIRS	20
77
#define	DUMPSYS_HAS_MD_WBINV	1
78
void dumpsys_wbinv_all(void);
79
73
#endif /* !_MACHINE_MD_VAR_H_ */
80
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/conf/files (+1 lines)
Lines 2927-2936 kern/kern_cons.c standard Link Here
2927
kern/kern_cpu.c			standard
2927
kern/kern_cpu.c			standard
2928
kern/kern_cpuset.c		standard
2928
kern/kern_cpuset.c		standard
2929
kern/kern_context.c		standard
2929
kern/kern_context.c		standard
2930
kern/kern_descrip.c		standard
2930
kern/kern_descrip.c		standard
2931
kern/kern_dtrace.c		optional kdtrace_hooks
2931
kern/kern_dtrace.c		optional kdtrace_hooks
2932
kern/kern_dump.c		standard
2932
kern/kern_environment.c		standard
2933
kern/kern_environment.c		standard
2933
kern/kern_et.c			standard
2934
kern/kern_et.c			standard
2934
kern/kern_event.c		standard
2935
kern/kern_event.c		standard
2935
kern/kern_exec.c		standard
2936
kern/kern_exec.c		standard
2936
kern/kern_exit.c		standard
2937
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/md_var.h (+5 lines)
Lines 113-118 void ppro_reenable_apic(void); Link Here
113
void	printcpuinfo(void);
113
void	printcpuinfo(void);
114
void	setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
114
void	setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
115
int     user_dbreg_trap(void);
115
int     user_dbreg_trap(void);
116
void	minidumpsys(struct dumperinfo *);
116
void	minidumpsys(struct dumperinfo *);
117
117
118
#define	KERNELDUMP_VERSION	KERNELDUMP_I386_VERSION
119
#define	EM_VALUE		EM_386
120
/* 20 phys_avail entry pairs correspond to 10 md_pa's */
121
#define	DUMPSYS_MD_PA_NPAIRS	10
122
118
#endif /* !_MACHINE_MD_VAR_H_ */
123
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/kern/kern_dump.c (+402 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/elf.h>
47
#include <machine/md_var.h>
48
#include <machine/pcb.h>
49
50
CTASSERT(sizeof(struct kerneldumpheader) == 512);
51
52
#ifndef __sparc__
53
int do_minidump = 1;
54
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
55
    "Enable mini crash dumps");
56
#endif
57
58
/*
59
 * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
60
 * is to protect us from metadata and to protect metadata from us.
61
 */
62
#define	SIZEOF_METADATA		(64*1024)
63
64
#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
65
#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
66
67
off_t dumplo;
68
69
/* Handle buffered writes. */
70
static char buffer[DEV_BSIZE];
71
static size_t fragsz;
72
73
struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
74
75
#ifndef DUMPSYS_HAS_MD_PA_INIT
76
static void
77
dumpsys_md_pa_init(void)
78
{
79
	int n, idx;
80
81
	bzero(dump_map, sizeof(dump_map));
82
	for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
83
		idx = n * 2;
84
		if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
85
			break;
86
		dump_map[n].md_start = dump_avail[idx];
87
		dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
88
	}
89
}
90
#endif
91
92
#ifndef DUMPSYS_HAS_MD_PA_NEXT
93
static struct md_pa *
94
dumpsys_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
#endif
106
107
#ifndef DUMPSYS_HAS_MD_WBINV
108
static void
109
dumpsys_wbinv_all(void)
110
{
111
112
	/* nop */;
113
}
114
#endif
115
116
#ifndef DUMPSYS_HAS_MD_UNMAP
117
static void
118
dumpsys_unmap_chunk(vm_paddr_t pa __unused, size_t chunk __unused,
119
    void *va __unused)
120
{
121
122
	/* nop */;
123
}
124
#endif
125
126
int
127
dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz)
128
{
129
	size_t len;
130
	int error;
131
132
	while (sz) {
133
		len = DEV_BSIZE - fragsz;
134
		if (len > sz)
135
			len = sz;
136
		bcopy(ptr, buffer + fragsz, len);
137
		fragsz += len;
138
		ptr += len;
139
		sz -= len;
140
		if (fragsz == DEV_BSIZE) {
141
			error = dump_write(di, buffer, 0, dumplo,
142
			    DEV_BSIZE);
143
			if (error)
144
				return error;
145
			dumplo += DEV_BSIZE;
146
			fragsz = 0;
147
		}
148
	}
149
150
	return (0);
151
}
152
153
int
154
dumpsys_buf_flush(struct dumperinfo *di)
155
{
156
	int error;
157
158
	if (fragsz == 0)
159
		return (0);
160
161
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
162
	dumplo += DEV_BSIZE;
163
	fragsz = 0;
164
	return (error);
165
}
166
167
CTASSERT(PAGE_SHIFT < 20);
168
#define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT))
169
170
int
171
dumpsys_cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
172
{
173
	struct dumperinfo *di = (struct dumperinfo*)arg;
174
	vm_paddr_t pa;
175
	void *va;
176
	uint64_t pgs;
177
	size_t counter, sz, chunk;
178
	int c, error, twiddle;
179
	u_int maxdumppgs;
180
181
	error = 0;	/* catch case in which chunk size is 0 */
182
	counter = 0;	/* Update twiddle every 16MB */
183
	twiddle = 0;
184
	va = 0;
185
	pgs = mdp->md_size / PAGE_SIZE;
186
	pa = mdp->md_start;
187
	maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS);
188
	if (maxdumppgs == 0)	/* seatbelt */
189
		maxdumppgs = 1;
190
191
	printf("  chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs),
192
	    (uintmax_t)pgs);
193
194
	dumpsys_wbinv_all();
195
	while (pgs) {
196
		chunk = pgs;
197
		if (chunk > maxdumppgs)
198
			chunk = maxdumppgs;
199
		sz = chunk << PAGE_SHIFT;
200
		counter += sz;
201
		if (counter >> 24) {
202
			printf(" %ju", (uintmax_t)PG2MB(pgs));
203
			counter &= (1<<24) - 1;
204
		}
205
206
		dumpsys_map_chunk(pa, chunk, &va);
207
#ifdef SW_WATCHDOG
208
		wdog_kern_pat(WD_LASTVAL);
209
#endif
210
211
		error = dump_write(di, va, 0, dumplo, sz);
212
		dumpsys_unmap_chunk(pa, chunk, va);
213
		if (error)
214
			break;
215
		dumplo += sz;
216
		pgs -= chunk;
217
		pa += sz;
218
219
		/* Check for user abort. */
220
		c = cncheckc();
221
		if (c == 0x03)
222
			return (ECANCELED);
223
		if (c != -1)
224
			printf(" (CTRL-C to abort) ");
225
	}
226
	printf(" ... %s\n", (error) ? "fail" : "ok");
227
	return (error);
228
}
229
230
int
231
dumpsys_foreach_chunk(dumpsys_callback_t cb, void *arg)
232
{
233
	struct md_pa *mdp;
234
	int error, seqnr;
235
236
	seqnr = 0;
237
	mdp = dumpsys_md_pa_next(NULL);
238
	while (mdp != NULL) {
239
		error = (*cb)(mdp, seqnr++, arg);
240
		if (error)
241
			return (-error);
242
		mdp = dumpsys_md_pa_next(mdp);
243
	}
244
	return (seqnr);
245
}
246
247
#ifndef DUMPSYS_HAS_MD_DUMPSYS
248
static off_t fileofs;
249
250
static int
251
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
252
{
253
	struct dumperinfo *di = (struct dumperinfo*)arg;
254
	Elf_Phdr phdr;
255
	uint64_t size;
256
	int error;
257
258
	size = mdp->md_size;
259
	bzero(&phdr, sizeof(phdr));
260
	phdr.p_type = PT_LOAD;
261
	phdr.p_flags = PF_R;			/* XXX */
262
	phdr.p_offset = fileofs;
263
#ifdef __powerpc__
264
	phdr.p_vaddr = (do_minidump? mdp->md_start : ~0L);
265
	phdr.p_paddr = (do_minidump? ~0L : mdp->md_start);
266
#else
267
	phdr.p_vaddr = mdp->md_start;
268
	phdr.p_paddr = mdp->md_start;
269
#endif
270
	phdr.p_filesz = size;
271
	phdr.p_memsz = size;
272
	phdr.p_align = PAGE_SIZE;
273
274
	error = dumpsys_buf_write(di, (char*)&phdr, sizeof(phdr));
275
	fileofs += phdr.p_filesz;
276
	return (error);
277
}
278
279
static int
280
cb_size(struct md_pa *mdp, int seqnr, void *arg)
281
{
282
	uint64_t *sz = (uint64_t*)arg;
283
284
	*sz += (uint64_t)mdp->md_size;
285
	return (0);
286
}
287
288
int
289
dumpsys(struct dumperinfo *di)
290
{
291
	struct kerneldumpheader kdh;
292
	Elf_Ehdr ehdr;
293
	uint64_t dumpsize;
294
	off_t hdrgap;
295
	size_t hdrsz;
296
	int error;
297
298
#ifndef __powerpc__
299
	if (do_minidump) {
300
		minidumpsys(di);
301
		return (0);
302
	}
303
#endif
304
	bzero(&ehdr, sizeof(ehdr));
305
	ehdr.e_ident[EI_MAG0] = ELFMAG0;
306
	ehdr.e_ident[EI_MAG1] = ELFMAG1;
307
	ehdr.e_ident[EI_MAG2] = ELFMAG2;
308
	ehdr.e_ident[EI_MAG3] = ELFMAG3;
309
	ehdr.e_ident[EI_CLASS] = ELF_CLASS;
310
#if BYTE_ORDER == LITTLE_ENDIAN
311
	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
312
#else
313
	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
314
#endif
315
	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
316
	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
317
	ehdr.e_type = ET_CORE;
318
	ehdr.e_machine = EM_VALUE;
319
	ehdr.e_phoff = sizeof(ehdr);
320
	ehdr.e_flags = 0;
321
	ehdr.e_ehsize = sizeof(ehdr);
322
	ehdr.e_phentsize = sizeof(Elf_Phdr);
323
	ehdr.e_shentsize = sizeof(Elf_Shdr);
324
325
	dumpsys_md_pa_init();
326
327
	/* Calculate dump size. */
328
	dumpsize = 0L;
329
	ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize);
330
	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
331
	fileofs = MD_ALIGN(hdrsz);
332
	dumpsize += fileofs;
333
	hdrgap = fileofs - DEV_ALIGN(hdrsz);
334
335
	/* Determine dump offset on device. */
336
	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
337
		error = ENOSPC;
338
		goto fail;
339
	}
340
	dumplo = di->mediaoffset + di->mediasize - dumpsize;
341
	dumplo -= sizeof(kdh) * 2;
342
343
	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize,
344
	    di->blocksize);
345
346
	printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
347
	    ehdr.e_phnum);
348
349
	/* Dump leader */
350
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
351
	if (error)
352
		goto fail;
353
	dumplo += sizeof(kdh);
354
355
	/* Dump ELF header */
356
	error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr));
357
	if (error)
358
		goto fail;
359
360
	/* Dump program headers */
361
	error = dumpsys_foreach_chunk(cb_dumphdr, di);
362
	if (error < 0)
363
		goto fail;
364
	dumpsys_buf_flush(di);
365
366
	/*
367
	 * All headers are written using blocked I/O, so we know the
368
	 * current offset is (still) block aligned. Skip the alignement
369
	 * in the file to have the segment contents aligned at page
370
	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
371
	 * care and may very well be unaligned within the dump device.
372
	 */
373
	dumplo += hdrgap;
374
375
	/* Dump memory chunks (updates dumplo) */
376
	error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
377
	if (error < 0)
378
		goto fail;
379
380
	/* Dump trailer */
381
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
382
	if (error)
383
		goto fail;
384
385
	/* Signal completion, signoff and exit stage left. */
386
	dump_write(di, NULL, 0, 0, 0);
387
	printf("\nDump complete\n");
388
	return (0);
389
390
 fail:
391
	if (error < 0)
392
		error = -error;
393
394
	if (error == ECANCELED)
395
		printf("\nDump aborted\n");
396
	else if (error == ENOSPC)
397
		printf("\nDump failed. Partition too small.\n");
398
	else
399
		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
400
	return (error);
401
}
402
#endif  /* !DUMPSYS_HAS_MD_DUMPSYS */
(-)b/sys/mips/include/md_var.h (+8 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
84
#define	KERNELDUMP_VERSION	KERNELDUMP_MIPS_VERSION
85
#define	EM_VALUE		EM_MIPS
86
/* XXX: I suppose 20 should be enough. */
87
#define	DUMPSYS_MD_PA_NPAIRS	20
88
#define	DUMPSYS_HAS_MD_WBINV	1
89
void dumpsys_wbinv_all(void);
90
83
#endif /* !_MACHINE_MD_VAR_H_ */
91
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/mips/mips/dump_machdep.c (-312 / +6 lines)
Lines 45-370 __FBSDID("$FreeBSD$"); Link Here
45
#include <machine/elf.h>
45
#include <machine/elf.h>
46
#include <machine/md_var.h>
46
#include <machine/md_var.h>
47
#include <machine/pcb.h>
47
#include <machine/pcb.h>
48
#include <machine/cache.h>
48
#include <machine/cache.h>
49
49
50
CTASSERT(sizeof(struct kerneldumpheader) == 512);
50
void
51
51
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
{
52
{
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
53
176
	/* Make sure we write coherent datas. */
54
	/* Make sure we write coherent datas. */
177
	mips_dcache_wbinv_all();
55
	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
}
56
}
259
57
260
int
58
void
261
dumpsys(struct dumperinfo *di)
59
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
262
{
60
{
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
61
363
	if (error == ECANCELED)
62
	/* XXX fix PA */
364
		printf("\nDump aborted\n");
63
	*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
}
64
}
(-)b/sys/powerpc/aim/mmu_oea.c (-89 / +78 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);
318
struct md_pa * moea_scan_md(mmu_t mmu, struct md_pa *prev);
320
319
321
static mmu_method_t moea_methods[] = {
320
static mmu_method_t moea_methods[] = {
322
	MMUMETHOD(mmu_clear_modify,	moea_clear_modify),
321
	MMUMETHOD(mmu_clear_modify,	moea_clear_modify),
323
	MMUMETHOD(mmu_copy_page,	moea_copy_page),
322
	MMUMETHOD(mmu_copy_page,	moea_copy_page),
324
	MMUMETHOD(mmu_copy_pages,	moea_copy_pages),
323
	MMUMETHOD(mmu_copy_pages,	moea_copy_pages),
Lines 361-370 static mmu_method_t moea_methods[] = { Link Here
361
	MMUMETHOD(mmu_unmapdev,		moea_unmapdev),
360
	MMUMETHOD(mmu_unmapdev,		moea_unmapdev),
362
	MMUMETHOD(mmu_kextract,		moea_kextract),
361
	MMUMETHOD(mmu_kextract,		moea_kextract),
363
	MMUMETHOD(mmu_kenter,		moea_kenter),
362
	MMUMETHOD(mmu_kenter,		moea_kenter),
364
	MMUMETHOD(mmu_kenter_attr,	moea_kenter_attr),
363
	MMUMETHOD(mmu_kenter_attr,	moea_kenter_attr),
365
	MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
364
	MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
365
	MMUMETHOD(mmu_scan_init,	moea_scan_init),
366
	MMUMETHOD(mmu_scan_md,		moea_scan_md),
366
	MMUMETHOD(mmu_scan_md,		moea_scan_md),
367
	MMUMETHOD(mmu_dumpsys_map,	moea_dumpsys_map),
367
	MMUMETHOD(mmu_dumpsys_map,	moea_dumpsys_map),
368
368
369
	{ 0, 0 }
369
	{ 0, 0 }
370
};
370
};
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;
2626
		sz -= len;
2627
	}
2627
	}
2628
	PMAP_UNLOCK(pm);
2628
	PMAP_UNLOCK(pm);
2629
}
2629
}
2630
2630
2631
vm_offset_t
2631
void
2632
moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2632
moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2633
    vm_size_t *sz)
2634
{
2633
{
2635
	if (md->md_vaddr == ~0UL)
2634
2636
	    return (md->md_paddr + ofs);
2635
	*va = (void *)pa;
2637
	else
2638
	    return (md->md_vaddr + ofs);
2639
}
2636
}
2640
2637
2641
struct pmap_md *
2638
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2642
moea_scan_md(mmu_t mmu, struct pmap_md *prev)
2639
static struct md_pa dump_vmap[4];
2640
2641
void
2642
moea_scan_init(mmu_t mmu)
2643
{
2643
{
2644
	static struct pmap_md md;
2645
	struct pvo_entry *pvo;
2644
	struct pvo_entry *pvo;
2646
	vm_offset_t va;
2645
	vm_offset_t va;
2647
 
2646
	int i;
2648
	if (dumpsys_minidump) {
2647
2649
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2648
	/* Initialize phys. segments for dumpsys(). */
2650
		if (prev == NULL) {
2649
	memset(&dump_map, 0, sizeof(dump_map));
2651
			/* 1st: kernel .data and .bss. */
2650
	mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
2652
			md.md_index = 1;
2651
	for (i = 0; i < pregions_sz; i++) {
2653
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2652
		dump_map[i].md_start = pregions[i].mr_start;
2654
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2653
		dump_map[i].md_size = pregions[i].mr_size;
2655
			return (&md);
2654
	}
2655
2656
	/* Virtual segments for minidumps: */
2657
	memset(&dump_vmap, 0, sizeof(dump_vmap));
2658
2659
	/* 1st: kernel .data and .bss. */
2660
	dump_vmap[0].md_start = trunc_page((uintptr_t)_etext);
2661
	dump_vmap[0].md_size = round_page((uintptr_t)_end) - dump_vmap[0].md_start;
2662
2663
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2664
	dump_vmap[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
2665
	dump_vmap[1].md_size = round_page(msgbufp->msg_size);
2666
2667
	/* 3rd: kernel VM. */
2668
	va = dump_vmap[1].md_start + dump_vmap[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;
2656
		}
2675
		}
2657
		switch (prev->md_index) {
2676
		pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL);
2658
		case 1:
2677
		if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
2659
			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2660
			md.md_index = 2;
2661
			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
2662
			md.md_size = round_page(msgbufp->msg_size);
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_vmap[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_vmap[2].md_size = va - dump_vmap[2].md_start;
2697
	}
2698
}
2699
2700
struct md_pa *
2701
moea_scan_md(mmu_t mmu, struct md_pa *prev)
2702
{
2703
2704
	if (prev == NULL) {
2705
		if (do_minidump)
2706
			return (&dump_vmap[0]);
2707
		else
2708
			return (&dump_map[0]);
2724
	}
2709
	}
2725
2710
2726
	return (&md);
2711
	prev++;
2712
	/* There's no next chunk. */
2713
	if (prev->md_size == 0)
2714
		return (NULL);
2715
	return (prev);
2727
}
2716
}
(-)b/sys/powerpc/aim/mmu_oea64.c (-86 / +78 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
struct md_pa * moea64_scan_md(mmu_t mmu, struct md_pa *prev);
332
void moea64_scan_init(mmu_t mmu);
333
333
334
static mmu_method_t moea64_methods[] = {
334
static mmu_method_t moea64_methods[] = {
335
	MMUMETHOD(mmu_clear_modify,	moea64_clear_modify),
335
	MMUMETHOD(mmu_clear_modify,	moea64_clear_modify),
336
	MMUMETHOD(mmu_copy_page,	moea64_copy_page),
336
	MMUMETHOD(mmu_copy_page,	moea64_copy_page),
337
	MMUMETHOD(mmu_copy_pages,	moea64_copy_pages),
337
	MMUMETHOD(mmu_copy_pages,	moea64_copy_pages),
Lines 373-382 static mmu_method_t moea64_methods[] = { Link Here
373
	MMUMETHOD(mmu_unmapdev,		moea64_unmapdev),
373
	MMUMETHOD(mmu_unmapdev,		moea64_unmapdev),
374
	MMUMETHOD(mmu_kextract,		moea64_kextract),
374
	MMUMETHOD(mmu_kextract,		moea64_kextract),
375
	MMUMETHOD(mmu_kenter,		moea64_kenter),
375
	MMUMETHOD(mmu_kenter,		moea64_kenter),
376
	MMUMETHOD(mmu_kenter_attr,	moea64_kenter_attr),
376
	MMUMETHOD(mmu_kenter_attr,	moea64_kenter_attr),
377
	MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
377
	MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
378
	MMUMETHOD(mmu_scan_init,	moea64_scan_init),
378
	MMUMETHOD(mmu_scan_md,		moea64_scan_md),
379
	MMUMETHOD(mmu_scan_md,		moea64_scan_md),
379
	MMUMETHOD(mmu_dumpsys_map,	moea64_dumpsys_map),
380
	MMUMETHOD(mmu_dumpsys_map,	moea64_dumpsys_map),
380
381
381
	{ 0, 0 }
382
	{ 0, 0 }
382
};
383
};
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;
2611
		sz -= len;
2611
	}
2612
	}
2612
	PMAP_UNLOCK(pm);
2613
	PMAP_UNLOCK(pm);
2613
}
2614
}
2614
2615
2615
vm_offset_t
2616
void
2616
moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2617
moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2617
    vm_size_t *sz)
2618
{
2618
{
2619
	if (md->md_vaddr == ~0UL)
2619
2620
	    return (md->md_paddr + ofs);
2620
	*va = (void *)pa;
2621
	else
2622
	    return (md->md_vaddr + ofs);
2623
}
2621
}
2624
2622
2625
struct pmap_md *
2623
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2626
moea64_scan_md(mmu_t mmu, struct pmap_md *prev)
2624
static struct md_pa dump_vmap[4];
2625
2626
void
2627
moea64_scan_init(mmu_t mmu)
2627
{
2628
{
2628
	static struct pmap_md md;
2629
	struct pvo_entry *pvo;
2629
	struct pvo_entry *pvo;
2630
	vm_offset_t va;
2630
	vm_offset_t va;
2631
 
2631
	int i;
2632
	if (dumpsys_minidump) {
2632
2633
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2633
	/* Initialize phys. segments for dumpsys(). */
2634
		if (prev == NULL) {
2634
	memset(&dump_map, 0, sizeof(dump_map));
2635
			/* 1st: kernel .data and .bss. */
2635
	mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
2636
			md.md_index = 1;
2636
	for (i = 0; i < pregions_sz; i++) {
2637
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2637
		dump_map[i].md_start = pregions[i].mr_start;
2638
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2638
		dump_map[i].md_size = pregions[i].mr_size;
2639
			return (&md);
2639
	}
2640
2641
	/* Virtual segments for minidumps: */
2642
	memset(&dump_vmap, 0, sizeof(dump_vmap));
2643
2644
	/* 1st: kernel .data and .bss. */
2645
	dump_vmap[0].md_start = trunc_page((uintptr_t)_etext);
2646
	dump_vmap[0].md_size = round_page((uintptr_t)_end) - dump_vmap[0].md_start;
2647
2648
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2649
	dump_vmap[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
2650
	dump_vmap[1].md_size = round_page(msgbufp->msg_size);
2651
2652
	/* 3rd: kernel VM. */
2653
	va = dump_vmap[1].md_start + dump_vmap[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;
2640
		}
2660
		}
2641
		switch (prev->md_index) {
2661
		pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF);
2642
		case 1:
2662
		if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
2643
			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2644
			md.md_index = 2;
2645
			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
2646
			md.md_size = round_page(msgbufp->msg_size);
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_vmap[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_vmap[2].md_size = va - dump_vmap[2].md_start;
2681
	}
2682
}
2683
2684
struct md_pa *
2685
moea64_scan_md(mmu_t mmu, struct md_pa *prev)
2686
{
2687
2688
	if (prev == NULL) {
2689
		if (do_minidump)
2690
			return (&dump_vmap[0]);
2691
		else
2692
			return (&dump_map[0]);
2705
	}
2693
	}
2706
2694
2707
	return (&md);
2695
	prev++;
2696
	/* There's no next chunk. */
2697
	if (prev->md_size == 0)
2698
		return (NULL);
2699
	return (prev);
2708
}
2700
}
(-)b/sys/powerpc/booke/pmap.c (-113 / +115 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);
329
static struct md_pa	*mmu_booke_scan_md(mmu_t, struct md_pa *);
330
330
331
static mmu_method_t mmu_booke_methods[] = {
331
static mmu_method_t mmu_booke_methods[] = {
332
	/* pmap dispatcher interface */
332
	/* pmap dispatcher interface */
333
	MMUMETHOD(mmu_clear_modify,	mmu_booke_clear_modify),
333
	MMUMETHOD(mmu_clear_modify,	mmu_booke_clear_modify),
334
	MMUMETHOD(mmu_copy,		mmu_booke_copy),
334
	MMUMETHOD(mmu_copy,		mmu_booke_copy),
Lines 379-388 static mmu_method_t mmu_booke_methods[] = { Link Here
379
	MMUMETHOD(mmu_unmapdev,		mmu_booke_unmapdev),
379
	MMUMETHOD(mmu_unmapdev,		mmu_booke_unmapdev),
380
380
381
	/* dumpsys() support */
381
	/* dumpsys() support */
382
	MMUMETHOD(mmu_dumpsys_map,	mmu_booke_dumpsys_map),
382
	MMUMETHOD(mmu_dumpsys_map,	mmu_booke_dumpsys_map),
383
	MMUMETHOD(mmu_dumpsys_unmap,	mmu_booke_dumpsys_unmap),
383
	MMUMETHOD(mmu_dumpsys_unmap,	mmu_booke_dumpsys_unmap),
384
	MMUMETHOD(mmu_scan_init,	mmu_booke_scan_init),
384
	MMUMETHOD(mmu_scan_md,		mmu_booke_scan_md),
385
	MMUMETHOD(mmu_scan_md,		mmu_booke_scan_md),
385
386
386
	{ 0, 0 }
387
	{ 0, 0 }
387
};
388
};
388
389
Lines 2532-2674 mmu_booke_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size) Link Here
2532
	}
2533
	}
2533
2534
2534
	return (EFAULT);
2535
	return (EFAULT);
2535
}
2536
}
2536
2537
2537
vm_offset_t
2538
void
2538
mmu_booke_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2539
mmu_booke_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
2539
    vm_size_t *sz)
2540
{
2540
{
2541
	vm_paddr_t pa, ppa;
2541
	vm_paddr_t ppa;
2542
	vm_offset_t va;
2542
	vm_offset_t ofs;
2543
	vm_size_t gran;
2543
	vm_size_t gran;
2544
2544
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. */
2545
	/* Minidumps are based on virtual memory addresses. */
2560
	va = md->md_vaddr + ofs;
2546
	if (do_minidump) {
2561
	if (va >= kernstart + kernsize) {
2547
		*va = (void *)pa;
2562
		gran = PAGE_SIZE - (va & PAGE_MASK);
2548
		return;
2563
		if (*sz > gran)
2564
			*sz = gran;
2565
	}
2549
	}
2566
	return (va);
2550
2551
	/* Raw physical memory dumps don't have a virtual address. */
2552
	/* We always map a 256MB page at 256M. */
2553
	gran = 256 * 1024 * 1024;
2554
	ppa = pa & ~(gran - 1);
2555
	ofs = pa - ppa;
2556
	*va = (void *)gran;
2557
	tlb1_set_entry((vm_offset_t)va, ppa, gran, _TLB_ENTRY_IO);
2558
2559
	if (sz > (gran - ofs))
2560
		tlb1_set_entry((vm_offset_t)(va + gran), ppa + gran, gran,
2561
		    _TLB_ENTRY_IO);
2567
}
2562
}
2568
2563
2569
void
2564
void
2570
mmu_booke_dumpsys_unmap(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
2565
mmu_booke_dumpsys_unmap(mmu_t mmu, vm_paddr_t pa, size_t sz, void *va)
2571
    vm_offset_t va)
2572
{
2566
{
2567
	vm_paddr_t ppa;
2568
	vm_offset_t ofs;
2569
	vm_size_t gran;
2570
2571
	/* Minidumps are based on virtual memory addresses. */
2572
	/* Nothing to do... */
2573
	if (do_minidump)
2574
		return;
2573
2575
2574
	/* Raw physical memory dumps don't have a virtual address. */
2576
	/* Raw physical memory dumps don't have a virtual address. */
2575
	if (md->md_vaddr == ~0UL) {
2577
	tlb1_idx--;
2578
	tlb1[tlb1_idx].mas1 = 0;
2579
	tlb1[tlb1_idx].mas2 = 0;
2580
	tlb1[tlb1_idx].mas3 = 0;
2581
	tlb1_write_entry(tlb1_idx);
2582
2583
	gran = 256 * 1024 * 1024;
2584
	ppa = pa & ~(gran - 1);
2585
	ofs = pa - ppa;
2586
	if (sz > (gran - ofs)) {
2576
		tlb1_idx--;
2587
		tlb1_idx--;
2577
		tlb1[tlb1_idx].mas1 = 0;
2588
		tlb1[tlb1_idx].mas1 = 0;
2578
		tlb1[tlb1_idx].mas2 = 0;
2589
		tlb1[tlb1_idx].mas2 = 0;
2579
		tlb1[tlb1_idx].mas3 = 0;
2590
		tlb1[tlb1_idx].mas3 = 0;
2580
		tlb1_write_entry(tlb1_idx);
2591
		tlb1_write_entry(tlb1_idx);
2581
		return;
2582
	}
2592
	}
2583
 
2584
	/* Minidumps are based on virtual memory addresses. */
2585
	/* Nothing to do... */
2586
}
2593
}
2587
2594
2588
struct pmap_md *
2595
extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
2589
mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
2596
static struct md_pa dump_vmap[4];
2597
2598
void
2599
mmu_booke_scan_init(mmu_t mmu)
2590
{
2600
{
2591
	static struct pmap_md md;
2592
	pte_t *pte;
2593
	vm_offset_t va;
2601
	vm_offset_t va;
2594
 
2602
	pte_t *pte;
2595
	if (dumpsys_minidump) {
2603
	int i;
2596
		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
2604
2597
		if (prev == NULL) {
2605
	/* Initialize phys. segments for dumpsys(). */
2598
			/* 1st: kernel .data and .bss. */
2606
	memset(&dump_map, 0, sizeof(dump_map));
2599
			md.md_index = 1;
2607
	mem_regions(&physmem_regions, &physmem_regions_sz, &availmem_regions,
2600
			md.md_vaddr = trunc_page((uintptr_t)_etext);
2608
	    &availmem_regions_sz);
2601
			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
2609
	for (i = 0; i < physmem_regions_sz; i++) {
2602
			return (&md);
2610
		dump_map[i].md_start = physmem_regions[i].mr_start;
2611
		dump_map[i].md_size = physmem_regions[i].mr_size;
2612
	}
2613
2614
	/* Virtual segments for minidumps: */
2615
	memset(&dump_vmap, 0, sizeof(dump_vmap));
2616
2617
	/* 1st: kernel .data and .bss. */
2618
	dump_vmap[0].md_start = trunc_page((uintptr_t)_etext);
2619
	dump_vmap[0].md_size = round_page((uintptr_t)_end) - dump_vmap[0].md_start;
2620
2621
	/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
2622
	dump_vmap[1].md_start = data_start;
2623
	dump_vmap[1].md_size = data_end - data_start;
2624
2625
	/* 3rd: kernel VM. */
2626
	va = dump_vmap[1].md_start + dump_vmap[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_vmap[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_vmap[2].md_size = va - dump_vmap[2].md_start;
2653
	}
2654
}
2655
2656
struct md_pa *
2657
mmu_booke_scan_md(mmu_t mmu, struct md_pa *prev)
2658
{
2659
2660
	if (prev == NULL) {
2661
		if (do_minidump)
2662
			return (&dump_vmap[0]);
2663
		else
2664
			return (&dump_map[0]);
2667
	}
2665
	}
2668
2666
2669
	return (&md);
2667
	prev++;
2668
	/* There's no next chunk. */
2669
	if (prev->md_size == 0)
2670
		return (NULL);
2671
	return (prev);
2670
}
2672
}
2671
2673
2672
/*
2674
/*
2673
 * Map a set of physical memory pages into the kernel virtual address space.
2675
 * 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
2676
 * Return a pointer to where it is mapped. This routine is intended to be used
(-)b/sys/powerpc/include/md_var.h (+10 lines)
Lines 64-69 void decr_tc_init(void); Link Here
64
void	cpu_setup(u_int);
64
void	cpu_setup(u_int);
65
65
66
struct	trapframe;
66
struct	trapframe;
67
void	powerpc_interrupt(struct trapframe *);
67
void	powerpc_interrupt(struct trapframe *);
68
68
69
#define	KERNELDUMP_VERSION	KERNELDUMP_POWERPC_VERSION
70
#define	EM_VALUE		ELF_ARCH /* Defined in powerpc/include/elf.h */
71
72
#define	DUMPSYS_HAS_MD_PA_INIT	1
73
#define	DUMPSYS_HAS_MD_PA_NEXT	1
74
#define	DUMPSYS_HAS_MD_UNMAP	1
75
void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *);
76
77
#define	DUMPSYS_MD_PA_NPAIRS	(PHYS_AVAIL_SZ + 1)
78
69
#endif /* !_MACHINE_MD_VAR_H_ */
79
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/powerpc/include/pmap.h (-11 / +2 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-263 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 *);
248
extern void dumpsys_md_pa_init(void);
256
extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t);
249
extern struct md_pa *dumpsys_md_pa_next(struct md_pa *);
257
258
extern struct pmap_md *pmap_scan_md(struct pmap_md *);
259
250
260
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
251
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
261
252
262
#endif
253
#endif
263
254
(-)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 (-19 / +22 lines)
Lines 903-950 METHOD void sync_icache { Link Here
903
903
904
904
905
/**
905
/**
906
 * @brief Create temporary memory mapping for use by dumpsys().
906
 * @brief Create temporary memory mapping for use by dumpsys().
907
 *
907
 *
908
 * @param _md		The memory chunk in which the mapping lies.
908
 * @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.
909
 * @param _sz		The requested size of the mapping.
911
 *
910
 * @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
 */
911
 */
917
METHOD vm_offset_t dumpsys_map {
912
METHOD void dumpsys_map {
918
	mmu_t		_mmu;
913
	mmu_t		_mmu;
919
	struct pmap_md	*_md;
914
	vm_paddr_t	_pa;
920
	vm_size_t	_ofs;
915
	size_t		_sz;
921
	vm_size_t	*_sz;
916
	void		**_va;
922
};
917
};
923
918
924
919
925
/**
920
/**
926
 * @brief Remove temporary dumpsys() mapping.
921
 * @brief Remove temporary dumpsys() mapping.
927
 *
922
 *
928
 * @param _md		The memory chunk in which the mapping lies.
923
 * @param _pa		The physical page to map.
929
 * @param _ofs		The offset within the chunk of the mapping.
924
 * @param _sz		The requested size of the mapping.
930
 * @param _va		The virtual address of the mapping.
925
 * @param _va		The virtual address of the mapping.
931
 */
926
 */
932
METHOD void dumpsys_unmap {
927
METHOD void dumpsys_unmap {
933
	mmu_t		_mmu;
928
	mmu_t		_mmu;
934
	struct pmap_md	*_md;
929
	vm_paddr_t	_pa;
935
	vm_size_t	_ofs;
930
	size_t		_sz;
936
	vm_offset_t	_va;
931
	void		*_va;
937
};
932
};
938
933
939
934
940
/**
935
/**
941
 * @brief Scan/iterate memory chunks.
936
 * @brief Scan/iterate memory chunks.
942
 *
937
 *
943
 * @param _prev		The previously returned chunk or NULL.
938
 * @param _prev		The previously returned chunk or NULL.
944
 *
939
 *
945
 * @retval		The next (or first when _prev is NULL) chunk.
940
 * @retval		The next (or first when _prev is NULL) chunk, or NULL (EOF).
946
 */
941
 */
947
METHOD struct pmap_md * scan_md {
942
METHOD struct md_pa * scan_md {
948
	mmu_t		_mmu;
943
	mmu_t		_mmu;
949
	struct pmap_md	*_prev;
944
	struct md_pa	*_prev;
950
} DEFAULT mmu_null_scan_md;
945
} DEFAULT mmu_null_scan_md;
946
947
948
/**
949
 * @brief Initialize memory chunks for dumpsys.
950
 */
951
METHOD void scan_init {
952
	mmu_t		_mmu;
953
};
(-)b/sys/powerpc/powerpc/pmap_dispatch.c (-9 / +19 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/md_var.h>
54
#include <machine/mmuvar.h>
56
#include <machine/mmuvar.h>
55
#include <machine/smp.h>
57
#include <machine/smp.h>
56
58
57
#include "mmu_if.h"
59
#include "mmu_if.h"
58
60
Lines 520-547 pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) Link Here
520
 
522
 
521
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz);
523
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz);
522
	return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
524
	return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
523
}
525
}
524
526
525
vm_offset_t
527
void
526
pmap_dumpsys_map(struct pmap_md *md, vm_size_t ofs, vm_size_t *sz)
528
dumpsys_map_chunk(vm_paddr_t pa, size_t sz, void **va)
529
{
530
531
	CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
532
	return (MMU_DUMPSYS_MAP(mmu_obj, pa, sz, va));
533
}
534
535
void
536
dumpsys_unmap_chunk(vm_paddr_t pa, size_t sz, void *va)
527
{
537
{
528
538
529
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, *sz);
539
	CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
530
	return (MMU_DUMPSYS_MAP(mmu_obj, md, ofs, sz));
540
	return (MMU_DUMPSYS_UNMAP(mmu_obj, pa, sz, va));
531
}
541
}
532
542
533
void
543
void
534
pmap_dumpsys_unmap(struct pmap_md *md, vm_size_t ofs, vm_offset_t va)
544
dumpsys_md_pa_init(void)
535
{
545
{
536
546
537
	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, va);
547
	CTR1(KTR_PMAP, "%s()", __func__);
538
	return (MMU_DUMPSYS_UNMAP(mmu_obj, md, ofs, va));
548
	return (MMU_SCAN_INIT(mmu_obj));
539
}
549
}
540
550
541
struct pmap_md *
551
struct md_pa *
542
pmap_scan_md(struct pmap_md *prev)
552
dumpsys_md_pa_next(struct md_pa *prev)
543
{
553
{
544
554
545
	CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
555
	CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
546
	return (MMU_SCAN_MD(mmu_obj, prev));
556
	return (MMU_SCAN_MD(mmu_obj, prev));
547
}
557
}
(-)b/sys/sparc64/include/md_var.h (+5 lines)
Lines 73-78 int scsi_da_bios_params(struct ccb_calc_geometry *ccg); Link Here
73
struct disk;
73
struct disk;
74
void sparc64_ata_disk_firmware_geom_adjust(struct disk *disk);
74
void sparc64_ata_disk_firmware_geom_adjust(struct disk *disk);
75
#define	ata_disk_firmware_geom_adjust(disk)				\
75
#define	ata_disk_firmware_geom_adjust(disk)				\
76
	sparc64_ata_disk_firmware_geom_adjust(disk)
76
	sparc64_ata_disk_firmware_geom_adjust(disk)
77
77
78
#define	DUMPSYS_MD_PA_NPAIRS	128
79
#define	DUMPSYS_HAS_MD_DUMPSYS	1
80
#define	DUMPSYS_HAS_MD_PA_INIT	1
81
void dumpsys_md_pa_init(void);
82
78
#endif /* !_MACHINE_MD_VAR_H_ */
83
#endif /* !_MACHINE_MD_VAR_H_ */
(-)b/sys/sparc64/sparc64/dump_machdep.c (-87 / +28 lines)
Lines 38-152 __FBSDID("$FreeBSD$"); Link Here
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/metadata.h>
42
#include <machine/metadata.h>
43
#include <machine/md_var.h>
43
#include <machine/kerneldump.h>
44
#include <machine/kerneldump.h>
44
#include <machine/ofw_mem.h>
45
#include <machine/ofw_mem.h>
45
#include <machine/tsb.h>
46
#include <machine/tsb.h>
46
#include <machine/tlb.h>
47
#include <machine/tlb.h>
47
48
48
CTASSERT(sizeof(struct kerneldumpheader) == DEV_BSIZE);
49
static off_t fileofs;
49
50
50
static struct kerneldumpheader kdh;
51
extern off_t dumplo;
51
static off_t dumplo, dumppos;
52
extern struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
52
53
53
/* Handle buffered writes. */
54
void
54
static char buffer[DEV_BSIZE];
55
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
{
56
{
62
	size_t len;
57
	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
58
83
	return (0);
59
	memset(dump_map, 0, sizeof(dump_map));
60
	for (i = 0; i < sparc64_nmemreg; i++) {
61
		dump_map[i].md_start = sparc64_memreg[i].mr_start;
62
		dump_map[i].md_size = sparc64_memreg[i].mr_size;
63
	}
84
}
64
}
85
65
86
static int
66
void
87
buf_flush(struct dumperinfo *di)
67
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
88
{
68
{
89
	int error;
90
91
	if (fragsz == 0)
92
		return (0);
93
69
94
	error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
70
	*va = (void*)TLB_PHYS_TO_DIRECT(pa);
95
	dumplo += DEV_BSIZE;
96
	fragsz = 0;
97
	return (error);
98
}
71
}
99
72
100
static int
73
static int
101
reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
74
reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
102
{
75
{
103
	struct sparc64_dump_reg r;
76
	struct sparc64_dump_reg r;
104
77
105
	r.dr_pa = pa;
78
	r.dr_pa = pa;
106
	r.dr_size = size;
79
	r.dr_size = size;
107
	r.dr_offs = dumppos;
80
	r.dr_offs = fileofs;
108
	dumppos += size;
81
	fileofs += size;
109
	return (buf_write(di, (char *)&r, sizeof(r)));
82
	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
}
83
}
144
84
145
int
85
int
146
dumpsys(struct dumperinfo *di)
86
dumpsys(struct dumperinfo *di)
147
{
87
{
88
	struct kerneldumpheader kdh;
148
	struct sparc64_dump_hdr hdr;
89
	struct sparc64_dump_hdr hdr;
149
	vm_size_t size, totsize, hdrsize;
90
	vm_size_t size, totsize, hdrsize;
150
	int error, i, nreg;
91
	int error, i, nreg;
151
92
152
	/* Calculate dump size. */
93
	/* Calculate dump size. */
Lines 187-216 dumpsys(struct dumperinfo *di) Link Here
187
	hdr.dh_tsb_pa = tsb_kernel_phys;
128
	hdr.dh_tsb_pa = tsb_kernel_phys;
188
	hdr.dh_tsb_size = tsb_kernel_size;
129
	hdr.dh_tsb_size = tsb_kernel_size;
189
	hdr.dh_tsb_mask = tsb_kernel_mask;
130
	hdr.dh_tsb_mask = tsb_kernel_mask;
190
	hdr.dh_nregions = nreg;
131
	hdr.dh_nregions = nreg;
191
132
192
	if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
133
	if (dumpsys_buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
193
		goto fail;
134
		goto fail;
194
135
195
	dumppos = hdrsize;
136
	fileofs = hdrsize;
196
	/* Now, write out the region descriptors. */
137
	/* Now, write out the region descriptors. */
197
	for (i = 0; i < sparc64_nmemreg; i++) {
138
	for (i = 0; i < sparc64_nmemreg; i++) {
198
		error = reg_write(di, sparc64_memreg[i].mr_start,
139
		error = reg_write(di, sparc64_memreg[i].mr_start,
199
		    sparc64_memreg[i].mr_size);
140
		    sparc64_memreg[i].mr_size);
200
		if (error != 0)
141
		if (error != 0)
201
			goto fail;
142
			goto fail;
202
	}
143
	}
203
	buf_flush(di);
144
	dumpsys_buf_flush(di);
204
145
205
	/* Dump memory chunks. */
146
	/* Dump memory chunks. */
206
	for (i = 0; i < sparc64_nmemreg; i++) {
147
	error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
207
		error = blk_dump(di, sparc64_memreg[i].mr_start,
148
	if (error < 0)
208
		    sparc64_memreg[i].mr_size);
149
		goto fail;
209
		if (error != 0)
210
			goto fail;
211
	}
212
150
213
	/* Dump trailer */
151
	/* Dump trailer */
214
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
152
	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
215
	if (error)
153
	if (error)
216
		goto fail;
154
		goto fail;
Lines 219-227 dumpsys(struct dumperinfo *di) Link Here
219
	dump_write(di, NULL, 0, 0, 0);
157
	dump_write(di, NULL, 0, 0, 0);
220
	printf("\nDump complete\n");
158
	printf("\nDump complete\n");
221
	return (0);
159
	return (0);
222
160
223
 fail:
161
 fail:
162
	if (error < 0)
163
		error = -error;
164
224
	/* XXX It should look more like VMS :-) */
165
	/* XXX It should look more like VMS :-) */
225
	printf("** DUMP FAILED (ERROR %d) **\n", error);
166
	printf("** DUMP FAILED (ERROR %d) **\n", error);
226
	return (error);
167
	return (error);
227
}
168
}
(-)b/sys/sys/conf.h (+12 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;
342
354
343
#endif /* _KERNEL */
355
#endif /* _KERNEL */
344
356
345
#endif /* !_SYS_CONF_H_ */
357
#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