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