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