1 /*	$NetBSD: powerpc_machdep.c,v 1.14 2002/09/06 13:18:43 gehenna Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "opt_altivec.h"
35 
36 #include <sys/param.h>
37 #include <sys/conf.h>
38 #include <sys/disklabel.h>
39 #include <sys/exec.h>
40 #include <sys/sysctl.h>
41 #include <sys/user.h>
42 
43 int cpu_timebase;
44 int cpu_printfataltraps;
45 #ifdef PPC_MPC6XX
46 extern int powersave;
47 #endif
48 
49 /*
50  * Set set up registers on exec.
51  */
52 void
53 setregs(p, pack, stack)
54 	struct proc *p;
55 	struct exec_package *pack;
56 	u_long stack;
57 {
58 	struct trapframe *tf = trapframe(p);
59 	struct ps_strings arginfo;
60 
61 	memset(tf, 0, sizeof *tf);
62 	tf->fixreg[1] = -roundup(-stack + 8, 16);
63 
64 	/*
65 	 * XXX Machine-independent code has already copied arguments and
66 	 * XXX environment to userland.  Get them back here.
67 	 */
68 	(void)copyin((char *)p->p_psstr, &arginfo, sizeof (arginfo));
69 
70 	/*
71 	 * Set up arguments for _start():
72 	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
73 	 *
74 	 * Notes:
75 	 *	- obj and cleanup are the auxiliary and termination
76 	 *	  vectors.  They are fixed up by ld.elf_so.
77 	 *	- ps_strings is a NetBSD extension, and will be
78 	 * 	  ignored by executables which are strictly
79 	 *	  compliant with the SVR4 ABI.
80 	 *
81 	 * XXX We have to set both regs and retval here due to different
82 	 * XXX calling convention in trap.c and init_main.c.
83 	 */
84 	tf->fixreg[3] = arginfo.ps_nargvstr;
85 	tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
86 	tf->fixreg[5] = (register_t)arginfo.ps_envstr;
87 	tf->fixreg[6] = 0;			/* auxillary vector */
88 	tf->fixreg[7] = 0;			/* termination vector */
89 	tf->fixreg[8] = (register_t)p->p_psstr;	/* NetBSD extension */
90 
91 	tf->srr0 = pack->ep_entry;
92 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
93 #ifdef ALTIVEC
94 	tf->vrsave = 0;
95 #endif
96 	p->p_addr->u_pcb.pcb_flags = 0;
97 }
98 
99 /*
100  * Machine dependent system variables.
101  */
102 int
103 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
104 	int *name;
105 	u_int namelen;
106 	void *oldp;
107 	size_t *oldlenp;
108 	void *newp;
109 	size_t newlen;
110 	struct proc *p;
111 {
112 	/* all sysctl names at this level are terminal */
113 	if (namelen != 1)
114 		return ENOTDIR;
115 
116 	switch (name[0]) {
117 	case CPU_CACHELINE:
118 		/* Deprecated */
119 		return sysctl_rdint(oldp, oldlenp, newp, CACHELINESIZE);
120 	case CPU_TIMEBASE:
121 		if (cpu_timebase)
122 			return sysctl_rdint(oldp, oldlenp, newp, cpu_timebase);
123 		break;
124 	case CPU_PRINTFATALTRAPS:
125 		return sysctl_int(oldp, oldlenp, newp, newlen,
126 				  &cpu_printfataltraps);
127 	case CPU_CACHEINFO:
128 		/* Use this instead of CPU_CACHELINE */
129 		return sysctl_rdstruct(oldp, oldlenp, newp,
130 			&curcpu()->ci_ci,
131 			sizeof(curcpu()->ci_ci));
132 #ifdef PPC_MPC6XX
133 	case CPU_POWERSAVE:
134 		if (powersave < 0)
135 			return sysctl_rdint(oldp, oldlenp, newp, powersave);
136 		return sysctl_int(oldp, oldlenp, newp, newlen, &powersave);
137 	case CPU_ALTIVEC:
138 		return sysctl_rdint(oldp, oldlenp, newp, cpu_altivec);
139 #else
140 	case CPU_ALTIVEC:
141 		return sysctl_rdint(oldp, oldlenp, newp, 0);
142 #endif
143 	case CPU_MODEL:
144 		return sysctl_rdstring(oldp, oldlenp, newp, cpu_model);
145 	default:
146 		break;
147 	}
148 	return EOPNOTSUPP;
149 }
150 
151 /*
152  * Crash dump handling.
153  */
154 u_int32_t dumpmag = 0x8fca0101;		/* magic number */
155 int dumpsize = 0;			/* size of dump in pages */
156 long dumplo = -1;			/* blocks */
157 
158 /*
159  * This is called by main to set dumplo and dumpsize.
160  */
161 void
162 cpu_dumpconf()
163 {
164 	const struct bdevsw *bdev;
165 	int nblks;		/* size of dump device */
166 	int skip;
167 
168 	if (dumpdev == NODEV)
169 		return;
170 	bdev = bdevsw_lookup(dumpdev);
171 	if (bdev == NULL)
172 		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
173 	if (bdev->d_psize == NULL)
174 		return;
175 	nblks = (*bdev->d_psize)(dumpdev);
176 	if (nblks <= ctod(1))
177 		return;
178 
179 	dumpsize = physmem;
180 
181 	/* Skip enough blocks at start of disk to preserve an eventual disklabel. */
182 	skip = LABELSECTOR + 1;
183 	skip += ctod(1) - 1;
184 	skip = ctod(dtoc(skip));
185 	if (dumplo < skip)
186 		dumplo = skip;
187 
188 	/* Put dump at end of partition */
189 	if (dumpsize > dtoc(nblks - dumplo))
190 		dumpsize = dtoc(nblks - dumplo);
191 	if (dumplo < nblks - ctod(dumpsize))
192 		dumplo = nblks - ctod(dumpsize);
193 }
194