xref: /netbsd-src/sys/arch/arm/arm32/stubs.c (revision 3b3140f5f6442fdc9bfff640ecc3058432700234)
1*3b3140f5Sskrll /*	$NetBSD: stubs.c,v 1.27 2020/07/03 15:31:25 skrll Exp $	*/
227f96e84Schris 
327f96e84Schris /*
427f96e84Schris  * Copyright (c) 1994-1998 Mark Brinicombe.
527f96e84Schris  * Copyright (c) 1994 Brini.
627f96e84Schris  * All rights reserved.
727f96e84Schris  *
827f96e84Schris  * This code is derived from software written for Brini by Mark Brinicombe
927f96e84Schris  *
1027f96e84Schris  * Redistribution and use in source and binary forms, with or without
1127f96e84Schris  * modification, are permitted provided that the following conditions
1227f96e84Schris  * are met:
1327f96e84Schris  * 1. Redistributions of source code must retain the above copyright
1427f96e84Schris  *    notice, this list of conditions and the following disclaimer.
1527f96e84Schris  * 2. Redistributions in binary form must reproduce the above copyright
1627f96e84Schris  *    notice, this list of conditions and the following disclaimer in the
1727f96e84Schris  *    documentation and/or other materials provided with the distribution.
1827f96e84Schris  * 3. All advertising materials mentioning features or use of this software
1927f96e84Schris  *    must display the following acknowledgement:
2027f96e84Schris  *	This product includes software developed by Mark Brinicombe
2127f96e84Schris  *	for the NetBSD Project.
2227f96e84Schris  * 4. The name of the company nor the name of the author may be used to
2327f96e84Schris  *    endorse or promote products derived from this software without specific
2427f96e84Schris  *    prior written permission.
2527f96e84Schris  *
2627f96e84Schris  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
2727f96e84Schris  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2827f96e84Schris  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2927f96e84Schris  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
3027f96e84Schris  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3127f96e84Schris  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3227f96e84Schris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3327f96e84Schris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3427f96e84Schris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3527f96e84Schris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3627f96e84Schris  * SUCH DAMAGE.
3727f96e84Schris  *
3827f96e84Schris  * Routines that are temporary or do not have a home yet.
3927f96e84Schris  *
4027f96e84Schris  * Created      : 17/09/94
4127f96e84Schris  */
4227f96e84Schris 
4308716eaeSlukem #include <sys/cdefs.h>
44*3b3140f5Sskrll __KERNEL_RCSID(0, "$NetBSD: stubs.c,v 1.27 2020/07/03 15:31:25 skrll Exp $");
4508716eaeSlukem 
4627f96e84Schris #include <sys/param.h>
4779ef8ec5Sskrll 
4827f96e84Schris #include <sys/conf.h>
4979ef8ec5Sskrll #include <sys/core.h>
5079ef8ec5Sskrll #include <sys/errno.h>
5179ef8ec5Sskrll #include <sys/kcore.h>
5227f96e84Schris #include <sys/msgbuf.h>
5379ef8ec5Sskrll #include <sys/proc.h>
5479ef8ec5Sskrll #include <sys/systm.h>
5579ef8ec5Sskrll 
5627f96e84Schris #include <uvm/uvm_extern.h>
5779ef8ec5Sskrll 
5827f96e84Schris #include <machine/cpu.h>
59792b7ebdSmatt #include <machine/intr.h>
6027f96e84Schris #include <machine/bootconfig.h>
6127f96e84Schris #include <machine/pcb.h>
6279ef8ec5Sskrll 
63e3a3a9f5Schris #include <arm/arm32/machdep.h>
64c93dd301Schris #include <arm/kcore.h>
6527f96e84Schris 
6627f96e84Schris extern dev_t dumpdev;
6727f96e84Schris 
68c93dd301Schris int	cpu_dump(void);
69c93dd301Schris int	cpu_dumpsize(void);
70c93dd301Schris u_long	cpu_dump_mempagecnt(void);
71c93dd301Schris 
7227f96e84Schris /*
7327f96e84Schris  * These variables are needed by /sbin/savecore
7427f96e84Schris  */
7508a4aba7Sskrll uint32_t dumpmag = 0x8fca0101;	/* magic number */
7627f96e84Schris int 	dumpsize = 0;		/* pages */
7727f96e84Schris long	dumplo = 0; 		/* blocks */
7827f96e84Schris 
7927f96e84Schris struct pcb dumppcb;
8027f96e84Schris 
8127f96e84Schris /*
8227f96e84Schris  * This is called by main to set dumplo and dumpsize.
83c93dd301Schris  * Dumps always skip the first PAGE_SIZE of disk space
8427f96e84Schris  * in case there might be a disk label stored there.
8527f96e84Schris  * If there is extra space, put dump at the end to
8627f96e84Schris  * reduce the chance that swapping trashes it.
8727f96e84Schris  */
8827f96e84Schris 
8927f96e84Schris void
cpu_dumpconf(void)90ebceae53Scegger cpu_dumpconf(void)
9127f96e84Schris {
92c93dd301Schris 	int nblks, dumpblks;	/* size of dump area */
9327f96e84Schris 
9427f96e84Schris 	if (dumpdev == NODEV)
9527f96e84Schris 		return;
969a4a666fSmrg 	nblks = bdev_size(dumpdev);
9727f96e84Schris 	if (nblks <= ctod(1))
9827f96e84Schris 		return;
9927f96e84Schris 
100c93dd301Schris 	dumpblks = cpu_dumpsize();
101c93dd301Schris 	if (dumpblks < 0)
102c93dd301Schris 		goto bad;
103c93dd301Schris 	dumpblks += ctod(cpu_dump_mempagecnt());
10427f96e84Schris 
105c93dd301Schris 	/* If dump won't fit (incl. room for possible label), punt. */
106c93dd301Schris 	if (dumpblks > (nblks - ctod(1)))
107c93dd301Schris 		goto bad;
10827f96e84Schris 
109c93dd301Schris 	/* Put dump at end of partition */
110c93dd301Schris 	dumplo = nblks - dumpblks;
111c93dd301Schris 
112c93dd301Schris 	/* dumpsize is in page units, and doesn't include headers. */
113c93dd301Schris 	dumpsize = cpu_dump_mempagecnt();
114c93dd301Schris 	return;
115c93dd301Schris 
116c93dd301Schris  bad:
117c93dd301Schris 	dumpsize = 0;
118c93dd301Schris }
119c93dd301Schris 
120c93dd301Schris /*
121c93dd301Schris  * cpu_dump: dump the machine-dependent kernel core dump headers.
122c93dd301Schris  */
123c93dd301Schris int
cpu_dump(void)124ebceae53Scegger cpu_dump(void)
125c93dd301Schris {
126c93dd301Schris 	int (*dump)(dev_t, daddr_t, void *, size_t);
127c93dd301Schris 	char bf[dbtob(1)];
128c93dd301Schris 	kcore_seg_t *segp;
129c93dd301Schris 	cpu_kcore_hdr_t *cpuhdrp;
130c93dd301Schris 	phys_ram_seg_t *memsegp;
131c93dd301Schris 	const struct bdevsw *bdev;
132c93dd301Schris 	int i;
133c93dd301Schris 
134c93dd301Schris 	bdev = bdevsw_lookup(dumpdev);
135c93dd301Schris 	if (bdev == NULL)
136df27e1efSskrll 		return ENXIO;
137c93dd301Schris 	dump = bdev->d_dump;
138c93dd301Schris 
139c93dd301Schris 	memset(bf, 0, sizeof bf);
140c93dd301Schris 	segp = (kcore_seg_t *)bf;
141c93dd301Schris 	cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))];
142c93dd301Schris 	memsegp = (phys_ram_seg_t *)&bf[ ALIGN(sizeof(*segp)) +
143c93dd301Schris 	    ALIGN(sizeof(*cpuhdrp))];
144c93dd301Schris 
145c93dd301Schris 	/*
146c93dd301Schris 	 * Generate a segment header.
147c93dd301Schris 	 */
148c93dd301Schris 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
149c93dd301Schris 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
150c93dd301Schris 
151c93dd301Schris 	/*
152c93dd301Schris 	 * Add the machine-dependent header info.
153c93dd301Schris 	 */
154c93dd301Schris 	cpuhdrp->version = 1;
155c93dd301Schris 	cpuhdrp->PAKernelL1Table = pmap_kernel_L1_addr();
156c93dd301Schris 	cpuhdrp->UserL1TableSize = 0;
157c93dd301Schris 	cpuhdrp->nmemsegs = bootconfig.dramblocks;
158c93dd301Schris 	cpuhdrp->omemsegs = ALIGN(sizeof(*cpuhdrp));
159c93dd301Schris 
160c93dd301Schris 	/*
161c93dd301Schris 	 * Fill in the memory segment descriptors.
162c93dd301Schris 	 */
163c93dd301Schris 	for (i = 0; i < bootconfig.dramblocks; i++) {
164c93dd301Schris 		memsegp[i].start = bootconfig.dram[i].address;
165c93dd301Schris 		memsegp[i].size = bootconfig.dram[i].pages * PAGE_SIZE;
166c93dd301Schris 	}
167c93dd301Schris 
168df27e1efSskrll 	return dump(dumpdev, dumplo, bf, dbtob(1));
169c93dd301Schris }
170c93dd301Schris 
171c93dd301Schris /*
172c93dd301Schris  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
173c93dd301Schris  */
174c93dd301Schris int
cpu_dumpsize(void)175ebceae53Scegger cpu_dumpsize(void)
176c93dd301Schris {
177c93dd301Schris 	int size;
178c93dd301Schris 
179c93dd301Schris 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
180c93dd301Schris 	    ALIGN( bootconfig.dramblocks * sizeof(phys_ram_seg_t));
181c93dd301Schris 	if (roundup(size, dbtob(1)) != dbtob(1))
182df27e1efSskrll 		return -1;
183c93dd301Schris 
184df27e1efSskrll 	return 1;
185c93dd301Schris }
186c93dd301Schris 
187c93dd301Schris 
188c93dd301Schris /*
189c93dd301Schris  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
190c93dd301Schris  */
191c93dd301Schris u_long
cpu_dump_mempagecnt(void)192ebceae53Scegger cpu_dump_mempagecnt(void)
193c93dd301Schris {
194c93dd301Schris 	u_long i, n;
195c93dd301Schris 
196c93dd301Schris 	n = 0;
197c93dd301Schris 	for (i = 0; i < bootconfig.dramblocks; i++) {
198c93dd301Schris 		n += bootconfig.dram[i].pages;
199c93dd301Schris 	}
200c93dd301Schris 
201df27e1efSskrll 	return n;
20227f96e84Schris }
20327f96e84Schris 
20427f96e84Schris /* This should be moved to machdep.c */
20527f96e84Schris 
206c93dd301Schris extern vaddr_t memhook;		/* XXX */
20727f96e84Schris 
20827f96e84Schris /*
20927f96e84Schris  * Doadump comes here after turning off memory management and
21027f96e84Schris  * getting on the dump stack, either when called above, or by
21127f96e84Schris  * the auto-restart code.
21227f96e84Schris  */
213c93dd301Schris void dodumpsys(void);
21427f96e84Schris 
21527f96e84Schris void
dodumpsys(void)216ebceae53Scegger dodumpsys(void)
21727f96e84Schris {
21877a6b82bSgehenna 	const struct bdevsw *bdev;
21927f96e84Schris 	daddr_t blkno;
22027f96e84Schris 	int psize;
22127f96e84Schris 	int error;
22227f96e84Schris 	int addr;
22327f96e84Schris 	int block;
22427f96e84Schris 	int len;
22527f96e84Schris 	vaddr_t dumpspace;
22627f96e84Schris 
227a97b6608Schris 	/* flush everything out of caches */
228a97b6608Schris 	cpu_dcache_wbinv_all();
22927f96e84Schris 
23027f96e84Schris 	if (dumpdev == NODEV)
23127f96e84Schris 		return;
23227f96e84Schris 	if (dumpsize == 0) {
23327f96e84Schris 		cpu_dumpconf();
23427f96e84Schris 	}
235c93dd301Schris 	if (dumplo <= 0 || dumpsize == 0) {
236d4b1297cShe 		printf("\ndump to dev %u,%u not possible\n",
2379273b335Scegger 		    major(dumpdev), minor(dumpdev));
238c93dd301Schris 		delay(5000000);
23927f96e84Schris 		return;
24027f96e84Schris 	}
241d4b1297cShe 	printf("\ndumping to dev %u,%u offset %ld\n",
2429273b335Scegger 	    major(dumpdev), minor(dumpdev), dumplo);
24327f96e84Schris 
24427f96e84Schris 
24577a6b82bSgehenna 	bdev = bdevsw_lookup(dumpdev);
24677a6b82bSgehenna 	if (bdev == NULL || bdev->d_psize == NULL)
24777a6b82bSgehenna 		return;
2489a4a666fSmrg 	psize = bdev_size(dumpdev);
24927f96e84Schris 	printf("dump ");
25027f96e84Schris 	if (psize == -1) {
25127f96e84Schris 		printf("area unavailable\n");
25227f96e84Schris 		return;
25327f96e84Schris 	}
25427f96e84Schris 
255c93dd301Schris 	if ((error = cpu_dump()) != 0)
256c93dd301Schris 		goto err;
257c93dd301Schris 
258c93dd301Schris 	blkno = dumplo + cpu_dumpsize();
259c93dd301Schris 	dumpspace = memhook;
26027f96e84Schris 	error = 0;
26127f96e84Schris 	len = 0;
26227f96e84Schris 
26327f96e84Schris 	for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) {
26427f96e84Schris 		addr = bootconfig.dram[block].address;
26527f96e84Schris 		for (;addr < (bootconfig.dram[block].address
26695281cabSthorpej 		    + (bootconfig.dram[block].pages * PAGE_SIZE));
26795281cabSthorpej 		     addr += PAGE_SIZE) {
26827f96e84Schris 		    	if ((len % (1024*1024)) == 0)
26927f96e84Schris 		    		printf("%d ", len / (1024*1024));
270c93dd301Schris 
2719480c51bScegger 			pmap_kenter_pa(dumpspace, addr, VM_PROT_READ, 0);
272a97b6608Schris 			pmap_update(pmap_kernel());
27377a6b82bSgehenna 			error = (*bdev->d_dump)(dumpdev,
27453524e44Schristos 			    blkno, (void *) dumpspace, PAGE_SIZE);
275c93dd301Schris 
276*3b3140f5Sskrll 			if (error)
277*3b3140f5Sskrll 				goto err;
27895281cabSthorpej 			blkno += btodb(PAGE_SIZE);
27995281cabSthorpej 			len += PAGE_SIZE;
28027f96e84Schris 		}
28127f96e84Schris 	}
282c93dd301Schris err:
28327f96e84Schris 	switch (error) {
28427f96e84Schris 	case ENXIO:
28527f96e84Schris 		printf("device bad\n");
28627f96e84Schris 		break;
28727f96e84Schris 
28827f96e84Schris 	case EFAULT:
28927f96e84Schris 		printf("device not ready\n");
29027f96e84Schris 		break;
29127f96e84Schris 
29227f96e84Schris 	case EINVAL:
29327f96e84Schris 		printf("area improper\n");
29427f96e84Schris 		break;
29527f96e84Schris 
29627f96e84Schris 	case EIO:
29727f96e84Schris 		printf("i/o error\n");
29827f96e84Schris 		break;
29927f96e84Schris 
30027f96e84Schris 	case EINTR:
30127f96e84Schris 		printf("aborted from console\n");
30227f96e84Schris 		break;
30327f96e84Schris 
304c93dd301Schris 	case 0:
30527f96e84Schris 		printf("succeeded\n");
30627f96e84Schris 		break;
307c93dd301Schris 
308c93dd301Schris 	default:
309c93dd301Schris 		printf("error %d\n", error);
310c93dd301Schris 		break;
31127f96e84Schris 	}
31227f96e84Schris 	printf("\n\n");
313c93dd301Schris 	delay(5000000);
31427f96e84Schris }
31527f96e84Schris 
31627f96e84Schris /* End of stubs.c */
317