From 09349c777d56efed6ebb384a6bb45244457ad007 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 18 Oct 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-10-18 --- bitsy/fns.h | 7 +- bitsy/l.s | 58 ++++++- bitsy/main.c | 27 +-- bitsy/mem.h | 2 +- bitsy/mmu.c | 77 +++++---- bitsy/sa1110uart.c | 400 +++++++++++++++++++++++++++++++++++++++++++++ bitsy/screen.c | 61 ++++--- bitsy/screen.h | 1 + bitsy/trap.c | 74 ++++++--- boot/local.c | 26 ++- pc/apm.c | 160 ++++++++++++++++++ pc/apmjump.s | 98 +++++++++++ pc/dat.h | 2 +- pc/devarch.c | 99 +++++++---- pc/fns.h | 2 +- pc/mem.h | 9 + pc/trap.c | 14 +- port/log.c | 65 ++++++-- port/portdat.h | 2 + port/portfns.h | 2 + port/proc.c | 1 + 21 files changed, 1015 insertions(+), 172 deletions(-) create mode 100644 bitsy/sa1110uart.c create mode 100644 pc/apm.c create mode 100644 pc/apmjump.s diff --git a/bitsy/fns.h b/bitsy/fns.h index 687f733b64864ae73c9e1c25ecc00fca1dee5846..fcc8d7154b05ecff10220df4297cc0f2bb13b264 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -1,7 +1,10 @@ #include "../port/portfns.h" void cacheflush(void); -void cacheflushaddr(ulong); +void cachewb(void); +void cachewbaddr(void*); +void cachewbregion(void*, int); +void dcacheinvalidate(void); int cistrcmp(char*, char*); int cistrncmp(char*, char*, int); void clockinit(void); @@ -14,6 +17,7 @@ ulong getfar(void); ulong getfsr(void); #define getpgcolor(a) 0 void h3650uartsetup(void); +void icacheinvalidate(void); void idle(void); #define idlehands() /* nothing to do in the runproc */ void intrenable(int, void (*)(Ureg*, void*), void*, char*); @@ -28,6 +32,7 @@ void mmuinit(void); void mmuenable(void); void mmudisable(void); void mmuinvalidate(void); +void mmuinvalidateaddr(ulong); void noted(Ureg*, ulong); int notify(Ureg*); #define procrestore(p) diff --git a/bitsy/l.s b/bitsy/l.s index 0ce9eaf7dbef3c39724c603e9b8f459b4c8e975f..98ef5d74c82484520547c3ec798d4787e5f0a4e4 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -39,17 +39,22 @@ TEXT mmuinvalidate(SB), $-4 MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7) RET +/* flush tlb's */ +TEXT mmuinvalidateaddr(SB), $-4 + MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1 + RET + /* write back and invalidate i and d caches */ TEXT cacheflush(SB), $-4 /* write back any dirty data */ MOVW $0xe0000000,R0 ADD $(8*1024),R0,R1 -_wbloop: - MOVW.W 32(R0),R2 +_cfloop: + MOVW.P 32(R0),R2 CMP R0,R1 - BNE _wbloop + BNE _cfloop - /* drain write buffer and flush i&d cache contents */ + /* drain write buffer and invalidate i&d cache contents */ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 @@ -60,13 +65,52 @@ _wbloop: MOVW R0,R0 RET -/* clean a single virtual address */ -TEXT cacheflushaddr(SB), $-4 +/* write back and invalidate i and d caches */ +TEXT cachewb(SB), $-4 + /* write back any dirty data */ + MOVW $0xe0000000,R0 + ADD $(8*1024),R0,R1 +_cwbloop: + MOVW.P 32(R0),R2 + CMP R0,R1 + BNE _cfloop + + /* drain write buffer */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + RET + +/* write back a single cache line */ +TEXT cachewbaddr(SB), $-4 + BIC $31,R0 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1 + B _wbflush + +/* write back a region of cache lines */ +TEXT cachewbregion(SB), $-4 + MOVW 4(FP),R1 + BIC $31,R0 + ADD R0,R1 + ADD $32,R1 +_cfrloop: MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1 + ADD $32,R0 + CMP.S R0,R1 + BNE _cfrloop + B _wbflush + +/* invalidate the dcache */ +TEXT dcacheinvalidate(SB), $-4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6) + RET + +/* invalidate the icache */ +TEXT icacheinvalidate(SB), $-4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9) RET /* drain write buffer */ TEXT wbflush(SB), $-4 +_wbflush: MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 RET @@ -100,7 +144,7 @@ TEXT putttb(SB), $-4 */ TEXT mmuenable(SB), $-4 MRC CpMMU, 0, R0, C(CpControl), C(0x0) - ORR $(CpCmmuena|CpCwb|CpCdcache), R0 + ORR $(CpCmmuena|CpCdcache|CpCwb), R0 MCR CpMMU, 0, R0, C(CpControl), C(0x0) RET diff --git a/bitsy/main.c b/bitsy/main.c index 8de68676fe5d0ce4e6c8af9666d0bd4e2f78ec2e..c133cc5981043ca2ea90d6f2f8ca38b81a05382b 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -29,12 +29,13 @@ main(void) m->ticks = 1; rs232power(1); - iprint("bitsy kernel\n"); + iprint("\nPlan 9 bitsy kernel\n"); confinit(); xinit(); mmuinit(); gpioinit(); trapinit(); + screeninit(); sa1100_uartsetup(1); printinit(); /* from here on, print works, before this we need iprint */ clockinit(); @@ -44,7 +45,6 @@ main(void) pageinit(); swapinit(); userinit(); -//iprint("schedinit(), death soon\n"); schedinit(); } @@ -60,34 +60,13 @@ exit(int ispanic) delay(1000); iprint("it's a wonderful day to die\n"); + cacheflush(); mmuinvalidate(); mmudisable(); f = nil; (*f)(); } -/* - * quicker panic - */ -void -qpanic(char *fmt, ...) -{ - int n; - va_list arg; - char buf[PRINTSIZE]; - - splhi(); - strcpy(buf, "panic: "); - va_start(arg, fmt); - n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - buf[n] = '\n'; - serialputs(buf, n+1); - - exit(1); -} - - static uchar *sp; /* diff --git a/bitsy/mem.h b/bitsy/mem.h index becedebd409b51055bab75107d440cae91ee78a1..76b49ae7541c3cfd6ebb493683ae3925ddd9094f 100644 --- a/bitsy/mem.h +++ b/bitsy/mem.h @@ -21,7 +21,7 @@ /* * Time */ -#define HZ (10) /* clock frequency */ +#define HZ (20) /* clock frequency */ #define MS2HZ (1000/HZ) /* millisec per clock tick */ #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ #define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */ diff --git a/bitsy/mmu.c b/bitsy/mmu.c index acaf5e5f8d1285dd8b3791c88440ccea2fb22190..06dd12015c1a18bb8ac79e4835f0765c20ad729c 100644 --- a/bitsy/mmu.c +++ b/bitsy/mmu.c @@ -220,40 +220,57 @@ static ulong mmubits[16] = * add an entry to the current map */ void -putmmu(ulong va, ulong pa, Page*) +putmmu(ulong va, ulong pa, Page *pg) { - Page *pg; - ulong *t; + Page *l2pg; + ulong *t, *l1p, *l2p; + int s; -print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa); - /* always point L1 entry to L2 page, can't hurt */ - pg = up->l1page[va>>20]; - if(pg == nil){ - pg = up->mmufree; - if(pg != nil){ - up->mmufree = pg->next; + s = splhi(); + + /* clear out the current entry */ + mmuinvalidateaddr(va); + + l2pg = up->l1page[va>>20]; + if(l2pg == nil){ + l2pg = up->mmufree; + if(l2pg != nil){ + up->mmufree = l2pg->next; } else { - pg = auxpage(); - if(pg == nil) + l2pg = auxpage(); + if(l2pg == nil) pexit("out of memory", 1); } - pg->va = VA(kmap(pg)); - up->l1page[va>>20] = pg; - memset((uchar*)(pg->va), 0, BY2PG); + l2pg->va = VA(kmap(l2pg)); + up->l1page[va>>20] = l2pg; + memset((uchar*)(l2pg->va), 0, BY2PG); } - l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask); - cacheflushaddr((ulong)&l1table[va>>20]); -print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]); - up->l1table[va>>20] = l1table[va>>20]; - t = (ulong*)pg->va; + + /* always point L1 entry to L2 page, can't hurt */ + l1p = &l1table[va>>20]; + *l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask); + up->l1table[va>>20] = *l1p; + t = (ulong*)l2pg->va; /* set L2 entry */ - t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] + l2p = &t[(va & (OneMeg-1))>>PGSHIFT]; + *l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)] | (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)); -print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]); - cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]); - wbflush(); + /* write back dirty entries - we need this because the pio() in + * fault.c is writing via a different virt addr and won't clean + * its changes out of the dcache. Page coloring doesn't work + * on this mmu because the virtual cache is set associative + * rather than direct mapped. + */ + cachewb(); + if(pg->cachectl[0] == PG_TXTFLUSH){ + /* pio() sets PG_TXTFLUSH whenever a text page has been written */ + icacheinvalidate(); + pg->cachectl[0] = PG_NOFLUSH; + } + + splx(s); } /* @@ -300,6 +317,7 @@ mmurelease(Proc* p) p->mmufree = nil; memset(l1table, 0, sizeof(p->l1table)); + cachewbregion(l1table, sizeof(p->l1table)); } void @@ -309,20 +327,19 @@ mmuswitch(Proc *p) return; m->mmupid = p->pid; + /* write back dirty cache entries and invalidate all cache entries */ + cacheflush(); + if(p->newtlb){ mmuptefree(p); p->newtlb = 0; } - /* write back dirty cache entries before changing map */ - cacheflush(); - /* move in new map */ memmove(l1table, p->l1table, sizeof(p->l1table)); - /* make sure map is in memory and drain write buffer */ - cacheflushaddr((ulong)l1table); - wbflush(); + /* make sure map is in memory */ + cachewbregion(l1table, sizeof(p->l1table)); /* lose any possible stale tlb entries */ mmuinvalidate(); diff --git a/bitsy/sa1110uart.c b/bitsy/sa1110uart.c new file mode 100644 index 0000000000000000000000000000000000000000..49741706f8b2fdfc57224287fb65fd88a855416a --- /dev/null +++ b/bitsy/sa1110uart.c @@ -0,0 +1,400 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#include "../port/netif.h" + +/* this isn't strictly a sa1100 driver. The rts/cts stuff is h3650 specific */ + +/* hardware registers */ +typedef struct Uartregs Uartregs; +struct Uartregs +{ + ulong ctl[4]; + ulong dummya; + ulong data; + ulong dummyb; + ulong status[2]; +}; + +enum +{ + /* ctl[0] bits */ + Parity= 1<<0, + Even= 1<<1, + Stop2= 1<<2, + Bits8= 1<<3, + SCE= 1<<4, /* synchronous clock enable */ + RCE= 1<<5, /* rx on falling edge of clock */ + TCE= 1<<6, /* tx on falling edge of clock */ + + /* ctl[3] bits */ + Rena= 1<<0, /* receiver enable */ + Tena= 1<<1, /* transmitter enable */ + Break= 1<<2, /* force TXD3 low */ + Rintena= 1<<3, /* enable receive interrupt */ + Tintena= 1<<4, /* enable transmitter interrupt */ + Loopback= 1<<5, /* loop back data */ + + /* data bits */ + DEparity= 1<<8, /* parity error */ + DEframe= 1<<9, /* framing error */ + DEoverrun= 1<<10, /* overrun error */ + + /* status[0] bits */ + Tint= 1<<0, /* transmit fifo half full interrupt */ + Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */ + Rint1= 1<<2, /* receiver fifo not empty and receiver idle */ + Breakstart= 1<<3, + Breakend= 1<<4, + Fifoerror= 1<<5, /* fifo error */ + + /* status[1] bits */ + Tbusy= 1<<0, /* transmitting */ + Rnotempty= 1<<1, /* receive fifo not empty */ + Tnotfull= 1<<2, /* transmit fifo not full */ + ParityError= 1<<3, + FrameError= 1<<4, + Overrun= 1<<5, +}; + +Uartregs *uart3regs = UART3REGS; + +static void sa1100_uartbaud(Uart *p, int rate); +static void sa1100_uartkick(Uart *p); +static void sa1100_uartrts(Uart *p, int on); +static void sa1100_uartintr(Ureg*, void*); +static void sa1100_uartbreak(Uart*, int); +static void sa1100_uartbits(Uart*, int); +static void sa1100_uartparity(Uart*, int); +static void sa1100_uartmodemctl(Uart*, int); +static void sa1100_uartstop(Uart*, int); +static void sa1100_uartdtr(Uart*, int); +static long sa1100_uartstatus(Uart*, void*, long, long); +static void sa1100_uartenable(Uart*, int); +static void sa1100_uartdisable(Uart*); + +PhysUart sa1100_uart = { + .enable= sa1100_uartenable, + .disable= sa1100_uartdisable, + .bits= sa1100_uartbits, + .kick= sa1100_uartkick, + .intr= sa1100_uartintr, + .modemctl= sa1100_uartmodemctl, + .baud= sa1100_uartbaud, + .stop= sa1100_uartstop, + .parity= sa1100_uartparity, + .dobreak= sa1100_uartbreak, + .rts= sa1100_uartrts, + .dtr= sa1100_uartdtr, + .status= sa1100_uartstatus, +}; + +#define R(p) ((Uartregs*)(p->regs)) + +/* + * enable a port's interrupts. set DTR and RTS + */ +static void +sa1100_uartenable(Uart *p, int intena) +{ + ulong s; + + s = R(p)->ctl[3] & ~(Rintena|Tintena|Rena|Tena); + if(intena) + R(p)->ctl[3] = s |Rintena|Tintena|Rena|Tena; + else + R(p)->ctl[3] = s | Rena|Tena; +} + +/* + * disable interrupts. clear DTR, and RTS + */ +static void +sa1100_uartdisable(Uart *p) +{ + R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena); +} + +static long +sa1100_uartstatus(Uart *p, void *buf, long n, long offset) +{ + char str[256]; + ulong ctl0; + + ctl0 = R(p)->ctl[0]; + snprint(str, sizeof(str), + "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n" + "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n", + + p->baud, + p->hup_dcd, + 0, + p->hup_dsr, + (ctl0 & Bits8) ? 8 : 7, + 0, + (ctl0 & Parity) ? ((ctl0 & Even) ? 'e' : 'o') : 'n', + 0, + (ctl0 & Stop2) ? 2 : 1, + 1, + + p->dev, + p->type, + p->frame, + p->overrun, + "", + "", + "", + "" ); + return readstr(offset, buf, n, str); +} + +/* + * set the buad rate + */ +static void +sa1100_uartbaud(Uart *p, int rate) +{ + ulong brconst; + + if(rate <= 0) + return; + + brconst = p->freq/(16*rate) - 1; + R(p)->ctl[1] = (brconst>>8) & 0xf; + R(p)->ctl[2] = brconst; + + p->baud = rate; +} + +/* + * send a break + */ +static void +sa1100_uartbreak(Uart *p, int ms) +{ + if(ms == 0) + ms = 200; + + R(p)->ctl[3] |= Break; + tsleep(&up->sleep, return0, 0, ms); + R(p)->ctl[3] &= ~Break; +} + +/* + * set bits/char + */ +static void +sa1100_uartbits(Uart *p, int n) +{ + switch(n){ + case 7: + R(p)->ctl[0] &= ~Bits8; + break; + case 8: + R(p)->ctl[0] |= Bits8; + break; + default: + error(Ebadarg); + } +} + +/* + * set stop bits + */ +static void +sa1100_uartstop(Uart *p, int n) +{ + switch(n){ + case 1: + R(p)->ctl[0] &= ~Stop2; + break; + case 2: + R(p)->ctl[0] |= Stop2; + break; + default: + error(Ebadarg); + } +} + +/* + * turn on/off rts + */ +static void +sa1100_uartrts(Uart*, int) +{ +} + +/* + * turn on/off dtr + */ +static void +sa1100_uartdtr(Uart*, int) +{ +} + +/* + * turn on/off modem flow control on/off (rts/cts) + */ +static void +sa1100_uartmodemctl(Uart *p, int on) +{ + if(on) { + } else { + p->cts = 1; + } +} + +/* + * set parity + */ +static void +sa1100_uartparity(Uart *p, int type) +{ + switch(type){ + case 'e': + R(p)->ctl[0] |= Parity|Even; + break; + case 'o': + R(p)->ctl[0] |= Parity; + break; + default: + R(p)->ctl[0] &= ~(Parity|Even); + break; + } +} + +/* + * restart output if not blocked and OK to send + */ +static void +sa1100_uartkick(Uart *p) +{ + int i; + + R(p)->ctl[3] &= ~Tintena; + + if(p->cts == 0 || p->blocked) + return; + + /* + * 128 here is an arbitrary limit to make sure + * we don't stay in this loop too long. If the + * chips output queue is longer than 128, too + * bad -- presotto + */ + for(i = 0; i < 128; i++){ + if(!(R(p)->status[1] & Tnotfull)){ + R(p)->ctl[3] |= Tintena; + break; + } + if(p->op >= p->oe && uartstageoutput(p) == 0) + break; + R(p)->data = *p->op++; + } +} + +/* + * for iprint, just write it + */ +void +serialputs(char *str, int n) +{ + Uartregs *ur; + + ur = uart3regs; + while(n-- > 0){ + /* wait for output ready */ + while((ur->status[1] & Tnotfull) == 0) + ; + ur->data = *str++; + } + while((ur->status[1] & Tbusy)) + ; +} + +/* + * take an interrupt + */ +static void +sa1100_uartintr(Ureg*, void *x) +{ + Uart *p; + ulong s; + Uartregs *regs; + + p = x; + regs = p->regs; + + /* remember and reset interrupt causes */ + s = regs->status[0]; + regs->status[0] |= s; + + if(s & Tint){ + /* transmitter interrupt, restart */ + uartkick(p); + } + + /* receiver interrupt, snarf bytes */ + while(regs->status[1] & Rnotempty) + uartrecv(p, regs->data); + + if(s & (ParityError|FrameError|Overrun)){ + if(s & ParityError) + p->parity++; + if(s & FrameError) + p->frame++; + if(s & Overrun) + p->overrun++; + } +} + +typedef struct Gpclkregs Gpclkregs; +struct Gpclkregs +{ + ulong r0; + ulong r1; + ulong dummya; + ulong r2; + ulong r3; +}; + +enum +{ + /* gpclk register 0 */ + Gpclk_sus= 1<<0, /* set uart mode */ +}; + +Gpclkregs *gpclkregs; + +/* + * setup all uarts (called early by main() to allow debugging output to + * a serial port) + */ +void +sa1100_uartsetup(int console) +{ + Uart *p; + Uartregs *uartregs; + + /* external serial port (eia0) */ + uart3regs = mapspecial(UART3REGS, 64); + p = uartsetup(&sa1100_uart, uart3regs, ClockFreq, "serialport3"); + intrenable(IRQuart3, sa1100_uartintr, p, p->name); + + /* set eia0 up as a console */ + if(console) + uartspecial(p, 115200, &kbdq, &printq, kbdcr2nl); + + /* port for talking to microcontroller (eia1) */ + gpclkregs = mapspecial(GPCLKREGS, 64); + gpclkregs->r0 = Gpclk_sus; /* set uart mode */ + uartregs = mapspecial(UART1REGS, 64); + p = uartsetup(&sa1100_uart, uartregs, ClockFreq, "serialport1"); + sa1100_uartbaud(p, 115200); + intrenable(IRQuart1b, sa1100_uartintr, p, p->name); +} diff --git a/bitsy/screen.c b/bitsy/screen.c index 189138475f7d5ac930e21810d5679248b1ed6991..f5c5901763e6e29340b585ea835f1c0856b124a0 100644 --- a/bitsy/screen.c +++ b/bitsy/screen.c @@ -18,13 +18,13 @@ enum { Ht = 240, Pal0 = 0x2000, /* 16-bit pixel data in active mode (12 in passive) */ - hsw = 0x4, + hsw = 0x04, elw = 0x11, - blw = 0xc, + blw = 0x0c, - vsw = 0x3, - efw = 0x1, - bfw = 0xa, + vsw = 0x03, + efw = 0x01, + bfw = 0x0a, pcd = 0x10, }; @@ -93,16 +93,16 @@ enum { }; struct sa1110regs { - ulong lccr0; /* 0xb0100000 */ - ulong lcsr; /* 0xb0100004 */ - ulong dummies[2]; /* unused 0xb0100008 and 0xb010000c */ - short* dbar1; /* 0xb0100010 */ - ulong dcar1; /* 0xb0100014 */ - ulong dbar2; /* 0xb0100018 */ - ulong dcar2; /* 0xb010001c */ - ulong lccr1; /* 0xb0100020 */ - ulong lccr2; /* 0xb0100024 */ - ulong lccr3; /* 0xb0100028 */ + ulong lccr0; + ulong lcsr; + ulong dummies[2]; + short* dbar1; + ulong dcar1; + ulong dbar2; + ulong dcar2; + ulong lccr1; + ulong lccr2; + ulong lccr3; } *lcd; Point ZP = {0, 0}; @@ -127,16 +127,32 @@ Memimage *conscol; Memimage *back; Memimage *hwcursor; +static void +lcdstop(void) { + ulong lccr0; + + lcd->lccr0 &= ~(0<lcsr & LDD) == 0) + sleep(1); + lcdpower(0); +} + static void lcdinit(void) { - lcd = (struct sa1110regs*)0xb0100000; + /* map the lcd regs into the kernel's virtual space */ + lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));; + + /* the following works because main memory is direct mapped */ + lcd->lccr0 &= ~(0<lcsr & LDD) == 0) + sleep(1); lcd->dbar1 = framebuf->palette; - lcd->lccr3 = (pcd << PCD) | (0 << ACB) | (0 << API) | (1 << VSP) | (1 << HSP); - lcd->lccr2 = ((Ht-1) << LPP) | (vsw << VSW) | (efw << EFW) | (bfw << BFW); - lcd->lccr1 = (Wid << PPL) | (hsw << HSW) | (elw << ELW) | (blw << BLW); - lcd->lccr0 = 1<lccr3 = pcd<lccr2 = (Ht-1)<lccr1 = (Wid-16)<lccr0 = 1<palette, 0, sizeof framebuf->palette); + memset(framebuf->pixel, 0xf8, sizeof framebuf->pixel); framebuf->palette[0] = Pal0; + print("LCD status before power up: 0x%lux\n", lcd->lcsr); + lcdpower(1); + print("LCD status after power up: 0x%lux\n", lcd->lcsr); lcdinit(); + print("LCD status after lcdinit: 0x%lux\n", lcd->lcsr); gscreen = &xgscreen; gscreen->data = (struct Memdata *)framebuf->pixel; diff --git a/bitsy/screen.h b/bitsy/screen.h index 76f6cbb977ccb685b1c5523a043387e3f8804331..60c5240452fae1d36a8c1fde1d13da0d38035841 100644 --- a/bitsy/screen.h +++ b/bitsy/screen.h @@ -1,2 +1,3 @@ extern void blankscreen(int); extern void flushmemscreen(Rectangle); + diff --git a/bitsy/trap.c b/bitsy/trap.c index 54c24abb2e8a2698bc2997490a19897774e62a81..b5e6c89d841deb93bc5842fdeed0c30e8ffbb953 100644 --- a/bitsy/trap.c +++ b/bitsy/trap.c @@ -79,23 +79,30 @@ trapinit(void) void trapdump(char *tag) { - iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n", + print("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n", tag, intrregs->icip, intrregs->icmr, intrregs->iclr, intrregs->iccr, intrregs->icfp); } void -dumpregs(Ureg *ur) +warnregs(Ureg *ur, char *tag) { - iprint("r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n", + char buf[512]; + char *e = buf+sizeof(buf); + char *p; + + p = seprint(buf, e, "%s:\n", tag); + p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n", ur->r0, ur->r1, ur->r2, ur->r3); - iprint("r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n", + p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n", ur->r4, ur->r5, ur->r6, ur->r7); - iprint("r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n", + p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n", ur->r8, ur->r9, ur->r10, ur->r11); - iprint("r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n", + p = seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n", ur->r12, ur->r13, ur->r14); - iprint("type %.8lux psr %.8lux pc %.8lux\n", ur->type, ur->psr, ur->pc); + seprint(p, e, "type %.8lux psr %.8lux pc %.8lux\n", + ur->type, ur->psr, ur->pc); + print("%s", buf); } /* @@ -131,29 +138,36 @@ faultarm(Ureg *ureg, ulong va, int user, int read) insyscall = up->insyscall; up->insyscall = 1; -//peekmmu(va); n = fault(va, read); -//iprint("fault returns %d\n", n); if(n < 0){ if(!user){ - dumpregs(ureg); - panic("fault: 0x%lux\n", va); + warnregs(ureg, "kernel fault"); + panic("fault: kernel accessing 0x%lux\n", va); } - dumpregs(ureg); - sprint(buf, "sys: trap: fault %s va=0x%lux", - read? "read" : "write", va); +// warnregs(ureg, "user fault"); + sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va); postnote(up, 1, buf, NDebug); } up->insyscall = insyscall; } -/* all Pabt+1 faults are caused by loads or stores. The Lbit of - * the instruction distinquishes between them. +/* + * returns 1 if the instruction writes memory, 0 otherwise */ -enum +int +writetomem(ulong inst) { - Lbit = 1<<20, /* load instruction */ -}; + /* swap always write memory */ + if((inst & 0x0FC00000) == 0x01000000) + return 1; + + /* loads and stores are distinguished by bit 20 */ + if(inst & (1<<20)) + return 0; + + return 1; +} + /* * here on all exceptions other than syscall (SWI) @@ -179,18 +193,21 @@ trap(Ureg *ureg) else ureg->pc -= 4; + if((user && (ureg->r13 & 0xf0000000)) || (ureg->psr & 0x10) != 0x10){ + warnregs(ureg, "wierd ureg"); + panic("bad ureg\n"); + } + switch(ureg->type){ default: panic("unknown trap"); break; case PsrMabt: /* prefetch fault */ -print("%d: prefetch abort at 0x%lux\n", m->lastpid, ureg->pc); faultarm(ureg, ureg->pc, user, 1); break; case PsrMabt+1: /* data fault */ va = getfar(); inst = *(ulong*)(ureg->pc); -print("%d: data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", m->lastpid, ureg->pc, inst, va, getfsr()); switch(getfsr() & 0xf){ case 0x0: panic("vector exception at %lux\n", ureg->pc); @@ -218,21 +235,23 @@ print("%d: data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", m->lastpid, ure case 0x5: case 0x7: /* translation fault, i.e., no pte entry */ - faultarm(ureg, va, user, inst & Lbit); + faultarm(ureg, va, user, !writetomem(inst)); break; case 0x9: case 0xb: /* domain fault, accessing something we shouldn't */ if(user){ - sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); + sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", + ureg->pc, va); postnote(up, 1, buf, NDebug); } else - panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); + panic("kernel access violation: pc 0x%lux va 0x%lux\n", + ureg->pc, va); break; case 0xd: case 0xf: /* permission error, copy on write or real permission error */ - faultarm(ureg, va, user, inst & Lbit); + faultarm(ureg, va, user, !writetomem(inst)); break; } break; @@ -552,10 +571,11 @@ forkchild(Proc *p, Ureg *ureg) { Ureg *cureg; +//print("%lud setting up for forking child %lud\n", up->pid, p->pid); p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg); p->sched.pc = (ulong)forkret; - cureg = (Ureg*)(p->sched.sp+2*BY2WD); + cureg = (Ureg*)(p->sched.sp); memmove(cureg, ureg, sizeof(Ureg)); /* syscall returns 0 for child */ @@ -582,7 +602,7 @@ execregs(ulong entry, ulong ssize, ulong nargs) memset(ureg, 0, 15*sizeof(ulong)); ureg->r13 = (ulong)sp; ureg->pc = entry; -print("execregs pc 0x%lux sp 0x%lux\n", ureg->pc, ureg->r13); +//print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13); return USTKTOP-BY2WD; /* address of user-level clock */ } diff --git a/boot/local.c b/boot/local.c index 51e0319486923d85f853be766134af6096055bbe..1b633d38c80e42934bf519df5e0c14b95fac566b 100644 --- a/boot/local.c +++ b/boot/local.c @@ -4,6 +4,7 @@ static char diskname[2*NAMELEN]; static char *disk; +static char **args; void configlocal(Method *mp) @@ -56,12 +57,12 @@ authlocal(void) int connectlocal(void) { - int p[2]; + int i, p[2]; Dir dir; char d[DIRLEN]; char partition[2*NAMELEN]; char *dev; - char *args[16], **argp; + char **arg, **argp; if(stat("/kfs", d) < 0) return -1; @@ -87,17 +88,26 @@ connectlocal(void) case -1: fatal("fork"); case 0: - dup(p[0], 0); - dup(p[1], 1); - close(p[0]); - close(p[1]); - argp = args; + arg = malloc((bargc+5)*sizeof(char*)); + argp = arg; *argp++ = "kfs"; *argp++ = "-f"; *argp++ = partition; *argp++ = "-s"; + for(i=1; inopt; i++){ + if(cistrncmp(isa->opt[i], name, nl)==0 && isa->opt[i][nl] == '='){ + *reg = strtoul(isa->opt[i]+nl+1, nil, 16); + return 0; + } + } + return -1; +} + +/* + * Segment descriptors look like this. + * + * d1: [base 31:24] [gran] [is32bit] [0] [unused] [limit 19:16] + [present] [privlev] [type 3:0] [base 23:16] + * d0: [base 15:00] [limit 15:00] + * + * gran is 0 for 1-byte granularity, 1 for 4k granularity + * type is 0 for system segment, 1 for code/data. + * + * clearly we know way too much about the memory unit. + * + * what a crock. + */ +static void +setgdt(int sel, ulong base, ulong limit, int flag) +{ + if(sel < 0 || sel >= NGDT) + panic("setgdt"); + + base = (ulong)KADDR(base); + m->gdt[sel].d0 = (base<<16) | (limit&0xFFFF); + m->gdt[sel].d1 = (base&0xFF000000) | (limit&0x000F0000) | + ((base>>16)&0xFF) | SEGP | SEGPL(0) | flag; +} + +static void +loadgdt(void) +{ + ulong x; + ushort ptr[3]; + + ptr[0] = sizeof(m->gdt); + x = (ulong)m->gdt; + ptr[1] = x & 0xFFFF; + ptr[2] = (x>>16) & 0xFFFF; + lgdt(ptr); +} + +/* + * Must run before mmuinit, since we modify the GDT that + * we want the processor to inherit. I think (but am not sure) + * that we could run after mmuinit on processor 0 and just + * modify m->gdt and then call lgdt() as mmuinit() does, + * but this is a bit simpler and safer. + */ +static ulong ax, cx, dx, di, ebx, esi; +static Ureg apmu; +static long +apmread(Chan*, void *a, long n, vlong off) +{ + if(off < 0) + error("badarg"); + + if(n+off > sizeof apmu) + n = sizeof apmu - off; + if(n <= 0) + return 0; + memmove(a, (char*)&apmu+off, n); + return n; +} + +static long +apmwrite(Chan*, void *a, long n, vlong off) +{ + int s; + if(off || n != sizeof apmu){ +// if(n == 5 && strncmp(a, "ether", 5) == 0){ +// ether589reset(); +// return 5; +// } + error("write a Ureg"); + } + + memmove(&apmu, a, sizeof apmu); + s = splhi(); + apmfarcall(APMCSEL, ebx, &apmu); + splx(s); + return n; +} + +void +apmlink(void) +{ + ISAConf isa; + char *s; + + if(isaconfig("apm", 0, &isa) == 0) + return; + + /* + * APM info passed from boot loader. + * Now we need to set up the GDT entries for APM. + * + * AX = 32-bit code segment base address + * EBX = 32-bit code segment offset + * CX = 16-bit code segment base address + * DX = 32-bit data segment base address + * ESI = <16-bit code segment length> <32-bit code segment length> (hi then lo) + * DI = 32-bit data segment length + */ + + if(getreg(&ax, &isa, s="ax") < 0 + || getreg(&ebx, &isa, s="ebx") < 0 + || getreg(&cx, &isa, s="cx") < 0 + || getreg(&dx, &isa, s="dx") < 0 + || getreg(&esi, &isa, s="esi") < 0 + || getreg(&di, &isa, s="di") < 0){ + print("apm: missing register %s\n", s); + return; + } + + /* + * We are required by the BIOS to set up three consecutive segments, + * one for the APM 32-bit code, one for the APM 16-bit code, and + * one for the APM data. The BIOS handler uses the code segment it + * get called with to determine the other two segment selector. + */ + setgdt(APMCSEG, ax<<4, ((esi&0xFFFF)-1)&0xFFFF, SEGEXEC|SEGR|SEGD); + setgdt(APMCSEG16, cx<<4, ((esi>>16)-1)&0xFFFF, SEGEXEC|SEGR); + setgdt(APMDSEG, dx<<4, (di-1)&0xFFFF, SEGDATA|SEGW|SEGD); + loadgdt(); + + addarchfile("apm", 0660, apmread, apmwrite); + +print("apm0: configured cbase %.8lux off %.8lux\n", ax<<4, ebx); + + return; +} + diff --git a/pc/apmjump.s b/pc/apmjump.s new file mode 100644 index 0000000000000000000000000000000000000000..cc10db6b0fe44e38c8461ba07084d7b440052bee --- /dev/null +++ b/pc/apmjump.s @@ -0,0 +1,98 @@ +/* + * Far call, absolute indirect. + * The argument is the offset. + * We use a global structure for the jump params, + * so this is *not* reentrant or thread safe. + */ + +#include "mem.h" + +#define SSOVERRIDE BYTE $0x36 +#define CSOVERRIDE BYTE $0x2E +#define RETF BYTE $0xCB + +GLOBL apmjumpstruct+0(SB), $8 + +TEXT fortytwo(SB), $0 + MOVL $42, AX + RETF + +TEXT getcs(SB), $0 + PUSHL CS + POPL AX + RET + +TEXT apmfarcall(SB), $0 + /* + * We call push and pop ourselves. + * As soon as we do the first push or pop, + * we can't use FP anymore. + */ + MOVL off+4(FP), BX + MOVL seg+0(FP), CX + MOVL BX, apmjumpstruct+0(SB) + MOVL CX, apmjumpstruct+4(SB) + + /* load necessary registers from Ureg */ + MOVL ureg+8(FP), DI + MOVL 28(DI), AX + MOVL 16(DI), BX + MOVL 24(DI), CX + MOVL 20(DI), DX + + /* save registers, segments */ + PUSHL DS + PUSHL ES + PUSHL FS + PUSHL GS + PUSHL BP + PUSHL DI + + /* + * paranoia: zero the segments, since it's the + * BIOS's responsibility to initialize them. + * (trick picked up from Linux driver). + PUSHL DX + XORL DX, DX + PUSHL DX + POPL DS + PUSHL DX + POPL ES + PUSHL DX + POPL FS + PUSHL DX + POPL GS + POPL DX + */ + + PUSHL $APMDSEG + POPL DS + + /* + * The actual call. + */ + CSOVERRIDE; BYTE $0xFF; BYTE $0x1D + LONG $apmjumpstruct+0(SB) + + /* restore segments, registers */ + POPL DI + POPL BP + POPL GS + POPL FS + POPL ES + POPL DS + + PUSHFL + POPL 64(DI) + + /* store interesting registers back in Ureg */ + MOVL AX, 28(DI) + MOVL BX, 16(DI) + MOVL CX, 24(DI) + MOVL DX, 20(DI) + MOVL SI, 4(DI) + + PUSHFL + POPL AX + ANDL $1, AX /* carry flag */ + RET diff --git a/pc/dat.h b/pc/dat.h index 3156d8821105ffa56494df71ab37025956b9d7cf..29c17aa66115aca20289d18b710ee2ba8871b7ee 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -148,7 +148,7 @@ struct Mach ulong* pdb; /* page directory base for this processor (va) */ Tss* tss; /* tss for this processor */ - Segdesc gdt[6]; /* gdt for this processor */ + Segdesc gdt[NGDT]; /* gdt for this processor */ Proc* proc; /* current process on this processor */ Proc* externup; /* extern register Proc *up */ diff --git a/pc/devarch.c b/pc/devarch.c index 71a85f015e50c40beb28734cfdf13158ce3aeee1..047465b60bb77d1948f239ebca5cc6b7d7dcb475 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -7,7 +7,6 @@ #include "ureg.h" #include "../port/error.h" - typedef struct IOMap IOMap; struct IOMap { @@ -28,23 +27,68 @@ static struct } iomap; enum { - Qdir, - Qcputype, - Qioalloc, + Qdir = CHDIR, + Qioalloc = 0, Qiob, Qiow, Qiol, - Qirqalloc, + Qbase, + + Qmax = 16, }; -static Dirtab ioallocdir[] = { - "cputype", { Qcputype, 0 }, 0, 0444, +typedef long Rdwrfn(Chan*, void*, long, vlong); + +static Rdwrfn *readfn[Qmax]; +static Rdwrfn *writefn[Qmax]; + +static Dirtab archdir[Qmax] = { "ioalloc", { Qioalloc, 0 }, 0, 0444, "iob", { Qiob, 0 }, 0, 0660, "iow", { Qiow, 0 }, 0, 0660, "iol", { Qiol, 0 }, 0, 0660, - "irqalloc", { Qirqalloc, 0}, 0, 0444, }; +Lock archwlock; /* the lock is only for changing archdir */ +int narchdir = Qbase; + +/* + * Add a file to the #P listing. Once added, you can't delete it. + * You can't add a file with the same name as one already there, + * and you get a pointer to the Dirtab entry so you can do things + * like change the Qid version. Changing the Qid path is disallowed. + */ +Dirtab* +addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn) +{ + int i; + Dirtab d; + Dirtab *dp; + + memset(&d, 0, sizeof d); + strcpy(d.name, name); + d.perm = perm; + + lock(&archwlock); + if(narchdir >= Qmax){ + unlock(&archwlock); + return nil; + } + + for(i=0; itag[sizeof(m->tag)-1] = 0; *l = m; - ioallocdir[0].qid.vers++; + archdir[0].qid.vers++; unlock(&iomap); return m->start; @@ -139,7 +181,7 @@ iofree(int port) if((*l)->start > port) break; } - ioallocdir[0].qid.vers++; + archdir[0].qid.vers++; unlock(&iomap); } @@ -179,19 +221,19 @@ archattach(char* spec) int archwalk(Chan* c, char* name) { - return devwalk(c, name, ioallocdir, nelem(ioallocdir), devgen); + return devwalk(c, name, archdir, narchdir, devgen); } static void archstat(Chan* c, char* dp) { - devstat(c, dp, ioallocdir, nelem(ioallocdir), devgen); + devstat(c, dp, archdir, narchdir, devgen); } static Chan* archopen(Chan* c, int omode) { - return devopen(c, omode, ioallocdir, nelem(ioallocdir), devgen); + return devopen(c, omode, archdir, narchdir, devgen); } static void @@ -207,17 +249,17 @@ enum static long archread(Chan *c, void *a, long n, vlong offset) { - char *p; - IOMap *m; - char buf[Linelen+1]; + char buf[Linelen+1], *p; int port; ushort *sp; ulong *lp; + IOMap *m; + Rdwrfn *fn; - switch(c->qid.path & ~CHDIR){ + switch(c->qid.path){ case Qdir: - return devdirread(c, a, n, ioallocdir, nelem(ioallocdir), devgen); + return devdirread(c, a, n, archdir, narchdir, devgen); case Qiob: port = offset; @@ -249,13 +291,9 @@ archread(Chan *c, void *a, long n, vlong offset) case Qioalloc: break; - case Qirqalloc: - return irqallocread(a, n, offset); - - case Qcputype: - return cputyperead(a, n, offset); - default: + if(c->qid.path < narchdir && (fn = readfn[c->qid.path])) + return fn(c, a, n, offset); error(Eperm); break; } @@ -282,10 +320,11 @@ archread(Chan *c, void *a, long n, vlong offset) static long archwrite(Chan *c, void *a, long n, vlong offset) { + char *p; int port; ushort *sp; ulong *lp; - char *p; + Rdwrfn *fn; switch(c->qid.path & ~CHDIR){ @@ -317,6 +356,8 @@ archwrite(Chan *c, void *a, long n, vlong offset) return n*4; default: + if(c->qid.path < narchdir && (fn = writefn[c->qid.path])) + return fn(c, a, n, offset); error(Eperm); break; } @@ -537,7 +578,7 @@ cpuidentify(void) } static long -cputyperead(char *a, int n, ulong offset) +cputyperead(Chan*, void *a, long n, vlong offset) { char str[32]; ulong mhz; @@ -592,6 +633,8 @@ archinit(void) if(X86FAMILY(m->cpuidax) >= 5) coherence = wbflush; + + addarchfile("cputype", 0444, cputyperead, nil); } void diff --git a/pc/fns.h b/pc/fns.h index 465aae9db0c9b59a7175d57617955f981a921feb..a4bef2c02507cb5300330a7d4dbc6f7c10d017ea 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -2,6 +2,7 @@ void aamloop(int); void addconf(char*, char*); +Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); //void addscsilink(char*, Scsiio (*)(int, ISAConf*)); void archinit(void); void bootargs(ulong); @@ -59,7 +60,6 @@ void ioinit(void); int iounused(int, int); int ioalloc(int, int, int, char*); int iprint(char*, ...); -int irqallocread(char*, long, vlong); int isaconfig(char*, int, ISAConf*); void kbdinit(void); void lgdt(ushort[3]); diff --git a/pc/mem.h b/pc/mem.h index a655de52571759906d9626f78581dfa0ea24822c..382c086f10c2ef2323d2b5a884be4ddfc384c105 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -63,6 +63,11 @@ #define UDSEG 3 /* user data/stack */ #define UESEG 4 /* user executable */ #define TSSSEG 5 /* task segment */ +#define APMCSEG 6 /* APM code segment */ +#define APMCSEG16 7 /* APM 16-bit code segment */ +#define APMDSEG 8 /* APM data segment */ +#define NGDT 10 /* number of GDT entries required */ +/* #define APM40SEG 8 /* APM segment 0x40 */ #define SELGDT (0<<2) /* selector is in gdt */ #define SELLDT (1<<2) /* selector is in ldt */ @@ -75,6 +80,10 @@ #define UESEL SELECTOR(UESEG, SELGDT, 3) #define UDSEL SELECTOR(UDSEG, SELGDT, 3) #define TSSSEL SELECTOR(TSSSEG, SELGDT, 0) +#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0) +#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0) +#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0) +/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */ /* * fields in segment descriptors diff --git a/pc/trap.c b/pc/trap.c index 3928680ae6a1d560de5f84bf436db301da09da54..23c34de0df8b1799b5589d616b5d7b6c1c0def1c 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -50,19 +50,19 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) iunlock(&vctllock); } -int -irqallocread(char *buf, long n, vlong offset) +static long +irqallocread(Chan*, void *vbuf, long n, vlong offset) { - int vno; - Vctl *v; + char *buf, *p, str[11+1+NAMELEN+1]; + int m, vno; long oldn; - char str[11+1+NAMELEN+1], *p; - int m; + Vctl *v; if(n < 0 || offset < 0) error(Ebadarg); oldn = n; + buf = vbuf; for(vno=0; vnonext){ m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name); @@ -164,6 +164,8 @@ trapinit(void) trapenable(VectorPF, fault386, 0, "fault386"); nmienable(); + + addarchfile("irqalloc", 0444, irqallocread, nil); } static char* excname[32] = { diff --git a/port/log.c b/port/log.c index 529ac4d7d2eaa105c212b3ee23bea73580e220c9..8b724bb12293eec6bb9fabf4510783b58c8ba997 100644 --- a/port/log.c +++ b/port/log.c @@ -7,10 +7,6 @@ static char Ebadlogctl[] = "unknown log ctl message"; -enum { - Nlog = 4*1024, -}; - void logopen(Log *alog) { @@ -20,10 +16,15 @@ logopen(Log *alog) nexterror(); } if(alog->opens == 0){ + if(alog->nlog == 0) + alog->nlog = 4*1024; + if(alog->minread == 0) + alog->minread = 1; if(alog->buf == nil) - alog->buf = malloc(Nlog); + alog->buf = malloc(alog->nlog); alog->rptr = alog->buf; - alog->end = alog->buf + Nlog; + alog->end = alog->buf + alog->nlog; + alog->len = 0; } alog->opens++; unlock(alog); @@ -52,7 +53,7 @@ logready(void *a) { Log *alog = a; - return alog->len; + return alog->len >= alog->minread; } long @@ -69,7 +70,7 @@ logread(Log *alog, void *a, ulong, long n) for(;;){ lock(alog); - if(alog->len){ + if(alog->len >= alog->minread || alog->len >= n){ if(n > alog->len) n = alog->len; d = 0; @@ -132,24 +133,22 @@ logctl(Log *alog, int argc, char *argv[], Logflag *flags) } void -log(Log *alog, int mask, char *fmt, ...) +logn(Log *alog, int mask, void *buf, int n) { - char buf[128], *t, *fp; - int i, n; - va_list arg; + char *fp, *t; + int dowake, i; if(!(alog->logmask & mask)) return; - va_start(arg, fmt); - n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - if(alog->opens == 0) return; + if(n > alog->nlog) + return; + lock(alog); - i = alog->len + n - Nlog; + i = alog->len + n - alog->nlog; if(i > 0){ alog->len -= i; alog->rptr += i; @@ -164,7 +163,37 @@ log(Log *alog, int mask, char *fmt, ...) t = alog->buf + (t - alog->end); *t++ = *fp++; } + dowake = alog->len >= alog->minread; unlock(alog); - wakeup(&alog->readr); + if(dowake) + wakeup(&alog->readr); +} + +void +vlog(Log *alog, int mask, char *fmt, va_list arg) +{ + char buf[128]; + int n; + + if(!(alog->logmask & mask)) + return; + + if(alog->opens == 0) + return; + + n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; + + logn(alog, mask, buf, n); +} + +void +log(Log *alog, int mask, char *fmt, ...) +{ + va_list arg; + + va_start(arg, fmt); + vlog(alog, mask, fmt, arg); + va_end(arg); } + diff --git a/port/portdat.h b/port/portdat.h index 8c6924d87e1d7608bfacbd2baafdd75b36172bcd..2588522808a543bed45cd9d1eabf8a8460460c3b 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -698,6 +698,8 @@ struct Log { char *end; char *rptr; int len; + int nlog; + int minread; int logmask; /* mask of things to debug */ diff --git a/port/portfns.h b/port/portfns.h index a19151cc5cd68fe9451a7972848c5ba62c5a52a5..fd09446ff1966b0f90d789776ea12277b0e25ffd 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -153,8 +153,10 @@ void lockinit(void); void logopen(Log*); void logclose(Log*); char* logctl(Log*, int, char**, Logflag*); +void logn(Log*, int, void*, int); long logread(Log*, void*, ulong, long); void log(Log*, int, char*, ...); +void vlog(Log*, int, char*, va_list); Page* lookpage(Image*, ulong); void machinit(void); void* mallocz(ulong, int); diff --git a/port/proc.c b/port/proc.c index dec843f746709e658070ab7308f03ce9f6639d83..2aa7721edb5c9d43ad0e908de60bffb35f46b8c3 100644 --- a/port/proc.c +++ b/port/proc.c @@ -1056,6 +1056,7 @@ kproc(char *name, void (*func)(void *), void *arg) * any mmu info about this process is now stale * and has to be discarded. */ + p->newtlb = 1; flushmmu(); }