From 7f34cfa6648f562d20c03744934cb61004ea3884 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 4 Apr 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-04-04 --- alphapc/cycintr.c | 27 ++++++ alphapc/dat.h | 12 +++ alphapc/fns.h | 4 + bitsy/devether.c | 2 +- bitsy/devflash.c | 2 +- bitsy/fns.h | 4 + mtx/cycintr.c | 27 ++++++ mtx/dat.h | 11 +++ mtx/fns.h | 4 + pc/dat.h | 3 +- pc/devarch.c | 16 ++-- pc/ether79c970.c | 6 +- pc/fns.h | 1 + pc/i8253.c | 7 +- pc/mp.c | 37 ++++++++ pc/screen.c | 7 ++ pc/screen.h | 2 + pc/trap.c | 12 +-- pc/vgavmware.c | 214 +++++++++++++++++++++++++++++++++++++++++++-- port/devcons.c | 31 +++++-- port/devdraw.c | 7 +- port/devrealtime.c | 6 ++ port/devwpsd.c | 72 +++++++++------ port/edf.c | 3 - port/portclock.c | 7 ++ port/portdat.h | 2 +- port/proc.c | 72 ++++++++++++++- port/qlock.c | 7 ++ port/sd.h | 2 - port/sysproc.c | 3 + port/taslock.c | 9 +- 31 files changed, 533 insertions(+), 86 deletions(-) create mode 100644 alphapc/cycintr.c create mode 100644 mtx/cycintr.c diff --git a/alphapc/cycintr.c b/alphapc/cycintr.c new file mode 100644 index 0000000000000000000000000000000000000000..acecf369e9901cd6cd333760ab622900d82d9365 --- /dev/null +++ b/alphapc/cycintr.c @@ -0,0 +1,27 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +int +havecycintr(void) +{ + return 0; +} + +void +cycintradd(Cycintr *) +{ +} + +void +cycintrdel(Cycintr *) +{ +} + +void +clockintrsched(void) +{ +} diff --git a/alphapc/dat.h b/alphapc/dat.h index b694d254c041957fb1e8622db7e210b2c315fdad..21102b39bf7b7883a88120f38b7ddb9e8e39a699 100644 --- a/alphapc/dat.h +++ b/alphapc/dat.h @@ -1,4 +1,5 @@ typedef struct Conf Conf; +typedef struct Cycintr Cycintr; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -247,3 +248,14 @@ struct DevConf int nports; /* Number of ports */ port_t *ports; /* The ports themselves */ }; + +/* + * fasttick timer interrupts (Dummy for now) + */ +struct Cycintr +{ + vlong when; /* fastticks when f should be called */ + void (*f)(Ureg*, Cycintr*); + void *a; + Cycintr *next; +}; diff --git a/alphapc/fns.h b/alphapc/fns.h index 5bf46043cd938afe38fb7b63921295009bdcf36e..77c7c984184ce0eafc9f8bed90e085dd9768f965 100644 --- a/alphapc/fns.h +++ b/alphapc/fns.h @@ -7,11 +7,14 @@ void arith(void); void clearmmucache(void); void clock(Ureg*); void clockinit(void); +void clockintrsched(void); #define coherence mb int cistrcmp(char*, char*); int cistrncmp(char*, char*, int); void cpuidprint(void); void cserve(ulong, ulong); +void cycintradd(Cycintr *); +void cycintrdel(Cycintr *); int dmacount(int); int dmadone(int); void dmaend(int); @@ -32,6 +35,7 @@ char *getconf(char*); ulong getfcr(void); ulong getstatus(void); void gotopc(ulong); +int havecycintr(void); int i8042auxcmd(int); void i8042auxenable(void (*)(int, int)); void i8042reset(void); diff --git a/bitsy/devether.c b/bitsy/devether.c index b083600248386bcd7b1038dfc01c9c446b57d82b..d6faa38645e49f2ef50e26c045c62fc66d78a618 100644 --- a/bitsy/devether.c +++ b/bitsy/devether.c @@ -87,7 +87,7 @@ etherconfig(int on, char *spec, DevConf *cf) if(ether->mem) p = seprint(p, e, " addr 0x%luX", PADDR(ether->mem)); if(ether->size) - p = seprint(p, e, " size 0x%luX", ether->size); + p = seprint(p, e, " size 0x%X", ether->size); p = seprint(p, e, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", ether->ea[0], ether->ea[1], ether->ea[2], ether->ea[3], ether->ea[4], ether->ea[5]); diff --git a/bitsy/devflash.c b/bitsy/devflash.c index c87943ea2b3b69228defb008b889fa7cd4171295..10f6005ce16bb65fc989f88e79ed4761d815233c 100644 --- a/bitsy/devflash.c +++ b/bitsy/devflash.c @@ -338,7 +338,7 @@ flashctlread(FPart *fp, void* a, long n, vlong off) buf = smalloc(1024); e = buf + 1024; - p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9lux\n", fp->end-fp->start, + p = seprint(buf, e, "0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n", fp->end-fp->start, flash.wbsize, flash.manid, flash.devid); addr = fp->start; for(i = 0; i < flash.nr && addr < fp->end; i++) diff --git a/bitsy/fns.h b/bitsy/fns.h index b60da056ab4ed5f95387040e79f1a070d4b636ba..709937b09b6935f9a6da111de21daad7c7f5ba1b 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -13,7 +13,10 @@ int cistrcmp(char*, char*); int cistrncmp(char*, char*, int); void clockinit(void); void clockpower(int); +void clockintrsched(void); #define coherence() +void cycintradd(Cycintr *); +void cycintrdel(Cycintr *); #define dcflush(a, b) void delay(int); void µdelay(ulong); @@ -40,6 +43,7 @@ void* getlink(void); ulong getsp(void); void gpiointrenable(ulong, int, void (*)(Ureg*, void*), void*, char*); void h3650uartsetup(void); +int havecycintr(void); void icacheinvalidate(void); void idle(void); void idlehands(void); diff --git a/mtx/cycintr.c b/mtx/cycintr.c new file mode 100644 index 0000000000000000000000000000000000000000..acecf369e9901cd6cd333760ab622900d82d9365 --- /dev/null +++ b/mtx/cycintr.c @@ -0,0 +1,27 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +int +havecycintr(void) +{ + return 0; +} + +void +cycintradd(Cycintr *) +{ +} + +void +cycintrdel(Cycintr *) +{ +} + +void +clockintrsched(void) +{ +} diff --git a/mtx/dat.h b/mtx/dat.h index 20566057bd66d4587abab46873b6e31eee3c356c..34f13e96b667926efd9c6bf4adb214c52eb00b4d 100644 --- a/mtx/dat.h +++ b/mtx/dat.h @@ -1,4 +1,5 @@ typedef struct Conf Conf; +typedef struct Cycintr Cycintr; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -191,6 +192,16 @@ struct ISAConf { int nopt; char *opt[NISAOPT]; }; +/* + * fasttick timer interrupts (Dummy for now) + */ +struct Cycintr +{ + vlong when; /* fastticks when f should be called */ + void (*f)(Ureg*, Cycintr*); + void *a; + Cycintr *next; +}; #define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG)) extern Mach mach0; diff --git a/mtx/fns.h b/mtx/fns.h index d2f2c7a0922bdc94da7c0348e45173764eaf1dbf..95836acc19e047753794a4c76f19e6e305fbf8fb 100644 --- a/mtx/fns.h +++ b/mtx/fns.h @@ -6,7 +6,10 @@ int cistrncmp(char*, char*, int); void clockcheck(void); void clockinit(void); void clockintr(Ureg*); +void clockintrsched(void); #define coherence() eieio() +void cycintradd(Cycintr *); +void cycintrdel(Cycintr *); void cpuidentify(void); void cpuidprint(void); void dcflush(void*, ulong); @@ -33,6 +36,7 @@ ulong getpvr(void); ulong gettbl(void); ulong gettbu(void); void gotopc(ulong); +int havecycintr(void); void hwintrinit(void); void i8250console(void); void i8259init(void); diff --git a/pc/dat.h b/pc/dat.h index 8101c1b1d702bdf15b1bc34d9674cb2cba469375..291ff99e5d4f78a83455da4c42307b20d45f7436 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -1,4 +1,5 @@ typedef struct Conf Conf; +typedef struct Cycintr Cycintr; typedef struct FPsave FPsave; typedef struct ISAConf ISAConf; typedef struct Label Label; @@ -199,8 +200,6 @@ struct Mach int stack[1]; }; -typedef struct Cycintr Cycintr; - /* * fasttick timer interrupts */ diff --git a/pc/devarch.c b/pc/devarch.c index 9cc63cebd1ee9cd577a536d004db0b7e5b843ed6..06df0b7f0b56fa705153ce5111d0ad3fc9b93a73 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -363,21 +363,19 @@ archread(Chan *c, void *a, long n, vlong offset) if(n & 1) error(Ebadarg); checkport(offset, offset+n); - n /= 2; sp = a; for(port = offset; port < offset+n; port += 2) *sp++ = ins(port); - return n*2; + return n; case Qiol: if(n & 3) error(Ebadarg); checkport(offset, offset+n); - n /= 4; lp = a; for(port = offset; port < offset+n; port += 4) *lp++ = inl(port); - return n*4; + return n; case Qioalloc: break; @@ -427,24 +425,22 @@ archwrite(Chan *c, void *a, long n, vlong offset) return n; case Qiow: - if((n & 01) || (offset & 01)) + if(n & 1) error(Ebadarg); checkport(offset, offset+n); - n /= 2; sp = a; for(port = offset; port < offset+n; port += 2) outs(port, *sp++); - return n*2; + return n; case Qiol: - if((n & 0x03) || (offset & 0x03)) + if(n & 3) error(Ebadarg); checkport(offset, offset+n); - n /= 4; lp = a; for(port = offset; port < offset+n; port += 4) outl(port, *lp++); - return n*4; + return n; default: if(c->qid.path < narchdir && (fn = writefn[c->qid.path])) diff --git a/pc/ether79c970.c b/pc/ether79c970.c index 66447ba42939ece21f76f7871965b934e52e3978..3d90379b8140725965b0c6b1b843eba9c2fb9d78 100644 --- a/pc/ether79c970.c +++ b/pc/ether79c970.c @@ -501,9 +501,6 @@ reset(Ether* ether) /* * Allocate a controller structure and start to initialise it. */ - if(ioalloc(ctlr->port, 0x20, 0, "ether79c970") < 0) - return -1; - ether->ctlr = ctlr; ether->port = ctlr->port; ether->irq = ctlr->pcidev->intl; @@ -523,6 +520,7 @@ reset(Ether* ether) ctlr->iow = io32w; }else{ print("#l%d: card doesn't talk right\n", ether->ctlrno); +iprint("#l%d: card doesn't talk right\n", ether->ctlrno); iunlock(ctlr); return -1; } @@ -539,6 +537,8 @@ reset(Ether* ether) default: print("#l%d: unknown PCnet card version %.7ux\n", ether->ctlrno, x&0xFFFFFFF); +iprint("#l%d: unknown PCnet card version %.7ux\n", + ether->ctlrno, x&0xFFFFFFF); iunlock(ctlr); return -1; } diff --git a/pc/fns.h b/pc/fns.h index b7dd73c4542e98a86cbc3800a049a00bb2c39fdf..b07e5aa48b925ee5cf302cedc59acad9087978d9 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -3,6 +3,7 @@ void aamloop(int); Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); //void addscsilink(char*, Scsiio (*)(int, ISAConf*)); +void apicclkenable(void); void archinit(void); void bootargs(ulong); vlong checkcycintr(Ureg*, void*); diff --git a/pc/i8253.c b/pc/i8253.c index 7d6f478af37a150040ccddd51901062bbb54a00b..f11a835fc5102a46e11bdefd63ac611bbeb7def8 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -118,33 +118,30 @@ i8253init(int aalcycles, int havecycleclock) * prefetch buffer. * */ - outb(Tmode, Latch0); if(havecycleclock) rdtsc(&a); + outb(Tmode, Latch0); x = inb(T0cntr); x |= inb(T0cntr)<<8; aamloop(loops); - outb(Tmode, Latch0); if(havecycleclock) rdtsc(&b); y = inb(T0cntr); y |= inb(T0cntr)<<8; x -= y; - + if(x < 0) x += Freq/HZ; if(x > Freq/(3*HZ)) break; } - /* * figure out clock frequency and a loop multiplier for delay(). * n.b. counter goes up by 2*Freq */ cpufreq = loops*((aalcycles*2*Freq)/x); m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */ - if(havecycleclock){ /* counter goes up by 2*Freq */ diff --git a/pc/mp.c b/pc/mp.c index d702b4c19b33f1f2a532e2774f71f3138ef4ff45..60a9aadc2b789ea7a38ada4f3bd0910393f5a677 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -43,6 +43,43 @@ static char* buses[] = { 0, }; +void +apicclkenable(void) +{ + Apic *apic; + + i8259init(); + + /* Uniprocessor local apic init for apic clock */ + apic = &mpapic[0]; + apic->type = PcmpPROCESSOR; + apic->apicno = 0; + apic->flags = 0; + apic->lintr[0] = ApicIMASK; + apic->lintr[1] = ApicIMASK; + apic->machno = 0; + apic->addr = (ulong*)0xfee00000; + machno2apicno[0] = 0; + + /* + * Map the local APIC. + */ + if(mmukmap((ulong)apic->addr, 0, 1024) == 0) + return; + + /* + * These interrupts are local to the processor + * and do not appear in the I/O APIC so it is OK + * to set them now. + */ + intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN, "clock"); + intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); + intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); + + lapicinit(apic); + lapiconline(); +} + static Apic* mkprocessor(PCMPprocessor* p) { diff --git a/pc/screen.c b/pc/screen.c index b987f6fb07ae1393e9191685b2d51bde23cb2875..baa8f48494ffae134d307a23f434a45d9662e8e9 100644 --- a/pc/screen.c +++ b/pc/screen.c @@ -72,6 +72,9 @@ screensize(int x, int y, int z, ulong chan) if(gscreen == nil) return -1; + if(scr->dev && scr->dev->flush) + scr->useflush = 1; + scr->palettedepth = 6; /* default */ scr->gscreendata = &gscreendata; scr->memdefont = getmemdefont(); @@ -147,6 +150,10 @@ flushmemscreen(Rectangle r) int y, len, incs, off, page; scr = &vgascreen[0]; + if(scr->dev && scr->dev->flush){ + scr->dev->flush(scr, r); + return; + } if(scr->gscreen == nil || scr->useflush == 0) return; if(scr->dev == nil || scr->dev->page == nil) diff --git a/pc/screen.h b/pc/screen.h index 890a1981498ec9befb14421f3b0e572ce703cceb..e6e2b151f69b5601ce8b0785ed30d9f0de1223d8 100644 --- a/pc/screen.h +++ b/pc/screen.h @@ -70,6 +70,7 @@ struct VGAdev { int (*fill)(VGAscr*, Rectangle, ulong); void (*ovlctl)(VGAscr*, Chan*, void*, int); int (*ovlwrite)(VGAscr*, void*, int, vlong); + void (*flush)(VGAscr*, Rectangle); }; struct VGAcur { @@ -144,6 +145,7 @@ extern void deletescreenimage(void); extern int drawhasclients(void); extern ulong blanktime; extern void setscreenimageclipr(Rectangle); +extern void drawflush(void); /* vga.c */ extern void vgascreenwin(VGAscr*); diff --git a/pc/trap.c b/pc/trap.c index f512d6a3be18d61f8293d0c00c8d3d3053c9e11e..3064eb4867205144e50fe8c55f0515b6f15e86dd 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -434,15 +434,17 @@ callwithureg(void (*fn)(Ureg*)) static void _dumpstack(Ureg *ureg) { - ulong l, v, i; + ulong l, v, i, estack; extern ulong etext; - if(up == 0) - return; - print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp); i = 0; - for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ + if(up) + estack = (ulong)up->kstack+KSTACK; + else + estack = (ulong)m+MACHSIZE; + + for(l=(ulong)&l; lrd, v); } +static void +vmwait(Vmware *vm) +{ + vmwr(vm, Rsync, 1); + while(vmrd(vm, Rbusy)) + ; +} + static ulong vmwarelinear(VGAscr* scr, int* size, int* align) { @@ -97,6 +157,7 @@ vmwarelinear(VGAscr* scr, int* size, int* align) oapsize = scr->apsize; wasupamem = scr->isupamem; +iprint("osize %d oaperture %.8lux oapsize %d wasupamem %d\n", osize, oaperture, oapsize, wasupamem); p = pcimatch(nil, PCIVMWARE, 0); if(p == nil) error("no vmware card found"); @@ -128,33 +189,111 @@ vmwarelinear(VGAscr* scr, int* size, int* align) if(wasupamem && upamalloc(oaperture, oapsize, 0)) scr->isupamem = 1; }else +{ +memset((void*)KADDR(aperture), 0x7F, 1048576); scr->isupamem = 1; +} +iprint("aperture %lux size %lux\n", aperture, *size); if(oaperture && aperture != oaperture) print("warning (BUG): redefinition of aperture does not change vmwarescreen segment\n"); addvgaseg("vmwarescreen", aperture, osize); + return aperture; } static void -vmwaredisable(VGAscr*) +vmfifowr(Vmware *vm, ulong v) { + ulong *mm; + + mm = vm->mmio; + if(mm == nil){ + iprint("!"); + return; + } + + if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop] + || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax] + && mm[FifoStop] == mm[FifoMin])) + vmwait(vm); + + mm[mm[FifoNextCmd]/sizeof(ulong)] = v; + mm[FifoNextCmd] += sizeof(ulong); + if(mm[FifoNextCmd]==mm[FifoMax]) + mm[FifoNextCmd] = mm[FifoMin]; +} + +static void +vmwareflush(VGAscr*, Rectangle r) +{ + if(vm->mmio == nil) + return; + + vmfifowr(vm, Xupdate); + vmfifowr(vm, r.min.x); + vmfifowr(vm, r.min.y); + vmfifowr(vm, r.max.x-r.min.x); + vmfifowr(vm, r.max.y-r.min.y); + vmwait(vm); } static void -vmwareload(VGAscr*, Cursor*) +vmwareload(VGAscr*, Cursor *c) { + int i; + ulong clr, set; + ulong and[16]; + ulong xor[16]; + + if(vm->mmio == nil) + return; + vmfifowr(vm, Xdefinecursor); + vmfifowr(vm, 1); /* cursor id */ + vmfifowr(vm, -c->offset.x); + vmfifowr(vm, -c->offset.y); + + vmfifowr(vm, 16); /* width */ + vmfifowr(vm, 16); /* height */ + vmfifowr(vm, 1); /* depth for and mask */ + vmfifowr(vm, 1); /* depth for xor mask */ + + for(i=0; i<16; i++){ + clr = (c->clr[i*2+1]<<8) | c->clr[i*2]; + set = (c->set[i*2+1]<<8) | c->set[i*2]; + and[i] = ~(clr|set); /* clr and set pixels => black */ + xor[i] = clr&~set; /* clr pixels => white */ + } + for(i=0; i<16; i++) + vmfifowr(vm, and[i]); + for(i=0; i<16; i++) + vmfifowr(vm, xor[i]); + + vmwait(vm); } static int -vmwaremove(VGAscr*, Point) +vmwaremove(VGAscr*, Point p) { + vmwr(vm, Rcursorid, 1); + vmwr(vm, Rcursorx, p.x); + vmwr(vm, Rcursory, p.y); + vmwr(vm, Rcursoron, CursorOnShow); return 0; } +static void +vmwaredisable(VGAscr*) +{ + vmwr(vm, Rcursorid, 1); + vmwr(vm, Rcursoron, CursorOnHide); +} + static void vmwareenable(VGAscr*) { + vmwr(vm, Rcursorid, 1); + vmwr(vm, Rcursoron, CursorOnShow); } static void @@ -162,9 +301,70 @@ vmwareblank(int) { } +static int +vmwarescroll(VGAscr*, Rectangle r, Rectangle sr) +{ + if(vm->mmio == nil) + return 0; + vmfifowr(vm, Xrectropcopy); + vmfifowr(vm, r.max.x); + vmfifowr(vm, r.max.y); + vmfifowr(vm, r.min.x); + vmfifowr(vm, r.min.y); + vmfifowr(vm, sr.min.x - r.min.x); + vmfifowr(vm, sr.min.y - r.min.y); + vmfifowr(vm, 3); /* code for copy */ + vmwait(vm); + return 1; +} + +static int +vmwarefill(VGAscr*, Rectangle r, ulong sval) +{ + if(vm->mmio == nil) + return 0; + vmfifowr(vm, Xrectfill); + vmfifowr(vm, sval); + vmfifowr(vm, r.min.x); + vmfifowr(vm, r.min.y); + vmfifowr(vm, r.max.x-r.min.x); + vmfifowr(vm, r.max.y-r.min.y); + vmwait(vm); + return 1; +} + static void -vmwaredrawinit(VGAscr*) +vmwaredrawinit(VGAscr *scr) { + ulong mmiobase, mmiosize; + +extern int iprintscreenputs; + iprintscreenputs = 0; + + if(scr->mmio==nil){ + mmiobase = vmrd(vm, Rmemstart); + if(mmiobase == 0){ + iprint("mmiobase 0\n"); + return; + } + mmiosize = vmrd(vm, Rmemsize); + scr->mmio = KADDR(upamalloc(mmiobase, mmiosize, 0)); +iprint("mmio %p\n", scr->mmio); + vm->mmio = scr->mmio; + vm->mmiosize = mmiosize; + if(scr->mmio == nil) + return; + addvgaseg("vmwaremmio", mmiobase, mmiosize); + } + + scr->mmio[FifoMin] = 4*sizeof(ulong); + scr->mmio[FifoMax] = vm->mmiosize; + scr->mmio[FifoNextCmd] = 4*sizeof(ulong); + scr->mmio[FifoStop] = 4*sizeof(ulong); + vmwr(vm, Rconfigdone, 1); + + scr->scroll = vmwarescroll; + scr->fill = vmwarefill; } VGAdev vgavmwaredev = { @@ -175,6 +375,10 @@ VGAdev vgavmwaredev = { 0, vmwarelinear, vmwaredrawinit, + 0, + 0, + 0, + vmwareflush, }; VGAcur vgavmwarecur = { diff --git a/port/devcons.c b/port/devcons.c index 700ad119a1d5b6da309ee9e6633dbb3258263a65..88ed1c6ddc22b81d973a3993379b7b5b82fcb09b 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -16,6 +16,7 @@ Queue* lineq; /* processed console input */ Queue* serialoq; /* serial console output */ Queue* kprintoq; /* console output, for /dev/kprint */ ulong kprintinuse; /* test and set whether /dev/kprint is open */ +int iprintscreenputs = 1; static struct { @@ -56,7 +57,7 @@ enum CMpanic, }; -Cmdtab reboottbl[] = +Cmdtab rebootmsg[] = { CMreboot, "reboot", 0, CMpanic, "panic", 0, @@ -185,7 +186,7 @@ iprint(char *fmt, ...) va_start(arg, fmt); n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); - if(screenputs != nil) + if(screenputs != nil && iprintscreenputs) screenputs(buf, n); if(serialputs != nil) serialputs(buf, n); @@ -348,15 +349,21 @@ echo(char *buf, int n) /* ^T escapes */ ctrlt = 0; switch(*p){ + case 'S': + x = splhi(); + dumpstack(); + procdump(); + splx(x); + return; case 's': dumpstack(); - break; + return; case 'x': xsummary(); ixsummary(); mallocsummary(); pagersummary(); - break; + return; case 'd': if(consdebug == nil) consdebug = rdb; @@ -376,14 +383,22 @@ echo(char *buf, int n) return; case 'q': scheddump(); - break; + return; +#ifdef RSC +case 'Q': +{ +extern void dumpschedlog(void); +dumpschedlog(); +return; +} +#endif case 'k': if(!cpuserver) killbig(); - break; + return; case 'r': exit(0); - break; + return; } } @@ -924,7 +939,7 @@ conswrite(Chan *c, void *va, long n, vlong off) free(cb); nexterror(); } - ct = lookupcmd(cb, reboottbl, nelem(reboottbl)); + ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg)); switch(ct->index) { case CMreboot: rebootcmd(cb->nf-1, cb->f+1); diff --git a/port/devdraw.c b/port/devdraw.c index 7bd58443b4fba7edd6c195d54d74db58fb69e090..2f2a6d8a33818a9f972439cafbe4249365554cee 100644 --- a/port/devdraw.c +++ b/port/devdraw.c @@ -368,7 +368,8 @@ addflush(Rectangle r) return; } /* emit current state */ - flushmemscreen(flushrect); + if(flushrect.min.x < flushrect.max.x) + flushmemscreen(flushrect); flushrect = r; waste = 0; } @@ -395,11 +396,11 @@ dstflush(int dstid, Memimage *dst, Rectangle r) addflush(r); } -static void drawflush(void) { - flushmemscreen(flushrect); + if(flushrect.min.x < flushrect.max.x) + flushmemscreen(flushrect); flushrect = Rect(10000, 10000, -10000, -10000); } diff --git a/port/devrealtime.c b/port/devrealtime.c index e971de81170c8ace89c4be60cdb6b296bf0c5d3a..ea633d95b1f5c66319999463b40d0aff33c4b517 100644 --- a/port/devrealtime.c +++ b/port/devrealtime.c @@ -224,12 +224,16 @@ devrtinit(void) static Chan * devrtattach(char *param) { + if(havecycintr() == 0) + error("no edf on multiprocessors"); return devattach('R', param); } static Walkqid * devrtwalk(Chan *c, Chan *nc, char **name, int nname) { + if (havecycintr() == 0) + error("no edf on multiprocessors"); return devwalk(c, nc, name, nname, nil, 0, schedgen); } @@ -263,6 +267,8 @@ devrtopen(Chan *c, int mode) { Task *t; + if (havecycintr() == 0) + error("no edf on multiprocessors"); switch ((ulong)c->qid.path){ case Qlog: case Qnblog: diff --git a/port/devwpsd.c b/port/devwpsd.c index efc251a2da018951aba18272be0e4b59ff7cacf4..64a07a25c01f8fcfcc6e4b671b7e3e32918c108a 100644 --- a/port/devwpsd.c +++ b/port/devwpsd.c @@ -1,3 +1,6 @@ +/* + * Storage Device. + */ #include "u.h" #include "../port/lib.h" #include "mem.h" @@ -9,11 +12,7 @@ #include "../port/sd.h" -/* - * Storage Device. - */ - -extern Dev sddevtab; +extern Dev wpsddevtab; extern SDifc* sdifc[]; typedef struct { @@ -31,6 +30,20 @@ enum { Rawstatus, }; +enum +{ + CMpart, + CMdelpart, + CMwildcard, +}; + +Cmdtab ctlmsg[] = +{ + CMpart, "part", 3, + CMdelpart, "delpart", 1, + CMwildcard, "*", 0, +}; + enum { Qtopdir = 1, /* top level directory */ Qtopbase, @@ -461,7 +474,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) case Qtopdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + sprint(up->genbuf, "#%C", wpsddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } @@ -507,7 +520,7 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) case Qunitdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + sprint(up->genbuf, "#%C", wpsddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } @@ -591,7 +604,7 @@ sdattach(char* spec) int idno, subno, i; if(ndevs == 0 || *spec == '\0'){ - c = devattach(sddevtab.dc, spec); + c = devattach(wpsddevtab.dc, spec); mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR); return c; } @@ -615,7 +628,7 @@ sdattach(char* spec) incref(&sdev->r); qunlock(&devslock); - c = devattach(sddevtab.dc, spec); + c = devattach(wpsddevtab.dc, spec); mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR); c->dev = (sdev->idno << UnitLOG) + subno; decref(&sdev->r); @@ -657,7 +670,7 @@ sdopen(Chan* c, int omode) break; case Qraw: c->qid.vers = unit->vers; - if(!canlock(&unit->rawinuse)){ + if(tas(&unit->rawinuse) != 0){ c->flag &= ~COPEN; error(Einuse); } @@ -698,7 +711,7 @@ sdclose(Chan* c) sdev = sdgetdev(DEV(c->qid)); if (sdev) { unit = sdev->unit[UNIT(c->qid)]; - unlock(&unit->rawinuse); + unit->rawinuse = 0; decref(&sdev->r); } break; @@ -783,6 +796,8 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) } offset = off%unit->secsize; + if(offset+len > nb*unit->secsize) + len = nb*unit->secsize - offset; if(write){ if(offset || (len%unit->secsize)){ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); @@ -1081,6 +1096,7 @@ static long sdwrite(Chan* c, void* a, long n, vlong off) { Cmdbuf *cb; + Cmdtab *ct; SDreq *req; SDunit *unit; SDev *sdev; @@ -1130,18 +1146,18 @@ sdwrite(Chan* c, void* a, long n, vlong off) error(Ebadarg); } - if(sddevtab.config == nil) + if(wpsddevtab.config == nil) error("No configuration function"); - sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); + wpsddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); break; } case Qctl: - cb = parsecmd(a, n); sdev = sdgetdev(DEV(c->qid)); if (sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; + cb = parsecmd(a, n); qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); @@ -1152,29 +1168,27 @@ sdwrite(Chan* c, void* a, long n, vlong off) if(unit->vers != c->qid.vers) error(Eio); - if(cb->nf < 1) - error(Ebadctl); - if(strcmp(cb->f[0], "part") == 0){ - if(cb->nf != 4) - error(Ebadctl); + ct = lookupcmd(cb, ctlmsg, nelem(ctlmsg)); + switch(ct->index) { + case CMpart: if(unit->sectors == 0 && !sdinitpart(unit)) error(Eio); start = strtoul(cb->f[2], 0, 0); end = strtoul(cb->f[3], 0, 0); sdaddpart(unit, cb->f[1], start, end); - } - else if(strcmp(cb->f[0], "delpart") == 0){ - if(cb->nf != 2 || unit->part == nil) - error(Ebadctl); + break; + case CMdelpart: sddelpart(unit, cb->f[1]); - } - else if(unit->dev->ifc->wctl) + break; + case CMwildcard: + if(unit->dev->ifc->wctl == nil) + error(Ebadctl); unit->dev->ifc->wctl(unit, cb); - else - error(Ebadctl); + break; + } + poperror(); qunlock(&unit->ctl); decref(&sdev->r); - poperror(); free(cb); break; @@ -1448,7 +1462,7 @@ sdconfig(int on, char* spec, DevConf* cf) return unconfigure(spec); } -Dev sddevtab = { +Dev wpwpsddevtab = { 'S', "sd", diff --git a/port/edf.c b/port/edf.c index 1063251d66b46d4d686a24c838ed30f4c8e0e616..589c469bd0305981437fb5d3a75d9c8b3f069a42 100644 --- a/port/edf.c +++ b/port/edf.c @@ -477,8 +477,6 @@ edfdeadlineintr(Ureg*, Cycintr*) } } } - if (up->nlocks) - iprint("have %lud locks at deadline\n", up->nlocks); } iunlock(&edflock); sched(); @@ -869,7 +867,6 @@ edf_testschedulability(Task *thetask) } H=0; G=0; - ticks = 0; for(steps = 0; steps < Maxsteps; steps++){ t = qschedulability; qschedulability = t->testnext; diff --git a/port/portclock.c b/port/portclock.c index 1692beb54c460eb1bb4246256dd3c9cb74e2a7cf..7a8fe5ef20e17e6e58c3b6796512f8548b25d6f1 100644 --- a/port/portclock.c +++ b/port/portclock.c @@ -5,6 +5,7 @@ #include "fns.h" #include "io.h" #include "ureg.h" +#include "../port/edf.h" void (*kproftimer)(ulong); @@ -75,6 +76,12 @@ portclock(Ureg *ur) if(up == 0 || up->state != Running) return; + // i.e. don't schedule an EDF process here! + if(!isedf(up) && anyready()){ + sched(); + splhi(); + } + /* user profiling clock */ if(userureg(ur)) { (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); diff --git a/port/portdat.h b/port/portdat.h index ef26e4b46608ca226e386988802a6f184be6319f..3528ace7771a27dd6fe21f626c79217de3a4e04c 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -640,7 +640,7 @@ struct Proc Mach *wired; Mach *mp; /* machine this process last ran on */ - ulong nlocks; /* number of locks held by proc */ + ulong nlocks; /* number of locks held by proc */ ulong delaysched; ulong priority; /* priority level */ ulong basepri; /* base priority level */ diff --git a/port/proc.c b/port/proc.c index 82b15b8eac9ab52331a249304f3175ba5cdb115a..9964219936c38bd79ff9e793d40fbb95c4606241 100644 --- a/port/proc.c +++ b/port/proc.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" +#include "../port/edf.h" int nrdy; Ref noteidalloc; @@ -42,6 +43,37 @@ char *statename[] = static void pidhash(Proc*); static void pidunhash(Proc*); +/*DEBUGGING: scheduling event log */ +#ifdef RSC +static ulong *lg; +enum {Nlg = 1024*1024}; +static ulong wp, rp; +static void +le(int c, Proc *p) +{ + if(lg==nil) + lg = malloc(Nlg*sizeof(lg[0])); + lg[wp++&(Nlg-1)] = MACHP(0)->ticks; + lg[wp++&(Nlg-1)] = c; + lg[wp++&(Nlg-1)] = (ulong)p; +} +void +dumpschedlog(void) +{ + int i; + + i=0; + iprint("%lux=>%lux\n", rp, wp); + while((rp&(Nlg-1))!=(wp&(Nlg-1))){ + iprint("%lux ", lg[rp++&(Nlg-1)]); + if(++i%8==0) + iprint("\n"); + } + if(i%8) + iprint("\n"); +} +#endif + /* * Always splhi()'ed. */ @@ -57,6 +89,8 @@ schedinit(void) /* never returns */ break; case Moribund: up->state = Dead; + if (isedf(up)) + edf_bury(up); /* * Holding locks from pexit: @@ -73,6 +107,9 @@ schedinit(void) /* never returns */ break; } up->mach = 0; +#ifdef RSC +le('e', up); +#endif up = nil; } sched(); @@ -106,6 +143,9 @@ sched(void) gotolabel(&m->sched); } up = runproc(); +#ifdef RSC +le('u',up); +#endif up->state = Running; up->mach = MACHP(m->machno); m->proc = up; @@ -116,7 +156,7 @@ sched(void) int anyready(void) { - return nrdy; + return nrdy || edf_anyready(); } int @@ -146,7 +186,15 @@ ready(Proc *p) Schedq *rq; s = splhi(); +#ifdef RSC +le('r',p); +#endif + if(isedf(p)){ + edf_ready(p); + splx(s); + return; + } if(p->fixedpri){ pri = p->basepri; } else { @@ -197,6 +245,9 @@ runproc(void) Proc *p, *l; ulong rt; + if ((p = edf_runproc()) != nil) + return p; + loop: /* @@ -348,6 +399,8 @@ newproc(void) p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; + p->nlocks = 0; + p->delaysched = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); @@ -433,6 +486,9 @@ sleep(Rendez *r, int (*f)(void*), void *arg) s = splhi(); + if (up->nlocks) + print("process %lud sleeps with %lud locks held, last lock 0x%p locked at pc 0x%lux\n", + up->pid, up->nlocks, up->lastlock, up->lastlock->pc); lock(r); lock(&up->rlock); if(r->p){ @@ -480,9 +536,11 @@ sleep(Rendez *r, int (*f)(void*), void *arg) */ unlock(&up->rlock); unlock(r); - // Behind unlock, we may call wakeup on ourselves. + if (isedf(up)) + edf_block(up); + gotolabel(&m->sched); } } @@ -690,6 +748,8 @@ addbroken(Proc *p) broken.p[broken.n++] = p; qunlock(&broken); + if (isedf(up)) + edf_bury(up); p->state = Broken; p->psstate = 0; sched(); @@ -857,6 +917,8 @@ pexit(char *exitstr, int freemem) lock(&procalloc); lock(&palloc); + if (isedf(up)) + edf_bury(up); up->state = Moribund; sched(); panic("pexit"); @@ -932,9 +994,9 @@ dumpaproc(Proc *p) s = p->psstate; if(s == 0) s = statename[p->state]; - print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux\n", + print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux nl %lud nd %lud lpc %lux\n", p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state], - p->time[0], p->time[1], bss, p->qpc); + p->time[0], p->time[1], bss, p->qpc, p->nlocks, p->delaysched, p->lastlock ? p->lastlock->pc : 0); } void @@ -1109,6 +1171,8 @@ procctl(Proc *p) qunlock(&p->debug); splhi(); p->state = Stopped; + if (isedf(up)) + edf_block(up); sched(); p->psstate = state; splx(s); diff --git a/port/qlock.c b/port/qlock.c index 09e1aaa7cc3c2409a8eb1fee00e60492de590820..1f8dbbeefab5bb4d06ab76cc85f45bcb77a1ca68 100644 --- a/port/qlock.c +++ b/port/qlock.c @@ -3,6 +3,7 @@ #include "mem.h" #include "dat.h" #include "fns.h" +#include "../port/edf.h" struct { ulong rlock; @@ -39,6 +40,8 @@ qlock(QLock *q) mp->state = Queueing; up->qpc = getcallerpc(&q); unlock(&q->use); + if (isedf(mp)) + edf_block(mp); sched(); } @@ -102,6 +105,8 @@ rlock(RWlock *q) mp->qnext = 0; mp->state = QueueingR; unlock(&q->use); + if (isedf(mp)) + edf_block(mp); sched(); } @@ -158,6 +163,8 @@ wlock(RWlock *q) mp->qnext = 0; mp->state = QueueingW; unlock(&q->use); + if (isedf(mp)) + edf_block(mp); sched(); } diff --git a/port/sd.h b/port/sd.h index 7a50c35e68bc15997dcbe8a684de386cd0efb72e..443d4648847227ac47f55a74841a252a95fc1f42 100644 --- a/port/sd.h +++ b/port/sd.h @@ -42,8 +42,6 @@ typedef struct SDunit { int state; SDreq* req; SDperm rawperm; - - Log log; } SDunit; /* diff --git a/port/sysproc.c b/port/sysproc.c index e41c93bfc466d15d2f4c813ccc5b5f40c91edeb4..4acaacb1ae733b257527768c43ce605ae65b6fc3 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -4,6 +4,7 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" +#include "../port/edf.h" #include @@ -825,6 +826,8 @@ sysrendezvous(ulong *arg) *l = up; up->state = Rendezvous; unlock(up->rgrp); + if (isedf(up)) + edf_block(up); sched(); diff --git a/port/taslock.c b/port/taslock.c index e3ebf479e98ed8d39d47cb85c2e33a829e7b7427..f2885beadcf01f716ea9ef86715b9af3c630557d 100644 --- a/port/taslock.c +++ b/port/taslock.c @@ -53,7 +53,8 @@ lock(Lock *l) if(up) up->nlocks++; /* prevent being scheded */ if(tas(&l->key) == 0){ - if (up) up->lastlock = l; + if(up) + up->lastlock = l; l->pc = pc; l->p = up; l->isilock = 0; @@ -85,6 +86,7 @@ lock(Lock *l) if(up) up->nlocks--; } + return 0; /* For the compiler */ } void @@ -120,7 +122,8 @@ ilock(Lock *l) ; x = splhi(); if(tas(&l->key) == 0){ - if (up) up->lastlock = l; + if(up) + up->lastlock = l; l->sr = x; l->pc = pc; l->p = up; @@ -158,7 +161,6 @@ unlock(Lock *l) print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc); if(l->p != up) print("unlock: up changed: pc %lux, acquired at pc %lux, lock p 0x%p, unlock up 0x%p\n", getcallerpc(&l), l->pc, l->p, up); - l->pc = ~0; l->key = 0; if (up && --up->nlocks == 0 && up->delaysched){ up->delaysched = 0; @@ -178,7 +180,6 @@ iunlock(Lock *l) print("iunlock of lock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc); sr = l->sr; - l->pc = ~1; l->key = 0; coherence();