From cc01e61703af9f49ee42563fce64ca40f103e67e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 20 Apr 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-04-20 --- alphapc/dat.h | 1 + bitsy/dat.h | 1 + mtx/dat.h | 1 + pc/dat.h | 1 + pc/pci.c | 16 +-- pc/trap.c | 1 + pc/vgai81x.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++ port/edf.c | 3 + port/proc.c | 8 +- port/qlock.c | 31 ++++-- port/segment.c | 2 +- port/taslock.c | 14 +-- 12 files changed, 327 insertions(+), 33 deletions(-) create mode 100644 pc/vgai81x.c diff --git a/alphapc/dat.h b/alphapc/dat.h index b694d254c041957fb1e8622db7e210b2c315fdad..9601a269389410431d17774d4776e2c9111c26d7 100644 --- a/alphapc/dat.h +++ b/alphapc/dat.h @@ -156,6 +156,7 @@ struct Mach int load; int intr; int flushmmu; /* make current proc flush it's mmu state */ + int ilockdepth; ulong spuriousintr; int lastintr; diff --git a/bitsy/dat.h b/bitsy/dat.h index 03755258b191feca3451c9790795132087e0184b..f0b43550e626a9a5b4f1540a523b7574cfe30496 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -136,6 +136,7 @@ struct Mach vlong intrts; /* time stamp of last interrupt */ ulong spuriousintr; int lastintr; + int ilockdepth; int flushmmu; /* make current proc flush it's mmu state */ Proc *pid2proc[31]; /* what proc holds what pid */ diff --git a/mtx/dat.h b/mtx/dat.h index 20566057bd66d4587abab46873b6e31eee3c356c..34f661a1544bd362657834a63627792c5f69c516 100644 --- a/mtx/dat.h +++ b/mtx/dat.h @@ -151,6 +151,7 @@ struct Mach int load; int intr; int flushmmu; /* make current proc flush it's mmu state */ + int ilockdepth; ulong ptabbase; /* start of page table in kernel virtual space */ int slotgen; /* next pte (byte offset) when pteg is full */ diff --git a/pc/dat.h b/pc/dat.h index e757e0bb0d2cadf940a377689e1fa309e54817f2..0c94fb0644abcb8cf20cd16028f48c6c20d34195 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -177,6 +177,7 @@ struct Mach int intr; vlong intrts; /* time stamp of last interrupt */ int flushmmu; /* make current proc flush it's mmu state */ + int ilockdepth; ulong spuriousintr; int lastintr; diff --git a/pc/pci.c b/pc/pci.c index 7f0ce297554a1ff238d07f65bd101617957a0ff7..0c5879c82c08db2ddb3b8cb9ea2eb96a78fe7f5f 100644 --- a/pc/pci.c +++ b/pc/pci.c @@ -57,7 +57,7 @@ enum }; static Lock pcicfglock; -static QLock pcicfginitlock; +static Lock pcicfginitlock; static int pcicfgmode = -1; static int pcimaxbno = 7; static int pcimaxdno; @@ -498,9 +498,9 @@ pciscan(int bno, Pcidev **list) { int ubn; - qlock(&pcicfginitlock); + lock(&pcicfginitlock); ubn = pcilscan(bno, list); - qunlock(&pcicfginitlock); + unlock(&pcicfginitlock); return ubn; } @@ -747,7 +747,7 @@ pcicfginit(void) Pcidev **list; ulong mema, ioa; - qlock(&pcicfginitlock); + lock(&pcicfginitlock); if(pcicfgmode != -1) goto out; @@ -839,14 +839,14 @@ pcicfginit(void) pcibusmap(pciroot, &mema, &ioa, 1); DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa); - qunlock(&pcicfginitlock); + unlock(&pcicfginitlock); return; } pcirouting(); out: - qunlock(&pcicfginitlock); + unlock(&pcicfginitlock); } @@ -1117,9 +1117,9 @@ pcihinv(Pcidev* p) { if(pcicfgmode == -1) pcicfginit(); - qlock(&pcicfginitlock); + lock(&pcicfginitlock); pcilhinv(p); - qunlock(&pcicfginitlock); + unlock(&pcicfginitlock); } void diff --git a/pc/trap.c b/pc/trap.c index c8d2bccd21f79faf99315ada6f736066f74aab97..99ce39904473ce36903930e0a4875967ee69cc88 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -287,6 +287,7 @@ trap(Ureg* ureg) */ if(ctl->isintr && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK) if(up && up->state == Running) + if(up->nlocks == 0) if(anyhigher()) if(up->preempted == 0) if(!active.exiting){ diff --git a/pc/vgai81x.c b/pc/vgai81x.c new file mode 100644 index 0000000000000000000000000000000000000000..6a326d54f0d224c45f2daac88aa8facd787efd3a --- /dev/null +++ b/pc/vgai81x.c @@ -0,0 +1,281 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +typedef struct +{ + ushort ctl; + ushort pad; + ulong base; + ulong pos; +} CursorI81x; + +enum { + Fbsize = 8*MB, + + hwCur = 0x70080, +}; + +static Pcidev * +i81xpcimatch(void) +{ + Pcidev *p; + + p = nil; + while((p = pcimatch(p, 0x8086, 0)) != nil){ + switch(p->did){ + default: + continue; + case 0x7121: + case 0x7123: + case 0x7125: + case 0x1102: + case 0x1112: + case 0x1132: + return p; + } + } + return nil; +} + +static ulong +i81xlinear(VGAscr* scr, int* size, int* align) +{ + Pcidev *p; + int oapsize, wasupamem; + ulong aperture, oaperture, fbuf, fbend, *rp; + + oaperture = scr->aperture; + oapsize = scr->apsize; + wasupamem = scr->isupamem; + + aperture = 0; + p = i81xpcimatch(); + if(p != nil) { + aperture = p->mem[0].bar & ~0x0F; + *size = p->mem[0].size; + if(*size > Fbsize) + *size = Fbsize; + } + + if(wasupamem){ + if(oaperture == aperture) + return oaperture; + upafree(oaperture, oapsize); + } + scr->isupamem = 0; + + aperture = upamalloc(aperture, *size, *align); + if(aperture == 0){ + if(wasupamem && upamalloc(oaperture, oapsize, 0)){ + aperture = oaperture; + scr->isupamem = 1; + } + else + scr->isupamem = 0; + } + else + scr->isupamem = 1; + + /* allocate space for frame buffer, populate page table */ + if(oapsize == 0) { + fbuf = PADDR(xspanalloc(*size, BY2PG, 0)); + fbend = PGROUND(fbuf+*size); + rp = KADDR(scr->io+0x10000); + while(fbuf < fbend) { + *rp++ = fbuf | (1<<0); + fbuf += BY2PG; + } + } + return aperture; +} + +static void +i81xenable(VGAscr* scr) +{ + Pcidev *p; + int align, size; + Mach *mach0; + ulong aperture, pgtbl, *rp, cursor, *pte; + + /* + * Only once, can't be disabled for now. + * scr->io holds the physical address of + * the MMIO registers. + */ + if(scr->io) + return; + p = i81xpcimatch(); + if(p == nil) + return; + scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0); + if(scr->io == 0) + return; + + /* allocate page table */ + pgtbl = PADDR(xspanalloc(64*1024, BY2PG, 0)); + rp = KADDR(scr->io+0x2020); + *rp = pgtbl | 1; + + addvgaseg("i81xmmio", (ulong)scr->io, p->mem[0].size); + + size = p->mem[0].size; + align = 0; + aperture = i81xlinear(scr, &size, &align); + if(aperture){ + scr->aperture = aperture; + scr->apsize = size; + addvgaseg("i81xscreen", aperture, size); + } + + /* + * allocate space for the cursor data in system memory. + * must be uncached. + */ + cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0); + mach0 = MACHP(0); + pte = mmuwalk(mach0->pdb, cursor, 2, 0); + if(pte == nil) + panic("i81x cursor"); + *pte |= PTEUNCACHED; + scr->storage = PADDR(cursor); +} + +static void +i81xcurdisable(VGAscr* scr) +{ + CursorI81x *hwcurs; + + if(scr->io == 0) + return; + hwcurs = KADDR(scr->io+hwCur); + hwcurs->ctl = (1<<4); +} + +static void +i81xcurload(VGAscr* scr, Cursor* curs) +{ + int y; + uchar *p; + CursorI81x *hwcurs; + + if(scr->io == 0) + return; + hwcurs = KADDR(scr->io+hwCur); + + /* + * Disable the cursor then load the new image in + * the top-left of the 32x32 array. + * Unused portions of the image have been initialised to be + * transparent. + */ + hwcurs->ctl = (1<<4); + p = KADDR(scr->storage); + for(y = 0; y < 16; y += 2) { + *p++ = ~(curs->clr[2*y]|curs->set[2*y]); + *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]); + p += 2; + *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]); + *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]); + p += 2; + *p++ = curs->set[2*y]; + *p++ = curs->set[2*y+1]; + p += 2; + *p++ = curs->set[2*y+2]; + *p++ = curs->set[2*y+3]; + p += 2; + } + + /* + * Save the cursor hotpoint and enable the cursor. + * The 0,0 cursor point is top-left. + */ + scr->offset.x = curs->offset.x; + scr->offset.y = curs->offset.y; + hwcurs->ctl = (1<<4)|1; +} + +static int +i81xcurmove(VGAscr* scr, Point p) +{ + int x, y; + ulong pos; + CursorI81x *hwcurs; + + if(scr->io == 0) + return 1; + hwcurs = KADDR(scr->io+hwCur); + + x = p.x+scr->offset.x; + y = p.y+scr->offset.y; + pos = 0; + if(x < 0) { + pos |= (1<<15); + x = -x; + } + if(y < 0) { + pos |= (1<<31); + y = -y; + } + pos |= ((y&0x7ff)<<16)|(x&0x7ff); + hwcurs->pos = pos; + + return 0; +} + +static void +i81xcurenable(VGAscr* scr) +{ + int i; + uchar *p; + CursorI81x *hwcurs; + + i81xenable(scr); + if(scr->io == 0) + return; + hwcurs = KADDR(scr->io+hwCur); + + /* + * Initialise the 32x32 cursor to be transparent in 2bpp mode. + */ + hwcurs->base = scr->storage; + p = KADDR(scr->storage); + for(i = 0; i < 32/2; i++) { + memset(p, 0xff, 8); + memset(p+8, 0, 8); + p += 16; + } + /* + * Load, locate and enable the 32x32 cursor in 2bpp mode. + */ + i81xcurload(scr, &arrow); + i81xcurmove(scr, ZP); +} + +VGAdev vgai81xdev = { + "i81x", + + i81xenable, + nil, + nil, + i81xlinear, +}; + +VGAcur vgai81xcur = { + "i81xhwgc", + + i81xcurenable, + i81xcurdisable, + i81xcurload, + i81xcurmove, +}; diff --git a/port/edf.c b/port/edf.c index fc1761209477332a1d869dda58fcacb6a4cc8b14..8d307ba9031b4871dc82391769a34cdef5fda17b 100644 --- a/port/edf.c +++ b/port/edf.c @@ -40,6 +40,7 @@ int ntasks; Resource resources[Maxresources]; int nresources; int edfstateupdate; +int misseddeadlines; enum{ Deadline, /* Invariant for schedulability test: Deadline < Release */ @@ -465,6 +466,8 @@ edfdeadlineintr(Ureg*, Timer*) if (t->d <= now || t->S == 0LL){ /* Task has reached its deadline/slice, remove from queue */ + if (t->S > 0LL) + misseddeadlines++; deadline(up, SSlice); while (t = edfstack[m->machno].head){ if (now < t->d) diff --git a/port/proc.c b/port/proc.c index e6e17772508c7c12c027d7b3c2227a068b3a3a91..f117892ed5329e755d3508c6c81ed091bd0f5ba5 100644 --- a/port/proc.c +++ b/port/proc.c @@ -87,10 +87,12 @@ schedinit(void) /* never returns */ void sched(void) { + if(m->ilockdepth) + panic("ilockdepth %d", m->ilockdepth); + if(up){ - if(up->state == Running && up->nlocks){ - up->delaysched = 1; - delayedscheds++; + if(up->nlocks && up->state != Moribund){ + delayedscheds++; return; } diff --git a/port/qlock.c b/port/qlock.c index f763d46c57fbd0eacb8b9ba2a57aafaf77631506..70ee44147fbdbd1db3aac9087374b9b0a9c90f3d 100644 --- a/port/qlock.c +++ b/port/qlock.c @@ -13,10 +13,22 @@ struct { ulong qlockq; } rwstats; +int shutup=1; /* RSC: you can take this out, it's just to silence a print in a loop on the dist floppy */ void qlock(QLock *q) { - Proc *p, *mp; + Proc *p; + + if(up == 0) + panic("qlock"); + if(m->ilockdepth != 0 && !shutup){ + print("qlock: %lux: ilockdepth %d", getcallerpc(&q), m->ilockdepth); + shutup = 1; + } + if(up->nlocks && !shutup){ + print("qlock: %lux: nlocks %d", getcallerpc(&q), up->nlocks); + shutup = 1; + } lock(&q->use); rwstats.qlock++; @@ -27,20 +39,17 @@ qlock(QLock *q) } rwstats.qlockq++; p = q->tail; - mp = up; - if(mp == nil) - panic("qlock"); if(p == 0) - q->head = mp; + q->head = up; else - p->qnext = mp; - q->tail = mp; - mp->qnext = 0; - mp->state = Queueing; + p->qnext = up; + q->tail = up; + up->qnext = 0; + up->state = Queueing; up->qpc = getcallerpc(&q); unlock(&q->use); - if (isedf(mp)) - edfblock(mp); + if (isedf(up)) + edfblock(up); sched(); } diff --git a/port/segment.c b/port/segment.c index 161c721a7aa324a30306a2bb4508d54ff5b8e973..018df80493e5c66212e642d52ea3a6af4a6f2af5 100644 --- a/port/segment.c +++ b/port/segment.c @@ -112,6 +112,7 @@ putseg(Segment *s) unlock(s); return; } + unlock(s); qlock(&s->lk); if(i) @@ -127,7 +128,6 @@ putseg(Segment *s) free(s->map); if(s->profile != 0) free(s->profile); - unlock(s); /* keep lock/unlocks balanced */ free(s); } diff --git a/port/taslock.c b/port/taslock.c index 6b884791c135df8626d3eedf5855767d9e454e78..a48c9fbe7c97c381d53d67dc25298e752c30f7c6 100644 --- a/port/taslock.c +++ b/port/taslock.c @@ -36,9 +36,6 @@ lockloop(Lock *l, ulong pc) dumpaproc(up); if(p != nil) dumpaproc(p); - - if(up && up->state == Running && islo()) - sched(); } int @@ -99,6 +96,7 @@ ilock(Lock *l) lockstats.locks++; x = splhi(); + m->ilockdepth++; if(tas(&l->key) == 0){ if(up) up->lastlock = l; @@ -164,13 +162,8 @@ unlock(Lock *l) l->key = 0; coherence(); - /* give up the processor if ... */ - if(up && --up->nlocks == 0 /* we've closed the last nexted lock */ - && up->delaysched /* we delayed scheduling because of the lock */ - && up->state == Running){ /* we're in running state */ - up->delaysched = 0; - sched(); - } + if(up) + --up->nlocks; } void @@ -190,5 +183,6 @@ iunlock(Lock *l) coherence(); m->splpc = getcallerpc(&l); + m->ilockdepth--; splxpc(sr); }