From 076532721ebfd039d0341a2ade6afe0c70079d10 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 12 Apr 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-04-12 --- bitsy/power.c | 4 +- bitsy/uartsa1110.c | 52 ++++++++++++----------- boot/boot.h | 3 ++ boot/paq.c | 67 ++++++++++++++++++++++++++++++ mtx/uarti8250.c | 72 ++++++++++++++------------------ pc/dat.h | 5 ++- pc/devarch.c | 67 ++++++++++++++++++++++++++---- pc/main.c | 5 ++- pc/mem.h | 100 ++++++++++++++++++++++++--------------------- pc/memory.c | 8 ++++ pc/mmu.c | 76 +++++++++++++++++++++++++++------- pc/mp.c | 8 +++- pc/trap.c | 9 +++- pc/uarti8250.c | 66 ++++++++++++------------------ port/devaudio.c | 18 ++++++++ port/devcons.c | 12 ++---- port/devuart.c | 38 +++++++++++++++++ port/portclock.c | 2 +- port/portdat.h | 4 ++ port/portfns.h | 5 ++- port/rdb.c | 2 +- port/sysproc.c | 14 +++++++ 22 files changed, 443 insertions(+), 194 deletions(-) create mode 100644 boot/paq.c diff --git a/bitsy/power.c b/bitsy/power.c index e982ba39491ade35b5dcf513e93bb81b3efb6bac..a3188036d0821f731ce1454a077f50a6d6356e33 100644 --- a/bitsy/power.c +++ b/bitsy/power.c @@ -286,12 +286,12 @@ idlehands(void) char *msga = "doze returns with splhi\n"; if(!islo()){ - serialputs(msga, strlen(msga)); + uartputs(msga, strlen(msga)); spllo(); } doze(); if(!islo()){ - serialputs(msgb, strlen(msgb)); + uartputs(msgb, strlen(msgb)); spllo(); } } diff --git a/bitsy/uartsa1110.c b/bitsy/uartsa1110.c index 6c297bab7b86f87de6f61a846dc7e46f208ccd62..1309f6066fd92b530419738fccc564cee98799d2 100644 --- a/bitsy/uartsa1110.c +++ b/bitsy/uartsa1110.c @@ -80,7 +80,6 @@ Uart sa1110uart[2] = { .special = 0, .next = nil, }, }; -static Uart* consuart; static Uart* µcuart; #define R(p) ((Uartregs*)((p)->regs)) @@ -381,6 +380,31 @@ sa1110_pnp(void) return sa1110uart; } +static int +sa1110_getc(Uart *uart) +{ + Uartregs *ur; + + ur = uart->regs; + while((ur->status[1] & Rnotempty) == 0) + ; + return ur->data; +} + +static void +sa1110_putc(Uart *uart, int c) +{ + Uartregs *ur; + + ur = uart->regs; + /* wait for output ready */ + while((ur->status[1] & Tnotfull) == 0) + ; + ur->data = c; + while((ur->status[1] & Tbusy)) + ; +} + PhysUart sa1110physuart = { .name= "sa1110", .pnp= sa1110_pnp, @@ -397,29 +421,10 @@ PhysUart sa1110physuart = { .dtr= sa1110_uartdtr, .status= sa1110_uartstatus, .power= sa1110_uartpower, + .getc= sa1110_getc, + .putc= sa1110_putc, }; -/* - * for iprint, just write it - */ -static void -sa1110puts(char *str, int n) -{ - Uartregs *ur; - - if(consuart == nil) - return; - ur = consuart->regs; - while(n-- > 0){ - /* wait for output ready */ - while((ur->status[1] & Tnotfull) == 0) - ; - ur->data = *str++; - } - while((ur->status[1] & Tbusy)) - ; -} - /* * for iprint, just write it */ @@ -465,10 +470,9 @@ sa1110_uartsetup(int console) /* set eia0 up as a console */ if(console){ uartctl(p, "b115200 l8 pn s1"); - consuart = p; (*p->phys->enable)(p, 0); - serialputs = sa1110puts; p->console = 1; + consuart = p; } intrenable(IRQ, IRQuart3, sa1110_uartintr, p, p->name); diff --git a/boot/boot.h b/boot/boot.h index 972176531cb1a5fa345e95567289c90fe468e2c2..6021220b614966dca398c35b2c5d2a060606d5ac 100644 --- a/boot/boot.h +++ b/boot/boot.h @@ -64,6 +64,9 @@ extern int connectlocal(void); extern void configsac(Method*); extern int connectsac(void); +extern void configpaq(Method*); +extern int connectpaq(void); + extern void configrc(Method*); extern int connectrc(void); diff --git a/boot/paq.c b/boot/paq.c new file mode 100644 index 0000000000000000000000000000000000000000..93101834061449addb8148e2ecb11879ddbe1311 --- /dev/null +++ b/boot/paq.c @@ -0,0 +1,67 @@ +#include +#include +#include <../boot/boot.h> + +char *fparts[] = +{ + "add bootldr 0x0000000 0x0040000", + "add params 0x0040000 0x0080000", + "add kernel 0x0080000 0x0140000", + "add user 0x0140000 0x0200000", + "add ramdisk 0x0200000 0x0800000", +}; + +void +configpaq(Method*) +{ + int fd; + int i; + + if(bind("#F", "/dev", MAFTER) < 0) + fatal("bind #c"); + if(bind("#p", "/proc", MREPL) < 0) + fatal("bind #p"); + fd = open("/dev/flash/flashctl", OWRITE); + if(fd < 0) + fatal("opening flashctl"); + for(i = 0; i < nelem(fparts); i++) + if(fprint(fd, fparts[i]) < 0) + fatal(fparts[i]); + close(fd); +} + +int +connectpaq(void) +{ + int p[2]; + char **arg, **argp; + + print("paq..."); + if(pipe(p)<0) + fatal("pipe"); + switch(fork()){ + case -1: + fatal("fork"); + case 0: + arg = malloc(10*sizeof(char*)); + argp = arg; + *argp++ = "paqfs"; + *argp++ = "-v"; + *argp++ = "-i"; + *argp++ = "/dev/flash/ramdisk"; + *argp = 0; + + dup(p[0], 0); + dup(p[1], 1); + close(p[0]); + close(p[1]); + exec("/paqfs", arg); + fatal("can't exec paqfs"); + default: + break; + } + waitpid(); + + close(p[1]); + return p[0]; +} diff --git a/mtx/uarti8250.c b/mtx/uarti8250.c index b2ca39d58a0a3a1f00f37dde8c9d5863308c41a3..ce68e686851fafdbdc332e0050b30cadee694c55 100644 --- a/mtx/uarti8250.c +++ b/mtx/uarti8250.c @@ -146,8 +146,6 @@ static Uart i8250uart[2] = { .next = nil, }, }; -static Uart* consuart; - #define csr8r(c, r) inb((c)->io+(r)) #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v)) @@ -560,6 +558,31 @@ i8250pnp(void) return i8250uart; } +static int +i8250getc(Uart *uart) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + while(!(csr8r(ctlr, Lsr)&Dr)) + delay(1); + return csr8r(ctlr, Rbr); +} + +static void +i8250putc(Uart *uart, int c) +{ + int i; + Ctlr *ctlr; + + ctlr = uart->regs; + for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) + delay(1); + outb(ctlr->io+Thr, c); + for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) + delay(1); +} + PhysUart i8250physuart = { .name = "i8250", .pnp = i8250pnp, @@ -576,44 +599,10 @@ PhysUart i8250physuart = { .dtr = i8250dtr, .status = i8250status, .fifo = i8250fifo, + .getc = i8250getc, + .putc = i8250putc, }; -int -serialgetc(void) -{ - return -1; -} - -static void -i8250putc(Ctlr* ctlr, int c) -{ - int i; - - for(i = 0; i < 128; i++){ - if(csr8r(ctlr, Lsr) & Thre) - break; - delay(1); - } - outb(ctlr->io+Thr, c); -} - -static void -i8250puts(char* s, int n) -{ - Ctlr *ctlr; - Uart *uart; - - if((uart = consuart) == nil) - return; - - ctlr = uart->regs; - while(n--){ - if(*s == '\n') - i8250putc(ctlr, '\r'); - i8250putc(ctlr, *s++); - } -} - void i8250console(void) { @@ -637,12 +626,11 @@ i8250console(void) break; } - if(*cmd == 0) - cmd = "b9600 l8 pn s1"; - uartctl(uart, cmd); + uartctl(uart, "b9600 l8 pn s1"); + if(*cmd != '\0') + uartctl(uart, cmd); (*uart->phys->enable)(uart, 0); consuart = uart; - serialputs = i8250puts; uart->console = 1; } diff --git a/pc/dat.h b/pc/dat.h index 33154eae2afaa4be9232120393e4155265128e64..a2ed325f79922b126faf8af8b584260971121900 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -147,12 +147,12 @@ struct Segdesc struct Mach { - int machno; /* physical id of processor */ + int machno; /* physical id of processor (KNOWN TO ASSEMBLY) */ ulong splpc; /* pc of last caller to splhi */ ulong* pdb; /* page directory base for this processor (va) */ Tss* tss; /* tss for this processor */ - Segdesc gdt[NGDT]; /* gdt for this processor */ + Segdesc *gdt; /* gdt for this processor */ Proc* proc; /* current process on this processor */ Proc* externup; /* extern register Proc *up */ @@ -191,6 +191,7 @@ struct Mach char cpuidid[16]; char* cpuidtype; int havetsc; + int havepge; vlong mtrrcap; vlong mtrrdef; diff --git a/pc/devarch.c b/pc/devarch.c index ad4f885cc3a7802d35f8ff8d25033692763ff024..7efbc53e0092a8b7b01fe7e1b02f91d3ab9a2ad1 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -623,26 +623,26 @@ cpuidentify(void) { char *p; int family, model, nomce; - X86type *t; + X86type *t, *tab; ulong cr4; vlong mca, mct; cpuid(m->cpuidid, &m->cpuidax, &m->cpuiddx); if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0) - t = x86amd; + tab = x86amd; else if(strncmp(m->cpuidid, "CentaurHauls", 12) == 0) - t = x86winchip; + tab = x86winchip; else - t = x86intel; + tab = x86intel; + family = X86FAMILY(m->cpuidax); model = X86MODEL(m->cpuidax); - while(t->name){ + for(t=tab; t->name; t++) if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; - t++; - } + m->cpuidtype = t->name; /* @@ -682,10 +682,31 @@ cpuidentify(void) rdmsr(0x01, &mct); } - if(t->family >= 6){ + /* + * Detect whether the chip supports the global bit + * in page directory and page table entries. When set + * in a particular entry, it means ``don't bother removing + * this from the TLB when CR3 changes.'' + * + * We flag all kernel pages with this bit. Doing so lessens the + * overhead of switching processes on bare hardware, + * even more so on VMware. See mmu.c:/^memglobal. + * + * This feature exists on Intel Pentium Pro and later + * processors. Presumably the AMD processors have + * a similar notion, but I can't find it in the meager + * documentation I've tried. + * + * For future reference, should we ever need to do a + * full TLB flush, it can be accomplished by clearing + * the PGE bit in CR4, writing to CR3, and then + * restoring the PGE bit. + */ + if(tab==x86intel && t->family >= 6){ cr4 = getcr4(); cr4 |= 0x80; /* page global enable bit */ putcr4(cr4); + m->havepge = 1; } cputype = t; @@ -704,6 +725,35 @@ cputyperead(Chan*, void *a, long n, vlong offset) return readstr(offset, a, n, str); } +static long +pgewrite(Chan*, void *a, long n, vlong) +{ + if(!m->havepge) + error("processor does not support pge"); + + if(n==3 && memcmp(a, "off", 3)==0){ + putcr4(getcr4() & ~0x80); + return n; + } + if(n==2 && memcmp(a, "on", 2)==0){ + putcr4(getcr4() | 0x80); + return n; + } + error("invalid control message"); + return -1; +} + +static long +pgeread(Chan*, void *a, long n, vlong offset) +{ + if(n < 16) + error("need more room"); + if(offset) + return 0; + n = snprint(a, n, "%s pge; %s", m->havepge ? "have" : "no", getcr4()&0x80 ? "on" : "off"); + return n; +} + void archinit(void) { @@ -742,6 +792,7 @@ archinit(void) conf.copymode = 1; addarchfile("cputype", 0444, cputyperead, nil); + addarchfile("pge", 0664, pgeread, pgewrite); } /* diff --git a/pc/main.c b/pc/main.c index 99d72c64f89ce70f2cb20531fb81dc735097c1e4..a974090fabe25666aa71145cb548d28ec2170d3c 100644 --- a/pc/main.c +++ b/pc/main.c @@ -117,6 +117,7 @@ mach0init(void) conf.nmach = 1; MACHP(0) = (Mach*)CPU0MACH; m->pdb = (ulong*)CPU0PDB; + m->gdt = (Segdesc*)CPU0GDT; machinit(); @@ -129,12 +130,15 @@ machinit(void) { int machno; ulong *pdb; + Segdesc *gdt; machno = m->machno; pdb = m->pdb; + gdt = m->gdt; memset(m, 0, sizeof(Mach)); m->machno = machno; m->pdb = pdb; + m->gdt = gdt; /* * For polled uart output at boot, need @@ -561,7 +565,6 @@ procsave(Proc *p) } /* - * Switch to the prototype page tables for this processor. * While this processor is in the scheduler, the process could run * on another processor and exit, returning the page tables to * the free list where they could be reallocated and overwritten. diff --git a/pc/mem.h b/pc/mem.h index 0f7ec98bbc2977922c37993751edcab1aa36caaf..a41890daf6d190289f1cd0f82c25a2c83d9b654d 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -6,18 +6,18 @@ * Sizes */ #define BI2BY 8 /* bits per byte */ -#define BI2WD 32 /* bits per word */ +#define BI2WD 32 /* bits per word */ #define BY2WD 4 /* bytes per word */ #define BY2V 8 /* bytes per double word */ #define BY2PG 4096 /* bytes per page */ #define WD2PG (BY2PG/BY2WD) /* words per page */ #define PGSHIFT 12 /* log(BY2PG) */ -#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) -#define PGROUND(s) ROUND(s, BY2PG) -#define BLOCKALIGN 8 +#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) +#define PGROUND(s) ROUND(s, BY2PG) +#define BLOCKALIGN 8 #define MAXMACH 8 /* max # cpus system can run */ -#define KSTACK 4096 /* Size of kernel stack */ +#define KSTACK 4096 /* Size of kernel stack */ /* * Time @@ -29,15 +29,21 @@ /* * Fundamental addresses */ -#define IDTADDR 0x80000800 /* idt */ +#define IDTADDR 0x80000800 /* idt */ #define REBOOTADDR 0x00001000 /* reboot code - physical address */ -#define APBOOTSTRAP 0x80001000 /* AP bootstrap code */ -#define CONFADDR 0x80001200 /* info passed from boot loader */ -#define CPU0PDB 0x80002000 /* bootstrap processor PDB */ -#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-4MB */ -#define MACHADDR 0x80004000 /* as seen by current processor */ -#define CPU0MACH 0x80005000 /* Mach for bootstrap processor */ +#define APBOOTSTRAP 0x80001000 /* AP bootstrap code */ +#define CONFADDR 0x80001200 /* info passed from boot loader */ +#define CPU0PDB 0x80002000 /* bootstrap processor PDB */ +#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-4MB */ +#define CPU0GDT 0x80004000 /* bootstrap processor GDT */ +#define MACHADDR 0x80005000 /* as seen by current processor */ +#define CPU0MACH 0x80006000 /* Mach for bootstrap processor */ #define MACHSIZE BY2PG +/* + * N.B. ramscan knows that CPU0MACH+BY2PG is the end of reserved data + * N.B. _start0x00100020 knows that CPU0PDB is the first reserved page + * and that there are 5 of them. + */ /* * Address spaces @@ -52,7 +58,7 @@ #define USTKTOP (KZERO-BY2PG) /* byte just beyond user stack */ #define USTKSIZE (16*1024*1024) /* size of user stack */ #define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */ -#define TSTKSIZ 100 +#define TSTKSIZ 100 /* * known x86 segments (in GDT) and their selectors @@ -62,57 +68,57 @@ #define KESEG 2 /* kernel executable */ #define UDSEG 3 /* user data/stack */ #define UESEG 4 /* user executable */ -#define TSSSEG 5 /* task segment */ +#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 NGDT 10 /* number of GDT entries required */ /* #define APM40SEG 8 /* APM segment 0x40 */ -#define SELGDT (0<<2) /* selector is in gdt */ +#define SELGDT (0<<2) /* selector is in gdt */ #define SELLDT (1<<2) /* selector is in ldt */ -#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) +#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) -#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) -#define KDSEL SELECTOR(KDSEG, SELGDT, 0) -#define KESEL SELECTOR(KESEG, SELGDT, 0) -#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) */ +#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) +#define KDSEL SELECTOR(KDSEG, SELGDT, 0) +#define KESEL SELECTOR(KESEG, SELGDT, 0) +#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 */ -#define SEGDATA (0x10<<8) /* data/stack segment */ -#define SEGEXEC (0x18<<8) /* executable segment */ +#define SEGDATA (0x10<<8) /* data/stack segment */ +#define SEGEXEC (0x18<<8) /* executable segment */ #define SEGTSS (0x9<<8) /* TSS segment */ -#define SEGCG (0x0C<<8) /* call gate */ +#define SEGCG (0x0C<<8) /* call gate */ #define SEGIG (0x0E<<8) /* interrupt gate */ -#define SEGTG (0x0F<<8) /* trap gate */ -#define SEGTYPE (0x1F<<8) +#define SEGTG (0x0F<<8) /* trap gate */ +#define SEGTYPE (0x1F<<8) -#define SEGP (1<<15) /* segment present */ -#define SEGPL(x) ((x)<<13) /* priority level */ -#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ -#define SEGG (1<<23) /* granularity 1==4k (for other) */ -#define SEGE (1<<10) /* expand down */ -#define SEGW (1<<9) /* writable (for data/stack) */ +#define SEGP (1<<15) /* segment present */ +#define SEGPL(x) ((x)<<13) /* priority level */ +#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ +#define SEGG (1<<23) /* granularity 1==4k (for other) */ +#define SEGE (1<<10) /* expand down */ +#define SEGW (1<<9) /* writable (for data/stack) */ #define SEGR (1<<9) /* readable (for code) */ -#define SEGD (1<<22) /* default 1==32bit (for code) */ +#define SEGD (1<<22) /* default 1==32bit (for code) */ /* * virtual MMU */ -#define PTEMAPMEM (1024*1024) +#define PTEMAPMEM (1024*1024) #define PTEPERTAB (PTEMAPMEM/BY2PG) -#define SEGMAPSIZE 1984 -#define SSEGMAPSIZE 16 -#define PPN(x) ((x)&~(BY2PG-1)) +#define SEGMAPSIZE 1984 +#define SSEGMAPSIZE 16 +#define PPN(x) ((x)&~(BY2PG-1)) /* * physical MMU @@ -120,7 +126,7 @@ #define PTEVALID (1<<0) #define PTEWT (1<<3) #define PTEUNCACHED (1<<4) -#define PTEWRITE (1<<1) +#define PTEWRITE (1<<1) #define PTERONLY (0<<1) #define PTEKERNEL (0<<2) #define PTEUSER (1<<2) @@ -131,7 +137,7 @@ * Macros for calculating offsets within the page directory base * and page tables. */ -#define PDX(va) ((((ulong)(va))>>22) & 0x03FF) -#define PTX(va) ((((ulong)(va))>>12) & 0x03FF) +#define PDX(va) ((((ulong)(va))>>22) & 0x03FF) +#define PTX(va) ((((ulong)(va))>>12) & 0x03FF) -#define getpgcolor(a) 0 +#define getpgcolor(a) 0 diff --git a/pc/memory.c b/pc/memory.c index df86e096aade94efbcc3fc136990c1ee654e2848..e3f77f83b12f20bba0b9afdf6594b5da99072ae1 100644 --- a/pc/memory.c +++ b/pc/memory.c @@ -425,6 +425,14 @@ ramscan(ulong maxmem) mmuflushtlb(PADDR(m->pdb)); x += 0x3141526; } + + /* + * If we didn't reach the end of the 4MB chunk, that part won't + * be mapped. Commit the already initialised space for the page table. + */ + if(pa % (4*MB)) + map = 0; + if(map) mapfree(&rmapram, map, BY2PG); if(pa < maxmem) diff --git a/pc/mmu.c b/pc/mmu.c index d72fe7e81b1f097b4888389f93d7159a57fd7e23..3e7080e8a9152181e7a33dd91c465195b69e9e95 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -36,19 +36,45 @@ taskswitch(ulong pdb, ulong stack) putcr3(pdb); } -void -gdtinit(void) +/* + * On processors that support it, we set the PTEGLOBAL bit in + * page table and page directory entries that map kernel memory. + * Doing this tells the processor not to bother flushing them + * from the TLB when doing the TLB flush associated with a + * context switch (write to CR3). Since kernel memory mappings + * are never removed, this is safe. (If we ever remove kernel memory + * mappings, we can do a full flush by turning off the PGE bit in CR4, + * writing to CR3, and then turning the PGE bit back on.) + * + * See also mmukmap below. + * + * Processor support for the PTEGLOBAL bit is enabled in devarch.c. + */ +static void +memglobal(void) { - ulong x; - ushort ptr[3]; - - memmove(m->gdt, gdt, sizeof(m->gdt)); - - ptr[0] = sizeof(m->gdt)-1; - x = (ulong)m->gdt; - ptr[1] = x & 0xFFFF; - ptr[2] = (x>>16) & 0xFFFF; - lgdt(ptr); + int i, j; + ulong *pde, *pte; + + /* only need to do this once, on bootstrap processor */ + if(m->machno != 0) + return; + + if(!m->havepge) + return; + + pde = m->pdb; + for(i=512; i<1024; i++){ /* 512: start at entry for virtual 0x80000000 */ + if(pde[i] & PTEVALID){ + pde[i] |= PTEGLOBAL; + if(!(pde[i] & PTESIZE)){ + pte = KADDR(pde[i]&~(BY2PG-1)); + for(j=0; j<1024; j++) + if(pte[j] & PTEVALID) + pte[j] |= PTEGLOBAL; + } + } + } } void @@ -57,15 +83,27 @@ mmuinit(void) ulong x, *p; ushort ptr[3]; + memglobal(); + m->tss = malloc(sizeof(Tss)); memset(m->tss, 0, sizeof(Tss)); - memmove(m->gdt, gdt, sizeof(m->gdt)); + /* + * We used to keep the GDT in the Mach structure, but it + * turns out that that slows down access to the rest of the + * page. Since the Mach structure is accessed quite often, + * it pays off anywhere from a factor of 1.25 to 2 on real + * hardware to separate them (the AMDs are more sensitive + * than Intels in this regard). Under VMware it pays off + * a factor of about 10 to 100. + */ + + memmove(m->gdt, gdt, sizeof gdt); x = (ulong)m->tss; m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; - ptr[0] = sizeof(m->gdt)-1; + ptr[0] = sizeof(gdt)-1; x = (ulong)m->gdt; ptr[1] = x & 0xFFFF; ptr[2] = (x>>16) & 0xFFFF; @@ -395,14 +433,24 @@ mmukmap(ulong pa, ulong va, int size) * starts on a 4MB boundary, size >= 4MB and processor can do it. * If not a big page, walk the walk, talk the talk. * Sync is set. + * + * If we're creating a kernel mapping, we know that it will never + * expire and thus we can set the PTEGLOBAL bit to make the entry + * persist in the TLB across flushes. If we do add support later for + * unmapping kernel addresses, see devarch.c for instructions on + * how to do a full TLB flush. */ if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){ *table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID; + if((va&KZERO) && m->havepge) + *table |= PTEGLOBAL; pgsz = 4*MB; } else{ pte = mmuwalk(mach0->pdb, va, 2, 1); *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID; + if((va&KZERO) && m->havepge) + *pte |= PTEGLOBAL; pgsz = BY2PG; } pa += pgsz; diff --git a/pc/mp.c b/pc/mp.c index fa5094f6246d03d61741ca5374a31cc745fd909c..720c561390cd95efa2e583575a30ef7851264711 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -390,7 +390,7 @@ mpstartap(Apic* apic) * the PTE for the Mach structure. * Xspanalloc will panic if an allocation can't be made. */ - p = xspanalloc(3*BY2PG, BY2PG, 0); + p = xspanalloc(4*BY2PG, BY2PG, 0); pdb = (ulong*)p; memmove(pdb, mach0->pdb, BY2PG); p += BY2PG; @@ -399,17 +399,23 @@ mpstartap(Apic* apic) return; memmove(p, KADDR(PPN(*pte)), BY2PG); *pte = PADDR(p)|PTEWRITE|PTEVALID; + if(mach0->havepge) + *pte |= PTEGLOBAL; p += BY2PG; mach = (Mach*)p; if((pte = mmuwalk(pdb, MACHADDR, 2, 0)) == nil) return; *pte = PADDR(mach)|PTEWRITE|PTEVALID; + if(mach0->havepge) + *pte |= PTEGLOBAL; + p += BY2PG; machno = apic->machno; MACHP(machno) = mach; mach->machno = machno; mach->pdb = pdb; + mach->gdt = (Segdesc*)p; /* filled by mmuinit */ /* * Tell the AP where its kernel vector and pdb are. diff --git a/pc/trap.c b/pc/trap.c index 3064eb4867205144e50fe8c55f0515b6f15e86dd..b6c8157fada15db19aac5eca5e11424b2f77b8a6 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -439,10 +439,15 @@ _dumpstack(Ureg *ureg) print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp); i = 0; - if(up) + if(up + && (ulong)&l >= (ulong)up->kstack + && (ulong)&l <= (ulong)up->kstack+KSTACK) estack = (ulong)up->kstack+KSTACK; - else + else if((ulong)&l >= (ulong)m->stack + && (ulong)&l <= (ulong)m+BY2PG) estack = (ulong)m+MACHSIZE; + else + return; for(l=(ulong)&l; lio+(r)) #define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v)) @@ -597,6 +595,31 @@ i8250pnp(void) return i8250uart; } +static int +i8250getc(Uart *uart) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + while(!(csr8r(ctlr, Lsr)&Dr)) + delay(1); + return csr8r(ctlr, Rbr); +} + +static void +i8250putc(Uart *uart, int c) +{ + int i; + Ctlr *ctlr; + + ctlr = uart->regs; + for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) + delay(1); + outb(ctlr->io+Thr, c); + for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) + delay(1); +} + PhysUart i8250physuart = { .name = "i8250", .pnp = i8250pnp, @@ -613,44 +636,10 @@ PhysUart i8250physuart = { .dtr = i8250dtr, .status = i8250status, .fifo = i8250fifo, + .getc = i8250getc, + .putc = i8250putc, }; -int -serialgetc(void) -{ - return -1; -} - -static void -i8250putc(Ctlr* ctlr, int c) -{ - int i; - - for(i = 0; i < 128; i++){ - if(csr8r(ctlr, Lsr) & Thre) - break; - delay(1); - } - outb(ctlr->io+Thr, c); -} - -static void -i8250puts(char* s, int n) -{ - Ctlr *ctlr; - Uart *uart; - - if((uart = consuart) == nil) - return; - - ctlr = uart->regs; - while(n--){ - if(*s == '\n') - i8250putc(ctlr, '\r'); - i8250putc(ctlr, *s++); - } -} - void i8250console(void) { @@ -680,6 +669,5 @@ i8250console(void) (*uart->phys->enable)(uart, 0); consuart = uart; - serialputs = i8250puts; uart->console = 1; } diff --git a/port/devaudio.c b/port/devaudio.c index 67f8c2453172b75bd0bdb9fd2443aca0ca6c6ec9..1146dea816488253a4716e1e963d9a856a3ebe89 100644 --- a/port/devaudio.c +++ b/port/devaudio.c @@ -745,6 +745,17 @@ audioinit(void) print("#A: bad port 0x%lux\n", sbconf.port); return; } + + if(ioalloc(sbconf.port, 0x10, 0, "audio") < 0){ + print("#A: cannot ioalloc range %x+0x10\n", sbconf.port); + return; + } + if(ioalloc(sbconf.port+0x100, 1, 0, "audio.mpu401") < 0){ + iofree(sbconf.port); + print("#A: cannot ioalloc range %x+0x01\n", sbconf.port+0x100); + return; + } + switch(sbconf.irq){ case 2: case 5: @@ -754,6 +765,8 @@ audioinit(void) break; default: print("#A: bad irq %lud\n", sbconf.irq); + iofree(sbconf.port); + iofree(sbconf.port+0x100); return; } @@ -783,6 +796,8 @@ audioinit(void) i = sbread(); if(i != 0xaa) { print("#A: no response #%.2x\n", i); + iofree(sbconf.port); + iofree(sbconf.port+0x100); return; } @@ -794,6 +809,8 @@ audioinit(void) if(audio.major != 3 || audio.minor != 1 || ess1688(&sbconf)){ print("#A: model 0x%.2x 0x%.2x; not SB 16 compatible\n", audio.major, audio.minor); + iofree(sbconf.port); + iofree(sbconf.port+0x100); return; } audio.major = 4; @@ -821,6 +838,7 @@ audioinit(void) (sbconf.irq==9)? 1: (sbconf.irq==10)? 8: 0); + mxcmd(0x81, 1<phys->getc == nil) + return -1; + return consuart->phys->getc(consuart); +} + +void +uartputc(int c) +{ + if(consuart == nil || consuart->phys->putc == nil) + return; + consuart->phys->putc(consuart, c); +} + +void +uartputs(char *s, int n) +{ + char *e; + + if(consuart == nil || consuart->phys->putc == nil) + return; + + e = s+n; + for(; sphys->putc(consuart, '\r'); + consuart->phys->putc(consuart, *s); + } +} diff --git a/port/portclock.c b/port/portclock.c index 611bba9fc95b2fe3e6fa6cf310e45e0295b4b324..fcdde883ccacf2700ed41e0f341cbbf663ee62c7 100644 --- a/port/portclock.c +++ b/port/portclock.c @@ -127,7 +127,7 @@ hzclock(Ureg *ur) if(up == 0 || up->state != Running) return; - // i.e. don't schedule an EDF process here! + /* i.e. don't deschedule an EDF process here! */ if(anyready() && !isedf(up)){ sched(); splhi(); diff --git a/port/portdat.h b/port/portdat.h index 9d746f3b499217152ee4ee99102d7db59b224b9d..d3d61cd47f7599f4d0f8eeb68a703404939591c3 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -766,6 +766,8 @@ struct PhysUart long (*status)(Uart*, void*, long, long); void (*fifo)(Uart*, int); void (*power)(Uart*, int); + int (*getc)(Uart*); /* polling versions, for iprint, rdb */ + void (*putc)(Uart*, int); }; enum { @@ -828,6 +830,8 @@ struct Uart Rendez r; }; +extern Uart* consuart; + /* * fasttick timer interrupts (Dummy for now) */ diff --git a/port/portfns.h b/port/portfns.h index a5275b41a07b7039e866939583a5dd9913c51376..27aae6fd9fda94e7481dd6ef0c49b90cdb30e5fd 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -307,8 +307,6 @@ long seconds(void); ulong segattach(Proc*, ulong, char *, ulong, ulong); void segclock(ulong); void segpage(Segment*, Page*); -int serialgetc(void); -void (*serialputs)(char*, int); int setcolor(ulong, ulong, ulong, ulong); void setkernur(Ureg*, Proc*); int setlabel(Label*); @@ -340,7 +338,10 @@ void todset(vlong, vlong, int); Block* trimblock(Block*, int, int); void tsleep(Rendez*, int (*)(void*), void*, int); int uartctl(Uart*, char*); +int uartgetc(void); void uartkick(void*); +void uartputc(int); +void uartputs(char*, int); void uartrecv(Uart*, char); Uart* uartsetup(Uart*); int uartstageoutput(Uart*); diff --git a/port/rdb.c b/port/rdb.c index ff5c6487d44427ea5a69ec0a3762cca365432d82..5d0d848d910763a78f97034716378a451b7def71 100644 --- a/port/rdb.c +++ b/port/rdb.c @@ -30,7 +30,7 @@ getline(void) int i, c; for(;;){ - for(i=0; i 0) + return incref(&sysr1ref); + if(a < 0) + return decref(&sysr1ref); + return sysr1ref.ref; + +/* extern int chandebug; extern void dumpmount(void); @@ -21,6 +34,7 @@ sysr1(ulong *arg) dumpmount(); return 0; +*/ } long