stub.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
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