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