xref: /netbsd-src/sys/arch/arm/arm32/stubs.c (revision 3b3140f5f6442fdc9bfff640ecc3058432700234)
1 /*	$NetBSD: stubs.c,v 1.27 2020/07/03 15:31:25 skrll Exp $	*/
2 
3 /*
4  * Copyright (c) 1994-1998 Mark Brinicombe.
5  * Copyright (c) 1994 Brini.
6  * All rights reserved.
7  *
8  * This code is derived from software written for Brini by Mark Brinicombe
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by Mark Brinicombe
21  *	for the NetBSD Project.
22  * 4. The name of the company nor the name of the author may be used to
23  *    endorse or promote products derived from this software without specific
24  *    prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
27  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * Routines that are temporary or do not have a home yet.
39  *
40  * Created      : 17/09/94
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: stubs.c,v 1.27 2020/07/03 15:31:25 skrll Exp $");
45 
46 #include <sys/param.h>
47 
48 #include <sys/conf.h>
49 #include <sys/core.h>
50 #include <sys/errno.h>
51 #include <sys/kcore.h>
52 #include <sys/msgbuf.h>
53 #include <sys/proc.h>
54 #include <sys/systm.h>
55 
56 #include <uvm/uvm_extern.h>
57 
58 #include <machine/cpu.h>
59 #include <machine/intr.h>
60 #include <machine/bootconfig.h>
61 #include <machine/pcb.h>
62 
63 #include <arm/arm32/machdep.h>
64 #include <arm/kcore.h>
65 
66 extern dev_t dumpdev;
67 
68 int	cpu_dump(void);
69 int	cpu_dumpsize(void);
70 u_long	cpu_dump_mempagecnt(void);
71 
72 /*
73  * These variables are needed by /sbin/savecore
74  */
75 uint32_t dumpmag = 0x8fca0101;	/* magic number */
76 int 	dumpsize = 0;		/* pages */
77 long	dumplo = 0; 		/* blocks */
78 
79 struct pcb dumppcb;
80 
81 /*
82  * This is called by main to set dumplo and dumpsize.
83  * Dumps always skip the first PAGE_SIZE of disk space
84  * in case there might be a disk label stored there.
85  * If there is extra space, put dump at the end to
86  * reduce the chance that swapping trashes it.
87  */
88 
89 void
cpu_dumpconf(void)90 cpu_dumpconf(void)
91 {
92 	int nblks, dumpblks;	/* size of dump area */
93 
94 	if (dumpdev == NODEV)
95 		return;
96 	nblks = bdev_size(dumpdev);
97 	if (nblks <= ctod(1))
98 		return;
99 
100 	dumpblks = cpu_dumpsize();
101 	if (dumpblks < 0)
102 		goto bad;
103 	dumpblks += ctod(cpu_dump_mempagecnt());
104 
105 	/* If dump won't fit (incl. room for possible label), punt. */
106 	if (dumpblks > (nblks - ctod(1)))
107 		goto bad;
108 
109 	/* Put dump at end of partition */
110 	dumplo = nblks - dumpblks;
111 
112 	/* dumpsize is in page units, and doesn't include headers. */
113 	dumpsize = cpu_dump_mempagecnt();
114 	return;
115 
116  bad:
117 	dumpsize = 0;
118 }
119 
120 /*
121  * cpu_dump: dump the machine-dependent kernel core dump headers.
122  */
123 int
cpu_dump(void)124 cpu_dump(void)
125 {
126 	int (*dump)(dev_t, daddr_t, void *, size_t);
127 	char bf[dbtob(1)];
128 	kcore_seg_t *segp;
129 	cpu_kcore_hdr_t *cpuhdrp;
130 	phys_ram_seg_t *memsegp;
131 	const struct bdevsw *bdev;
132 	int i;
133 
134 	bdev = bdevsw_lookup(dumpdev);
135 	if (bdev == NULL)
136 		return ENXIO;
137 	dump = bdev->d_dump;
138 
139 	memset(bf, 0, sizeof bf);
140 	segp = (kcore_seg_t *)bf;
141 	cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))];
142 	memsegp = (phys_ram_seg_t *)&bf[ ALIGN(sizeof(*segp)) +
143 	    ALIGN(sizeof(*cpuhdrp))];
144 
145 	/*
146 	 * Generate a segment header.
147 	 */
148 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
149 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
150 
151 	/*
152 	 * Add the machine-dependent header info.
153 	 */
154 	cpuhdrp->version = 1;
155 	cpuhdrp->PAKernelL1Table = pmap_kernel_L1_addr();
156 	cpuhdrp->UserL1TableSize = 0;
157 	cpuhdrp->nmemsegs = bootconfig.dramblocks;
158 	cpuhdrp->omemsegs = ALIGN(sizeof(*cpuhdrp));
159 
160 	/*
161 	 * Fill in the memory segment descriptors.
162 	 */
163 	for (i = 0; i < bootconfig.dramblocks; i++) {
164 		memsegp[i].start = bootconfig.dram[i].address;
165 		memsegp[i].size = bootconfig.dram[i].pages * PAGE_SIZE;
166 	}
167 
168 	return dump(dumpdev, dumplo, bf, dbtob(1));
169 }
170 
171 /*
172  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
173  */
174 int
cpu_dumpsize(void)175 cpu_dumpsize(void)
176 {
177 	int size;
178 
179 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
180 	    ALIGN( bootconfig.dramblocks * sizeof(phys_ram_seg_t));
181 	if (roundup(size, dbtob(1)) != dbtob(1))
182 		return -1;
183 
184 	return 1;
185 }
186 
187 
188 /*
189  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
190  */
191 u_long
cpu_dump_mempagecnt(void)192 cpu_dump_mempagecnt(void)
193 {
194 	u_long i, n;
195 
196 	n = 0;
197 	for (i = 0; i < bootconfig.dramblocks; i++) {
198 		n += bootconfig.dram[i].pages;
199 	}
200 
201 	return n;
202 }
203 
204 /* This should be moved to machdep.c */
205 
206 extern vaddr_t memhook;		/* XXX */
207 
208 /*
209  * Doadump comes here after turning off memory management and
210  * getting on the dump stack, either when called above, or by
211  * the auto-restart code.
212  */
213 void dodumpsys(void);
214 
215 void
dodumpsys(void)216 dodumpsys(void)
217 {
218 	const struct bdevsw *bdev;
219 	daddr_t blkno;
220 	int psize;
221 	int error;
222 	int addr;
223 	int block;
224 	int len;
225 	vaddr_t dumpspace;
226 
227 	/* flush everything out of caches */
228 	cpu_dcache_wbinv_all();
229 
230 	if (dumpdev == NODEV)
231 		return;
232 	if (dumpsize == 0) {
233 		cpu_dumpconf();
234 	}
235 	if (dumplo <= 0 || dumpsize == 0) {
236 		printf("\ndump to dev %u,%u not possible\n",
237 		    major(dumpdev), minor(dumpdev));
238 		delay(5000000);
239 		return;
240 	}
241 	printf("\ndumping to dev %u,%u offset %ld\n",
242 	    major(dumpdev), minor(dumpdev), dumplo);
243 
244 
245 	bdev = bdevsw_lookup(dumpdev);
246 	if (bdev == NULL || bdev->d_psize == NULL)
247 		return;
248 	psize = bdev_size(dumpdev);
249 	printf("dump ");
250 	if (psize == -1) {
251 		printf("area unavailable\n");
252 		return;
253 	}
254 
255 	if ((error = cpu_dump()) != 0)
256 		goto err;
257 
258 	blkno = dumplo + cpu_dumpsize();
259 	dumpspace = memhook;
260 	error = 0;
261 	len = 0;
262 
263 	for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) {
264 		addr = bootconfig.dram[block].address;
265 		for (;addr < (bootconfig.dram[block].address
266 		    + (bootconfig.dram[block].pages * PAGE_SIZE));
267 		     addr += PAGE_SIZE) {
268 		    	if ((len % (1024*1024)) == 0)
269 		    		printf("%d ", len / (1024*1024));
270 
271 			pmap_kenter_pa(dumpspace, addr, VM_PROT_READ, 0);
272 			pmap_update(pmap_kernel());
273 			error = (*bdev->d_dump)(dumpdev,
274 			    blkno, (void *) dumpspace, PAGE_SIZE);
275 
276 			if (error)
277 				goto err;
278 			blkno += btodb(PAGE_SIZE);
279 			len += PAGE_SIZE;
280 		}
281 	}
282 err:
283 	switch (error) {
284 	case ENXIO:
285 		printf("device bad\n");
286 		break;
287 
288 	case EFAULT:
289 		printf("device not ready\n");
290 		break;
291 
292 	case EINVAL:
293 		printf("area improper\n");
294 		break;
295 
296 	case EIO:
297 		printf("i/o error\n");
298 		break;
299 
300 	case EINTR:
301 		printf("aborted from console\n");
302 		break;
303 
304 	case 0:
305 		printf("succeeded\n");
306 		break;
307 
308 	default:
309 		printf("error %d\n", error);
310 		break;
311 	}
312 	printf("\n\n");
313 	delay(5000000);
314 }
315 
316 /* End of stubs.c */
317