1/*- 2 * Copyright (c) 2002 Marcel Moolenaar 3 * Copyright (c) 2002 Thomas Moestl 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/conf.h> 34#include <sys/cons.h> 35#include <sys/kernel.h> 36#include <sys/kerneldump.h> 37 38#include <vm/vm.h> 39#include <vm/vm_param.h> 40#include <vm/pmap.h> 41 42#include <machine/dump.h> 43#include <machine/md_var.h> 44#include <machine/metadata.h> 45#include <machine/kerneldump.h> 46#include <machine/ofw_mem.h> 47#include <machine/tsb.h> 48#include <machine/tlb.h> 49 50static off_t fileofs; 51 52extern off_t dumplo; 53extern struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; 54 55int do_minidump = 0; 56 57void 58dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va) 59{ 60 61 *va = (void *)TLB_PHYS_TO_DIRECT(pa); 62} 63 64static int 65reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size) 66{ 67 struct sparc64_dump_reg r; 68 69 r.dr_pa = pa; 70 r.dr_size = size; 71 r.dr_offs = fileofs; 72 fileofs += size; 73 return (dumpsys_buf_write(di, (char *)&r, sizeof(r))); 74} 75 76int 77dumpsys(struct dumperinfo *di) 78{ 79 static struct kerneldumpheader kdh; 80 struct sparc64_dump_hdr hdr; 81 vm_size_t size, totsize, hdrsize; 82 int error, i, nreg; 83 84 /* Set up dump_map and calculate dump size. */ 85 size = 0; 86 nreg = sparc64_nmemreg; 87 memset(dump_map, 0, sizeof(dump_map)); 88 for (i = 0; i < nreg; i++) { 89 dump_map[i].pa_start = sparc64_memreg[i].mr_start; 90 size += dump_map[i].pa_size = sparc64_memreg[i].mr_size; 91 } 92 /* Account for the header size. */ 93 hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg, 94 DEV_BSIZE); 95 size += hdrsize; 96 97 totsize = size + 2 * sizeof(kdh); 98 if (totsize > di->mediasize) { 99 printf("Insufficient space on device (need %ld, have %ld), " 100 "refusing to dump.\n", (long)totsize, 101 (long)di->mediasize); 102 error = ENOSPC; 103 goto fail; 104 } 105 106 /* Determine dump offset on device. */ 107 dumplo = di->mediaoffset + di->mediasize - totsize; 108 109 mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size, 110 di->blocksize); 111 112 printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); 113 114 /* Dump leader */ 115 error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); 116 if (error) 117 goto fail; 118 dumplo += sizeof(kdh); 119 120 /* Dump the private header. */ 121 hdr.dh_hdr_size = hdrsize; 122 hdr.dh_tsb_pa = tsb_kernel_phys; 123 hdr.dh_tsb_size = tsb_kernel_size; 124 hdr.dh_tsb_mask = tsb_kernel_mask; 125 hdr.dh_nregions = nreg; 126 127 if (dumpsys_buf_write(di, (char *)&hdr, sizeof(hdr)) != 0) 128 goto fail; 129 130 fileofs = hdrsize; 131 /* Now, write out the region descriptors. */ 132 for (i = 0; i < nreg; i++) { 133 error = reg_write(di, sparc64_memreg[i].mr_start, 134 sparc64_memreg[i].mr_size); 135 if (error != 0) 136 goto fail; 137 } 138 dumpsys_buf_flush(di); 139 140 /* Dump memory chunks. */ 141 error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); 142 if (error < 0) 143 goto fail; 144 145 /* Dump trailer */ 146 error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); 147 if (error) 148 goto fail; 149 150 /* Signal completion, signoff and exit stage left. */ 151 dump_write(di, NULL, 0, 0, 0); 152 printf("\nDump complete\n"); 153 return (0); 154 155 fail: 156 if (error < 0) 157 error = -error; 158 159 /* XXX It should look more like VMS :-) */ 160 printf("** DUMP FAILED (ERROR %d) **\n", error); 161 return (error); 162} 163