stub.c (7582B)
1 2 #define WANT_M 3 4 #ifdef __APPLE__ 5 #define __DARWIN_UNIX03 0 6 #endif 7 8 #include "u.h" 9 #include <sched.h> 10 #include <signal.h> 11 #include "lib.h" 12 #include "mem.h" 13 #include "dat.h" 14 #include "fns.h" 15 #include "error.h" 16 17 int tracefp; 18 19 /* 20 * Simple xalloc memory allocator. 21 */ 22 static int xalloced; 23 24 void* 25 xallocz(ulong size, int zero) 26 { 27 void *v; 28 29 v = malloc(size); 30 if(v && zero) 31 memset(v, 0, size); 32 if(v) 33 xalloced += size; 34 return v; 35 } 36 37 void* 38 xalloc(ulong size) 39 { 40 return xallocz(size, 1); 41 } 42 43 void 44 xfree(void *p) 45 { 46 free(p); 47 } 48 49 void 50 xsummary(void) 51 { 52 print("%d allocated\n", xalloced); 53 } 54 55 /* 56 * Very simple non-caching cache implementation. 57 */ 58 void 59 cinit(void) 60 { 61 } 62 63 void 64 copen(Chan *c) 65 { 66 USED(c); 67 } 68 69 int 70 cread(Chan *c, uchar *buf, int len, vlong off) 71 { 72 USED(c); 73 USED(buf); 74 USED(len); 75 USED(off); 76 77 return 0; 78 } 79 80 void 81 cupdate(Chan *c, uchar *buf, int len, vlong off) 82 { 83 USED(c); 84 USED(buf); 85 USED(len); 86 USED(off); 87 } 88 89 void 90 cwrite(Chan* c, uchar *buf, int len, vlong off) 91 { 92 USED(c); 93 USED(buf); 94 USED(len); 95 USED(off); 96 } 97 98 /* 99 * Interrupt priority level 100 */ 101 int 102 _splx(int s) 103 { 104 int ospl; 105 106 ospl = m->spl; 107 m->spl = s; 108 return ospl; 109 } 110 111 int 112 splhi(void) 113 { 114 return _splx(1); 115 } 116 117 int 118 spllo(void) 119 { 120 return _splx(0); 121 } 122 123 int 124 islo(void) 125 { 126 return m->spl == 0; 127 } 128 129 void 130 splx(int s) 131 { 132 _splx(s); 133 } 134 135 136 /* 137 * Floating point. 138 */ 139 void 140 fpoff(void) 141 { 142 } 143 144 void 145 fpinit(void) 146 { 147 if(tracefp) 148 iprint("fpinit\n"); 149 150 #ifdef i386 151 asm volatile( 152 "finit\n" 153 "fwait\n" 154 "pushw $0x232\n" 155 "fldcw 0(%%esp)\n" 156 "popw %%ax\n" 157 "fwait\n" : : : "memory"); 158 #else 159 asm volatile( 160 "finit\n" 161 "fwait\n" 162 "pushq $0x232\n" 163 "fldcw 0(%%rsp)\n" 164 "popq %%rax\n" 165 "fwait\n" : : : "memory"); 166 #endif 167 168 } 169 170 void 171 fpsave(FPsave *s) 172 { 173 #ifdef i386 174 asm volatile("fnsave 0(%%eax)\n" : : "a" (s) : "memory"); 175 #else 176 asm volatile("fnsave 0(%%rax)\n" : : "a" (s) : "memory"); 177 #endif 178 if(tracefp) 179 iprint("fpsave: %#x %#x %#x %#ux\n", s->control, s->status, s->tag, s->pc); 180 } 181 182 void 183 fprestore(FPsave *s) 184 { 185 if(tracefp) 186 iprint("fprestore: %#x %#x %#x %#ux\n", s->control, s->status, s->tag, s->pc); 187 #ifdef i386 188 asm volatile("frstor 0(%%eax); fwait\n" : : "a" (s) : "memory"); 189 #else 190 asm volatile("frstor 0(%%rax); fwait\n" : : "a" (s) : "memory"); 191 #endif 192 } 193 194 void 195 fpenv(FPsave *s) 196 { 197 if(tracefp) 198 iprint("fpenv: %#x %#x %#x %#ux\n", s->control, s->status, s->tag, s->pc); 199 #ifdef i386 200 asm volatile("fstenv 0(%%eax)\n" : : "a" (s) : "memory"); 201 #else 202 asm volatile("fstenv 0(%%rax)\n" : : "a" (s) : "memory"); 203 #endif 204 } 205 206 void 207 fpclear(void) 208 { 209 if(tracefp) 210 iprint("fpclear\n"); 211 asm volatile("fclex\n"); 212 } 213 214 ulong 215 fpstatus(void) 216 { 217 ushort x; 218 asm volatile("fstsw %%ax\n" : "=a" (x)); 219 return x; 220 } 221 222 223 /* 224 * Malloc (#defined to _kmalloc) zeros its memory. 225 */ 226 void* 227 malloc(ulong size) 228 { 229 return calloc(1, size); 230 } 231 232 void 233 mallocsummary(void) 234 { 235 } 236 237 void 238 setmalloctag(void *v, ulong tag) 239 { 240 } 241 242 void* 243 smalloc(ulong size) 244 { 245 void *v; 246 247 for(;;){ 248 v = malloc(size); 249 if(v != nil){ 250 memset(v, 0, size); // XXX 251 return v; 252 } 253 tsleep(&up->sleep, return0, 0, 100); 254 } 255 } 256 257 258 #undef malloc 259 void* 260 mallocz(ulong size, int clr) 261 { 262 if(clr) 263 return calloc(1, size); 264 else 265 return malloc(size); 266 } 267 #define malloc _kmalloc 268 269 270 /* 271 * Spin locks 272 */ 273 int 274 tas(void *x) 275 { 276 int v; 277 278 #ifdef i386 279 __asm__( "movl $1, %%eax\n\t" 280 "xchgl %%eax,(%%ecx)" 281 : "=a" (v) 282 : "c" (x) 283 ); 284 #else 285 __asm__( "movl $1, %%eax\n\t" 286 "xchgl %%eax,(%%rcx)" 287 : "=a" (v) 288 : "c" (x) 289 ); 290 #endif 291 292 switch(v) { 293 case 0: 294 case 1: 295 return v; 296 default: 297 print("tas: corrupted lock 0x%lux\n", v); 298 return 1; 299 } 300 } 301 302 int 303 _tas(void *x) 304 { 305 return tas(x); 306 } 307 308 int 309 lock(Lock *lk) 310 { 311 int i, j, printed; 312 313 for(i=0; i<1000; i++){ 314 if(canlock(lk)) 315 return 1; 316 sched_yield(); 317 } 318 for(j=10; j<=1000; j*=10) 319 for(i=0; i<10; i++){ 320 if(canlock(lk)) 321 return 1; 322 microdelay(j); 323 } 324 printed = 0; 325 for(;;){ 326 if(canlock(lk)) 327 return 1; 328 if(!printed++) 329 iprint("cpu%d deadlock? %p caller=%p\n", 330 m->machno, lk, getcallerpc(&lk)); 331 microdelay(10000); 332 } 333 return 0; 334 } 335 336 void 337 unlock(Lock *l) 338 { 339 if(l->key == 0) 340 iprint("unlock: not locked: pc %luX\n", 341 getcallerpc(&l)); 342 if(l->isilock) 343 iprint("unlock of ilock: pc %lux, held by %lux\n", 344 getcallerpc(&l), l->pc); 345 if(l->p != up) 346 iprint("unlock: up changed: pc %lux, acquired at pc %lux, lock p 0x%p, unlock up 0x%p\n", 347 getcallerpc(&l), l->pc, l->p, up); 348 l->m_ = nil; 349 if(up) 350 up->nlocks.ref--; 351 l->key = 0; 352 } 353 354 int 355 canlock(Lock *l) 356 { 357 if(up) 358 up->nlocks.ref++; 359 if(tas(&l->key)){ 360 if(up) 361 up->nlocks.ref--; 362 return 0; 363 } 364 365 if(up) 366 up->lastlock = l; 367 l->pc = getcallerpc(&l); 368 l->p = up; 369 l->m_ = MACHP(m->machno); 370 l->isilock = 0; 371 return 1; 372 } 373 374 void 375 ilock(Lock *lk) 376 { 377 int s; 378 379 s = splhi(); 380 lock(lk); 381 lk->sr = s; 382 } 383 384 void 385 iunlock(Lock *lk) 386 { 387 int s; 388 389 s = lk->sr; 390 unlock(lk); 391 splx(s); 392 } 393 394 395 /* 396 * One of a kind 397 */ 398 #include "kerndate.h" 399 400 ulong 401 getcallerpc(void *v) 402 { 403 return ((ulong*)v)[-1]; 404 } 405 406 static int randfd = -1; 407 void 408 randominit(void) 409 { 410 if((randfd = open("/dev/urandom", OREAD)) < 0) 411 if((randfd = open("/dev/random", OREAD)) < 0) 412 panic("open /dev/random: %r"); 413 } 414 415 ulong 416 randomread(void *v, ulong n) 417 { 418 int r; 419 420 if(randfd < 0) 421 randominit(); 422 if((r = read(randfd, v, n)) != n) 423 panic("short read from /dev/random: %d but %d", n, r); 424 return r; 425 } 426 427 int cpuserver = 0; 428 429 void 430 rebootcmd(int argc, char **argv) 431 { 432 int i; 433 restoretty(); 434 for(i = 0; i < argc; i++) 435 iprint("%s%s", argv[i], argc - i > 1 ? " " : ""); 436 if(argc > 0) 437 iprint("\n"); 438 exit(0); 439 error(Egreg); 440 } 441 442 void 443 labelinit(Label *l, ulong pc, ulong sp) 444 { 445 assert(l); 446 setlabel(l); 447 l->pc = pc; 448 449 /* 450 * Stack pointer at call instruction (before return address 451 * gets pushed) must be 16-byte aligned. 452 */ 453 if((uintptr)sp%4) 454 panic("labelinit %#lux %#lux", pc, sp); 455 while((uintptr)sp%64) 456 sp -= 4; 457 sp -= 8; // trial and error on OS X 458 l->sp = sp; 459 //iprint("labelinit %p %p\n", pc, sp); 460 } 461 462 void 463 dumpstack(void) 464 { 465 } 466 467 void 468 rdb(void) 469 { 470 } 471 472 void 473 halt(void) 474 { 475 } 476 477 void 478 checkmmu(ulong a, ulong b) 479 { 480 } 481 482 void 483 delay(int x) 484 { 485 // no 486 } 487 488 void 489 reboot(void *entry, void *code, ulong size) 490 { 491 restoretty(); exit(0); 492 error(Egreg); 493 } 494 495 void 496 countpagerefs(ulong *ref, int print) 497 { 498 panic("countpagerefs"); 499 } 500 501 502 /* 503 * Debugging prints go to standard error, always. 504 */ 505 int 506 iprint(char *fmt, ...) 507 { 508 int n; 509 va_list arg; 510 char buf[PRINTSIZE]; 511 512 va_start(arg, fmt); 513 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; 514 va_end(arg); 515 write(2, buf, n); 516 return n; 517 } 518 519 void 520 talktome(void) 521 { 522 int i; 523 static char cmd[512]; 524 while (fgets(cmd, sizeof(cmd), stdin)) { 525 if (! strcmp(cmd, "mach")) { 526 for(i = 0; i < MAXMACH; i++) { 527 fprintf(stderr, "%ld ", MACHP(i)->splpc); 528 } 529 } 530 } 531 fprintf(stderr, "We're done talking\n"); 532 } 533 /* 534 * Panics go to standard error. 535 */ 536 int panicking; 537 void 538 panic(char *fmt, ...) 539 { 540 int n; 541 va_list arg; 542 char buf[PRINTSIZE]; 543 544 if(panicking) 545 for(;;); 546 panicking = 1; 547 548 strcpy(buf, "9vx panic: "); 549 va_start(arg, fmt); 550 n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; 551 va_end(arg); 552 buf[n] = '\n'; 553 write(2, buf, n+1); 554 restoretty(); 555 if(doabort){ 556 #ifdef __APPLE__ 557 fprint(2, "sleeping, so you can attach gdb to pid %d\n", (int)getpid()); 558 for(;;) 559 microdelay(1000000); 560 #else 561 fprint(2, "aborting, to dump core.\n"); 562 talktome(); 563 abort(); 564 #endif 565 } 566 exit(0); 567 } 568 569 /* 570 * Sleazy: replace vsnprintf with vsnprint, so that 571 * vxprint will use the Fmt library, which behaves 572 * better on small stacks. 573 * 574 * TODO: Apple linker doesn't like this. 575 */ 576 #ifndef __APPLE__ 577 int 578 vsnprintf(char *buf, size_t nbuf, const char *fmt, va_list arg) 579 { 580 return vsnprint(buf, nbuf, (char*)fmt, arg); 581 } 582 #endif