19a527560SKonstantin Belousov /*-
29a527560SKonstantin Belousov  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
39a527560SKonstantin Belousov  *
49a527560SKonstantin Belousov  * Copyright (c) 2006 Peter Wemm
59a527560SKonstantin Belousov  * All rights reserved.
69a527560SKonstantin Belousov  *
79a527560SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
89a527560SKonstantin Belousov  * modification, are permitted provided that the following conditions
99a527560SKonstantin Belousov  * are met:
109a527560SKonstantin Belousov  *
119a527560SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
129a527560SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
139a527560SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
149a527560SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
159a527560SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
169a527560SKonstantin Belousov  *
179a527560SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189a527560SKonstantin Belousov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199a527560SKonstantin Belousov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209a527560SKonstantin Belousov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219a527560SKonstantin Belousov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229a527560SKonstantin Belousov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239a527560SKonstantin Belousov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249a527560SKonstantin Belousov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259a527560SKonstantin Belousov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269a527560SKonstantin Belousov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279a527560SKonstantin Belousov  */
289a527560SKonstantin Belousov 
299a527560SKonstantin Belousov #include <sys/cdefs.h>
309a527560SKonstantin Belousov __FBSDID("$FreeBSD$");
319a527560SKonstantin Belousov 
329a527560SKonstantin Belousov #include "opt_watchdog.h"
339a527560SKonstantin Belousov 
349a527560SKonstantin Belousov #include <sys/param.h>
359a527560SKonstantin Belousov #include <sys/systm.h>
369a527560SKonstantin Belousov #include <sys/conf.h>
379a527560SKonstantin Belousov #include <sys/cons.h>
389a527560SKonstantin Belousov #include <sys/kernel.h>
399a527560SKonstantin Belousov #include <sys/kerneldump.h>
409a527560SKonstantin Belousov #include <sys/msgbuf.h>
419a527560SKonstantin Belousov #include <sys/watchdog.h>
429a527560SKonstantin Belousov #include <vm/vm.h>
4321943937SJeff Roberson #include <vm/vm_param.h>
4421943937SJeff Roberson #include <vm/vm_page.h>
4521943937SJeff Roberson #include <vm/vm_phys.h>
466f3b523cSKonstantin Belousov #include <vm/vm_dumpset.h>
479a527560SKonstantin Belousov #include <vm/pmap.h>
489a527560SKonstantin Belousov #include <machine/atomic.h>
499a527560SKonstantin Belousov #include <machine/elf.h>
509a527560SKonstantin Belousov #include <machine/md_var.h>
519a527560SKonstantin Belousov #include <machine/minidump.h>
529a527560SKonstantin Belousov 
539a527560SKonstantin Belousov CTASSERT(sizeof(struct kerneldumpheader) == 512);
549a527560SKonstantin Belousov 
559a527560SKonstantin Belousov #define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
569a527560SKonstantin Belousov #define	DEV_ALIGN(x)	roundup2((off_t)(x), DEV_BSIZE)
579a527560SKonstantin Belousov 
589a527560SKonstantin Belousov static struct kerneldumpheader kdh;
599a527560SKonstantin Belousov 
609a527560SKonstantin Belousov /* Handle chunked writes. */
619a527560SKonstantin Belousov static size_t fragsz;
629a527560SKonstantin Belousov static void *dump_va;
639a527560SKonstantin Belousov 
649a527560SKonstantin Belousov static int
659a527560SKonstantin Belousov blk_flush(struct dumperinfo *di)
669a527560SKonstantin Belousov {
679a527560SKonstantin Belousov 	int error;
689a527560SKonstantin Belousov 
699a527560SKonstantin Belousov 	if (fragsz == 0)
709a527560SKonstantin Belousov 		return (0);
719a527560SKonstantin Belousov 
729a527560SKonstantin Belousov 	error = dump_append(di, dump_va, 0, fragsz);
739a527560SKonstantin Belousov 	fragsz = 0;
749a527560SKonstantin Belousov 	return (error);
759a527560SKonstantin Belousov }
769a527560SKonstantin Belousov 
779a527560SKonstantin Belousov static int
789a527560SKonstantin Belousov blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
799a527560SKonstantin Belousov {
809a527560SKonstantin Belousov 	size_t len;
819a527560SKonstantin Belousov 	int error, i, c;
829a527560SKonstantin Belousov 	u_int maxdumpsz;
839a527560SKonstantin Belousov 
849a527560SKonstantin Belousov 	maxdumpsz = min(di->maxiosize, MAXDUMPPGS * PAGE_SIZE);
859a527560SKonstantin Belousov 	if (maxdumpsz == 0)	/* seatbelt */
869a527560SKonstantin Belousov 		maxdumpsz = PAGE_SIZE;
879a527560SKonstantin Belousov 	error = 0;
889a527560SKonstantin Belousov 	if ((sz % PAGE_SIZE) != 0) {
899a527560SKonstantin Belousov 		printf("size not page aligned\n");
909a527560SKonstantin Belousov 		return (EINVAL);
919a527560SKonstantin Belousov 	}
929a527560SKonstantin Belousov 	if (ptr != NULL && pa != 0) {
939a527560SKonstantin Belousov 		printf("cant have both va and pa!\n");
949a527560SKonstantin Belousov 		return (EINVAL);
959a527560SKonstantin Belousov 	}
969a527560SKonstantin Belousov 	if (pa != 0 && (((uintptr_t)ptr) % PAGE_SIZE) != 0) {
979a527560SKonstantin Belousov 		printf("address not page aligned\n");
989a527560SKonstantin Belousov 		return (EINVAL);
999a527560SKonstantin Belousov 	}
1009a527560SKonstantin Belousov 	if (ptr != NULL) {
1019a527560SKonstantin Belousov 		/* If we're doing a virtual dump, flush any pre-existing pa pages */
1029a527560SKonstantin Belousov 		error = blk_flush(di);
1039a527560SKonstantin Belousov 		if (error)
1049a527560SKonstantin Belousov 			return (error);
1059a527560SKonstantin Belousov 	}
1069a527560SKonstantin Belousov 	while (sz) {
1079a527560SKonstantin Belousov 		len = maxdumpsz - fragsz;
1089a527560SKonstantin Belousov 		if (len > sz)
1099a527560SKonstantin Belousov 			len = sz;
1109a527560SKonstantin Belousov 
111ab4ed843SMitchell Horne 		dumpsys_pb_progress(len);
1129a527560SKonstantin Belousov 		wdog_kern_pat(WD_LASTVAL);
1139a527560SKonstantin Belousov 
1149a527560SKonstantin Belousov 		if (ptr) {
1159a527560SKonstantin Belousov 			error = dump_append(di, ptr, 0, len);
1169a527560SKonstantin Belousov 			if (error)
1179a527560SKonstantin Belousov 				return (error);
1189a527560SKonstantin Belousov 			ptr += len;
1199a527560SKonstantin Belousov 			sz -= len;
1209a527560SKonstantin Belousov 		} else {
1219a527560SKonstantin Belousov 			for (i = 0; i < len; i += PAGE_SIZE)
1229a527560SKonstantin Belousov 				dump_va = pmap_kenter_temporary(pa + i, (i + fragsz) >> PAGE_SHIFT);
1239a527560SKonstantin Belousov 			fragsz += len;
1249a527560SKonstantin Belousov 			pa += len;
1259a527560SKonstantin Belousov 			sz -= len;
1269a527560SKonstantin Belousov 			if (fragsz == maxdumpsz) {
1279a527560SKonstantin Belousov 				error = blk_flush(di);
1289a527560SKonstantin Belousov 				if (error)
1299a527560SKonstantin Belousov 					return (error);
1309a527560SKonstantin Belousov 			}
1319a527560SKonstantin Belousov 		}
1329a527560SKonstantin Belousov 
1339a527560SKonstantin Belousov 		/* Check for user abort. */
1349a527560SKonstantin Belousov 		c = cncheckc();
1359a527560SKonstantin Belousov 		if (c == 0x03)
1369a527560SKonstantin Belousov 			return (ECANCELED);
1379a527560SKonstantin Belousov 		if (c != -1)
1389a527560SKonstantin Belousov 			printf(" (CTRL-C to abort) ");
1399a527560SKonstantin Belousov 	}
1409a527560SKonstantin Belousov 
1419a527560SKonstantin Belousov 	return (0);
1429a527560SKonstantin Belousov }
1439a527560SKonstantin Belousov 
1449a527560SKonstantin Belousov /* A fake page table page, to avoid having to handle both 4K and 2M pages */
1459a527560SKonstantin Belousov static pt_entry_t fakept[NPTEPG];
1469a527560SKonstantin Belousov 
1479a527560SKonstantin Belousov #ifdef PMAP_PAE_COMP
1481adebe3cSMitchell Horne #define	cpu_minidumpsys		cpu_minidumpsys_pae
1499a527560SKonstantin Belousov #define	IdlePTD			IdlePTD_pae
1509a527560SKonstantin Belousov #else
1511adebe3cSMitchell Horne #define	cpu_minidumpsys		cpu_minidumpsys_nopae
1529a527560SKonstantin Belousov #define	IdlePTD			IdlePTD_nopae
1539a527560SKonstantin Belousov #endif
1549a527560SKonstantin Belousov 
1559a527560SKonstantin Belousov int
1561adebe3cSMitchell Horne cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state)
1579a527560SKonstantin Belousov {
1589a527560SKonstantin Belousov 	uint64_t dumpsize;
1599a527560SKonstantin Belousov 	uint32_t ptesize;
160681bd710SMitchell Horne 	vm_offset_t va, kva_end;
1619a527560SKonstantin Belousov 	int error;
1629a527560SKonstantin Belousov 	uint64_t pa;
163681bd710SMitchell Horne 	pd_entry_t *pd, pde;
164681bd710SMitchell Horne 	pt_entry_t *pt, pte;
165ab041f71SD Scott Phillips 	int j, k;
1669a527560SKonstantin Belousov 	struct minidumphdr mdhdr;
1671d2d1418SMitchell Horne 	struct msgbuf *mbp;
1689a527560SKonstantin Belousov 
169681bd710SMitchell Horne 	/* Snapshot the KVA upper bound in case it grows. */
170681bd710SMitchell Horne 	kva_end = kernel_vm_end;
171681bd710SMitchell Horne 
172681bd710SMitchell Horne 	/*
173681bd710SMitchell Horne 	 * Walk the kernel page table pages, setting the active entries in the
174681bd710SMitchell Horne 	 * dump bitmap.
175681bd710SMitchell Horne 	 *
176681bd710SMitchell Horne 	 * NB: for a live dump, we may be racing with updates to the page
177681bd710SMitchell Horne 	 * tables, so care must be taken to read each entry only once.
178681bd710SMitchell Horne 	 */
1799a527560SKonstantin Belousov 	ptesize = 0;
180681bd710SMitchell Horne 	for (va = KERNBASE; va < kva_end; va += NBPDR) {
1819a527560SKonstantin Belousov 		/*
1829a527560SKonstantin Belousov 		 * We always write a page, even if it is zero. Each
1839a527560SKonstantin Belousov 		 * page written corresponds to 2MB of space
1849a527560SKonstantin Belousov 		 */
1859a527560SKonstantin Belousov 		ptesize += PAGE_SIZE;
1869a527560SKonstantin Belousov 		pd = IdlePTD;	/* always mapped! */
1879a527560SKonstantin Belousov 		j = va >> PDRSHIFT;
188681bd710SMitchell Horne 		pde = pte_load(&pd[va >> PDRSHIFT]);
189681bd710SMitchell Horne 		if ((pde & (PG_PS | PG_V)) == (PG_PS | PG_V))  {
1909a527560SKonstantin Belousov 			/* This is an entire 2M page. */
191681bd710SMitchell Horne 			pa = pde & PG_PS_FRAME;
1929a527560SKonstantin Belousov 			for (k = 0; k < NPTEPG; k++) {
19331991a5aSMitchell Horne 				if (vm_phys_is_dumpable(pa))
1949a527560SKonstantin Belousov 					dump_add_page(pa);
1959a527560SKonstantin Belousov 				pa += PAGE_SIZE;
1969a527560SKonstantin Belousov 			}
1979a527560SKonstantin Belousov 			continue;
1989a527560SKonstantin Belousov 		}
199681bd710SMitchell Horne 		if ((pde & PG_V) == PG_V) {
2009a527560SKonstantin Belousov 			/* set bit for each valid page in this 2MB block */
201681bd710SMitchell Horne 			pt = pmap_kenter_temporary(pde & PG_FRAME, 0);
2029a527560SKonstantin Belousov 			for (k = 0; k < NPTEPG; k++) {
203681bd710SMitchell Horne 				pte = pte_load(&pt[k]);
204681bd710SMitchell Horne 				if ((pte & PG_V) == PG_V) {
205681bd710SMitchell Horne 					pa = pte & PG_FRAME;
20631991a5aSMitchell Horne 					if (vm_phys_is_dumpable(pa))
2079a527560SKonstantin Belousov 						dump_add_page(pa);
2089a527560SKonstantin Belousov 				}
2099a527560SKonstantin Belousov 			}
2109a527560SKonstantin Belousov 		} else {
2119a527560SKonstantin Belousov 			/* nothing, we're going to dump a null page */
2129a527560SKonstantin Belousov 		}
2139a527560SKonstantin Belousov 	}
2149a527560SKonstantin Belousov 
2159a527560SKonstantin Belousov 	/* Calculate dump size. */
2161d2d1418SMitchell Horne 	mbp = state->msgbufp;
2179a527560SKonstantin Belousov 	dumpsize = ptesize;
2181d2d1418SMitchell Horne 	dumpsize += round_page(mbp->msg_size);
21900e66147SD Scott Phillips 	dumpsize += round_page(sizeof(dump_avail));
220ab041f71SD Scott Phillips 	dumpsize += round_page(BITSET_SIZE(vm_page_dump_pages));
221ab041f71SD Scott Phillips 	VM_PAGE_DUMP_FOREACH(pa) {
2229a527560SKonstantin Belousov 		/* Clear out undumpable pages now if needed */
22331991a5aSMitchell Horne 		if (vm_phys_is_dumpable(pa)) {
2249a527560SKonstantin Belousov 			dumpsize += PAGE_SIZE;
2259a527560SKonstantin Belousov 		} else {
2269a527560SKonstantin Belousov 			dump_drop_page(pa);
2279a527560SKonstantin Belousov 		}
2289a527560SKonstantin Belousov 	}
2299a527560SKonstantin Belousov 	dumpsize += PAGE_SIZE;
2309a527560SKonstantin Belousov 
231ab4ed843SMitchell Horne 	dumpsys_pb_init(dumpsize);
2329a527560SKonstantin Belousov 
2339a527560SKonstantin Belousov 	/* Initialize mdhdr */
2349a527560SKonstantin Belousov 	bzero(&mdhdr, sizeof(mdhdr));
2359a527560SKonstantin Belousov 	strcpy(mdhdr.magic, MINIDUMP_MAGIC);
2369a527560SKonstantin Belousov 	mdhdr.version = MINIDUMP_VERSION;
2371d2d1418SMitchell Horne 	mdhdr.msgbufsize = mbp->msg_size;
238ab041f71SD Scott Phillips 	mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages));
2399a527560SKonstantin Belousov 	mdhdr.ptesize = ptesize;
2409a527560SKonstantin Belousov 	mdhdr.kernbase = KERNBASE;
2419a527560SKonstantin Belousov 	mdhdr.paemode = pae_mode;
24200e66147SD Scott Phillips 	mdhdr.dumpavailsize = round_page(sizeof(dump_avail));
2439a527560SKonstantin Belousov 
2449a527560SKonstantin Belousov 	dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_I386_VERSION,
2459a527560SKonstantin Belousov 	    dumpsize);
2469a527560SKonstantin Belousov 
2479a527560SKonstantin Belousov 	error = dump_start(di, &kdh);
2489a527560SKonstantin Belousov 	if (error != 0)
2499a527560SKonstantin Belousov 		goto fail;
2509a527560SKonstantin Belousov 
2519a527560SKonstantin Belousov 	printf("Physical memory: %ju MB\n", ptoa((uintmax_t)physmem) / 1048576);
2529a527560SKonstantin Belousov 	printf("Dumping %llu MB:", (long long)dumpsize >> 20);
2539a527560SKonstantin Belousov 
2549a527560SKonstantin Belousov 	/* Dump my header */
2559a527560SKonstantin Belousov 	bzero(&fakept, sizeof(fakept));
2569a527560SKonstantin Belousov 	bcopy(&mdhdr, &fakept, sizeof(mdhdr));
2579a527560SKonstantin Belousov 	error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
2589a527560SKonstantin Belousov 	if (error)
2599a527560SKonstantin Belousov 		goto fail;
2609a527560SKonstantin Belousov 
2619a527560SKonstantin Belousov 	/* Dump msgbuf up front */
2621d2d1418SMitchell Horne 	error = blk_write(di, (char *)mbp->msg_ptr, 0,
2631d2d1418SMitchell Horne 	    round_page(mbp->msg_size));
2649a527560SKonstantin Belousov 	if (error)
2659a527560SKonstantin Belousov 		goto fail;
2669a527560SKonstantin Belousov 
26700e66147SD Scott Phillips 	/* Dump dump_avail */
26800e66147SD Scott Phillips 	_Static_assert(sizeof(dump_avail) <= sizeof(fakept),
26900e66147SD Scott Phillips 	    "Large dump_avail not handled");
27000e66147SD Scott Phillips 	bzero(fakept, sizeof(fakept));
27100e66147SD Scott Phillips 	memcpy(fakept, dump_avail, sizeof(dump_avail));
27200e66147SD Scott Phillips 	error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
27300e66147SD Scott Phillips 	if (error)
27400e66147SD Scott Phillips 		goto fail;
27500e66147SD Scott Phillips 
2769a527560SKonstantin Belousov 	/* Dump bitmap */
277ab041f71SD Scott Phillips 	error = blk_write(di, (char *)vm_page_dump, 0,
278ab041f71SD Scott Phillips 	    round_page(BITSET_SIZE(vm_page_dump_pages)));
2799a527560SKonstantin Belousov 	if (error)
2809a527560SKonstantin Belousov 		goto fail;
2819a527560SKonstantin Belousov 
2829a527560SKonstantin Belousov 	/* Dump kernel page table pages */
283681bd710SMitchell Horne 	for (va = KERNBASE; va < kva_end; va += NBPDR) {
2849a527560SKonstantin Belousov 		/* We always write a page, even if it is zero */
2859a527560SKonstantin Belousov 		pd = IdlePTD;	/* always mapped! */
286681bd710SMitchell Horne 		pde = pte_load(&pd[va >> PDRSHIFT]);
287681bd710SMitchell Horne 		if ((pde & (PG_PS | PG_V)) == (PG_PS | PG_V))  {
2889a527560SKonstantin Belousov 			/* This is a single 2M block. Generate a fake PTP */
289681bd710SMitchell Horne 			pa = pde & PG_PS_FRAME;
2909a527560SKonstantin Belousov 			for (k = 0; k < NPTEPG; k++) {
2919a527560SKonstantin Belousov 				fakept[k] = (pa + (k * PAGE_SIZE)) | PG_V | PG_RW | PG_A | PG_M;
2929a527560SKonstantin Belousov 			}
2939a527560SKonstantin Belousov 			error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
2949a527560SKonstantin Belousov 			if (error)
2959a527560SKonstantin Belousov 				goto fail;
2969a527560SKonstantin Belousov 			/* flush, in case we reuse fakept in the same block */
2979a527560SKonstantin Belousov 			error = blk_flush(di);
2989a527560SKonstantin Belousov 			if (error)
2999a527560SKonstantin Belousov 				goto fail;
3009a527560SKonstantin Belousov 			continue;
3019a527560SKonstantin Belousov 		}
302681bd710SMitchell Horne 		if ((pde & PG_V) == PG_V) {
303681bd710SMitchell Horne 			pa = pde & PG_FRAME;
3049a527560SKonstantin Belousov 			error = blk_write(di, 0, pa, PAGE_SIZE);
3059a527560SKonstantin Belousov 			if (error)
3069a527560SKonstantin Belousov 				goto fail;
3079a527560SKonstantin Belousov 		} else {
3089a527560SKonstantin Belousov 			bzero(fakept, sizeof(fakept));
3099a527560SKonstantin Belousov 			error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE);
3109a527560SKonstantin Belousov 			if (error)
3119a527560SKonstantin Belousov 				goto fail;
3129a527560SKonstantin Belousov 			/* flush, in case we reuse fakept in the same block */
3139a527560SKonstantin Belousov 			error = blk_flush(di);
3149a527560SKonstantin Belousov 			if (error)
3159a527560SKonstantin Belousov 				goto fail;
3169a527560SKonstantin Belousov 		}
3179a527560SKonstantin Belousov 	}
3189a527560SKonstantin Belousov 
3199a527560SKonstantin Belousov 	/* Dump memory chunks */
320ab041f71SD Scott Phillips 	VM_PAGE_DUMP_FOREACH(pa) {
3219a527560SKonstantin Belousov 		error = blk_write(di, 0, pa, PAGE_SIZE);
3229a527560SKonstantin Belousov 		if (error)
3239a527560SKonstantin Belousov 			goto fail;
3249a527560SKonstantin Belousov 	}
3259a527560SKonstantin Belousov 
3269a527560SKonstantin Belousov 	error = blk_flush(di);
3279a527560SKonstantin Belousov 	if (error)
3289a527560SKonstantin Belousov 		goto fail;
3299a527560SKonstantin Belousov 
3309a527560SKonstantin Belousov 	error = dump_finish(di, &kdh);
3319a527560SKonstantin Belousov 	if (error != 0)
3329a527560SKonstantin Belousov 		goto fail;
3339a527560SKonstantin Belousov 
3349a527560SKonstantin Belousov 	printf("\nDump complete\n");
3359a527560SKonstantin Belousov 	return (0);
3369a527560SKonstantin Belousov 
3379a527560SKonstantin Belousov  fail:
3389a527560SKonstantin Belousov 	if (error < 0)
3399a527560SKonstantin Belousov 		error = -error;
3409a527560SKonstantin Belousov 
3419a527560SKonstantin Belousov 	if (error == ECANCELED)
3429a527560SKonstantin Belousov 		printf("\nDump aborted\n");
34357f317e6SNavdeep Parhar 	else if (error == E2BIG || error == ENOSPC) {
34457f317e6SNavdeep Parhar 		printf("\nDump failed. Partition too small (about %lluMB were "
34557f317e6SNavdeep Parhar 		    "needed this time).\n", (long long)dumpsize >> 20);
34657f317e6SNavdeep Parhar 	} else
3479a527560SKonstantin Belousov 		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
3489a527560SKonstantin Belousov 	return (error);
3499a527560SKonstantin Belousov }
350