1 /* machdep.c 3.25 09/30/80 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/map.h" 8 #include "../h/reg.h" 9 #include "../h/mtpr.h" 10 #include "../h/clock.h" 11 #include "../h/pte.h" 12 #include "../h/vm.h" 13 #include "../h/proc.h" 14 #include "../h/psl.h" 15 #include "../h/uba.h" 16 17 char version[] = "VM/UNIX (Berkeley Version 3.25) 10/14/12 \n"; 18 int icode[] = 19 { 20 0x9f19af9f, /* pushab [&"init.vm",0]; pushab */ 21 0x02dd09af, /* "/etc/init.vm"; pushl $2 */ 22 0xbc5c5ed0, /* movl sp,ap; chmk */ 23 0x2ffe110b, /* $exec; brb .; "/ */ 24 0x2f637465, /* etc/ */ 25 0x74696e69, /* init */ 26 0x006d762e, /* .vm"; 0 */ 27 0x00000014, /* [&"init", */ 28 0x00000000, /* 0] */ 29 }; 30 int szicode = sizeof(icode); 31 int memchk(); 32 33 /* 34 * Machine-dependent startup code 35 */ 36 startup(firstaddr) 37 { 38 register int unixsize; 39 register int i; 40 register struct pte *pte; 41 42 /* 43 * Good {morning,afternoon,evening,night}. 44 */ 45 46 printf(version); 47 printf("real mem = %d\n", ctob(maxmem)); 48 49 /* 50 * Allow for the u. area of process 0 and its (single) 51 * page of page tables. 52 */ 53 unixsize = (firstaddr+UPAGES+1); 54 55 /* 56 * Initialze buffers 57 */ 58 pte = bufmap; 59 for (i = 0; i < NBUF * CLSIZE; i++) 60 *(int *)pte++ = PG_V | PG_KW | unixsize++; 61 mtpr(TBIA, 1); 62 63 #ifdef ERNIE 64 if (coresw) 65 maxmem = 4096; 66 #endif 67 68 /* 69 * Initialize maps. 70 */ 71 meminit(unixsize, maxmem); 72 maxmem = freemem; 73 printf("avail mem = %d\n", ctob(maxmem)); 74 mfree(kernelmap, USRPTSIZE, 1); 75 ubainit(); 76 timeout(memchk, (caddr_t)0, 60); /* it will pick its own intvl */ 77 } 78 79 /* 80 * set up a physical address 81 * into users virtual address space. 82 */ 83 sysphys() 84 { 85 86 if(!suser()) 87 return; 88 u.u_error = EINVAL; 89 } 90 91 /* 92 * Initialze the clock, based on the time base which is, e.g. 93 * from a filesystem. Base provides the time to within six months, 94 * and the time of year clock provides the rest. 95 */ 96 clkinit(base) 97 time_t base; 98 { 99 register unsigned todr = mfpr(TODR); 100 long deltat; 101 int year = YRREF; 102 103 /* 104 * Have been told that VMS keeps time internally with base TODRZERO. 105 * If this is correct, then this routine and VMS should maintain 106 * the same date, and switching shouldn't be painful. 107 */ 108 if (todr < TODRZERO) { 109 printf("WARNING: todr too small (battery backup failed?)"); 110 time = base; 111 /* 112 * Believe the time in the file system for lack of 113 * anything better, resetting the TODR. 114 */ 115 clkset(); 116 goto check; 117 } 118 /* 119 * Sneak to within 6 month of the time in the filesystem, 120 * by starting with the time of the year suggested by the TODR, 121 * and advancing through succesive years. Adding the number of 122 * seconds in the current year takes us to the end of the current year 123 * and then around into the next year to the same position. 124 */ 125 for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) { 126 if (LEAPYEAR(year)) 127 time += SECDAY; 128 year++; 129 } 130 131 /* 132 * See if we gained/lost two or more days; 133 * if so, assume something is amiss. 134 */ 135 deltat = time - base; 136 if (deltat < 0) 137 deltat = -deltat; 138 if (deltat < 2*SECDAY) 139 return; 140 printf("WARNING: clock %s %d days", 141 time < base ? "lost" : "gained", deltat / SECDAY); 142 check: 143 printf(" -- CHECK AND RESET THE DATE!\n"); 144 } 145 146 /* 147 * Reset the TODR based on the time value; used when the TODR 148 * has a preposterous value and also when the time is reset 149 * by the stime system call. Also called when the TODR goes past 150 * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) 151 * to wrap the TODR around. 152 */ 153 clkset() 154 { 155 int year = YRREF; 156 unsigned secyr; 157 unsigned yrtime = time; 158 159 /* 160 * Whittle the time down to an offset in the current year, 161 * by subtracting off whole years as long as possible. 162 */ 163 for (;;) { 164 secyr = SECYR; 165 if (LEAPYEAR(year)) 166 secyr += SECDAY; 167 if (yrtime < secyr) 168 break; 169 yrtime -= secyr; 170 year++; 171 } 172 mtpr(TODR, TODRZERO + yrtime*100); 173 } 174 175 #ifdef PGINPROF 176 /* 177 * Return the difference (in microseconds) 178 * between the current time and a previous 179 * time as represented by the arguments. 180 * If there is a pending clock interrupt 181 * which has not been serviced due to high 182 * ipl, return error code. 183 */ 184 vmtime(otime, olbolt, oicr) 185 register int otime, olbolt, oicr; 186 { 187 188 if (mfpr(ICCS)&ICCS_INT) 189 return(-1); 190 else 191 return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr); 192 } 193 #endif 194 195 #ifdef TRACE 196 /* 197 * Put the current time into the trace, 198 * in fractional seconds (i.e. 12345 means the 199 * current time is ``n.12345'' for some n. 200 */ 201 ttime() 202 { 203 204 trace("%d ", (lbolt*16667 + mfpr(ICR))); 205 } 206 #endif 207 208 /* 209 * Send an interrupt to process 210 * 211 * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION 212 * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS. 213 */ 214 sendsig(p, n) 215 { 216 register int *usp, *regs; 217 218 regs = u.u_ar0; 219 usp = (int *)regs[SP]; 220 #ifdef FASTVAX 221 usp -= 5; 222 if ((int)usp <= USRSTACK - ctob(u.u_ssize)) 223 (void) grow((unsigned)usp); 224 ; /* Avoid asm() label botch */ 225 asm("probew $3,$20,(r11)"); 226 asm("beql bad"); 227 *usp++ = n; 228 *usp++ = n == SIGILL ? u.u_cfcode : 0; 229 *usp++ = p; 230 *usp++ = regs[PC]; 231 *usp++ = regs[PS]; 232 regs[SP] = (int)(usp - 5); 233 #else 234 (void) grow((unsigned)(usp-5)); 235 if (suword((caddr_t)--usp, regs[PS])) 236 goto bad; 237 if (suword((caddr_t)--usp, regs[PC])) 238 goto bad; 239 if (suword((caddr_t)--usp, p)) 240 goto bad; 241 if (suword((caddr_t)--usp, n==SIGILL ? u.u_cfcode : 0)) 242 goto bad; 243 if (suword((caddr_t)--usp, n)) 244 goto bad; 245 regs[SP] = (int)usp; 246 #endif 247 regs[PS] &= ~(PSL_CM|PSL_FPD); 248 regs[PC] = (int)u.u_pcb.pcb_sigc; 249 return; 250 251 #ifdef FASTVAX 252 asm("bad:"); 253 #endif 254 bad: 255 printf("%d: cant send signal\n", u.u_procp->p_pid); 256 psignal(u.u_procp, SIGKILL); 257 } 258 259 dorti() 260 { 261 struct frame { 262 int handler; 263 unsigned int 264 psw:16, 265 mask:12, 266 :1, 267 s:1, 268 spa:2; 269 int savap; 270 int savfp; 271 int savpc; 272 } frame; 273 register int sp; 274 register int reg, mask; 275 extern int ipcreg[]; 276 277 (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame)); 278 sp = u.u_ar0[FP] + sizeof (frame); 279 u.u_ar0[PC] = frame.savpc; 280 u.u_ar0[FP] = frame.savfp; 281 u.u_ar0[AP] = frame.savap; 282 mask = frame.mask; 283 for (reg = 0; reg <= 11; reg++) { 284 if (mask&1) { 285 u.u_ar0[ipcreg[reg]] = fuword(sp); 286 sp += 4; 287 } 288 mask >>= 1; 289 } 290 sp += frame.spa; 291 u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.psw; 292 if (frame.s) 293 sp += 4 + 4 * (fuword(sp) & 0xff); 294 /* phew, now the rei */ 295 u.u_ar0[PC] = fuword(sp); 296 sp += 4; 297 u.u_ar0[PS] = fuword(sp); 298 sp += 4; 299 u.u_ar0[PS] |= PSL_CURMOD|PSL_PRVMOD; 300 u.u_ar0[PS] &= ~PSL_USERCLR; 301 } 302 303 /* 304 * Check memory controller for memory parity errors 305 */ 306 #define MEMINTVL (60*60*10) /* 10 minutes */ 307 int memintvl = MEMINTVL; 308 309 #define MHIERR 0x20000000 310 #define MERLOG 0x10000000 311 312 memchk() 313 { 314 register int c = mcr[2]; 315 316 if (c & MERLOG) { 317 printf("MEMERR: mcra %X mcrb %X mcrc %X\n", mcr[0], 318 mcr[1], c); 319 mcr[2] = (MERLOG|MHIERR); 320 } 321 if (memintvl > 0) 322 timeout(memchk, (caddr_t)0, memintvl); 323 } 324 325 /* 326 * Invalidate single all pte's in a cluster 327 */ 328 tbiscl(v) 329 unsigned v; 330 { 331 register caddr_t addr; /* must be first reg var */ 332 register int i; 333 334 asm(".set TBIS,58"); 335 addr = ptob(v); 336 for (i = 0; i < CLSIZE; i++) { 337 #ifdef lint 338 mtpr(TBIS, addr); 339 #else 340 asm("mtpr r11,$TBIS"); 341 #endif 342 addr += NBPG; 343 } 344 } 345 346 int hangcnt; 347 348 unhang() 349 { 350 register struct uba_regs *up = (struct uba_regs *)UBA0; 351 352 if (up->uba_sr == 0) 353 return; 354 hangcnt++; 355 if (hangcnt > 5*HZ) { 356 hangcnt = 0; 357 printf("HANG "); 358 ubareset(); 359 } 360 } 361