diff options
author | Alex Musolino <alex@musolino.id.au> | 2020-12-15 20:55:41 +1030 |
---|---|---|
committer | Alex Musolino <alex@musolino.id.au> | 2020-12-15 20:55:41 +1030 |
commit | 3749e92cdb88a157f99c0709a264bd508603be9b (patch) | |
tree | 49ce703965ba4114490729c5aeabd9ba120d9b78 /sys/src | |
parent | 404c901f299c4d93cb159a3c44c2977a25408319 (diff) | |
parent | 32291b52bcbd6976051acff1692b571e321ac859 (diff) |
merge
Diffstat (limited to 'sys/src')
109 files changed, 2450 insertions, 2074 deletions
diff --git a/sys/src/9/pc/cputemp.c b/sys/src/9/pc/cputemp.c index 1ffbeb08b..40e1d6b12 100644 --- a/sys/src/9/pc/cputemp.c +++ b/sys/src/9/pc/cputemp.c @@ -13,7 +13,7 @@ intelcputempok(void) if(m->cpuiddx & Acpif) if(strcmp(m->cpuidid, "GenuineIntel") == 0){ - cpuid(6, regs); + cpuid(6, 0, regs); return regs[0] & 1; } return 0; @@ -28,7 +28,7 @@ cputemprd0(Chan*, void *a, long n, vlong offset) ulong regs[4]; static ulong tj; - cpuid(6, regs); + cpuid(6, 0, regs); if((regs[0] & 1) == 0) goto unsup; if(tj == 0){ diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 644fab2a8..6d1ff430e 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -250,7 +250,7 @@ struct Mach int pdbfree; u32int dr7; /* shadow copy of dr7 */ - + u32int xcr0; void* vmx; int stack[1]; diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 6617d3e7b..4058808f5 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -18,11 +18,6 @@ enum { Qmax = 32, }; -enum { - CR4Osfxsr = 1 << 9, - CR4Oxmmex = 1 << 10, -}; - enum { /* cpuid standard function codes */ Highstdfunc = 0, /* also returns vendor string */ Procsig, @@ -496,24 +491,27 @@ cpuidprint(void) * (if so turn it on) * - whether or not it supports the page global flag * (if so turn it on) + * - detect PAT feature and add write-combining entry + * - detect MTRR support and synchronize state with cpu0 + * - detect NX support and enable it for AMD64 + * - detect watchpoint support + * - detect FPU features and enable the FPU */ int cpuidentify(void) { - char *p; - int family, model, nomce; + int family, model; X86type *t, *tab; - uintptr cr4; ulong regs[4]; - vlong mca, mct, pat; + uintptr cr4; - cpuid(Highstdfunc, regs); + cpuid(Highstdfunc, 0, regs); memmove(m->cpuidid, ®s[1], BY2WD); /* bx */ memmove(m->cpuidid+4, ®s[3], BY2WD); /* dx */ memmove(m->cpuidid+8, ®s[2], BY2WD); /* cx */ m->cpuidid[12] = '\0'; - cpuid(Procsig, regs); + cpuid(Procsig, 0, regs); m->cpuidax = regs[0]; m->cpuidcx = regs[2]; m->cpuiddx = regs[3]; @@ -572,14 +570,13 @@ cpuidentify(void) * If machine check was enabled clear out any lingering status. */ if(m->cpuiddx & (Pge|Mce|Pse)){ + vlong mca, mct; + cr4 = getcr4(); if(m->cpuiddx & Pse) cr4 |= 0x10; /* page size extensions */ - if(p = getconf("*nomce")) - nomce = strtoul(p, 0, 0); - else - nomce = 0; - if((m->cpuiddx & Mce) != 0 && !nomce){ + + if((m->cpuiddx & Mce) != 0 && getconf("*nomce") == nil){ if((m->cpuiddx & Mca) != 0){ vlong cap; int bank; @@ -631,7 +628,6 @@ cpuidentify(void) cr4 |= 0x80; /* page global enable bit */ m->havepge = 1; } - putcr4(cr4); if((m->cpuiddx & (Mca|Mce)) == Mce) @@ -640,25 +636,20 @@ cpuidentify(void) #ifdef PATWC /* IA32_PAT write combining */ - if((m->cpuiddx & Pat) != 0 && rdmsr(0x277, &pat) != -1){ - pat &= ~(255LL<<(PATWC*8)); - pat |= 1LL<<(PATWC*8); /* WC */ - wrmsr(0x277, pat); + if((m->cpuiddx & Pat) != 0){ + vlong pat; + + if(rdmsr(0x277, &pat) != -1){ + pat &= ~(255LL<<(PATWC*8)); + pat |= 1LL<<(PATWC*8); /* WC */ + wrmsr(0x277, pat); + } } #endif - if(m->cpuiddx & Mtrr) + if((m->cpuiddx & Mtrr) != 0 && getconf("*nomtrr") == nil) mtrrsync(); - if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ - fpsave = fpssesave; - fprestore = fpsserestore; - putcr4(getcr4() | CR4Osfxsr|CR4Oxmmex); - } else { - fpsave = fpx87save; - fprestore = fpx87restore; - } - if(strcmp(m->cpuidid, "GenuineIntel") == 0 && (m->cpuidcx & Rdrnd) != 0) hwrandbuf = rdrandbuf; else @@ -669,9 +660,9 @@ cpuidentify(void) m->havewatchpt8 = 1; /* check and enable NX bit */ - cpuid(Highextfunc, regs); + cpuid(Highextfunc, 0, regs); if(regs[0] >= Procextfeat){ - cpuid(Procextfeat, regs); + cpuid(Procextfeat, 0, regs); if((regs[3] & (1<<20)) != 0){ vlong efer; @@ -689,14 +680,16 @@ cpuidentify(void) || family == 6 && (model == 15 || model == 23 || model == 28)) m->havewatchpt8 = 1; /* Intel SDM claims amd64 support implies 8-byte watchpoint support */ - cpuid(Highextfunc, regs); + cpuid(Highextfunc, 0, regs); if(regs[0] >= Procextfeat){ - cpuid(Procextfeat, regs); + cpuid(Procextfeat, 0, regs); if((regs[3] & 1<<29) != 0) m->havewatchpt8 = 1; } } + fpuinit(); + cputype = t; return t->family; } diff --git a/sys/src/9/pc/devvmx.c b/sys/src/9/pc/devvmx.c index 407862731..ba6f596e7 100644 --- a/sys/src/9/pc/devvmx.c +++ b/sys/src/9/pc/devvmx.c @@ -44,6 +44,7 @@ enum { PROCB_CTLS = 0x4002, PROCB_IRQWIN = 1<<2, + PROCB_TSCOFFSET = 1<<3, PROCB_EXITHLT = 1<<7, PROCB_EXITINVLPG = 1<<9, PROCB_EXITMWAIT = 1<<10, @@ -100,6 +101,7 @@ enum { VMENTRY_INTRCODE = 0x4018, VMENTRY_INTRILEN = 0x401a, + VMCS_TSC_OFFSET = 0x2010, VMCS_LINK = 0x2800, GUEST_ES = 0x800, @@ -264,7 +266,9 @@ struct Vmx { int index, machno; char errstr[ERRMAX]; Ureg ureg; + uvlong tscoffset; uintptr cr2; + uintptr xcr0; uintptr dr[8]; /* DR7 is also kept in VMCS */ u8int launched; u8int vpid; @@ -484,6 +488,13 @@ dr7write(Vmx *vmx, char *s) } static int +xcr0write(Vmx *vmx, char *s) +{ + vmx->xcr0 = parseval(s) & 7; + return 0; +} + +static int readonly(Vmx *, char *) { return -1; @@ -581,6 +592,7 @@ static GuestReg guestregs[] = { {VMXVAR(dr[2]), 0, "dr2"}, {VMXVAR(dr[3]), 0, "dr3"}, {VMXVAR(dr[6]), 0, "dr6", nil, dr6write}, + {VMXVAR(xcr0), 0, "xcr0", nil, xcr0write}, {GUEST_DR7, 0, "dr7", nil, dr7write}, {VM_INSTRERR, 4, "instructionerror", nil, readonly}, {VM_EXREASON, 4, "exitreason", nil, readonly}, @@ -857,7 +869,7 @@ vmxreset(void) vlong msr; int i; - cpuid(1, regs); + cpuid(1, 0, regs); if((regs[2] & 1<<5) == 0) return; /* check if disabled by BIOS */ if(rdmsr(0x3a, &msr) < 0) return; @@ -945,8 +957,8 @@ vmcsinit(Vmx *vmx) if(rdmsr(VMX_PROCB_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_PROCB_CTLS_MSR failed"); x = (u32int)procb_ctls | 1<<1 | 7<<4 | 1<<8 | 1<<13 | 1<<14 | 1<<26; /* currently reserved default1 bits */ - x |= PROCB_EXITHLT | PROCB_EXITMWAIT; - x |= PROCB_EXITMOVDR | PROCB_EXITIO | PROCB_EXITMONITOR | PROCB_MSRBITMAP; + x |= PROCB_TSCOFFSET | PROCB_EXITMWAIT | PROCB_EXITMONITOR | PROCB_EXITHLT; + x |= PROCB_EXITMOVDR | PROCB_EXITIO | PROCB_MSRBITMAP; x |= PROCB_USECTLS2; x &= msr >> 32; vmcswrite(PROCB_CTLS, x); @@ -1042,8 +1054,8 @@ vmcsinit(Vmx *vmx) vmx->onentry = FLUSHVPID | FLUSHEPT; fpinit(); - fpsave(&vmx->fp); - + vmx->xcr0 = m->xcr0 & 1; /* x87 alone */ + memset(vmx->msrbits, -1, 4096); vmxtrapmsr(vmx, Efer, 0); vmcswrite(VMENTRY_MSRLDADDR, PADDR(vmx->msrguest)); @@ -1051,6 +1063,9 @@ vmcsinit(Vmx *vmx) vmcswrite(VMEXIT_MSRLDADDR, PADDR(vmx->msrhost)); vmcswrite(MSR_BITMAP, PADDR(vmx->msrbits)); + cycles(&vmx->tscoffset); + vmcswrite(VMCS_TSC_OFFSET, vmx->tscoffset); + if(sizeof(uintptr) == 8){ vmxaddmsr(vmx, Star, 0); vmxaddmsr(vmx, Lstar, 0); @@ -1074,7 +1089,7 @@ vmxstart(Vmx *vmx) uintptr cr; vlong x; - putcr4(getcr4() | 0x2000); /* set VMXE */ + putcr4(getcr4() | CR4VMXE); putcr0(getcr0() | 0x20); /* set NE */ cr = getcr0(); if(rdmsr(VMX_CR0_FIXED0, &msr) < 0) error("rdmsr(VMX_CR0_FIXED0) failed"); @@ -1590,8 +1605,9 @@ runcmd(Vmx *vmx) static void vmxproc(void *vmxp) { - int init, rc, x; + int init, rc, x, useend; u32int procbctls, defprocbctls; + u64int start, end, adj; vlong v; Vmx *vmx; @@ -1599,6 +1615,8 @@ vmxproc(void *vmxp) procwired(up, vmx->machno); sched(); init = 0; + useend = 0; + adj = 0; defprocbctls = 0; while(waserror()){ kstrcpy(vmx->errstr, up->errstr, ERRMAX); @@ -1653,11 +1671,29 @@ vmxproc(void *vmxp) } if((vmx->dr[7] & ~0xd400) != 0) putdr01236(vmx->dr); - fpsserestore(&vmx->fp); - putcr2(vmx->cr2); + + fprestore(&vmx->fp); + if(m->xcr0 != 0 && vmx->xcr0 != m->xcr0) + putxcr0(vmx->xcr0); + if(vmx->cr2 != getcr2()) + putcr2(vmx->cr2); + cycles(&start); + if(useend){ + vmx->tscoffset -= end - start + adj; + vmcswrite(VMCS_TSC_OFFSET, vmx->tscoffset); + } + if(adj == 0){ + cycles(&adj); + adj -= start; + } rc = vmlaunch(&vmx->ureg, vmx->launched); + cycles(&end); + useend = 1; vmx->cr2 = getcr2(); - fpssesave(&vmx->fp); + if(m->xcr0 != 0 && vmx->xcr0 != m->xcr0) + putxcr0(m->xcr0); + fpsave(&vmx->fp); + splx(x); if(rc < 0) error("vmlaunch failed"); @@ -1799,6 +1835,7 @@ vmxnew(void) free(vmx); nexterror(); } + memset(vmx, 0, sizeof(Vmx)); vmx->state = VMXINIT; vmx->lastcmd = &vmx->firstcmd; vmx->mem.next = &vmx->mem; diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 36ac1911b..b107707ae 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -15,7 +15,8 @@ void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); int cmpswap486(long*, long, long); void (*coherence)(void); -void cpuid(int, ulong regs[]); +void cpuid(int, int, ulong regs[]); +void fpuinit(void); int cpuidentify(void); void cpuidprint(void); void (*cycles)(uvlong*); @@ -40,12 +41,6 @@ void fpinit(void); void fpoff(void); void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); -void fpsserestore(FPsave*); -void fpssesave(FPsave*); -void fpx87restore(FPsave*); -void fpx87restore0(FPsave*); -void fpx87save(FPsave*); -void fpx87save0(FPsave*); ulong getcr0(void); ulong getcr2(void); ulong getcr3(void); @@ -83,7 +78,6 @@ int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void* kaddr(ulong); #define kmapinval() -void ldmxcsr(ulong); void lgdt(ushort[3]); void lldt(ulong); void lidt(ushort[3]); @@ -138,6 +132,7 @@ void putcr0(ulong); void putcr2(ulong); void putcr3(ulong); void putcr4(ulong); +void putxcr0(ulong); void putdr(u32int*); void putdr01236(uintptr*); void putdr6(u32int); diff --git a/sys/src/9/pc/fpu.c b/sys/src/9/pc/fpu.c new file mode 100644 index 000000000..e9467fc52 --- /dev/null +++ b/sys/src/9/pc/fpu.c @@ -0,0 +1,309 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" + +enum { + CR4Osfxsr = 1 << 9, + CR4Oxmmex = 1 << 10, +}; + +/* from l.s */ +extern void fpsserestore(FPsave*); +extern void fpssesave(FPsave*); +extern void fpx87restore0(FPsave*); +extern void fpx87save0(FPsave*); +extern void ldmxcsr(ulong); + +void +putxcr0(ulong) +{ +} + +/* + * we keep FPsave structure in SSE format emulating FXSAVE / FXRSTOR + * instructions for legacy x87 fpu. + */ +static void +fpx87save(FPsave *fps) +{ + ushort tag; + + fpx87save0(fps); + + /* + * convert x87 tag word to fxsave tag byte: + * 00, 01, 10 -> 1, 11 -> 0 + */ + tag = ~fps->tag; + tag = (tag | (tag >> 1)) & 0x5555; + tag = (tag | (tag >> 1)) & 0x3333; + tag = (tag | (tag >> 2)) & 0x0F0F; + tag = (tag | (tag >> 4)) & 0x00FF; + + /* NOP fps->fcw = fps->control; */ + fps->fsw = fps->status; + fps->ftw = tag; + fps->fop = fps->opcode; + fps->fpuip = fps->pc; + fps->cs = fps->selector; + fps->fpudp = fps->operand; + fps->ds = fps->oselector; + +#define MOVA(d,s) \ + *((ushort*)(d+8)) = *((ushort*)(s+8)), \ + *((ulong*)(d+4)) = *((ulong*)(s+4)), \ + *((ulong*)(d)) = *((ulong*)(s)) + + MOVA(fps->xregs+0x70, fps->regs+70); + MOVA(fps->xregs+0x60, fps->regs+60); + MOVA(fps->xregs+0x50, fps->regs+50); + MOVA(fps->xregs+0x40, fps->regs+40); + MOVA(fps->xregs+0x30, fps->regs+30); + MOVA(fps->xregs+0x20, fps->regs+20); + MOVA(fps->xregs+0x10, fps->regs+10); + MOVA(fps->xregs+0x00, fps->regs+00); + +#undef MOVA + +#define CLR6(d) \ + *((ulong*)(d)) = 0, \ + *((ushort*)(d+4)) = 0 + + CLR6(fps->xregs+0x70+10); + CLR6(fps->xregs+0x60+10); + CLR6(fps->xregs+0x50+10); + CLR6(fps->xregs+0x40+10); + CLR6(fps->xregs+0x30+10); + CLR6(fps->xregs+0x20+10); + CLR6(fps->xregs+0x10+10); + CLR6(fps->xregs+0x00+10); + +#undef CLR6 + + fps->rsrvd1 = fps->rsrvd2 = fps->mxcsr = fps->mxcsr_mask = 0; +} + +static void +fpx87restore(FPsave *fps) +{ + ushort msk, tos, tag, *reg; + + /* convert fxsave tag byte to x87 tag word */ + tag = 0; + tos = 7 - ((fps->fsw >> 11) & 7); + for(msk = 0x80; msk != 0; tos--, msk >>= 1){ + tag <<= 2; + if((fps->ftw & msk) != 0){ + reg = (ushort*)&fps->xregs[(tos & 7) << 4]; + switch(reg[4] & 0x7fff){ + case 0x0000: + if((reg[0] | reg[1] | reg[2] | reg[3]) == 0){ + tag |= 1; /* 01 zero */ + break; + } + /* no break */ + case 0x7fff: + tag |= 2; /* 10 special */ + break; + default: + if((reg[3] & 0x8000) == 0) + break; /* 00 valid */ + tag |= 2; /* 10 special */ + break; + } + }else{ + tag |= 3; /* 11 empty */ + } + } + +#define MOVA(d,s) \ + *((ulong*)(d)) = *((ulong*)(s)), \ + *((ulong*)(d+4)) = *((ulong*)(s+4)), \ + *((ushort*)(d+8)) = *((ushort*)(s+8)) + + MOVA(fps->regs+00, fps->xregs+0x00); + MOVA(fps->regs+10, fps->xregs+0x10); + MOVA(fps->regs+20, fps->xregs+0x20); + MOVA(fps->regs+30, fps->xregs+0x30); + MOVA(fps->regs+40, fps->xregs+0x40); + MOVA(fps->regs+50, fps->xregs+0x50); + MOVA(fps->regs+60, fps->xregs+0x60); + MOVA(fps->regs+70, fps->xregs+0x70); + +#undef MOVA + + fps->oselector = fps->ds; + fps->operand = fps->fpudp; + fps->opcode = fps->fop & 0x7ff; + fps->selector = fps->cs; + fps->pc = fps->fpuip; + fps->tag = tag; + fps->status = fps->fsw; + /* NOP fps->control = fps->fcw; */ + + fps->r1 = fps->r2 = fps->r3 = fps->r4 = 0; + + fpx87restore0(fps); +} + +static char* mathmsg[] = +{ + nil, /* handled below */ + "denormalized operand", + "division by zero", + "numeric overflow", + "numeric underflow", + "precision loss", +}; + +static void +mathnote(ulong status, ulong pc) +{ + char *msg, note[ERRMAX]; + int i; + + /* + * Some attention should probably be paid here to the + * exception masks and error summary. + */ + msg = "unknown exception"; + for(i = 1; i <= 5; i++){ + if(!((1<<i) & status)) + continue; + msg = mathmsg[i]; + break; + } + if(status & 0x01){ + if(status & 0x40){ + if(status & 0x200) + msg = "stack overflow"; + else + msg = "stack underflow"; + }else + msg = "invalid operation"; + } + snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux", + msg, pc, status); + postnote(up, 1, note, NDebug); +} + +/* + * math coprocessor error + */ +static void +matherror(Ureg*, void*) +{ + /* + * a write cycle to port 0xF0 clears the interrupt latch attached + * to the error# line from the 387 + */ + if(!(m->cpuiddx & Fpuonchip)) + outb(0xF0, 0xFF); + + /* + * get floating point state to check out error + */ + fpsave(up->fpsave); + up->fpstate = FPinactive; + mathnote(up->fpsave->fsw, up->fpsave->fpuip); +} + +/* + * SIMD error + */ +static void +simderror(Ureg *ureg, void*) +{ + fpsave(up->fpsave); + up->fpstate = FPinactive; + mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc); +} + +/* + * math coprocessor emulation fault + */ +static void +mathemu(Ureg *ureg, void*) +{ + ulong status, control; + + if(up->fpstate & FPillegal){ + /* someone did floating point in a note handler */ + postnote(up, 1, "sys: floating point in note handler", NDebug); + return; + } + switch(up->fpstate){ + case FPinit: + fpinit(); + if(fpsave == fpssesave) + ldmxcsr(0x1f80); /* no simd exceptions on 386 */ + while(up->fpsave == nil) + up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0); + up->fpstate = FPactive; + break; + case FPinactive: + /* + * Before restoring the state, check for any pending + * exceptions, there's no way to restore the state without + * generating an unmasked exception. + * More attention should probably be paid here to the + * exception masks and error summary. + */ + status = up->fpsave->fsw; + control = up->fpsave->fcw; + if((status & ~control) & 0x07F){ + mathnote(status, up->fpsave->fpuip); + break; + } + fprestore(up->fpsave); + up->fpstate = FPactive; + break; + case FPactive: + panic("math emu pid %ld %s pc 0x%lux", + up->pid, up->text, ureg->pc); + break; + } +} + +/* + * math coprocessor segment overrun + */ +static void +mathover(Ureg*, void*) +{ + pexit("math overrun", 0); +} + +void +mathinit(void) +{ + trapenable(VectorCERR, matherror, 0, "matherror"); + if(m->cpuidfamily == 3) + intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); + trapenable(VectorCNA, mathemu, 0, "mathemu"); + trapenable(VectorCSO, mathover, 0, "mathover"); + trapenable(VectorSIMD, simderror, 0, "simderror"); +} + +/* + * fpuinit(), called from cpuidentify() for each cpu. + */ +void +fpuinit(void) +{ + uintptr cr4; + + if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ + fpsave = fpssesave; + fprestore = fpsserestore; + cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; + putcr4(cr4); + } else { + fpsave = fpx87save; + fprestore = fpx87restore; + } +} diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 4f1bc788b..ede492af8 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -520,7 +520,7 @@ TEXT _peekinst(SB), $0 * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be * toggled then it's an older 486 of some kind. * - * cpuid(fun, regs[4]); + * cpuid(fn, sublvl, regs[4]); */ TEXT cpuid(SB), $0 MOVL $0x240000, AX @@ -539,6 +539,7 @@ TEXT cpuid(SB), $0 TESTL $0x200000, AX /* Id */ JZ _cpu486 /* can't toggle this bit on some 486 */ MOVL fn+0(FP), AX + MOVL sublvl+4(FP), CX CPUID JMP _cpuid _cpu486: @@ -555,7 +556,7 @@ _zaprest: XORL CX, CX XORL DX, DX _cpuid: - MOVL regs+4(FP), BP + MOVL regs+8(FP), BP MOVL AX, 0(BP) MOVL BX, 4(BP) MOVL CX, 8(BP) diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 646724b54..7d2bd04c5 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -234,272 +234,6 @@ confinit(void) } /* - * we keep FPsave structure in SSE format emulating FXSAVE / FXRSTOR - * instructions for legacy x87 fpu. - */ -void -fpx87save(FPsave *fps) -{ - ushort tag; - - fpx87save0(fps); - - /* - * convert x87 tag word to fxsave tag byte: - * 00, 01, 10 -> 1, 11 -> 0 - */ - tag = ~fps->tag; - tag = (tag | (tag >> 1)) & 0x5555; - tag = (tag | (tag >> 1)) & 0x3333; - tag = (tag | (tag >> 2)) & 0x0F0F; - tag = (tag | (tag >> 4)) & 0x00FF; - - /* NOP fps->fcw = fps->control; */ - fps->fsw = fps->status; - fps->ftw = tag; - fps->fop = fps->opcode; - fps->fpuip = fps->pc; - fps->cs = fps->selector; - fps->fpudp = fps->operand; - fps->ds = fps->oselector; - -#define MOVA(d,s) \ - *((ushort*)(d+8)) = *((ushort*)(s+8)), \ - *((ulong*)(d+4)) = *((ulong*)(s+4)), \ - *((ulong*)(d)) = *((ulong*)(s)) - - MOVA(fps->xregs+0x70, fps->regs+70); - MOVA(fps->xregs+0x60, fps->regs+60); - MOVA(fps->xregs+0x50, fps->regs+50); - MOVA(fps->xregs+0x40, fps->regs+40); - MOVA(fps->xregs+0x30, fps->regs+30); - MOVA(fps->xregs+0x20, fps->regs+20); - MOVA(fps->xregs+0x10, fps->regs+10); - MOVA(fps->xregs+0x00, fps->regs+00); - -#undef MOVA - -#define CLR6(d) \ - *((ulong*)(d)) = 0, \ - *((ushort*)(d+4)) = 0 - - CLR6(fps->xregs+0x70+10); - CLR6(fps->xregs+0x60+10); - CLR6(fps->xregs+0x50+10); - CLR6(fps->xregs+0x40+10); - CLR6(fps->xregs+0x30+10); - CLR6(fps->xregs+0x20+10); - CLR6(fps->xregs+0x10+10); - CLR6(fps->xregs+0x00+10); - -#undef CLR6 - - fps->rsrvd1 = fps->rsrvd2 = fps->mxcsr = fps->mxcsr_mask = 0; -} - -void -fpx87restore(FPsave *fps) -{ - ushort msk, tos, tag, *reg; - - /* convert fxsave tag byte to x87 tag word */ - tag = 0; - tos = 7 - ((fps->fsw >> 11) & 7); - for(msk = 0x80; msk != 0; tos--, msk >>= 1){ - tag <<= 2; - if((fps->ftw & msk) != 0){ - reg = (ushort*)&fps->xregs[(tos & 7) << 4]; - switch(reg[4] & 0x7fff){ - case 0x0000: - if((reg[0] | reg[1] | reg[2] | reg[3]) == 0){ - tag |= 1; /* 01 zero */ - break; - } - /* no break */ - case 0x7fff: - tag |= 2; /* 10 special */ - break; - default: - if((reg[3] & 0x8000) == 0) - break; /* 00 valid */ - tag |= 2; /* 10 special */ - break; - } - }else{ - tag |= 3; /* 11 empty */ - } - } - -#define MOVA(d,s) \ - *((ulong*)(d)) = *((ulong*)(s)), \ - *((ulong*)(d+4)) = *((ulong*)(s+4)), \ - *((ushort*)(d+8)) = *((ushort*)(s+8)) - - MOVA(fps->regs+00, fps->xregs+0x00); - MOVA(fps->regs+10, fps->xregs+0x10); - MOVA(fps->regs+20, fps->xregs+0x20); - MOVA(fps->regs+30, fps->xregs+0x30); - MOVA(fps->regs+40, fps->xregs+0x40); - MOVA(fps->regs+50, fps->xregs+0x50); - MOVA(fps->regs+60, fps->xregs+0x60); - MOVA(fps->regs+70, fps->xregs+0x70); - -#undef MOVA - - fps->oselector = fps->ds; - fps->operand = fps->fpudp; - fps->opcode = fps->fop & 0x7ff; - fps->selector = fps->cs; - fps->pc = fps->fpuip; - fps->tag = tag; - fps->status = fps->fsw; - /* NOP fps->control = fps->fcw; */ - - fps->r1 = fps->r2 = fps->r3 = fps->r4 = 0; - - fpx87restore0(fps); -} - -static char* mathmsg[] = -{ - nil, /* handled below */ - "denormalized operand", - "division by zero", - "numeric overflow", - "numeric underflow", - "precision loss", -}; - -static void -mathnote(ulong status, ulong pc) -{ - char *msg, note[ERRMAX]; - int i; - - /* - * Some attention should probably be paid here to the - * exception masks and error summary. - */ - msg = "unknown exception"; - for(i = 1; i <= 5; i++){ - if(!((1<<i) & status)) - continue; - msg = mathmsg[i]; - break; - } - if(status & 0x01){ - if(status & 0x40){ - if(status & 0x200) - msg = "stack overflow"; - else - msg = "stack underflow"; - }else - msg = "invalid operation"; - } - snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux", - msg, pc, status); - postnote(up, 1, note, NDebug); -} - -/* - * math coprocessor error - */ -static void -matherror(Ureg*, void*) -{ - /* - * a write cycle to port 0xF0 clears the interrupt latch attached - * to the error# line from the 387 - */ - if(!(m->cpuiddx & Fpuonchip)) - outb(0xF0, 0xFF); - - /* - * get floating point state to check out error - */ - fpsave(up->fpsave); - up->fpstate = FPinactive; - mathnote(up->fpsave->fsw, up->fpsave->fpuip); -} - -/* - * SIMD error - */ -static void -simderror(Ureg *ureg, void*) -{ - fpsave(up->fpsave); - up->fpstate = FPinactive; - mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc); -} - -/* - * math coprocessor emulation fault - */ -static void -mathemu(Ureg *ureg, void*) -{ - ulong status, control; - - if(up->fpstate & FPillegal){ - /* someone did floating point in a note handler */ - postnote(up, 1, "sys: floating point in note handler", NDebug); - return; - } - switch(up->fpstate){ - case FPinit: - fpinit(); - if(fpsave == fpssesave) - ldmxcsr(0x1f80); /* no simd exceptions on 386 */ - while(up->fpsave == nil) - up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0); - up->fpstate = FPactive; - break; - case FPinactive: - /* - * Before restoring the state, check for any pending - * exceptions, there's no way to restore the state without - * generating an unmasked exception. - * More attention should probably be paid here to the - * exception masks and error summary. - */ - status = up->fpsave->fsw; - control = up->fpsave->fcw; - if((status & ~control) & 0x07F){ - mathnote(status, up->fpsave->fpuip); - break; - } - fprestore(up->fpsave); - up->fpstate = FPactive; - break; - case FPactive: - panic("math emu pid %ld %s pc 0x%lux", - up->pid, up->text, ureg->pc); - break; - } -} - -/* - * math coprocessor segment overrun - */ -static void -mathover(Ureg*, void*) -{ - pexit("math overrun", 0); -} - -void -mathinit(void) -{ - trapenable(VectorCERR, matherror, 0, "matherror"); - if(m->cpuidfamily == 3) - intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); - trapenable(VectorCNA, mathemu, 0, "mathemu"); - trapenable(VectorCSO, mathover, 0, "mathover"); - trapenable(VectorSIMD, simderror, 0, "simderror"); -} - -/* * set up floating point for a new process */ void diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index c72705fda..3bc3d5fca 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -49,6 +49,7 @@ PORT=\ OBJ=\ l.$O\ cga.$O\ + fpu.$O\ i8253.$O\ i8259.$O\ main.$O\ diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index 3f72e9f64..f840b159d 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -289,9 +289,9 @@ physmask(void) ulong regs[4]; uvlong mask; - cpuid(Exthighfunc, regs); + cpuid(Exthighfunc, 0, regs); if(regs[0] >= Extaddrsz) { /* ax */ - cpuid(Extaddrsz, regs); + cpuid(Extaddrsz, 0, regs); mask = (1ULL << (regs[0] & 0xFF)) - 1; /* ax */ } else { mask = (1ULL << 36) - 1; @@ -305,11 +305,13 @@ getstate(State *s) vlong v; int i; - s->mask = physmask(); + if(rdmsr(MTRRCap, &s->cap) < 0) + return -1; - if(rdmsr(MTRRDefaultType, &s->def) < 0) + if((s->cap & (Capfix|Capvcnt)) == 0) return -1; - if(rdmsr(MTRRCap, &s->cap) < 0) + + if(rdmsr(MTRRDefaultType, &s->def) < 0) return -1; if(s->cap & Capfix){ @@ -332,6 +334,8 @@ getstate(State *s) return -1; } + s->mask = physmask(); + if(strcmp(m->cpuidid, "AuthenticAMD") != 0 || m->cpuidfamily < 15 || rdmsr(AMDK8SysCfg, &v) < 0 @@ -354,7 +358,7 @@ enum { static void putstate(State *s) { - ulong cr0, cr4; + uintptr cr0, cr4; int i, x; x = splhi(); @@ -674,6 +678,10 @@ mtrr(uvlong base, uvlong size, char *tstr) if((new.type = str2type(tstr)) < 0) return "bad cache type"; + if(new.type == Writecomb + && (cpu0state.cap & Capwc) == 0) + return "write combining not supported"; + qlock(&mtrrlk); newstate = cpu0state; nr = getranges(&newstate, ranges, Nranges, &new); diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 63ac8559b..4297e330b 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -21,7 +21,6 @@ #define idprint(...) if(prid) print(__VA_ARGS__); else USED(prid) #define aprint(...) if(datapi) print(__VA_ARGS__); else USED(datapi) #define ledprint(...) if(dled) print(__VA_ARGS__); else USED(dled) -#define Pciwaddrh(a) 0 #define Tname(c) tname[(c)->type] #define Ticks MACHP(0)->ticks #define MS2TK(t) (((ulong)(t)*HZ)/1000) @@ -284,20 +283,23 @@ mkalist(Aportm *m, uint flags, uchar *data, int len) Actab *t; Alist *l; Aprdt *p; + uvlong pa; t = m->ctab; if(data && len > 0){ + pa = PCIWADDR(data); p = &t->prdt; - p->dba = PCIWADDR(data); - p->dbahi = Pciwaddrh(data); + p->dba = pa; + p->dbahi = pa>>32; p->count = 1<<31 | len - 2 | 1; flags |= 1<<16; } + pa = PCIWADDR(t); l = m->list; l->flags = flags | 0x5; l->len = 0; - l->ctab = PCIWADDR(t); - l->ctabhi = Pciwaddrh(t); + l->ctab = pa; + l->ctabhi = pa>>32; return l; } @@ -600,6 +602,7 @@ ahciwakeup(Aportc *c, uint mode) static int ahciconfigdrive(Ahba *h, Aportc *c, int mode) { + uvlong pa; Aportm *m; Aport *p; int i; @@ -618,10 +621,12 @@ ahciconfigdrive(Ahba *h, Aportc *c, int mode) return -1; } - p->list = PCIWADDR(m->list); - p->listhi = Pciwaddrh(m->list); - p->fis = PCIWADDR(m->fis.base); - p->fishi = Pciwaddrh(m->fis.base); + pa = PCIWADDR(m->list); + p->list = pa; + p->listhi = pa>>32; + pa = PCIWADDR(m->fis.base); + p->fis = pa; + p->fishi = pa>>32; p->cmd |= Afre; @@ -1553,7 +1558,6 @@ iaenable(SDev *s) } if(c->ndrive == 0) panic("iaenable: zero s->ctlr->ndrive"); - pcisetbme(c->pci); snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name); intrenable(c->pci->intl, iainterrupt, c, c->pci->tbdf, name); /* supposed to squelch leftover interrupts here. */ @@ -2228,6 +2232,7 @@ iapnp(void) c->drive[d->driveno] = d; iadrive[niadrive + d->driveno] = d; } + pcisetbme(c->pci); for(i = 0; i < n; i++){ c->drive[i]->mode = DMautoneg; configdrive(c->drive[i]); diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index 84efe9a2c..b597f8988 100644 --- a/sys/src/9/pc64/dat.h +++ b/sys/src/9/pc64/dat.h @@ -2,6 +2,8 @@ typedef struct BIOS32si BIOS32si; typedef struct BIOS32ci BIOS32ci; typedef struct Conf Conf; typedef struct Confmem Confmem; +typedef struct FPssestate FPssestate; +typedef struct FPavxstate FPavxstate; typedef struct FPsave FPsave; typedef struct PFPU PFPU; typedef struct ISAConf ISAConf; @@ -49,7 +51,7 @@ struct Label uintptr pc; }; -struct FPsave +struct FPssestate { u16int fcw; /* x87 control word */ u16int fsw; /* x87 status word */ @@ -65,6 +67,18 @@ struct FPsave uchar ign[96]; /* reserved, ignored */ }; +struct FPavxstate +{ + FPssestate; + uchar header[64]; /* XSAVE header */ + uchar ymm[256]; /* upper 128-bit regs (AVX) */ +}; + +struct FPsave +{ + FPavxstate; +}; + enum { /* this is a state */ @@ -224,9 +238,10 @@ struct Mach int havewatchpt8; int havenx; uvlong tscticks; - + u64int dr7; /* shadow copy of dr7 */ - + u64int xcr0; + void* vmx; uintptr stack[1]; @@ -270,8 +285,14 @@ struct PCArch /* cpuid instruction result register bits */ enum { + /* ax */ + Xsaveopt = 1<<0, + Xsaves = 1<<3, + /* cx */ Monitor = 1<<3, + Xsave = 1<<26, + Avx = 1<<28, /* dx */ Fpuonchip = 1<<0, diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index ad5315b5e..90d831e3a 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -15,7 +15,8 @@ void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); int cmpswap486(long*, long, long); void (*coherence)(void); -void cpuid(int, ulong regs[]); +void cpuid(int, int, ulong regs[]); +void fpuinit(void); int cpuidentify(void); void cpuidprint(void); void (*cycles)(uvlong*); @@ -38,16 +39,17 @@ int ecwrite(uchar addr, uchar val); void fpinit(void); void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); -void fpsserestore(FPsave*); -void fpssesave(FPsave*); -void fpx87restore(FPsave*); -void fpx87save(FPsave*); +void fpuprocsetup(Proc*); +void fpuprocfork(Proc*); +void fpuprocsave(Proc*); +void fpuprocrestore(Proc*); int fpusave(void); void fpurestore(int); u64int getcr0(void); u64int getcr2(void); u64int getcr3(void); u64int getcr4(void); +u64int getxcr0(void); u64int getdr6(void); char* getconf(char*); void guesscpuhz(int); @@ -138,6 +140,7 @@ void putcr0(u64int); void putcr2(u64int); void putcr3(u64int); void putcr4(u64int); +void putxcr0(u64int); void putdr(u64int*); void putdr01236(u64int*); void putdr6(u64int); diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c new file mode 100644 index 000000000..1a5f31251 --- /dev/null +++ b/sys/src/9/pc64/fpu.c @@ -0,0 +1,374 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "ureg.h" +#include "io.h" + +enum { + CR4Osfxsr = 1 << 9, + CR4Oxmmex = 1 << 10, + CR4Oxsave = 1 << 18, +}; + +/* + * SIMD Floating Point. + * Assembler support to get at the individual instructions + * is in l.s. + */ +extern void _clts(void); +extern void _fldcw(u16int); +extern void _fnclex(void); +extern void _fninit(void); +extern void _fxrstor(void*); +extern void _fxsave(void*); +extern void _xrstor(void*); +extern void _xsave(void*); +extern void _xsaveopt(void*); +extern void _fwait(void); +extern void _ldmxcsr(u32int); +extern void _stts(void); + +static void +fpssesave(FPsave *s) +{ + _fxsave(s); + _stts(); +} +static void +fpsserestore(FPsave *s) +{ + _clts(); + _fxrstor(s); +} + +static void +fpxsave(FPsave *s) +{ + _xsave(s); + _stts(); +} +static void +fpxrestore(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +static void +fpxsaves(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} +static void +fpxrestores(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +static void +fpxsaveopt(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} + +static char* mathmsg[] = +{ + nil, /* handled below */ + "denormalized operand", + "division by zero", + "numeric overflow", + "numeric underflow", + "precision loss", +}; + +static void +mathnote(ulong status, uintptr pc) +{ + char *msg, note[ERRMAX]; + int i; + + /* + * Some attention should probably be paid here to the + * exception masks and error summary. + */ + msg = "unknown exception"; + for(i = 1; i <= 5; i++){ + if(!((1<<i) & status)) + continue; + msg = mathmsg[i]; + break; + } + if(status & 0x01){ + if(status & 0x40){ + if(status & 0x200) + msg = "stack overflow"; + else + msg = "stack underflow"; + }else + msg = "invalid operation"; + } + snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=0x%lux", + msg, pc, status); + postnote(up, 1, note, NDebug); +} + +/* + * math coprocessor error + */ +static void +matherror(Ureg *, void*) +{ + /* + * Save FPU state to check out the error. + */ + fpsave(up->fpsave); + up->fpstate = FPinactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); + mathnote(up->fpsave->fsw, up->fpsave->rip); +} + +/* + * SIMD error + */ +static void +simderror(Ureg *ureg, void*) +{ + fpsave(up->fpsave); + up->fpstate = FPinactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); + mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc); +} + +void +fpinit(void) +{ + /* + * A process tries to use the FPU for the + * first time and generates a 'device not available' + * exception. + * Turn the FPU on and initialise it for use. + * Set the precision and mask the exceptions + * we don't care about from the generic Mach value. + */ + _clts(); + _fninit(); + _fwait(); + _fldcw(0x0232); + _ldmxcsr(0x1900); +} + +/* + * math coprocessor emulation fault + */ +static void +mathemu(Ureg *ureg, void*) +{ + ulong status, control; + int index; + + if(up->fpstate & FPillegal){ + /* someone did floating point in a note handler */ + postnote(up, 1, "sys: floating point in note handler", NDebug); + return; + } + switch(up->fpstate & ~(FPnouser|FPkernel|FPindexm)){ + case FPactive | FPpush: + _clts(); + fpsave(up->fpsave); + case FPinactive | FPpush: + up->fpstate += FPindex1; + case FPinit | FPpush: + case FPinit: + fpinit(); + index = up->fpstate >> FPindexs; + if(index < 0 || index > (FPindexm>>FPindexs)) + panic("fpslot index overflow: %d", index); + if(userureg(ureg)){ + if(index != 0) + panic("fpslot index %d != 0 for user", index); + } else { + if(index == 0) + up->fpstate |= FPnouser; + up->fpstate |= FPkernel; + } + while(up->fpslot[index] == nil) + up->fpslot[index] = mallocalign(sizeof(FPsave), FPalign, 0, 0); + up->fpsave = up->fpslot[index]; + up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); + break; + case FPinactive: + /* + * Before restoring the state, check for any pending + * exceptions, there's no way to restore the state without + * generating an unmasked exception. + * More attention should probably be paid here to the + * exception masks and error summary. + */ + status = up->fpsave->fsw; + control = up->fpsave->fcw; + if((status & ~control) & 0x07F){ + mathnote(status, up->fpsave->rip); + break; + } + fprestore(up->fpsave); + up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); + break; + case FPactive: + panic("math emu pid %ld %s pc %#p", + up->pid, up->text, ureg->pc); + break; + } +} + +/* + * math coprocessor segment overrun + */ +static void +mathover(Ureg*, void*) +{ + pexit("math overrun", 0); +} + +void +mathinit(void) +{ + trapenable(VectorCERR, matherror, 0, "matherror"); + if(m->cpuidfamily == 3) + intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); + trapenable(VectorCNA, mathemu, 0, "mathemu"); + trapenable(VectorCSO, mathover, 0, "mathover"); + trapenable(VectorSIMD, simderror, 0, "simderror"); +} + +/* + * fpuinit(), called from cpuidentify() for each cpu. + */ +void +fpuinit(void) +{ + u64int cr4; + ulong regs[4]; + + cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; + if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ + cr4 |= CR4Oxsave; + putcr4(cr4); + m->xcr0 = 7; /* x87, sse, avx */ + putxcr0(m->xcr0); + cpuid(0xd, 1, regs); + if(regs[0] & Xsaves){ + fpsave = fpxsaves; + fprestore = fpxrestores; + } else { + if(regs[0] & Xsaveopt) + fpsave = fpxsaveopt; + else + fpsave = fpxsave; + fprestore = fpxrestore; + } + } else { + putcr4(cr4); + fpsave = fpssesave; + fprestore = fpsserestore; + } +} + +void +fpuprocsetup(Proc *p) +{ + p->fpstate = FPinit; + _stts(); +} + +void +fpuprocfork(Proc *p) +{ + int s; + + /* save floating point state */ + s = splhi(); + switch(up->fpstate & ~FPillegal){ + case FPactive | FPpush: + _clts(); + case FPactive: + fpsave(up->fpsave); + up->fpstate = FPinactive | (up->fpstate & FPpush); + case FPactive | FPkernel: + case FPinactive | FPkernel: + case FPinactive | FPpush: + case FPinactive: + while(p->fpslot[0] == nil) + p->fpslot[0] = mallocalign(sizeof(FPsave), FPalign, 0, 0); + memmove(p->fpsave = p->fpslot[0], up->fpslot[0], sizeof(FPsave)); + p->fpstate = FPinactive; + } + splx(s); +} + +void +fpuprocsave(Proc *p) +{ + switch(p->fpstate & ~(FPnouser|FPkernel|FPindexm)){ + case FPactive | FPpush: + _clts(); + case FPactive: + if(p->state == Moribund){ + _fnclex(); + _stts(); + break; + } + /* + * Fpsave() stores without handling pending + * unmasked exeptions. Postnote() can't be called + * here as sleep() already has up->rlock, so + * the handling of pending exceptions is delayed + * until the process runs again and generates an + * emulation fault to activate the FPU. + */ + fpsave(p->fpsave); + p->fpstate = FPinactive | (p->fpstate & ~FPactive); + break; + } +} + +void +fpuprocrestore(Proc*) +{ +} + + +/* + * Fpusave and fpurestore lazily save and restore FPU state across + * system calls and the pagefault handler so that we can take + * advantage of SSE instructions such as AES-NI in the kernel. + */ +int +fpusave(void) +{ + int ostate = up->fpstate; + if((ostate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) + _stts(); + up->fpstate = FPpush | (ostate & ~FPillegal); + return ostate; +} +void +fpurestore(int ostate) +{ + int astate = up->fpstate; + if(astate == (FPpush | (ostate & ~FPillegal))){ + if((ostate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) + _clts(); + } else { + if(astate == FPinit) /* don't restore on procexec()/procsetup() */ + return; + if((astate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) + _stts(); + up->fpsave = up->fpslot[ostate>>FPindexs]; + if(ostate & FPactive) + ostate = FPinactive | (ostate & ~FPactive); + } + up->fpstate = ostate; +} diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index c00a24fc7..76aa2e241 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -249,9 +249,10 @@ _idle: */ TEXT cpuid(SB), $-4 MOVL RARG, AX /* function in AX */ + MOVL cx+8(FP), CX /* sub-level in CX */ CPUID - MOVQ info+8(FP), BP + MOVQ info+16(FP), BP MOVL AX, 0(BP) MOVL BX, 4(BP) MOVL CX, 8(BP) @@ -399,6 +400,21 @@ TEXT putcr4(SB), 1, $-4 MOVQ RARG, CR4 RET +TEXT getxcr0(SB), 1, $-4 /* XCR0 - extended control */ + XORQ CX, CX + WORD $0x010f; BYTE $0xd0 // XGETBV + SHLQ $32, DX + ORQ DX, AX + RET + +TEXT putxcr0(SB), 1, $-4 + XORQ CX, CX + MOVL RARG, DX + SHRQ $32, DX + MOVL RARG, AX + WORD $0x010f; BYTE $0xd1 // XSETBV + RET + TEXT mb386(SB), 1, $-4 /* hack */ TEXT mb586(SB), 1, $-4 XORL AX, AX @@ -626,6 +642,36 @@ TEXT _fxsave(SB), 1, $-4 FXSAVE64 (RARG) RET +TEXT _xrstor(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x6d; BYTE $0x00 // XRSTOR (RARG) + RET + +TEXT _xrstors(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xc7; BYTE $0x5d; BYTE $0x00 // XRSTORS (RARG) + RET + +TEXT _xsave(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x65; BYTE $0x00 // XSAVE (RARG) + RET + +TEXT _xsaveopt(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x75; BYTE $0x00 // XSAVEOPT (RARG) + RET + +TEXT _xsaves(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xc7; BYTE $0x6d; BYTE $0x00 // XSAVES (RARG) + RET + TEXT _fwait(SB), 1, $-4 WAIT RET diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 5ece4cfd8..4083e33f6 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -293,218 +293,10 @@ reboot(void *entry, void *code, ulong size) rebootjump((uintptr)entry & (ulong)~0xF0000000UL, PADDR(code), size); } -/* - * SIMD Floating Point. - * Assembler support to get at the individual instructions - * is in l.s. - */ -extern void _clts(void); -extern void _fldcw(u16int); -extern void _fnclex(void); -extern void _fninit(void); -extern void _fxrstor(void*); -extern void _fxsave(void*); -extern void _fwait(void); -extern void _ldmxcsr(u32int); -extern void _stts(void); - -/* - * not used, AMD64 mandated SSE - */ -void -fpx87save(FPsave*) -{ -} -void -fpx87restore(FPsave*) -{ -} - -void -fpssesave(FPsave *s) -{ - _fxsave(s); - _stts(); -} -void -fpsserestore(FPsave *s) -{ - _clts(); - _fxrstor(s); -} - -static char* mathmsg[] = -{ - nil, /* handled below */ - "denormalized operand", - "division by zero", - "numeric overflow", - "numeric underflow", - "precision loss", -}; - -static void -mathnote(ulong status, uintptr pc) -{ - char *msg, note[ERRMAX]; - int i; - - /* - * Some attention should probably be paid here to the - * exception masks and error summary. - */ - msg = "unknown exception"; - for(i = 1; i <= 5; i++){ - if(!((1<<i) & status)) - continue; - msg = mathmsg[i]; - break; - } - if(status & 0x01){ - if(status & 0x40){ - if(status & 0x200) - msg = "stack overflow"; - else - msg = "stack underflow"; - }else - msg = "invalid operation"; - } - snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=0x%lux", - msg, pc, status); - postnote(up, 1, note, NDebug); -} - -/* - * math coprocessor error - */ -static void -matherror(Ureg *, void*) -{ - /* - * Save FPU state to check out the error. - */ - fpsave(up->fpsave); - up->fpstate = FPinactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); - mathnote(up->fpsave->fsw, up->fpsave->rip); -} - -/* - * SIMD error - */ -static void -simderror(Ureg *ureg, void*) -{ - fpsave(up->fpsave); - up->fpstate = FPinactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); - mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc); -} - -void -fpinit(void) -{ - /* - * A process tries to use the FPU for the - * first time and generates a 'device not available' - * exception. - * Turn the FPU on and initialise it for use. - * Set the precision and mask the exceptions - * we don't care about from the generic Mach value. - */ - _clts(); - _fninit(); - _fwait(); - _fldcw(0x0232); - _ldmxcsr(0x1900); -} - -/* - * math coprocessor emulation fault - */ -static void -mathemu(Ureg *ureg, void*) -{ - ulong status, control; - int index; - - if(up->fpstate & FPillegal){ - /* someone did floating point in a note handler */ - postnote(up, 1, "sys: floating point in note handler", NDebug); - return; - } - switch(up->fpstate & ~(FPnouser|FPkernel|FPindexm)){ - case FPactive | FPpush: - _clts(); - fpsave(up->fpsave); - case FPinactive | FPpush: - up->fpstate += FPindex1; - case FPinit | FPpush: - case FPinit: - fpinit(); - index = up->fpstate >> FPindexs; - if(index < 0 || index > (FPindexm>>FPindexs)) - panic("fpslot index overflow: %d", index); - if(userureg(ureg)){ - if(index != 0) - panic("fpslot index %d != 0 for user", index); - } else { - if(index == 0) - up->fpstate |= FPnouser; - up->fpstate |= FPkernel; - } - while(up->fpslot[index] == nil) - up->fpslot[index] = mallocalign(sizeof(FPsave), FPalign, 0, 0); - up->fpsave = up->fpslot[index]; - up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); - break; - case FPinactive: - /* - * Before restoring the state, check for any pending - * exceptions, there's no way to restore the state without - * generating an unmasked exception. - * More attention should probably be paid here to the - * exception masks and error summary. - */ - status = up->fpsave->fsw; - control = up->fpsave->fcw; - if((status & ~control) & 0x07F){ - mathnote(status, up->fpsave->rip); - break; - } - fprestore(up->fpsave); - up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); - break; - case FPactive: - panic("math emu pid %ld %s pc %#p", - up->pid, up->text, ureg->pc); - break; - } -} - -/* - * math coprocessor segment overrun - */ -static void -mathover(Ureg*, void*) -{ - pexit("math overrun", 0); -} - -void -mathinit(void) -{ - trapenable(VectorCERR, matherror, 0, "matherror"); - if(m->cpuidfamily == 3) - intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); - trapenable(VectorCNA, mathemu, 0, "mathemu"); - trapenable(VectorCSO, mathover, 0, "mathover"); - trapenable(VectorSIMD, simderror, 0, "simderror"); -} - void procsetup(Proc *p) { - p->fpstate = FPinit; - _stts(); + fpuprocsetup(p); /* clear debug registers */ memset(p->dr, 0, sizeof(p->dr)); @@ -520,29 +312,10 @@ procsetup(Proc *p) void procfork(Proc *p) { - int s; - p->kentry = up->kentry; p->pcycles = -p->kentry; - /* save floating point state */ - s = splhi(); - switch(up->fpstate & ~FPillegal){ - case FPactive | FPpush: - _clts(); - case FPactive: - fpsave(up->fpsave); - up->fpstate = FPinactive | (up->fpstate & FPpush); - case FPactive | FPkernel: - case FPinactive | FPkernel: - case FPinactive | FPpush: - case FPinactive: - while(p->fpslot[0] == nil) - p->fpslot[0] = mallocalign(sizeof(FPsave), FPalign, 0, 0); - memmove(p->fpsave = p->fpslot[0], up->fpslot[0], sizeof(FPsave)); - p->fpstate = FPinactive; - } - splx(s); + fpuprocfork(p); } void @@ -558,6 +331,8 @@ procrestore(Proc *p) if(p->vmx != nil) vmxprocrestore(p); + fpuprocrestore(p); + if(p->kp) return; @@ -582,27 +357,7 @@ procsave(Proc *p) if(p->state == Moribund) p->dr[7] = 0; - switch(p->fpstate & ~(FPnouser|FPkernel|FPindexm)){ - case FPactive | FPpush: - _clts(); - case FPactive: - if(p->state == Moribund){ - _fnclex(); - _stts(); - break; - } - /* - * Fpsave() stores without handling pending - * unmasked exeptions. Postnote() can't be called - * here as sleep() already has up->rlock, so - * the handling of pending exceptions is delayed - * until the process runs again and generates an - * emulation fault to activate the FPU. - */ - fpsave(p->fpsave); - p->fpstate = FPinactive | (p->fpstate & ~FPactive); - break; - } + fpuprocsave(p); /* * While this processor is in the scheduler, the process could run @@ -617,36 +372,3 @@ procsave(Proc *p) */ mmuflushtlb(); } - -/* - * Fpusave and fpurestore lazily save and restore FPU state across - * system calls and the pagefault handler so that we can take - * advantage of SSE instructions such as AES-NI in the kernel. - */ -int -fpusave(void) -{ - int ostate = up->fpstate; - if((ostate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) - _stts(); - up->fpstate = FPpush | (ostate & ~FPillegal); - return ostate; -} -void -fpurestore(int ostate) -{ - int astate = up->fpstate; - if(astate == (FPpush | (ostate & ~FPillegal))){ - if((ostate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) - _clts(); - } else { - if(astate == FPinit) /* don't restore on procexec()/procsetup() */ - return; - if((astate & ~(FPnouser|FPkernel|FPindexm)) == FPactive) - _stts(); - up->fpsave = up->fpslot[ostate>>FPindexs]; - if(ostate & FPactive) - ostate = FPinactive | (ostate & ~FPactive); - } - up->fpstate = ostate; -} diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index c6f9bba70..4541a62a0 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -26,7 +26,7 @@ #define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) #define PGROUND(s) ROUND(s, BY2PG) #define BLOCKALIGN 8 -#define FPalign 16 +#define FPalign 64 #define MAXMACH 128 /* max # cpus system can run */ diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index f34201e0d..083ab92f9 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -47,6 +47,7 @@ PORT=\ OBJ=\ l.$O\ cga.$O\ + fpu.$O\ i8253.$O\ i8259.$O\ main.$O\ diff --git a/sys/src/9/port/auth.c b/sys/src/9/port/auth.c index 2cc54c657..b6b19bd63 100644 --- a/sys/src/9/port/auth.c +++ b/sys/src/9/port/auth.c @@ -97,13 +97,12 @@ sysfauth(va_list list) nexterror(); } - fd = newfd(ac); + /* always mark it close on exec */ + fd = newfd(ac, OCEXEC); if(fd < 0) error(Enofd); poperror(); /* ac */ - /* always mark it close on exec */ - ac->flag |= CCEXEC; return (uintptr)fd; } diff --git a/sys/src/9/port/chan.c b/sys/src/9/port/chan.c index 58a47cc83..e60561d1a 100644 --- a/sys/src/9/port/chan.c +++ b/sys/src/9/port/chan.c @@ -1468,9 +1468,6 @@ namec(char *aname, int amode, int omode, ulong perm) saveregisters(); c = devtab[c->type]->open(c, omode&~OCEXEC); - - if(omode & OCEXEC) - c->flag |= CCEXEC; if(omode & ORCLOSE) c->flag |= CRCLOSE; break; @@ -1571,11 +1568,9 @@ namec(char *aname, int amode, int omode, ulong perm) incref(cnew->path); cnew = devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); - poperror(); - if(omode & OCEXEC) - cnew->flag |= CCEXEC; if(omode & ORCLOSE) cnew->flag |= CRCLOSE; + poperror(); putmhead(m); cclose(c); c = cnew; diff --git a/sys/src/9/port/devdup.c b/sys/src/9/port/devdup.c index 2ba718729..79c7d90ff 100644 --- a/sys/src/9/port/devdup.c +++ b/sys/src/9/port/devdup.c @@ -63,6 +63,8 @@ dupopen(Chan *c, int omode) Chan *f; int fd, twicefd; + if(omode & ORCLOSE) + error(Eperm); if(c->qid.type & QTDIR){ if(omode != 0) error(Eisdir); diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c index 940e8ef97..cec16c753 100644 --- a/sys/src/9/port/devmouse.c +++ b/sys/src/9/port/devmouse.c @@ -304,8 +304,6 @@ setbuttonmap(char* map) one = two = three = 0; for(i = 0; i < 3; i++){ - if(map[i] == 0) - error(Ebadarg); if(map[i] == '1'){ if(one) error(Ebadarg); diff --git a/sys/src/9/port/devshr.c b/sys/src/9/port/devshr.c index 96e319221..225ba6c93 100644 --- a/sys/src/9/port/devshr.c +++ b/sys/src/9/port/devshr.c @@ -396,6 +396,8 @@ shropen(Chan *c, int omode) case Qcmpt: if(omode&OTRUNC) error(Eexist); + if(omode&ORCLOSE) + error(Eperm); shr = sch->shr; mpt = sch->mpt; devpermcheck(mpt->owner, mpt->perm, mode); diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 193fa6c8b..8128569a1 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -135,6 +135,8 @@ srvopen(Chan *c, int omode) if(omode&OTRUNC) error(Eexist); + if(omode&ORCLOSE) + error(Eperm); if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); devpermcheck(sp->owner, sp->perm, omode); @@ -338,8 +340,6 @@ srvwrite(Chan *c, void *va, long n, vlong) cclose(c1); nexterror(); } - if(c1->flag & (CCEXEC|CRCLOSE)) - error("posted fd has remove-on-close or close-on-exec"); if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); sp = srvlookup(nil, c->qid.path); diff --git a/sys/src/9/port/lib.h b/sys/src/9/port/lib.h index 1f7bf7d1d..06b423d9d 100644 --- a/sys/src/9/port/lib.h +++ b/sys/src/9/port/lib.h @@ -176,7 +176,7 @@ extern void qsort(void*, long, long, int (*)(void*, void*)); #define ORDWR 2 /* read and write */ #define OEXEC 3 /* execute, == read but check execute permission */ #define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ -#define OCEXEC 32 /* or'ed in, close on exec */ +#define OCEXEC 32 /* or'ed in (per file descriptor), close on exec */ #define ORCLOSE 64 /* or'ed in, remove on close */ #define OEXCL 0x1000 /* or'ed in, exclusive create */ diff --git a/sys/src/9/port/pgrp.c b/sys/src/9/port/pgrp.c index 5576acc57..408370d35 100644 --- a/sys/src/9/port/pgrp.c +++ b/sys/src/9/port/pgrp.c @@ -140,7 +140,8 @@ dupfgrp(Fgrp *f) new = smalloc(sizeof(Fgrp)); if(f == nil){ - new->fd = smalloc(DELTAFD*sizeof(Chan*)); + new->flag = smalloc(DELTAFD*sizeof(new->flag[0])); + new->fd = smalloc(DELTAFD*sizeof(new->fd[0])); new->nfd = DELTAFD; new->ref = 1; return new; @@ -152,12 +153,19 @@ dupfgrp(Fgrp *f) i = new->nfd%DELTAFD; if(i != 0) new->nfd += DELTAFD - i; - new->fd = malloc(new->nfd*sizeof(Chan*)); + new->fd = malloc(new->nfd*sizeof(new->fd[0])); if(new->fd == nil){ unlock(f); free(new); error("no memory for fgrp"); } + new->flag = malloc(new->nfd*sizeof(new->flag[0])); + if(new->flag == nil){ + unlock(f); + free(new->fd); + free(new); + error("no memory for fgrp"); + } new->ref = 1; new->maxfd = f->maxfd; @@ -165,6 +173,7 @@ dupfgrp(Fgrp *f) if((c = f->fd[i]) != nil){ incref(c); new->fd[i] = c; + new->flag[i] = f->flag[i]; } } unlock(f); @@ -194,6 +203,7 @@ closefgrp(Fgrp *f) up->closingfgrp = nil; free(f->fd); + free(f->flag); free(f); } diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 7c9aa7193..a5cdafa6a 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -125,7 +125,7 @@ enum COPEN = 0x0001, /* for i/o */ CMSG = 0x0002, /* the message channel for a mount */ /*rsc CCREATE = 0x0004, /* permits creation if c->mnt */ - CCEXEC = 0x0008, /* close on exec */ + CCEXEC = 0x0008, /* close on exec (per file descriptor) */ CFREE = 0x0010, /* not in use */ CRCLOSE = 0x0020, /* remove on close */ CCACHE = 0x0080, /* client cache */ @@ -509,6 +509,7 @@ struct Fgrp Ref; Lock; Chan **fd; + uchar *flag; /* per file-descriptor flags (CCEXEC) */ int nfd; /* number allocated */ int maxfd; /* highest fd in use */ int exceed; /* debugging */ diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 04550987f..00c7e8b96 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -201,7 +201,7 @@ Chan* namec(char*, int, int, ulong); void nameerror(char*, char*); int needpages(void*); Chan* newchan(void); -int newfd(Chan*); +int newfd(Chan*, int); Mhead* newmhead(Chan*); Mount* newmount(Chan*, int, char*); Page* newpage(int, Segment **, uintptr); diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c index ed8e5c7ad..a503b2cca 100644 --- a/sys/src/9/port/sysfile.c +++ b/sys/src/9/port/sysfile.c @@ -25,33 +25,45 @@ int growfd(Fgrp *f, int fd) /* fd is always >= 0 */ { Chan **newfd, **oldfd; + uchar *newflag, *oldflag; + int nfd; - if(fd < f->nfd) + nfd = f->nfd; + if(fd < nfd) return 0; - if(fd >= f->nfd+DELTAFD) + if(fd >= nfd+DELTAFD) return -1; /* out of range */ /* * Unbounded allocation is unwise; besides, there are only 16 bits * of fid in 9P */ - if(f->nfd >= 5000){ + if(nfd >= 5000){ Exhausted: print("no free file descriptors\n"); return -1; } - newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*)); + oldfd = f->fd; + oldflag = f->flag; + newfd = malloc((nfd+DELTAFD)*sizeof(newfd[0])); if(newfd == nil) goto Exhausted; - oldfd = f->fd; - memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); + memmove(newfd, oldfd, nfd*sizeof(newfd[0])); + newflag = malloc((nfd+DELTAFD)*sizeof(newflag[0])); + if(newflag == nil){ + free(newfd); + goto Exhausted; + } + memmove(newflag, oldflag, nfd*sizeof(newflag[0])); f->fd = newfd; - free(oldfd); - f->nfd += DELTAFD; + f->flag = newflag; + f->nfd = nfd+DELTAFD; if(fd > f->maxfd){ if(fd/100 > f->maxfd/100) f->exceed = (fd/100)*100; f->maxfd = fd; } + free(oldfd); + free(oldflag); return 1; } @@ -72,9 +84,9 @@ findfreefd(Fgrp *f, int start) } int -newfd(Chan *c) +newfd(Chan *c, int mode) { - int fd; + int fd, flag; Fgrp *f; f = up->fgrp; @@ -87,6 +99,13 @@ newfd(Chan *c) if(fd > f->maxfd) f->maxfd = fd; f->fd[fd] = c; + + /* per file-descriptor flags */ + flag = 0; + if(mode & OCEXEC) + flag |= CCEXEC; + f->flag[fd] = flag; + unlockfgrp(f); return fd; } @@ -112,6 +131,8 @@ newfd2(int fd[2], Chan *c[2]) f->maxfd = fd[1]; f->fd[fd[0]] = c[0]; f->fd[fd[1]] = c[1]; + f->flag[fd[0]] = 0; + f->flag[fd[1]] = 0; unlockfgrp(f); return 0; } @@ -247,6 +268,7 @@ sysdup(va_list list) oc = f->fd[fd]; f->fd[fd] = c; + f->flag[fd] = 0; unlockfgrp(f); if(oc != nil) cclose(oc); @@ -255,7 +277,7 @@ sysdup(va_list list) cclose(c); nexterror(); } - fd = newfd(c); + fd = newfd(c, 0); if(fd < 0) error(Enofd); poperror(); @@ -280,7 +302,7 @@ sysopen(va_list list) cclose(c); nexterror(); } - fd = newfd(c); + fd = newfd(c, mode); if(fd < 0) error(Enofd); poperror(); @@ -295,7 +317,7 @@ fdclose(int fd, int flag) lock(f); c = fd <= f->maxfd ? f->fd[fd] : nil; - if(c == nil || (flag != 0 && (c->flag&flag) == 0)){ + if(c == nil || (flag != 0 && ((f->flag[fd]|c->flag)&flag) == 0)){ unlock(f); return; } @@ -1166,7 +1188,7 @@ syscreate(va_list list) cclose(c); nexterror(); } - fd = newfd(c); + fd = newfd(c, mode); if(fd < 0) error(Enofd); poperror(); diff --git a/sys/src/9/xen/archxen.c b/sys/src/9/xen/archxen.c index c4f1b5607..6f3d1bfae 100644 --- a/sys/src/9/xen/archxen.c +++ b/sys/src/9/xen/archxen.c @@ -83,18 +83,3 @@ void outl(int, ulong) {} int mtrrprint(char*, long) { return 0; } char* mtrr(uvlong, uvlong, char *) { return nil; } void mtrrsync(void) {} - -/* - * XXX until fpsave is debugged - */ -void -fpssesave(FPsave* f) -{ - fpx87save(f); -} - -void -fpsserestore(FPsave* f) -{ - fpx87restore(f); -} diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h index 9dd3d239e..bc87a60ef 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -9,25 +9,18 @@ void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); int cmpswap486(long*, long, long); void (*coherence)(void); -void cpuid(int, ulong regs[]); +void cpuid(int, int, ulong regs[]); +void fpuinit(void); int cpuidentify(void); void cpuidprint(void); void (*cycles)(uvlong*); void delay(int); #define evenaddr(x) /* x86 doesn't care */ void fpclear(void); -void fpenv(FPsave*); void fpinit(void); void fpoff(void); void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); -void fpsserestore(FPsave*); -void fpsserestore0(FPsave*); -void fpssesave(FPsave*); -void fpssesave0(FPsave*); -ulong fpstatus(void); -void fpx87restore(FPsave*); -void fpx87save(FPsave*); ulong getcr4(void); char* getconf(char*); void guesscpuhz(int); diff --git a/sys/src/9/xen/l.s b/sys/src/9/xen/l.s index 466b84d8c..af246e70a 100644 --- a/sys/src/9/xen/l.s +++ b/sys/src/9/xen/l.s @@ -163,32 +163,40 @@ TEXT fpinit(SB), $0 /* enable and init */ WAIT RET -TEXT fpx87save(SB), $0 /* save state and disable */ +TEXT fpx87save0(SB), $0 /* save state and disable */ MOVL p+0(FP), AX FSAVE 0(AX) /* no WAIT */ FPOFF(l2) RET -TEXT fpx87restore(SB), $0 /* enable and restore state */ +TEXT fpx87restore0(SB), $0 /* enable and restore state */ FPON MOVL p+0(FP), AX FRSTOR 0(AX) WAIT RET -TEXT fpstatus(SB), $0 /* get floating point status */ - FSTSW AX +TEXT fpclear(SB), $0 /* clear pending exceptions */ + FPON + FCLEX /* no WAIT */ + FPOFF(l3) RET -TEXT fpenv(SB), $0 /* save state without waiting */ +TEXT fpssesave(SB), $0 /* save state and disable */ MOVL p+0(FP), AX - FSTENV 0(AX) + FXSAVE 0(AX) /* no WAIT */ + FPOFF(l4) RET -TEXT fpclear(SB), $0 /* clear pending exceptions */ +TEXT fpsserestore(SB), $0 /* enable and restore state */ FPON - FCLEX /* no WAIT */ - FPOFF(l3) + MOVL p+0(FP), AX + FXRSTOR 0(AX) + WAIT + RET + +TEXT ldmxcsr(SB), $0 /* Load MXCSR */ + LDMXCSR mxcsr+0(FP) RET /* diff --git a/sys/src/9/xen/main.c b/sys/src/9/xen/main.c index 19af3a820..76bdfe2f5 100644 --- a/sys/src/9/xen/main.c +++ b/sys/src/9/xen/main.c @@ -322,133 +322,6 @@ confinit(void) } } -static char* mathmsg[] = -{ - nil, /* handled below */ - "denormalized operand", - "division by zero", - "numeric overflow", - "numeric underflow", - "precision loss", -}; - -static void -mathnote(void) -{ - int i; - ulong status; - char *msg, note[ERRMAX]; - - status = up->fpsave->status; - - /* - * Some attention should probably be paid here to the - * exception masks and error summary. - */ - msg = "unknown exception"; - for(i = 1; i <= 5; i++){ - if(!((1<<i) & status)) - continue; - msg = mathmsg[i]; - break; - } - if(status & 0x01){ - if(status & 0x40){ - if(status & 0x200) - msg = "stack overflow"; - else - msg = "stack underflow"; - }else - msg = "invalid operation"; - } - snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux", - msg, up->fpsave->pc, status); - postnote(up, 1, note, NDebug); -} - -/* - * math coprocessor error - */ -static void -matherror(Ureg *ur, void*) -{ - /* - * a write cycle to port 0xF0 clears the interrupt latch attached - * to the error# line from the 387 - */ - if(!(m->cpuiddx & 0x01)) - outb(0xF0, 0xFF); - - /* - * save floating point state to check out error - */ - fpenv(up->fpsave); - mathnote(); - - if(ur->pc & KZERO) - panic("fp: status %ux fppc=0x%lux pc=0x%lux", - up->fpsave->status, up->fpsave->pc, ur->pc); -} - -/* - * math coprocessor emulation fault - */ -static void -mathemu(Ureg *ureg, void*) -{ - if(up->fpstate & FPillegal){ - /* someone did floating point in a note handler */ - postnote(up, 1, "sys: floating point in note handler", NDebug); - return; - } - switch(up->fpstate){ - case FPinit: - fpinit(); - while(up->fpsave == nil) - up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0); - up->fpstate = FPactive; - break; - case FPinactive: - /* - * Before restoring the state, check for any pending - * exceptions, there's no way to restore the state without - * generating an unmasked exception. - * More attention should probably be paid here to the - * exception masks and error summary. - */ - if((up->fpsave->status & ~up->fpsave->control) & 0x07F){ - mathnote(); - break; - } - fprestore(up->fpsave); - up->fpstate = FPactive; - break; - case FPactive: - panic("math emu pid %ld %s pc 0x%lux", - up->pid, up->text, ureg->pc); - break; - } -} - -/* - * math coprocessor segment overrun - */ -static void -mathover(Ureg*, void*) -{ - pexit("math overrun", 0); -} - -void -mathinit(void) -{ - trapenable(VectorCERR, matherror, 0, "matherror"); - //if(X86FAMILY(m->cpuidax) == 3) - // intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); - trapenable(VectorCNA, mathemu, 0, "mathemu"); - trapenable(VectorCSO, mathover, 0, "mathover"); -} - /* * set up floating point for a new process */ diff --git a/sys/src/9/xen/mkfile b/sys/src/9/xen/mkfile index e97857c01..befd7aed9 100644 --- a/sys/src/9/xen/mkfile +++ b/sys/src/9/xen/mkfile @@ -68,6 +68,7 @@ OBJ=\ plan9l.$O\ xen.$O\ main.$O\ + fpu.$O\ mmu.$O\ random.$O\ rdb.$O\ diff --git a/sys/src/cmd/aux/kbdfs/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c index 8a57b52fc..a7a5a6966 100644 --- a/sys/src/cmd/aux/kbdfs/kbdfs.c +++ b/sys/src/cmd/aux/kbdfs/kbdfs.c @@ -179,7 +179,7 @@ Rune kbtabesc1[Nscan] = [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome, [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend, [0x50] Kdown, Kpgdown,Kins, Kdel, 0, 0, 0, 0, -[0x58] 0, 0, 0, 0, 0, 0, 0, 0, +[0x58] 0, 0, 0, Kmod4, 0, 0, 0, 0, [0x60] 0, 0, 0, 0, 0, 0, 0, 0, [0x68] 0, 0, 0, 0, 0, 0, 0, 0, [0x70] 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/sys/src/cmd/aux/statusbar.c b/sys/src/cmd/aux/statusbar.c index 02d85176f..6d2db3295 100644 --- a/sys/src/cmd/aux/statusbar.c +++ b/sys/src/cmd/aux/statusbar.c @@ -21,10 +21,10 @@ initcolor(void) text = display->black; light = allocimagemix(display, DPalegreen, DWhite); dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen); + if(light == nil || dark == nil) sysfatal("initcolor: %r"); } Rectangle rbar; -Point ptext; vlong n, d; int last; int lastp = -1; @@ -75,7 +75,7 @@ drawbar(void) if(lastp != p){ sprint(buf, "%3d%%", p); - stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP); + stringbg(screen, Pt(screen->r.max.x-4-stringwidth(display->defaultfont, buf), screen->r.min.y+4), text, ZP, display->defaultfont, buf, light, ZP); lastp = p; } @@ -94,24 +94,13 @@ drawbar(void) void eresized(int new) { - Point p, q; - Rectangle r; - if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); - r = screen->r; - draw(screen, r, light, nil, ZP); - p = string(screen, addpt(r.min, Pt(4,4)), text, ZP, - display->defaultfont, title); - - p.x = r.min.x+4; - p.y += display->defaultfont->height+4; - - q = subpt(r.max, Pt(4,4)); - rbar = Rpt(p, q); - - ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4); + draw(screen, screen->r, light, nil, ZP); + if(title) string(screen, addpt(screen->r.min, Pt(4,4)), text, ZP, font, title); + rbar = insetrect(screen->r, 4); + rbar.min.y += font->height + 4; border(screen, rbar, -2, dark, ZP); last = 0; lastp = -1; @@ -163,7 +152,7 @@ bar(Biobuf *b) void usage(void) { - fprint(2, "usage: aux/statusbar [-kt] [-w minx,miny,maxx,maxy] 'title'\n"); + fprint(2, "usage: %s [-kt] [-w minx,miny,maxx,maxy] [title]\n", argv0); exits("usage"); } @@ -190,11 +179,14 @@ main(int argc, char **argv) usage(); }ARGEND; - if(argc != 1) + switch(argc){ + default: usage(); - - title = argv[0]; - + case 1: + title = argv[0]; + case 0: + break; + } lfd = dup(0, -1); while(q = strchr(p, ',')) @@ -204,7 +196,7 @@ main(int argc, char **argv) textmode = 1; rbar = Rect(0, 0, 60, 1); }else{ - if(initdraw(0, 0, title) < 0) + if(initdraw(0, 0, title ? title : argv0) < 0) exits("initdraw"); initcolor(); einit(Emouse|Ekeyboard); diff --git a/sys/src/cmd/aux/statusmsg.c b/sys/src/cmd/aux/statusmsg.c index 1133a090a..fa2f4790b 100644 --- a/sys/src/cmd/aux/statusmsg.c +++ b/sys/src/cmd/aux/statusmsg.c @@ -22,6 +22,7 @@ initcolor(void) { text = display->black; light = allocimagemix(display, DPalegreen, DWhite); + if(light == nil) sysfatal("initcolor: %r"); } void @@ -136,7 +137,6 @@ main(int argc, char **argv) usage(); case 1: title = argv[0]; - break; case 0: break; } @@ -153,7 +153,7 @@ main(int argc, char **argv) if((bout = Bfdopen(1, OWRITE)) == nil) sysfatal("Bfdopen: %r"); }else{ - if(initdraw(0, 0, title) < 0) + if(initdraw(0, 0, title ? title : argv0) < 0) sysfatal("initdraw: %r"); initcolor(); einit(Emouse|Ekeyboard); diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index 98080347d..3fb3a6d5e 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -37,7 +37,7 @@ char *patternfile; char *origargs; char *srvname = "ncpu"; -char *exportfs = "/bin/exportfs"; +char *exportfs = "/bin/oexportfs"; char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ diff --git a/sys/src/cmd/exportfs/exportfs.c b/sys/src/cmd/exportfs/exportfs.c index 275151a6c..b17cec499 100644 --- a/sys/src/cmd/exportfs/exportfs.c +++ b/sys/src/cmd/exportfs/exportfs.c @@ -1,135 +1,44 @@ -/* - * exportfs - Export a plan 9 name space across a network - */ #include <u.h> #include <libc.h> -#include <auth.h> #include <fcall.h> -#include <libsec.h> #define Extern #include "exportfs.h" -#define QIDPATH ((1LL<<48)-1) -vlong newqid = 0; - -enum { - Encnone, - Encssl, - Enctls, -}; - -void (*fcalls[])(Fsrpc*) = -{ - [Tversion] Xversion, - [Tauth] Xauth, - [Tflush] Xflush, - [Tattach] Xattach, - [Twalk] Xwalk, - [Topen] slave, - [Tcreate] Xcreate, - [Tclunk] Xclunk, - [Tread] slave, - [Twrite] slave, - [Tremove] Xremove, - [Tstat] Xstat, - [Twstat] Xwstat, -}; - -/* accounting and debugging counters */ -int filecnt; -int freecnt; -int qidcnt; -int qfreecnt; -int ncollision; - int srvfd = -1; -int nonone = 1; -char *filterp; -char *ealgs = "rc4_256 sha1"; -char *aanfilter = "/bin/aan"; -int encproto = Encnone; int readonly; -static void mksecret(char *, uchar *); -static char *anstring = "tcp!*!0"; - -char *netdir = "", *local = "", *remote = ""; - -void filter(int, char *, char *); - void usage(void) { - fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] " - "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] " - "[-A announce-string] [-B address]\n", argv0); + fprint(2, "usage: %s [-dsR] [-f dbgfile] [-m msize] [-r root] " + "[-S srvfile] [-P exclusion-file]\n", argv0); fatal("usage"); } -static void -noteconn(int fd) -{ - NetConnInfo *nci; - - nci = getnetconninfo(nil, fd); - if(nci == nil) - return; - netdir = estrdup(nci->dir); - local = estrdup(nci->lsys); - remote = estrdup(nci->rsys); - freenetconninfo(nci); -} - void main(int argc, char **argv) { - char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; - char *dbfile, *srv, *na, *nsfile, *keyspec; - int doauth, n, fd; - AuthInfo *ai; - Fsrpc *r; + char *dbfile, *srv, *srvfdfile; + int n; dbfile = "/tmp/exportdb"; srv = nil; srvfd = -1; srvfdfile = nil; - na = nil; - nsfile = nil; - keyspec = ""; - doauth = 0; - ai = nil; ARGBEGIN{ - case 'a': - doauth = 1; - break; - case 'd': dbg++; break; - case 'e': - ealgs = EARGF(usage()); - if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) - ealgs = nil; - break; - case 'f': dbfile = EARGF(usage()); break; - case 'k': - keyspec = EARGF(usage()); - break; - case 'm': messagesize = strtoul(EARGF(usage()), nil, 0); break; - case 'n': - nonone = 0; - break; - case 'r': srv = EARGF(usage()); break; @@ -138,22 +47,10 @@ main(int argc, char **argv) srv = "/"; break; - case 'A': - anstring = EARGF(usage()); - break; - - case 'B': - na = EARGF(usage()); - break; - case 'F': /* accepted but ignored, for backwards compatibility */ break; - case 'N': - nsfile = EARGF(usage()); - break; - case 'P': patternfile = EARGF(usage()); break; @@ -173,52 +70,15 @@ main(int argc, char **argv) }ARGEND USED(argc, argv); - if(na == nil && doauth){ - /* - * We use p9any so we don't have to visit this code again, with the - * cost that this code is incompatible with the old world, which - * requires p9sk2. (The two differ in who talks first, so compatibility - * is awkward.) - */ - ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec); - if(ai == nil) - fatal("auth_proxy: %r"); - if(nonone && strcmp(ai->cuid, "none") == 0) - fatal("exportfs by none disallowed"); - if(auth_chuid(ai, nsfile) < 0) - fatal("auth_chuid: %r"); - else { /* chown network connection */ - Dir nd; - nulldir(&nd); - nd.mode = 0660; - nd.uid = ai->cuid; - dirfwstat(0, &nd); - } - putenv("service", "exportfs"); - } - if(srvfdfile != nil){ + if(srv != nil){ + fprint(2, "exportfs: -S cannot be used with -r or -s\n"); + usage(); + } if((srvfd = open(srvfdfile, ORDWR)) < 0) fatal("open %s: %r", srvfdfile); - } - - if(na != nil){ - if(srv == nil) - fatal("-B requires -s"); - - local = "me"; - remote = na; - if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) - fatal("can't dial %s: %r", na); - - ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); - if(ai == nil) - fatal("%r: %s", na); - - dup(fd, 0); - dup(fd, 1); - close(fd); - } + } else if(srv == nil) + usage(); exclusions(); @@ -228,11 +88,6 @@ main(int argc, char **argv) close(n); } - if(srvfd >= 0 && srv != nil){ - fprint(2, "exportfs: -S cannot be used with -r or -s\n"); - usage(); - } - DEBUG(DFD, "exportfs: started\n"); rfork(RFNOTEG|RFREND); @@ -246,695 +101,18 @@ main(int argc, char **argv) fmtinstall('F', fcallfmt); - /* - * Get tree to serve from network connection, - * check we can get there and ack the connection - */ - if(srvfd != -1) { - /* do nothing */ - } - else if(srv != nil) { + if(srvfd == -1) { if(chdir(srv) < 0) { + char ebuf[ERRMAX]; ebuf[0] = '\0'; errstr(ebuf, sizeof ebuf); - r = getsbuf(); - r->work.tag = NOTAG; - r->work.fid = NOFID; - r->work.type = Rerror; - r->work.ename = ebuf; - n = convS2M(&r->work, r->buf, messagesize); - write(0, r->buf, n); DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf); - exits(ebuf); + mounterror(ebuf); } DEBUG(DFD, "invoked as server for %s", srv); - strncpy(buf, srv, sizeof buf); - } - else { - noteconn(0); - buf[0] = 0; - n = read(0, buf, sizeof(buf)-1); - if(n < 0) { - errstr(buf, sizeof buf); - fprint(0, "read(0): %s\n", buf); - DEBUG(DFD, "read(0): %s\n", buf); - exits(buf); - } - buf[n] = 0; - if(chdir(buf) < 0) { - errstr(ebuf, sizeof ebuf); - fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); - DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); - exits(ebuf); - } } DEBUG(DFD, "\niniting root\n"); initroot(); - - DEBUG(DFD, "exportfs: %s\n", buf); - - if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) - fatal("open ack write"); - - ini = initial; - n = readn(0, initial, sizeof(initial)); - if(n == 0) - fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */ - if(n < sizeof(initial)) - fatal("can't read initial string: %r"); - - if(memcmp(ini, "impo", 4) == 0) { - char buf[128], *p, *args[3]; - - ini = nil; - p = buf; - for(;;){ - if((n = read(0, p, 1)) < 0) - fatal("can't read impo arguments: %r"); - if(n == 0) - fatal("connection closed while reading arguments"); - if(*p == '\n') - *p = '\0'; - if(*p++ == '\0') - break; - if(p >= buf + sizeof(buf)) - fatal("import parameters too long"); - } - - if(tokenize(buf, args, nelem(args)) != 2) - fatal("impo arguments invalid: impo%s...", buf); - - if(strcmp(args[0], "aan") == 0) - filterp = aanfilter; - else if(strcmp(args[0], "nofilter") != 0) - fatal("import filter argument unsupported: %s", args[0]); - - if(strcmp(args[1], "ssl") == 0) - encproto = Encssl; - else if(strcmp(args[1], "tls") == 0) - encproto = Enctls; - else if(strcmp(args[1], "clear") != 0) - fatal("import encryption proto unsupported: %s", args[1]); - - if(encproto == Enctls) - fatal("%s: tls has not yet been implemented", argv[0]); - } - - if(encproto != Encnone && ealgs != nil && ai != nil) { - uchar key[16], digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - - if(ai->nsecret < 8) - fatal("secret too small for ssl"); - memmove(key+4, ai->secret, 8); - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i+12] = rand(); - - if(ini != nil) - fatal("Protocol botch: old import"); - if(readn(0, key, 4) != 4) - fatal("can't read key part; %r"); - - if(write(0, key+12, 4) != 4) - fatal("can't write key part; %r"); - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - if(filterp != nil) - filter(0, filterp, na); - - switch(encproto) { - case Encssl: - fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); - if(fd < 0) - fatal("can't establish ssl connection: %r"); - if(fd != 0){ - dup(fd, 0); - close(fd); - } - break; - case Enctls: - default: - fatal("Unsupported encryption protocol"); - } - } - else if(filterp != nil) { - if(ini != nil) - fatal("Protocol botch: don't know how to deal with this"); - filter(0, filterp, na); - } - dup(0, 1); - - if(ai != nil) - auth_freeAI(ai); - - if(ini != nil){ - r = getsbuf(); - memmove(r->buf, ini, BIT32SZ); - n = GBIT32(r->buf); - if(n <= BIT32SZ || n > messagesize) - fatal("bad length in 9P2000 message header"); - n -= BIT32SZ; - if(readn(0, r->buf+BIT32SZ, n) != n) - fatal(nil); - n += BIT32SZ; - goto Message; - } - - /* - * Start serving file requests from the network - */ - for(;;) { - r = getsbuf(); - n = read9pmsg(0, r->buf, messagesize); - if(n <= 0) - fatal(nil); - Message: - if(convM2S(r->buf, n, &r->work) != n) - fatal("convM2S format error"); - - DEBUG(DFD, "%F\n", &r->work); - (fcalls[r->work.type])(r); - } -} - -void -reply(Fcall *r, Fcall *t, char *err) -{ - uchar *data; - int n; - - t->tag = r->tag; - t->fid = r->fid; - if(err != nil) { - t->type = Rerror; - t->ename = err; - } - else - t->type = r->type + 1; - - DEBUG(DFD, "\t%F\n", t); - - data = malloc(messagesize); /* not mallocz; no need to clear */ - if(data == nil) - fatal(Enomem); - n = convS2M(t, data, messagesize); - if(write(0, data, n) != n){ - /* not fatal, might have got a note due to flush */ - fprint(2, "exportfs: short write in reply: %r\n"); - } - free(data); -} - -Fid * -getfid(int nr) -{ - Fid *f; - - for(f = fidhash(nr); f != nil; f = f->next) - if(f->nr == nr) - return f; - - return nil; -} - -int -freefid(int nr) -{ - Fid *f, **l; - char buf[128]; - - l = &fidhash(nr); - for(f = *l; f != nil; f = f->next) { - if(f->nr == nr) { - if(f->mid) { - snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); - unmount(0, buf); - psmap[f->mid] = 0; - } - if(f->f != nil) { - freefile(f->f); - f->f = nil; - } - if(f->dir != nil){ - free(f->dir); - f->dir = nil; - } - *l = f->next; - f->next = fidfree; - fidfree = f; - return 1; - } - l = &f->next; - } - - return 0; -} - -Fid * -newfid(int nr) -{ - Fid *new, **l; - int i; - - l = &fidhash(nr); - for(new = *l; new != nil; new = new->next) - if(new->nr == nr) - return nil; - - if(fidfree == nil) { - fidfree = emallocz(sizeof(Fid) * Fidchunk); - - for(i = 0; i < Fidchunk-1; i++) - fidfree[i].next = &fidfree[i+1]; - - fidfree[Fidchunk-1].next = nil; - } - - new = fidfree; - fidfree = new->next; - - memset(new, 0, sizeof(Fid)); - new->next = *l; - *l = new; - new->nr = nr; - new->fid = -1; - new->mid = 0; - - return new; -} - -static struct { - Lock; - Fsrpc *free; - - /* statistics */ - int nalloc; - int nfree; -} sbufalloc; - -Fsrpc * -getsbuf(void) -{ - Fsrpc *w; - - lock(&sbufalloc); - w = sbufalloc.free; - if(w != nil){ - sbufalloc.free = w->next; - w->next = nil; - sbufalloc.nfree--; - unlock(&sbufalloc); - } else { - sbufalloc.nalloc++; - unlock(&sbufalloc); - w = emallocz(sizeof(*w) + messagesize); - } - w->flushtag = NOTAG; - return w; -} - -void -putsbuf(Fsrpc *w) -{ - w->flushtag = NOTAG; - lock(&sbufalloc); - w->next = sbufalloc.free; - sbufalloc.free = w; - sbufalloc.nfree++; - unlock(&sbufalloc); -} - -void -freefile(File *f) -{ - File *parent, *child; - - while(--f->ref == 0){ - freecnt++; - DEBUG(DFD, "free %s\n", f->name); - /* delete from parent */ - parent = f->parent; - if(parent->child == f) - parent->child = f->childlist; - else{ - for(child = parent->child; child->childlist != f; child = child->childlist) { - if(child->childlist == nil) - fatal("bad child list"); - } - child->childlist = f->childlist; - } - freeqid(f->qidt); - free(f->name); - free(f); - f = parent; - } -} - -File * -file(File *parent, char *name) -{ - Dir *dir; - char *path; - File *f; - - DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); - - path = makepath(parent, name); - if(patternfile != nil && excludefile(path)){ - free(path); - return nil; - } - dir = dirstat(path); - free(path); - if(dir == nil) - return nil; - - for(f = parent->child; f != nil; f = f->childlist) - if(strcmp(name, f->name) == 0) - break; - - if(f == nil){ - f = emallocz(sizeof(File)); - f->name = estrdup(name); - - f->parent = parent; - f->childlist = parent->child; - parent->child = f; - parent->ref++; - f->ref = 0; - filecnt++; - } - f->ref++; - f->qid.type = dir->qid.type; - f->qid.vers = dir->qid.vers; - f->qidt = uniqueqid(dir); - f->qid.path = f->qidt->uniqpath; - - f->inval = 0; - - free(dir); - - return f; -} - -void -initroot(void) -{ - Dir *dir; - - root = emallocz(sizeof(File)); - root->name = estrdup("."); - - dir = dirstat(root->name); - if(dir == nil) - fatal("root stat"); - - root->ref = 1; - root->qid.vers = dir->qid.vers; - root->qidt = uniqueqid(dir); - root->qid.path = root->qidt->uniqpath; - root->qid.type = QTDIR; - free(dir); - - psmpt = emallocz(sizeof(File)); - psmpt->name = estrdup("/"); - - dir = dirstat(psmpt->name); - if(dir == nil) - return; - - psmpt->ref = 1; - psmpt->qid.vers = dir->qid.vers; - psmpt->qidt = uniqueqid(dir); - psmpt->qid.path = psmpt->qidt->uniqpath; - free(dir); - - psmpt = file(psmpt, "mnt"); - if(psmpt == nil) - return; - psmpt = file(psmpt, "exportfs"); -} - -char* -makepath(File *p, char *name) -{ - int i, n; - char *c, *s, *path, *seg[256]; - - seg[0] = name; - n = strlen(name)+2; - for(i = 1; i < 256 && p; i++, p = p->parent){ - seg[i] = p->name; - n += strlen(p->name)+1; - } - path = emallocz(n); - s = path; - - while(i--) { - for(c = seg[i]; *c; c++) - *s++ = *c; - *s++ = '/'; - } - while(s[-1] == '/') - s--; - *s = '\0'; - - return path; -} - -int -qidhash(vlong path) -{ - int h, n; - - h = 0; - for(n=0; n<64; n+=Nqidbits){ - h ^= path; - path >>= Nqidbits; - } - return h & (Nqidtab-1); -} - -void -freeqid(Qidtab *q) -{ - ulong h; - Qidtab *l; - - if(--q->ref) - return; - qfreecnt++; - h = qidhash(q->path); - if(qidtab[h] == q) - qidtab[h] = q->next; - else{ - for(l=qidtab[h]; l->next!=q; l=l->next) - if(l->next == nil) - fatal("bad qid list"); - l->next = q->next; - } - free(q); -} - -Qidtab* -qidlookup(Dir *d) -{ - ulong h; - Qidtab *q; - - h = qidhash(d->qid.path); - for(q=qidtab[h]; q!=nil; q=q->next) - if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) - return q; - return nil; -} - -int -qidexists(vlong path) -{ - int h; - Qidtab *q; - - for(h=0; h<Nqidtab; h++) - for(q=qidtab[h]; q!=nil; q=q->next) - if(q->uniqpath == path) - return 1; - return 0; -} - -Qidtab* -uniqueqid(Dir *d) -{ - ulong h; - vlong path; - Qidtab *q; - - q = qidlookup(d); - if(q != nil){ - q->ref++; - return q; - } - path = d->qid.path; - while(qidexists(path)){ - DEBUG(DFD, "collision on %s\n", d->name); - /* collision: find a new one */ - ncollision++; - path &= QIDPATH; - ++newqid; - if(newqid >= (1<<16)){ - DEBUG(DFD, "collision wraparound\n"); - newqid = 1; - } - path |= newqid<<48; - DEBUG(DFD, "assign qid %.16llux\n", path); - } - qidcnt++; - q = emallocz(sizeof(Qidtab)); - q->ref = 1; - q->type = d->type; - q->dev = d->dev; - q->path = d->qid.path; - q->uniqpath = path; - h = qidhash(d->qid.path); - q->next = qidtab[h]; - qidtab[h] = q; - return q; -} - -void -fatal(char *s, ...) -{ - char buf[ERRMAX]; - va_list arg; - Proc *m; - - if(s != nil) { - va_start(arg, s); - vsnprint(buf, ERRMAX, s, arg); - va_end(arg); - } - - /* Clear away the slave children */ - for(m = Proclist; m != nil; m = m->next) - postnote(PNPROC, m->pid, "kill"); - - if(s != nil) { - DEBUG(DFD, "%s\n", buf); - sysfatal("%s", buf); /* caution: buf could contain '%' */ - } else - exits(nil); -} - -void* -emallocz(uint n) -{ - void *p; - - p = mallocz(n, 1); - if(p == nil) - fatal(Enomem); - setmalloctag(p, getcallerpc(&n)); - return p; -} - -char* -estrdup(char *s) -{ - char *t; - - t = strdup(s); - if(t == nil) - fatal(Enomem); - setmalloctag(t, getcallerpc(&s)); - return t; -} - -void -filter(int fd, char *cmd, char *host) -{ - char addr[128], buf[256], *s, *file, *argv[16]; - int lfd, p[2], len, argc; - - if(host == nil){ - /* Get a free port and post it to the client. */ - if (announce(anstring, addr) < 0) - fatal("filter: Cannot announce %s: %r", anstring); - - snprint(buf, sizeof(buf), "%s/local", addr); - if ((lfd = open(buf, OREAD)) < 0) - fatal("filter: Cannot open %s: %r", buf); - if ((len = read(lfd, buf, sizeof buf - 1)) < 0) - fatal("filter: Cannot read %s: %r", buf); - close(lfd); - buf[len] = '\0'; - if ((s = strchr(buf, '\n')) != nil) - len = s - buf; - if (write(fd, buf, len) != len) - fatal("filter: cannot write port; %r"); - } else { - /* Read address string from connection */ - if ((len = read(fd, buf, sizeof buf - 1)) < 0) - sysfatal("filter: cannot write port; %r"); - buf[len] = '\0'; - - if ((s = strrchr(buf, '!')) == nil) - sysfatal("filter: illegally formatted port %s", buf); - strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); - strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); - } - - DEBUG(DFD, "filter: %s\n", addr); - - snprint(buf, sizeof(buf), "%s", cmd); - argc = tokenize(buf, argv, nelem(argv)-3); - if (argc == 0) - sysfatal("filter: empty command"); - - if(host != nil) - argv[argc++] = "-c"; - argv[argc++] = addr; - argv[argc] = nil; - - file = argv[0]; - if((s = strrchr(argv[0], '/')) != nil) - argv[0] = s+1; - - if(pipe(p) < 0) - sysfatal("pipe: %r"); - - switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { - case -1: - fatal("filter: rfork; %r\n"); - case 0: - close(fd); - if (dup(p[0], 1) < 0) - fatal("filter: Cannot dup to 1; %r"); - if (dup(p[0], 0) < 0) - fatal("filter: Cannot dup to 0; %r"); - close(p[0]); - close(p[1]); - exec(file, argv); - fatal("filter: exec; %r"); - default: - dup(p[1], fd); - close(p[0]); - close(p[1]); - } -} - -static void -mksecret(char *t, uchar *f) -{ - sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", - f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); + io(); } diff --git a/sys/src/cmd/exportfs/exportfs.h b/sys/src/cmd/exportfs/exportfs.h index b3587fab2..344304b7c 100644 --- a/sys/src/cmd/exportfs/exportfs.h +++ b/sys/src/cmd/exportfs/exportfs.h @@ -112,7 +112,10 @@ void Xwalk(Fsrpc*); void Xwstat(Fsrpc*); void slave(Fsrpc*); +void io(void); void reply(Fcall*, Fcall*, char*); +void mounterror(char*); + Fid *getfid(int); int freefid(int); Fid *newfid(int); diff --git a/sys/src/cmd/exportfs/exportsrv.c b/sys/src/cmd/exportfs/exportsrv.c index a413ed0dc..b7ddd64b5 100644 --- a/sys/src/cmd/exportfs/exportsrv.c +++ b/sys/src/cmd/exportfs/exportsrv.c @@ -5,8 +5,6 @@ #define Extern extern #include "exportfs.h" -extern char *netdir, *local, *remote; - char Ebadfid[] = "Bad fid"; char Enotdir[] = "Not a directory"; char Edupfid[] = "Fid already in use"; @@ -493,12 +491,6 @@ slave(Fsrpc *f) return; case 0: - if (local[0] != '\0') - if (netdir[0] != '\0') - procsetname("%s: %s -> %s", netdir, - local, remote); - else - procsetname("%s -> %s", local, remote); blockingslave(m); _exits(0); diff --git a/sys/src/cmd/exportfs/io.c b/sys/src/cmd/exportfs/io.c new file mode 100644 index 000000000..ad1d7154b --- /dev/null +++ b/sys/src/cmd/exportfs/io.c @@ -0,0 +1,503 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#define Extern +#include "exportfs.h" + +#define QIDPATH ((1LL<<48)-1) +vlong newqid = 0; + +void (*fcalls[])(Fsrpc*) = +{ + [Tversion] Xversion, + [Tauth] Xauth, + [Tflush] Xflush, + [Tattach] Xattach, + [Twalk] Xwalk, + [Topen] slave, + [Tcreate] Xcreate, + [Tclunk] Xclunk, + [Tread] slave, + [Twrite] slave, + [Tremove] Xremove, + [Tstat] Xstat, + [Twstat] Xwstat, +}; + +/* accounting and debugging counters */ +int filecnt; +int freecnt; +int qidcnt; +int qfreecnt; +int ncollision; + + +/* + * Start serving file requests from the network + */ +void +io(void) +{ + Fsrpc *r; + int n; + + for(;;) { + r = getsbuf(); + n = read9pmsg(0, r->buf, messagesize); + if(n <= 0) + fatal(nil); + if(convM2S(r->buf, n, &r->work) != n) + fatal("convM2S format error"); + + DEBUG(DFD, "%F\n", &r->work); + (fcalls[r->work.type])(r); + } +} + +void +reply(Fcall *r, Fcall *t, char *err) +{ + uchar *data; + int n; + + t->tag = r->tag; + t->fid = r->fid; + if(err != nil) { + t->type = Rerror; + t->ename = err; + } + else + t->type = r->type + 1; + + DEBUG(DFD, "\t%F\n", t); + + data = malloc(messagesize); /* not mallocz; no need to clear */ + if(data == nil) + fatal(Enomem); + n = convS2M(t, data, messagesize); + if(write(1, data, n) != n){ + /* not fatal, might have got a note due to flush */ + fprint(2, "exportfs: short write in reply: %r\n"); + } + free(data); +} + +void +mounterror(char *err) +{ + Fsrpc *r; + int n; + + r = getsbuf(); + r->work.tag = NOTAG; + r->work.fid = NOFID; + r->work.type = Rerror; + r->work.ename = err; + n = convS2M(&r->work, r->buf, messagesize); + write(1, r->buf, n); + exits(err); +} + +Fid * +getfid(int nr) +{ + Fid *f; + + for(f = fidhash(nr); f != nil; f = f->next) + if(f->nr == nr) + return f; + + return nil; +} + +int +freefid(int nr) +{ + Fid *f, **l; + char buf[128]; + + l = &fidhash(nr); + for(f = *l; f != nil; f = f->next) { + if(f->nr == nr) { + if(f->mid) { + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); + unmount(0, buf); + psmap[f->mid] = 0; + } + if(f->f != nil) { + freefile(f->f); + f->f = nil; + } + if(f->dir != nil){ + free(f->dir); + f->dir = nil; + } + *l = f->next; + f->next = fidfree; + fidfree = f; + return 1; + } + l = &f->next; + } + + return 0; +} + +Fid * +newfid(int nr) +{ + Fid *new, **l; + int i; + + l = &fidhash(nr); + for(new = *l; new != nil; new = new->next) + if(new->nr == nr) + return nil; + + if(fidfree == nil) { + fidfree = emallocz(sizeof(Fid) * Fidchunk); + + for(i = 0; i < Fidchunk-1; i++) + fidfree[i].next = &fidfree[i+1]; + + fidfree[Fidchunk-1].next = nil; + } + + new = fidfree; + fidfree = new->next; + + memset(new, 0, sizeof(Fid)); + new->next = *l; + *l = new; + new->nr = nr; + new->fid = -1; + new->mid = 0; + + return new; +} + +static struct { + Lock; + Fsrpc *free; + + /* statistics */ + int nalloc; + int nfree; +} sbufalloc; + +Fsrpc * +getsbuf(void) +{ + Fsrpc *w; + + lock(&sbufalloc); + w = sbufalloc.free; + if(w != nil){ + sbufalloc.free = w->next; + w->next = nil; + sbufalloc.nfree--; + unlock(&sbufalloc); + } else { + sbufalloc.nalloc++; + unlock(&sbufalloc); + w = emallocz(sizeof(*w) + messagesize); + } + w->flushtag = NOTAG; + return w; +} + +void +putsbuf(Fsrpc *w) +{ + w->flushtag = NOTAG; + lock(&sbufalloc); + w->next = sbufalloc.free; + sbufalloc.free = w; + sbufalloc.nfree++; + unlock(&sbufalloc); +} + +void +freefile(File *f) +{ + File *parent, *child; + + while(--f->ref == 0){ + freecnt++; + DEBUG(DFD, "free %s\n", f->name); + /* delete from parent */ + parent = f->parent; + if(parent->child == f) + parent->child = f->childlist; + else{ + for(child = parent->child; child->childlist != f; child = child->childlist) { + if(child->childlist == nil) + fatal("bad child list"); + } + child->childlist = f->childlist; + } + freeqid(f->qidt); + free(f->name); + free(f); + f = parent; + } +} + +File * +file(File *parent, char *name) +{ + Dir *dir; + char *path; + File *f; + + DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); + + path = makepath(parent, name); + if(patternfile != nil && excludefile(path)){ + free(path); + return nil; + } + dir = dirstat(path); + free(path); + if(dir == nil) + return nil; + + for(f = parent->child; f != nil; f = f->childlist) + if(strcmp(name, f->name) == 0) + break; + + if(f == nil){ + f = emallocz(sizeof(File)); + f->name = estrdup(name); + + f->parent = parent; + f->childlist = parent->child; + parent->child = f; + parent->ref++; + f->ref = 0; + filecnt++; + } + f->ref++; + f->qid.type = dir->qid.type; + f->qid.vers = dir->qid.vers; + f->qidt = uniqueqid(dir); + f->qid.path = f->qidt->uniqpath; + + f->inval = 0; + + free(dir); + + return f; +} + +void +initroot(void) +{ + Dir *dir; + + root = emallocz(sizeof(File)); + root->name = estrdup("."); + + dir = dirstat(root->name); + if(dir == nil) + fatal("root stat"); + + root->ref = 1; + root->qid.vers = dir->qid.vers; + root->qidt = uniqueqid(dir); + root->qid.path = root->qidt->uniqpath; + root->qid.type = QTDIR; + free(dir); + + psmpt = emallocz(sizeof(File)); + psmpt->name = estrdup("/"); + + dir = dirstat(psmpt->name); + if(dir == nil) + return; + + psmpt->ref = 1; + psmpt->qid.vers = dir->qid.vers; + psmpt->qidt = uniqueqid(dir); + psmpt->qid.path = psmpt->qidt->uniqpath; + free(dir); + + psmpt = file(psmpt, "mnt"); + if(psmpt == nil) + return; + psmpt = file(psmpt, "exportfs"); +} + +char* +makepath(File *p, char *name) +{ + int i, n; + char *c, *s, *path, *seg[256]; + + seg[0] = name; + n = strlen(name)+2; + for(i = 1; i < 256 && p; i++, p = p->parent){ + seg[i] = p->name; + n += strlen(p->name)+1; + } + path = emallocz(n); + s = path; + + while(i--) { + for(c = seg[i]; *c; c++) + *s++ = *c; + *s++ = '/'; + } + while(s[-1] == '/') + s--; + *s = '\0'; + + return path; +} + +int +qidhash(vlong path) +{ + int h, n; + + h = 0; + for(n=0; n<64; n+=Nqidbits){ + h ^= path; + path >>= Nqidbits; + } + return h & (Nqidtab-1); +} + +void +freeqid(Qidtab *q) +{ + ulong h; + Qidtab *l; + + if(--q->ref) + return; + qfreecnt++; + h = qidhash(q->path); + if(qidtab[h] == q) + qidtab[h] = q->next; + else{ + for(l=qidtab[h]; l->next!=q; l=l->next) + if(l->next == nil) + fatal("bad qid list"); + l->next = q->next; + } + free(q); +} + +Qidtab* +qidlookup(Dir *d) +{ + ulong h; + Qidtab *q; + + h = qidhash(d->qid.path); + for(q=qidtab[h]; q!=nil; q=q->next) + if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) + return q; + return nil; +} + +int +qidexists(vlong path) +{ + int h; + Qidtab *q; + + for(h=0; h<Nqidtab; h++) + for(q=qidtab[h]; q!=nil; q=q->next) + if(q->uniqpath == path) + return 1; + return 0; +} + +Qidtab* +uniqueqid(Dir *d) +{ + ulong h; + vlong path; + Qidtab *q; + + q = qidlookup(d); + if(q != nil){ + q->ref++; + return q; + } + path = d->qid.path; + while(qidexists(path)){ + DEBUG(DFD, "collision on %s\n", d->name); + /* collision: find a new one */ + ncollision++; + path &= QIDPATH; + ++newqid; + if(newqid >= (1<<16)){ + DEBUG(DFD, "collision wraparound\n"); + newqid = 1; + } + path |= newqid<<48; + DEBUG(DFD, "assign qid %.16llux\n", path); + } + qidcnt++; + q = emallocz(sizeof(Qidtab)); + q->ref = 1; + q->type = d->type; + q->dev = d->dev; + q->path = d->qid.path; + q->uniqpath = path; + h = qidhash(d->qid.path); + q->next = qidtab[h]; + qidtab[h] = q; + return q; +} + +void +fatal(char *s, ...) +{ + char buf[ERRMAX]; + va_list arg; + Proc *m; + + if(s != nil) { + va_start(arg, s); + vsnprint(buf, ERRMAX, s, arg); + va_end(arg); + } + + /* Clear away the slave children */ + for(m = Proclist; m != nil; m = m->next) + postnote(PNPROC, m->pid, "kill"); + + if(s != nil) { + DEBUG(DFD, "%s\n", buf); + sysfatal("%s", buf); /* caution: buf could contain '%' */ + } else + exits(nil); +} + +void* +emallocz(uint n) +{ + void *p; + + p = mallocz(n, 1); + if(p == nil) + fatal(Enomem); + setmalloctag(p, getcallerpc(&n)); + return p; +} + +char* +estrdup(char *s) +{ + char *t; + + t = strdup(s); + if(t == nil) + fatal(Enomem); + setmalloctag(t, getcallerpc(&s)); + return t; +} diff --git a/sys/src/cmd/exportfs/mkfile b/sys/src/cmd/exportfs/mkfile index cf1f51451..df89c4def 100644 --- a/sys/src/cmd/exportfs/mkfile +++ b/sys/src/cmd/exportfs/mkfile @@ -1,10 +1,10 @@ </$objtype/mkfile -TARG=exportfs +TARG=exportfs oexportfs OFILES=\ - exportfs.$O\ exportsrv.$O\ pattern.$O\ + io.$O\ HFILES=exportfs.h\ @@ -15,4 +15,4 @@ UPDATE=\ $HFILES\ ${OFILES:%.$O=%.c}\ -</sys/src/cmd/mkone +</sys/src/cmd/mkmany diff --git a/sys/src/cmd/exportfs/oexportfs.c b/sys/src/cmd/exportfs/oexportfs.c new file mode 100644 index 000000000..c6683a174 --- /dev/null +++ b/sys/src/cmd/exportfs/oexportfs.c @@ -0,0 +1,443 @@ +/* + * oexportfs - legacy exportfs for cpu and import + */ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <fcall.h> +#include <libsec.h> +#define Extern +#include "exportfs.h" + +enum { + Encnone, + Encssl, + Enctls, +}; + +int srvfd = -1; +int nonone = 1; +char *filterp; +char *ealgs = "rc4_256 sha1"; +char *aanfilter = "/bin/aan"; +int encproto = Encnone; +int readonly; + +static char *anstring = "tcp!*!0"; + +static void +filter(int fd, char *cmd, char *host) +{ + char addr[128], buf[256], *s, *file, *argv[16]; + int lfd, p[2], len, argc; + + if(host == nil){ + /* Get a free port and post it to the client. */ + if (announce(anstring, addr) < 0) + fatal("filter: Cannot announce %s: %r", anstring); + + snprint(buf, sizeof(buf), "%s/local", addr); + if ((lfd = open(buf, OREAD)) < 0) + fatal("filter: Cannot open %s: %r", buf); + if ((len = read(lfd, buf, sizeof buf - 1)) < 0) + fatal("filter: Cannot read %s: %r", buf); + close(lfd); + buf[len] = '\0'; + if ((s = strchr(buf, '\n')) != nil) + len = s - buf; + if (write(fd, buf, len) != len) + fatal("filter: cannot write port; %r"); + } else { + /* Read address string from connection */ + if ((len = read(fd, buf, sizeof buf - 1)) < 0) + sysfatal("filter: cannot write port; %r"); + buf[len] = '\0'; + + if ((s = strrchr(buf, '!')) == nil) + sysfatal("filter: illegally formatted port %s", buf); + strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); + strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); + } + + DEBUG(DFD, "filter: %s\n", addr); + + snprint(buf, sizeof(buf), "%s", cmd); + argc = tokenize(buf, argv, nelem(argv)-3); + if (argc == 0) + sysfatal("filter: empty command"); + + if(host != nil) + argv[argc++] = "-c"; + argv[argc++] = addr; + argv[argc] = nil; + + file = argv[0]; + if((s = strrchr(argv[0], '/')) != nil) + argv[0] = s+1; + + if(pipe(p) < 0) + sysfatal("pipe: %r"); + + switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { + case -1: + fatal("filter: rfork; %r\n"); + case 0: + close(fd); + if (dup(p[0], 1) < 0) + fatal("filter: Cannot dup to 1; %r"); + if (dup(p[0], 0) < 0) + fatal("filter: Cannot dup to 0; %r"); + close(p[0]); + close(p[1]); + exec(file, argv); + fatal("filter: exec; %r"); + default: + dup(p[1], fd); + close(p[0]); + close(p[1]); + } +} + +static void +mksecret(char *t, uchar *f) +{ + sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", + f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] " + "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] " + "[-A announce-string] [-B address]\n", argv0); + fatal("usage"); +} + +void +main(int argc, char **argv) +{ + char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; + char *dbfile, *srv, *na, *nsfile, *keyspec; + int doauth, n, fd; + AuthInfo *ai; + Fsrpc *r; + + dbfile = "/tmp/exportdb"; + srv = nil; + srvfd = -1; + srvfdfile = nil; + na = nil; + nsfile = nil; + keyspec = ""; + doauth = 0; + + ai = nil; + ARGBEGIN{ + case 'a': + doauth = 1; + break; + + case 'd': + dbg++; + break; + + case 'e': + ealgs = EARGF(usage()); + if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) + ealgs = nil; + break; + + case 'f': + dbfile = EARGF(usage()); + break; + + case 'k': + keyspec = EARGF(usage()); + break; + + case 'm': + messagesize = strtoul(EARGF(usage()), nil, 0); + break; + + case 'n': + nonone = 0; + break; + + case 'r': + srv = EARGF(usage()); + break; + + case 's': + srv = "/"; + break; + + case 'A': + anstring = EARGF(usage()); + break; + + case 'B': + na = EARGF(usage()); + break; + + case 'F': + /* accepted but ignored, for backwards compatibility */ + break; + + case 'N': + nsfile = EARGF(usage()); + break; + + case 'P': + patternfile = EARGF(usage()); + break; + + case 'R': + readonly = 1; + break; + + case 'S': + if(srvfdfile != nil) + usage(); + srvfdfile = EARGF(usage()); + break; + + default: + usage(); + }ARGEND + USED(argc, argv); + + if(na == nil && doauth){ + /* + * We use p9any so we don't have to visit this code again, with the + * cost that this code is incompatible with the old world, which + * requires p9sk2. (The two differ in who talks first, so compatibility + * is awkward.) + */ + ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec); + if(ai == nil) + fatal("auth_proxy: %r"); + if(nonone && strcmp(ai->cuid, "none") == 0) + fatal("exportfs by none disallowed"); + if(auth_chuid(ai, nsfile) < 0) + fatal("auth_chuid: %r"); + else { /* chown network connection */ + Dir nd; + nulldir(&nd); + nd.mode = 0660; + nd.uid = ai->cuid; + dirfwstat(0, &nd); + } + putenv("service", "exportfs"); + } + + if(srvfdfile != nil){ + if((srvfd = open(srvfdfile, ORDWR)) < 0) + fatal("open %s: %r", srvfdfile); + } + + if(na != nil){ + if(srv == nil) + fatal("-B requires -s"); + + if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) + fatal("can't dial %s: %r", na); + + ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); + if(ai == nil) + fatal("%r: %s", na); + + dup(fd, 0); + dup(fd, 1); + close(fd); + } + + exclusions(); + + if(dbg) { + n = create(dbfile, OWRITE|OTRUNC, 0666); + dup(n, DFD); + close(n); + } + + if(srvfd >= 0 && srv != nil){ + fprint(2, "%s: -S cannot be used with -r or -s\n", argv0); + usage(); + } + + DEBUG(DFD, "%s: started\n", argv0); + + rfork(RFNOTEG|RFREND); + + if(messagesize == 0){ + messagesize = iounit(0); + if(messagesize == 0) + messagesize = 8192+IOHDRSZ; + } + fhash = emallocz(sizeof(Fid*)*FHASHSIZE); + + fmtinstall('F', fcallfmt); + + /* + * Get tree to serve from network connection, + * check we can get there and ack the connection + */ + if(srvfd != -1) { + /* do nothing */ + } + else if(srv != nil) { + if(chdir(srv) < 0) { + ebuf[0] = '\0'; + errstr(ebuf, sizeof ebuf); + DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf); + mounterror(ebuf); + } + DEBUG(DFD, "invoked as server for %s", srv); + strncpy(buf, srv, sizeof buf); + } + else { + buf[0] = 0; + n = read(0, buf, sizeof(buf)-1); + if(n < 0) { + errstr(buf, sizeof buf); + fprint(0, "read(0): %s\n", buf); + DEBUG(DFD, "read(0): %s\n", buf); + exits(buf); + } + buf[n] = 0; + if(chdir(buf) < 0) { + errstr(ebuf, sizeof ebuf); + fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); + DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); + exits(ebuf); + } + } + + DEBUG(DFD, "\niniting root\n"); + initroot(); + + DEBUG(DFD, "%s: %s\n", argv0, buf); + + if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) + fatal("open ack write"); + + ini = initial; + n = readn(0, initial, sizeof(initial)); + if(n == 0) + fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */ + if(n < sizeof(initial)) + fatal("can't read initial string: %r"); + + if(memcmp(ini, "impo", 4) == 0) { + char buf[128], *p, *args[3]; + + ini = nil; + p = buf; + for(;;){ + if((n = read(0, p, 1)) < 0) + fatal("can't read impo arguments: %r"); + if(n == 0) + fatal("connection closed while reading arguments"); + if(*p == '\n') + *p = '\0'; + if(*p++ == '\0') + break; + if(p >= buf + sizeof(buf)) + fatal("import parameters too long"); + } + + if(tokenize(buf, args, nelem(args)) != 2) + fatal("impo arguments invalid: impo%s...", buf); + + if(strcmp(args[0], "aan") == 0) + filterp = aanfilter; + else if(strcmp(args[0], "nofilter") != 0) + fatal("import filter argument unsupported: %s", args[0]); + + if(strcmp(args[1], "ssl") == 0) + encproto = Encssl; + else if(strcmp(args[1], "tls") == 0) + encproto = Enctls; + else if(strcmp(args[1], "clear") != 0) + fatal("import encryption proto unsupported: %s", args[1]); + + if(encproto == Enctls) + fatal("%s: tls has not yet been implemented", argv[0]); + } + + if(encproto != Encnone && ealgs != nil && ai != nil) { + uchar key[16], digest[SHA1dlen]; + char fromclientsecret[21]; + char fromserversecret[21]; + int i; + + if(ai->nsecret < 8) + fatal("secret too small for ssl"); + memmove(key+4, ai->secret, 8); + + /* exchange random numbers */ + srand(truerand()); + for(i = 0; i < 4; i++) + key[i+12] = rand(); + + if(ini != nil) + fatal("Protocol botch: old import"); + if(readn(0, key, 4) != 4) + fatal("can't read key part; %r"); + + if(write(0, key+12, 4) != 4) + fatal("can't write key part; %r"); + + /* scramble into two secrets */ + sha1(key, sizeof(key), digest, nil); + mksecret(fromclientsecret, digest); + mksecret(fromserversecret, digest+10); + + if(filterp != nil) + filter(0, filterp, na); + + switch(encproto) { + case Encssl: + fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); + if(fd < 0) + fatal("can't establish ssl connection: %r"); + if(fd != 0){ + dup(fd, 0); + close(fd); + } + break; + case Enctls: + default: + fatal("Unsupported encryption protocol"); + } + } + else if(filterp != nil) { + if(ini != nil) + fatal("Protocol botch: don't know how to deal with this"); + filter(0, filterp, na); + } + dup(0, 1); + + if(ai != nil) + auth_freeAI(ai); + + if(ini != nil){ + extern void (*fcalls[])(Fsrpc*); + + r = getsbuf(); + memmove(r->buf, ini, BIT32SZ); + n = GBIT32(r->buf); + if(n <= BIT32SZ || n > messagesize) + fatal("bad length in 9P2000 message header"); + n -= BIT32SZ; + if(readn(0, r->buf+BIT32SZ, n) != n) + fatal(nil); + n += BIT32SZ; + + if(convM2S(r->buf, n, &r->work) != n) + fatal("convM2S format error"); + DEBUG(DFD, "%F\n", &r->work); + (fcalls[r->work.type])(r); + } + io(); +} diff --git a/sys/src/cmd/iostats.c b/sys/src/cmd/iostats.c index e61a7ff94..421f531a9 100644 --- a/sys/src/cmd/iostats.c +++ b/sys/src/cmd/iostats.c @@ -354,6 +354,7 @@ main(int argc, char **argv) sysfatal("fork: %r"); case 0: dup(efd[0], 0); + dup(efd[0], 1); close(efd[0]); close(efd[1]); close(pfd[1]); diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c index 7b9ed9f2c..e00c85b99 100644 --- a/sys/src/cmd/nusb/kb/kb.c +++ b/sys/src/cmd/nusb/kb/kb.c @@ -637,7 +637,7 @@ hidparse(int t, int f, int g[], int l[], int, void *a) s->h = v; break; - case 0x0D0051: /* Conteact identifier */ + case 0x0D0051: /* Contact identifier */ s->id = v; break; @@ -684,7 +684,7 @@ readerproc(void* a) { char err[ERRMAX], mbuf[80]; uchar lastk[64], uk, dk; - int i, c, nerrs, lastb, nlastk; + int i, c, nerrs, bpress, lastb, nlastk; int abs, x, y, z, b; Hidreport p; Hidslot lasts[nelem(p.s)], *s, *l; @@ -774,7 +774,7 @@ readerproc(void* a) continue; /* combine all the slots */ - abs = x = y = z = b = 0; + bpress = abs = x = y = z = b = 0; for(i=0; i<p.ns; *l = *s, i++){ s = &p.s[i]; @@ -785,7 +785,7 @@ readerproc(void* a) if(l == &lasts[nelem(lasts)-1] || !l->valid) *l = *s; - /* convet absolute z to relative */ + /* convert absolute z to relative */ z += s->z; if(s->abs & 4) z -= l->z; @@ -808,6 +808,7 @@ readerproc(void* a) b |= 2; if(s->b & 2) b |= 4; + bpress |= s->m; /* X/Y are absolute? */ if((s->abs & 3) == 3){ @@ -825,7 +826,9 @@ readerproc(void* a) y += s->y; } } - + + if(bpress == 0) + b = lastb & 7; if(z != 0) b |= z > 0 ? 8 : 16; diff --git a/sys/src/cmd/ptrap.c b/sys/src/cmd/ptrap.c index 7cf60f7d4..dae3c088d 100644 --- a/sys/src/cmd/ptrap.c +++ b/sys/src/cmd/ptrap.c @@ -8,6 +8,7 @@ typedef struct IOProc IOProc; typedef struct PFilter PFilter; +typedef struct FAttr FAttr; typedef struct PFid PFid; struct IOProc { @@ -27,11 +28,19 @@ struct PFid { }; Qid rootqid = {.type QTDIR}; +struct FAttr { + char *name; + Reprog *filt; + int invert; + FAttr *next; +}; + struct PFilter { char *name; Reprog *filt; - PFilter *next; int invert; + FAttr *attr; + PFilter *next; }; PFilter *filters; @@ -162,12 +171,32 @@ ptrapopen(Req *r) } static int +filter(PFilter *f, Plumbmsg *pm) +{ + FAttr *a; + char *value; + + if(!(regexec(f->filt, pm->data, nil, 0) ^ f->invert)) + return 0; + for(a = f->attr; a; a = a->next){ + value = plumblookup(pm->attr, a->name); + if(value == nil) + return 0; + if(!(regexec(a->filt, value, nil, 0) ^ f->attr->invert)) + return 0; + } + return 1; +} + +static int filterread(Req *r, PFid *pf) { int rc, len, more; char *buf; Plumbmsg *pm; + PFilter *f; + f = pf->filter; for(;;){ if(pf->msg != nil){ rc = r->ifcall.count; @@ -194,7 +223,7 @@ filterread(Req *r, PFid *pf) len += rc; } free(buf); - if(regexec(pf->filter->filt, pm->data, nil, 0) ^ pf->filter->invert){ + if(filter(f, pm)){ pf->msg = plumbpack(pm, &pf->msgn); pf->msgp = 0; } @@ -341,7 +370,7 @@ Srv ptrapsrv = { void usage(void) { - fprint(2, "usage: %s port regex [ port regex ... ]\n", argv0); + fprint(2, "usage: %s port regex [ +attr regex ... ] ...\n", argv0); exits("usage"); } @@ -349,6 +378,7 @@ void threadmain(int argc, char **argv) { PFilter *f; + FAttr *fa; char *p; int i; @@ -357,19 +387,33 @@ threadmain(int argc, char **argv) }ARGEND; if(argc == 0 || argc % 2) usage(); - for(i = 0; i < argc; i += 2){ + for(i = 0; i+1 < argc;){ + p = argv[i]; f = emalloc9p(sizeof(PFilter)); - f->name = strdup(argv[i]); + f->name = estrdup9p(p); p = argv[i+1]; - if(*p == '!'){ + if(p[0] == '!'){ p++; f->invert = 1; } - f->filt = regcomp(p); - if(f->filt == nil) - sysfatal("%r"); + if((f->filt = regcomp(p)) == nil) + sysfatal("regcomp: %r"); f->next = filters; filters = f; + for(i += 2; p = argv[i], i+1 < argc && p[0] == '+'; i += 2){ + p++; + fa = emalloc9p(sizeof(FAttr)); + fa->name = estrdup9p(p); + p = argv[i+1]; + if(p[0] == '!'){ + p++; + fa->invert = 1; + } + if((fa->filt = regcomp(p)) == nil) + sysfatal("regcomp: %r"); + fa->next = f->attr; + f->attr = fa; + } } threadpostmountsrv(&ptrapsrv, nil, "/mnt/plumb", MREPL | MCREATE); diff --git a/sys/src/cmd/rio/fsys.c b/sys/src/cmd/rio/fsys.c index 1562f71e8..be81a1d57 100644 --- a/sys/src/cmd/rio/fsys.c +++ b/sys/src/cmd/rio/fsys.c @@ -118,37 +118,27 @@ cexecpipe(int *p0, int *p1) Filsys* filsysinit(Channel *cxfidalloc) { - int n, fd, pid, p0; + int p0; Filsys *fs; Channel *c; - char buf[128]; fs = emalloc(sizeof(Filsys)); if(cexecpipe(&fs->cfd, &fs->sfd) < 0) goto Rescue; fmtinstall('F', fcallfmt); clockfd = open("/dev/time", OREAD|OCEXEC); - fd = open("/dev/user", OREAD); - strcpy(buf, "Jean-Paul_Belmondo"); - if(fd >= 0){ - n = read(fd, buf, sizeof buf-1); - if(n > 0) - buf[n] = 0; - close(fd); - } - fs->user = estrdup(buf); + fs->user = getuser(); fs->csyncflush = chancreate(sizeof(int), 0); if(fs->csyncflush == nil) error("chancreate syncflush"); fs->cxfidalloc = cxfidalloc; - pid = getpid(); /* * Create and post wctl pipe */ if(cexecpipe(&p0, &wctlfd) < 0) goto Rescue; - snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%d", fs->user, pid); + snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%lud", fs->user, (ulong)getpid()); post(srvwctl, "wctl", p0); close(p0); @@ -165,7 +155,7 @@ filsysinit(Channel *cxfidalloc) /* * Post srv pipe */ - snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%d", fs->user, pid); + snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%lud", fs->user, (ulong)getpid()); post(srvpipe, "wsys", fs->cfd); return fs; @@ -234,7 +224,7 @@ filsysmount(Filsys *fs, int id) char buf[32]; close(fs->sfd); /* close server end so mount won't hang if exiting */ - sprint(buf, "%d", id); + snprint(buf, sizeof buf, "%d", id); if(mount(fs->cfd, -1, "/mnt/wsys", MREPL, buf) == -1){ fprint(2, "mount failed: %r\n"); return -1; diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index a42721fac..a28fb2ccc 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -244,7 +244,7 @@ putsnarf(void) if(snarffd<0 || nsnarf==0) return; - fd = open("/dev/snarf", OWRITE); + fd = open("/dev/snarf", OWRITE|OCEXEC); if(fd < 0) return; /* snarf buffer could be huge, so fprint will truncate; do it in blocks */ @@ -394,12 +394,13 @@ portion(int x, int lo, int hi) { x -= lo; hi -= lo; - if(hi < 20) - return x > 0 ? 2 : 0; - if(x < 20) - return 0; - if(x > hi-20) - return 2; + if(x < hi/2){ + if(x < 20) + return 0; + } else { + if(x > hi-20) + return 2; + } return 1; } @@ -857,7 +858,7 @@ sweep(void) } void -drawedge(Image **bp, Rectangle r) +drawedge(Image **bp, Image *col, Rectangle r) { Image *b = *bp; if(b != nil && Dx(b->r) == Dx(r) && Dy(b->r) == Dy(r)) @@ -865,28 +866,30 @@ drawedge(Image **bp, Rectangle r) else{ freeimage(b); b = allocwindow(wscreen, r, Refbackup, DNofill); - if(b != nil) draw(b, r, sizecol, nil, ZP); + if(b != nil) draw(b, r, col, nil, ZP); *bp = b; } } void -drawborder(Rectangle r, int show) +drawborder(Rectangle r, Image *col) { - static Image *b[4]; - int i; - if(show == 0){ - for(i = 0; i < 4; i++){ - freeimage(b[i]); - b[i] = nil; - } - }else{ + static Image *b[4], *lastcol; + + if(col != lastcol){ + freeimage(b[0]), b[0] = nil; + freeimage(b[1]), b[1] = nil; + freeimage(b[2]), b[2] = nil; + freeimage(b[3]), b[3] = nil; + } + if(col != nil){ r = canonrect(r); - drawedge(&b[0], Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y)); - drawedge(&b[1], Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth)); - drawedge(&b[2], Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y)); - drawedge(&b[3], Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y)); + drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y)); + drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth)); + drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y)); + drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y)); } + lastcol = col; } Image* @@ -901,17 +904,17 @@ drag(Window *w) dm = subpt(om, w->screenr.min); d = subpt(w->screenr.max, w->screenr.min); op = subpt(om, dm); - drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1); + drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), sizecol); while(mouse->buttons==4){ p = subpt(mouse->xy, dm); if(!eqpt(p, op)){ - drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1); + drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), sizecol); op = p; } readmouse(mousectl); } r = Rect(op.x, op.y, op.x+d.x, op.y+d.y); - drawborder(r, 0); + drawborder(r, nil); p = mouse->xy; riosetcursor(inborder(r, p) ? corners[whichcorner(r, p)] : nil); menuing = FALSE; @@ -935,7 +938,7 @@ bandsize(Window *w) or = w->screenr; but = mouse->buttons; startp = onscreen(mouse->xy); - drawborder(or, 1); + drawborder(or, sizecol); while(mouse->buttons == but) { p = onscreen(mouse->xy); which = whichcorner(or, p); @@ -945,12 +948,14 @@ bandsize(Window *w) } r = whichrect(or, p, owhich); if(!eqrect(r, or) && goodrect(r)){ + drawborder(r, sizecol); or = r; - drawborder(r, 1); } readmouse(mousectl); } - drawborder(or, 0); + drawborder(or, nil); + if(!goodrect(or)) + riosetcursor(nil); if(mouse->buttons!=0 || !goodrect(or) || eqrect(or, w->screenr) || abs(p.x-startp.x)+abs(p.y-startp.y) <= 1){ flushimage(display, 1); diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c index 59c9246c9..bef98fda9 100644 --- a/sys/src/cmd/rio/wctl.c +++ b/sys/src/cmd/rio/wctl.c @@ -88,14 +88,19 @@ static char *params[] = { int goodrect(Rectangle r) { - if(!eqrect(canonrect(r), r)) + if(badrect(r) || !eqrect(canonrect(r), r)) return 0; /* reasonable sizes only please */ if(Dx(r) > BIG*Dx(screen->r)) return 0; if(Dy(r) > BIG*Dy(screen->r)) return 0; - if(Dx(r) < 100 || Dy(r) < 3*font->height) + /* + * the height has to be big enough to fit one line of text. + * that includes the border on each side with an extra pixel + * so that the text is still drawn + */ + if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height) return 0; /* window must be on screen */ if(!rectXrect(screen->r, r)) diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c index 9734fd18f..1fd1b671c 100644 --- a/sys/src/cmd/rio/wind.c +++ b/sys/src/cmd/rio/wind.c @@ -1420,7 +1420,7 @@ wclosewin(Window *w) void wsetpid(Window *w, int pid, int dolabel) { - char buf[64]; + char buf[32]; int ofd; ofd = w->notefd; @@ -1428,11 +1428,11 @@ wsetpid(Window *w, int pid, int dolabel) w->notefd = -1; else { if(dolabel){ - snprint(buf, sizeof(buf), "rc %d", pid); + snprint(buf, sizeof(buf), "rc %lud", (ulong)pid); free(w->label); w->label = estrdup(buf); } - snprint(buf, sizeof(buf), "/proc/%d/notepg", pid); + snprint(buf, sizeof(buf), "/proc/%lud/notepg", (ulong)pid); w->notefd = open(buf, OWRITE|OCEXEC); } if(ofd >= 0) diff --git a/sys/src/cmd/srvfs.c b/sys/src/cmd/srvfs.c index d5c028150..a500c8ed2 100644 --- a/sys/src/cmd/srvfs.c +++ b/sys/src/cmd/srvfs.c @@ -12,7 +12,7 @@ void main(int argc, char **argv) { char *ename, *arglist[16], **argp; - int n, fd, pipefd[2]; + int fd, pipefd[2]; char buf[64]; int perm = 0600; @@ -39,14 +39,27 @@ main(int argc, char **argv) *argp++ = "-R"; break; }ARGEND - *argp = 0; if(argc != 2) usage(); + *argp++ = "-r"; + *argp++ = argv[1]; + *argp = 0; if(pipe(pipefd) < 0){ fprint(2, "can't pipe: %r\n"); exits("pipe"); } + if(argv[0][0] == '/') + strecpy(buf, buf+sizeof buf, argv[0]); + else + snprint(buf, sizeof buf, "/srv/%s", argv[0]); + fd = create(buf, OWRITE|ORCLOSE, perm); + if(fd < 0){ + fprint(2, "can't create %s: %r\n", buf); + exits("create"); + } + fprint(fd, "%d", pipefd[1]); + close(pipefd[1]); switch(rfork(RFPROC|RFNOWAIT|RFNOTEG|RFFDG)){ case -1: @@ -56,39 +69,11 @@ main(int argc, char **argv) dup(pipefd[0], 0); dup(pipefd[0], 1); close(pipefd[0]); - close(pipefd[1]); exec(ename, arglist); fprint(2, "can't exec exportfs: %r\n"); exits("exec"); default: break; } - close(pipefd[0]); - if(fprint(pipefd[1], "%s", argv[1]) < 0){ - fprint(2, "can't write pipe: %r\n"); - exits("write"); - } - n = read(pipefd[1], buf, sizeof buf-1); - if(n < 0){ - fprint(2, "can't read pipe: %r\n"); - exits("read"); - } - buf[n] = 0; - if(n != 2 || strcmp(buf, "OK") != 0){ - fprint(2, "not OK (%d): %s\n", n, buf); - exits("OK"); - } - if(argv[0][0] == '/') - strecpy(buf, buf+sizeof buf, argv[0]); - else - snprint(buf, sizeof buf, "/srv/%s", argv[0]); - fd = create(buf, OWRITE, perm); - if(fd < 0){ - fprint(2, "can't create %s: %r\n", buf); - exits("create"); - } - fprint(fd, "%d", pipefd[1]); - close(fd); - close(pipefd[1]); exits(0); } diff --git a/sys/src/cmd/vmx/dat.h b/sys/src/cmd/vmx/dat.h index 25a1898a0..b6e375a8e 100644 --- a/sys/src/cmd/vmx/dat.h +++ b/sys/src/cmd/vmx/dat.h @@ -11,6 +11,7 @@ enum { VMDEAD, }; extern int state; +extern int debug; enum { BY2PG = 4096 diff --git a/sys/src/cmd/vmx/exith.c b/sys/src/cmd/vmx/exith.c index 48f054c01..185c22e07 100644 --- a/sys/src/cmd/vmx/exith.c +++ b/sys/src/cmd/vmx/exith.c @@ -1,9 +1,8 @@ #include <u.h> #include <libc.h> -#include <thread.h> -#include <bio.h> #include "dat.h" #include "fns.h" +#include "x86.h" int persist = 1; @@ -118,109 +117,167 @@ eptfault(ExitInfo *ei) typedef struct CPUID CPUID; struct CPUID { - u32int idx; u32int ax, bx, cx, dx; }; -static CPUID *cpuidf; -static int ncpuidf; +static u32int cpuidmax; +static u32int cpuidmaxext; +static CPUID leaf1; +static struct { + uvlong miscen; +}msr; -static void -auxcpuidproc(void *vpfd) -{ - int *pfd; - - pfd = vpfd; - close(pfd[1]); - close(0); - open("/dev/null", OREAD); - dup(pfd[0], 1); - close(pfd[0]); - procexecl(nil, "/bin/aux/cpuid", "cpuid", "-r", nil); - threadexits("exec: %r"); -} +static uchar _cpuid[] = { + 0x5E, /* POP SI (PC) */ + 0x5D, /* POP BP (CPUID&) */ + 0x58, /* POP AX */ + 0x59, /* POP CX */ + + 0x51, /* PUSH CX */ + 0x50, /* PUSH AX */ + 0x55, /* PUSH BP */ + 0x56, /* PUSH SI */ + + 0x31, 0xDB, /* XOR BX, BX */ + 0x31, 0xD2, /* XOR DX, DX */ + + 0x0F, 0xA2, /* CPUID */ + + 0x89, 0x45, 0x00, /* MOV AX, 0(BP) */ + 0x89, 0x5d, 0x04, /* MOV BX, 4(BP) */ + 0x89, 0x4d, 0x08, /* MOV CX, 8(BP) */ + 0x89, 0x55, 0x0C, /* MOV DX, 12(BP) */ + 0xC3, /* RET */ +}; + +static CPUID (*getcpuid)(ulong ax, ulong cx) = (CPUID(*)(ulong, ulong)) _cpuid; void cpuidinit(void) { - int pfd[2]; - Biobuf *bp; - char *l, *f[5]; - CPUID *cp; - - pipe(pfd); - procrfork(auxcpuidproc, pfd, 4096, RFFDG); - close(pfd[0]); - bp = Bfdopen(pfd[1], OREAD); - if(bp == nil) sysfatal("Bopenfd: %r"); - for(; l = Brdstr(bp, '\n', 1), l != nil; free(l)){ - if(tokenize(l, f, 5) < 5) continue; - cpuidf = realloc(cpuidf, (ncpuidf + 1) * sizeof(CPUID)); - cp = cpuidf + ncpuidf++; - cp->idx = strtoul(f[0], nil, 16); - cp->ax = strtoul(f[1], nil, 16); - cp->bx = strtoul(f[2], nil, 16); - cp->cx = strtoul(f[3], nil, 16); - cp->dx = strtoul(f[4], nil, 16); - } - Bterm(bp); - close(pfd[1]); -} + CPUID r; + int f; -CPUID * -getcpuid(ulong idx) -{ - CPUID *cp; - - for(cp = cpuidf; cp < cpuidf + ncpuidf; cp++) - if(cp->idx == idx) - return cp; - return nil; + if(sizeof(uintptr) == 8) /* patch out POP BP -> POP AX */ + _cpuid[1] = 0x58; + segflush(_cpuid, sizeof(_cpuid)); + + r = getcpuid(0, 0); + cpuidmax = r.ax; + r = getcpuid(0x80000000, 0); + cpuidmaxext = r.ax; + leaf1 = getcpuid(1, 0); + + memset(&msr, 0, sizeof(msr)); + if((f = open("/dev/msr", OREAD)) >= 0){ + pread(f, &msr.miscen, 8, 0x1a0); + msr.miscen &= 1<<0; /* fast strings */ + close(f); + } } -int maxcpuid = 7; +static int xsavesz[] = { + [1] = 512+64, + [3] = 512+64, + [7] = 512+64+256, +}; static void cpuid(ExitInfo *ei) { u32int ax, bx, cx, dx; - CPUID *cp; - static CPUID def; - + CPUID cp; + ax = rget(RAX); - cp = getcpuid(ax); - if(cp == nil) cp = &def; + cx = rget(RCX); + bx = dx = 0; + cp = getcpuid(ax, cx); switch(ax){ - case 0: /* highest register & GenuineIntel */ - ax = maxcpuid; - bx = cp->bx; - dx = cp->dx; - cx = cp->cx; + case 0x00: /* highest register & GenuineIntel */ + ax = MIN(cpuidmax, 0x18); + bx = cp.bx; + dx = cp.dx; + cx = cp.cx; break; - case 1: /* features */ - ax = cp->ax; - bx = cp->bx & 0xffff; - cx = cp->cx & 0x60de2203; - dx = cp->dx & 0x0782a179; + case 0x01: /* features */ + ax = cp.ax; + bx = cp.bx & 0xffff; + /* some features removed, hypervisor added */ + cx = cp.cx & 0x76de3217 | 0x80000000UL; + dx = cp.dx & 0x0f8aa579; + if(leaf1.cx & 1<<27){ + if(rget("cr4real") & Cr4Osxsave) + cx |= 1<<27; + }else{ + cx &= ~0x1c000000; + } break; - case 2: goto literal; /* cache stuff */ - case 3: goto zero; /* processor serial number */ - case 4: goto zero; /* cache stuff */ - case 5: goto zero; /* monitor/mwait */ - case 6: goto zero; /* thermal management */ - case 7: goto zero; /* more features */ - case 10: goto zero; /* performance counters */ + case 0x02: goto literal; /* cache stuff */ + case 0x03: goto zero; /* processor serial number */ + case 0x04: goto literal; /* cache stuff */ + case 0x05: goto zero; /* monitor/mwait */ + case 0x06: goto zero; /* thermal management */ + case 0x07: /* more features */ + if(cx == 0){ + ax = 0; + bx = cp.bx & 0x2369; + cx = 0; + if((leaf1.cx & 1<<27) == 0) + bx &= ~0xdc230020; + }else{ + goto zero; + } + break; + case 0x08: goto zero; + case 0x09: goto literal; /* direct cache access */ + case 0x0a: goto zero; /* performance counters */ + case 0x0b: goto zero; /* extended topology */ + case 0x0c: goto zero; + case 0x0d: /* extended state */ + if((leaf1.cx & 1<<27) == 0) + goto zero; + if(cx == 0){ /* main leaf */ + ax = cp.ax & 7; /* x87, sse, avx */ + bx = xsavesz[rget("xcr0")]; /* current xsave size */ + cx = xsavesz[ax]; /* max xsave size */ + }else if(cx == 1){ /* sub leaf */ + ax = cp.ax & 7; /* xsaveopt, xsavec, xgetbv1 */ + bx = xsavesz[rget("xcr0")]; + cx = 0; + }else if(cx == 2){ + ax = xsavesz[7] - xsavesz[3]; + bx = xsavesz[3]; + cx = 0; + }else{ + goto zero; + } + break; + case 0x0f: goto zero; /* RDT */ + case 0x10: goto zero; /* RDT */ + case 0x12: goto zero; /* SGX */ + case 0x14: goto zero; /* PT */ + case 0x15: goto zero; /* TSC */ + case 0x16: goto zero; /* cpu clock */ + case 0x17: goto zero; /* SoC */ + case 0x18: goto literal; /* pages, tlb */ + + case 0x40000000: /* hypervisor */ + ax = 0; + bx = 0x4b4d564b; /* act as KVM */ + cx = 0x564b4d56; + dx = 0x4d; + break; + case 0x80000000: /* highest register */ - ax = 0x80000008; - bx = cx = dx = 0; + ax = MIN(cpuidmaxext, 0x80000008); + cx = 0; break; case 0x80000001: /* signature & ext features */ - ax = cp->ax; - bx = 0; - cx = cp->cx & 0x121; + ax = cp.ax; + cx = cp.cx & 0x121; if(sizeof(uintptr) == 8) - dx = cp->dx & 0x24100800; + dx = cp.dx & 0x24100800; else - dx = cp->dx & 0x04100000; + dx = cp.dx & 0x04100000; break; case 0x80000002: goto literal; /* brand string */ case 0x80000003: goto literal; /* brand string */ @@ -230,18 +287,16 @@ cpuid(ExitInfo *ei) case 0x80000007: goto zero; /* invariant tsc */ case 0x80000008: goto literal; /* address bits */ literal: - ax = cp->ax; - bx = cp->bx; - cx = cp->cx; - dx = cp->dx; + ax = cp.ax; + bx = cp.bx; + cx = cp.cx; + dx = cp.dx; break; default: - vmerror("unknown cpuid field eax=%#ux", ax); + if((ax & 0xf0000000) != 0x40000000) + vmdebug("unknown cpuid field eax=%#ux", ax); zero: - ax = 0; - bx = 0; - cx = 0; - dx = 0; + ax = cx = 0; break; } rset(RAX, ax); @@ -267,12 +322,15 @@ rdwrmsr(ExitInfo *ei) else rset("pat", val); break; case 0x8B: val = 0; break; /* microcode update */ + case 0x1A0: /* IA32_MISC_ENABLE */ + if(rd) val = msr.miscen; + break; default: if(rd){ - vmerror("read from unknown MSR %#ux ignored", cx); + vmdebug("read from unknown MSR %#ux ignored", cx); val = 0; }else - vmerror("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val); + vmdebug("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val); break; } if(rd){ @@ -310,7 +368,7 @@ movcr(ExitInfo *ei) case 0: switch(q >> 4 & 3){ case 0: - vmdebug("illegal CR0 write, value %#ux", rget(x86reg[q >> 8 & 15])); + vmdebug("illegal CR0 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15])); rset("cr0real", rget(x86reg[q >> 8 & 15])); skipinstr(ei); break; @@ -332,7 +390,7 @@ movcr(ExitInfo *ei) case 4: switch(q >> 4 & 3){ case 0: - vmdebug("illegal CR4 write, value %#ux", rget(x86reg[q >> 8 & 15])); + vmdebug("illegal CR4 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15])); rset("cr4real", rget(x86reg[q >> 8 & 15])); skipinstr(ei); break; @@ -347,7 +405,7 @@ movcr(ExitInfo *ei) } break; default: - vmerror("access to unknown control register CR%d", ei->qual & 15); + vmerror("access to unknown control register CR%ud", q & 15); postexc("#ud", NOERRC); } } @@ -373,6 +431,26 @@ irqackhand(ExitInfo *ei) irqack(ei->qual); } +static void +xsetbv(ExitInfo *ei) +{ + uvlong v; + + /* this should also #ud if LOCK prefix is used */ + + v = rget(RAX)&0xffffffff | rget(RDX)<<32; + if(rget(RCX) & 0xffffffff) + postexc("#gp", 0); + else if(v != 1 && v != 3 && v != 7) + postexc("#gp", 0); + else if((leaf1.cx & 1<<26) == 0 || (rget("cr4real") & Cr4Osxsave) == 0) + postexc("#ud", NOERRC); + else{ + rset("xcr0", v); + skipinstr(ei); + } +} + typedef struct ExitType ExitType; struct ExitType { char *name; @@ -389,6 +467,7 @@ static ExitType etypes[] = { {".movdr", movdr}, {"#db", dbgexc}, {"movcr", movcr}, + {".xsetbv", xsetbv}, }; void diff --git a/sys/src/cmd/vmx/fns.h b/sys/src/cmd/vmx/fns.h index d73e5fe1d..06643a9aa 100644 --- a/sys/src/cmd/vmx/fns.h +++ b/sys/src/cmd/vmx/fns.h @@ -1,3 +1,4 @@ +#define MIN(a,b) ((a)<(b)?(a):(b)) void *emalloc(ulong); void loadkernel(char *); uvlong rget(char *); @@ -10,7 +11,8 @@ void pitadvance(void); void rtcadvance(void); void settimer(vlong targ); void vmerror(char *, ...); -#define vmdebug vmerror +#pragma varargck argpos vmerror 1 +#define vmdebug if(!debug) {} else vmerror int ctl(char *, ...); void registermmio(uvlong, uvlong, uvlong (*)(int, uvlong, uvlong)); void irqline(int, int); diff --git a/sys/src/cmd/vmx/ide.c b/sys/src/cmd/vmx/ide.c index 162cac1c0..1e7cd1a7e 100644 --- a/sys/src/cmd/vmx/ide.c +++ b/sys/src/cmd/vmx/ide.c @@ -118,7 +118,7 @@ idegoio(IDE *d, int wr) addr = getlba(d); if(addr < 0){ - vmerror("ide%d: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec); + vmerror("ide%zd: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec); postexc("#bp", NOERRC); d->stat = IDEDRDY | IDEDSC | IDEDRQ | IDEERR; d->err = IDEIDNF; @@ -325,7 +325,7 @@ ideioproc(void *dp) qunlock(io); werrstr("eof"); if(getsector(a+i, p) < 0 && pread(d->fd, p, 512, (a+i)*512) < 512){ - vmerror("ide%d: read: %r", d - ide); + vmerror("ide%zd: read: %r", d - ide); qlock(io); io->err = IDEUNC; qunlock(io); @@ -355,7 +355,7 @@ idecmd(IDE *d, u8int cmd) break; default: if((d->flags & IDEPRESENT) == 0){ - vmerror("ide%d: command %#ux issued to absent drive", d-ide, cmd); + vmerror("ide%zd: command %#ux issued to absent drive", d-ide, cmd); return; } } @@ -435,7 +435,7 @@ idecmd(IDE *d, u8int cmd) case 0x66: d->flags |= IDEKEEPFEAT; break; /* retain settings */ case 0xcc: d->flags &= ~IDEKEEPFEAT; break; /* revert to default on reset */ default: - vmerror("ide%d: unknown feature %#ux", d-ide, d->feat); + vmerror("ide%zd: unknown feature %#ux", d-ide, d->feat); d->stat = IDEDRDY|IDEDSC|IDEERR; d->err = IDEABRT; return; @@ -443,7 +443,7 @@ idecmd(IDE *d, u8int cmd) d->stat = IDEDRDY|IDEDSC; break; default: - vmerror("ide%d: unknown command %#ux", d-ide, cmd); + vmerror("ide%zd: unknown command %#ux", d-ide, cmd); d->stat = IDEDRDY|IDEDSC|IDEERR; d->err = IDEABRT; } diff --git a/sys/src/cmd/vmx/io.c b/sys/src/cmd/vmx/io.c index 2de8fe605..25244b4e0 100644 --- a/sys/src/cmd/vmx/io.c +++ b/sys/src/cmd/vmx/io.c @@ -292,7 +292,7 @@ picio(int isin, u16int port, u32int val, int sz, void *) p->imr = 0; p->prio = 7; p->flags = 0; - if((val & 0x0b) != 0x01) vmerror("PIC%ld ICW1 with unsupported value %#ux", p-pic, val); + if((val & 0x0b) != 0x01) vmerror("PIC%zd ICW1 with unsupported value %#ux", p-pic, (u32int)val); p->init = 1; return 0; } @@ -347,7 +347,7 @@ picio(int isin, u16int port, u32int val, int sz, void *) case 0xa1: switch(p->init){ default: - vmerror("write to PIC%ld in init=%d state", p-pic, p->init); + vmerror("write to PIC%zd in init=%d state", p-pic, p->init); return 0; case 1: p->base = val; @@ -355,11 +355,11 @@ picio(int isin, u16int port, u32int val, int sz, void *) return 0; case 2: if(p == &pic[0] && val != 4 || p == &pic[1] && val != 2) - vmerror("PIC%ld ICW3 with unsupported value %#ux", p-pic, val); + vmerror("PIC%zd ICW3 with unsupported value %#ux", p-pic, val); p->init = 3; return 0; case 3: - if((val & 0xfd) != 1) vmerror("PIC%ld ICW4 with unsupported value %#ux", p-pic, val); + if((val & 0xfd) != 1) vmerror("PIC%zd ICW4 with unsupported value %#ux", p-pic, val); if((val & 2) != 0) p->flags |= AEOI; p->init = 4; picupdate(p); @@ -726,7 +726,7 @@ kbdcmd(u8int val) case 0xf2: keyputc(0xfa); keyputc(0xab); keyputc(0x41); break; /* keyboard id */ case 0xee: keyputc(0xee); break; /* echo */ default: - vmerror("unknown kbd command %#ux", val); + vmdebug("unknown kbd command %#ux", val); keyputc(0xfe); } } @@ -1203,9 +1203,9 @@ u32int iowhine(int isin, u16int port, u32int val, int sz, void *mod) { if(isin) - vmerror("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC)); + vmdebug("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC)); else - vmerror("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC)); + vmdebug("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC)); return -1; } diff --git a/sys/src/cmd/vmx/mkfile b/sys/src/cmd/vmx/mkfile index e52b53466..78842c3dc 100644 --- a/sys/src/cmd/vmx/mkfile +++ b/sys/src/cmd/vmx/mkfile @@ -2,6 +2,7 @@ BIN=/$objtype/bin TARG=vmx +CLEANFILES=$O.vmxgdb HFILES=dat.h fns.h OFILES=\ vmx.$O \ @@ -19,6 +20,10 @@ OFILES=\ </sys/src/cmd/mkone +default:V: all + +all:V: $O.out $O.vmxgdb + install:V: $BIN/vmxgdb $BIN/vmxgdb: $O.vmxgdb diff --git a/sys/src/cmd/vmx/nanosec.c b/sys/src/cmd/vmx/nanosec.c index ac418483d..1301e9faf 100644 --- a/sys/src/cmd/vmx/nanosec.c +++ b/sys/src/cmd/vmx/nanosec.c @@ -17,14 +17,15 @@ nanosec(void) return nsec() - xstart; if(fasthz == 0){ - if((fasthz = _tos->cyclefreq) == 0){ - fasthz = ~0ULL; + if(_tos->cyclefreq){ + cycles(&xstart); + fasthz = _tos->cyclefreq; + } else { xstart = nsec(); + fasthz = ~0ULL; fprint(2, "cyclefreq not available, falling back to nsec()\n"); fprint(2, "you might want to disable aux/timesync\n"); return 0; - }else{ - cycles(&xstart); } } cycles(&x); diff --git a/sys/src/cmd/vmx/vesa.c b/sys/src/cmd/vmx/vesa.c index 35c7a0d38..61eeb5c2c 100644 --- a/sys/src/cmd/vmx/vesa.c +++ b/sys/src/cmd/vmx/vesa.c @@ -622,7 +622,8 @@ vesathread(void *) if(vesaddc(&ur) < 0 || vesasetregs(sp, &ur) < 0) continue; break; default: - vmerror("vesa: unsupported function %#x", ur.ax); + vesasetax(sp, 0x0100); + vmdebug("vesa: unsupported function %#x", ur.ax); } } } diff --git a/sys/src/cmd/vmx/vga.c b/sys/src/cmd/vmx/vga.c index 9fadff15e..b59eb44a1 100644 --- a/sys/src/cmd/vmx/vga.c +++ b/sys/src/cmd/vmx/vga.c @@ -178,7 +178,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) switch(vga.sidx){ case 0: vga.seq[vga.sidx] = val & 3; return 0; case 4: vga.seq[vga.sidx] = val & 0xe; return 0; - default: vmerror("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; + default: vmdebug("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; } case 0x3c6: return 0; case 0x3c7: vga.rdidx = val << 2; return 0; @@ -194,7 +194,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 4: vga.graph[vga.gidx] = val & 3; break; case 8: vga.graph[vga.gidx] = val; break; default: - vmerror("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val); + vmdebug("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val); } return 0; case 0x3d4: vga.cidx = val; return 0; @@ -204,7 +204,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) vga.crtc[vga.cidx] = val; return 0; default: - vmerror("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val); + vmdebug("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val); } return 0; case 0x103c0: return vga.aidx & 0x3f; @@ -215,7 +215,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 0: case 4: return vga.seq[vga.sidx]; - default: vmerror("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; + default: vmdebug("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; } case 0x103c6: return 0xff; case 0x103c7: return vga.rdidx >> 2; @@ -232,7 +232,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 8: return vga.graph[vga.gidx]; default: - vmerror("vga: read from unknown graphics register %#ux", vga.gidx); + vmdebug("vga: read from unknown graphics register %#ux", vga.gidx); return 0; } case 0x103d4: return vga.cidx; @@ -241,7 +241,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 10: case 11: case 12: case 13: case 14: case 15: return vga.crtc[vga.cidx]; default: - vmerror("vga: read from unknown CRTC register %#ux", vga.cidx); + vmdebug("vga: read from unknown CRTC register %#ux", vga.cidx); return 0; } case 0x103ca: @@ -374,7 +374,7 @@ keyproc(void *) nkdown[k->code >> 6] |= 1ULL<<(k->code&63); break; } - if(k == nil) vmerror("unknown key %d", r); + if(k == nil) vmdebug("unknown key %d", r); } if(mousegrab && (nkdown[0]>>29 & 1) != 0 && (nkdown[0]>>56 & 1) != 0){ mousegrab = 0; @@ -737,7 +737,7 @@ vgafbparse(char *fbstring) void -vgainit(void) +vgainit(int new) { char buf[512]; int i; @@ -760,7 +760,7 @@ vgainit(void) sysfatal("got nil ptr for framebuffer"); } snprint(buf, sizeof(buf), "-dx %d -dy %d", maxw+50, maxh+50); - if(newwindow(buf) < 0 || initdraw(nil, nil, "vmx") < 0) + if((new && newwindow(buf) < 0) || initdraw(nil, nil, "vmx") < 0) sysfatal("failed to initialize graphics: %r"); screeninit(1); flushimage(display, 1); diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c index 1a974a042..b3b73d845 100644 --- a/sys/src/cmd/vmx/vmx.c +++ b/sys/src/cmd/vmx/vmx.c @@ -11,7 +11,7 @@ Region *mmap; int ctlfd, regsfd, mapfd, waitfd; Channel *waitch, *sleepch, *notifch; enum { MSEC = 1000*1000, MinSleep = MSEC, SleeperPoll = 2000*MSEC } ; -int getexit, state; +int getexit, state, debug; typedef struct VmxNotif VmxNotif; struct VmxNotif { void (*f)(void *); @@ -320,9 +320,6 @@ gend(void *v) return (u8int *) v + gavail(v); } -void *tmp, *vgamem; -uvlong tmpoff, vgamemoff; - static void mksegment(char *sn) { @@ -355,8 +352,9 @@ mksegment(char *sn) close(fd); gmem = segattach(0, sn, nil, sz); if(gmem == (void*)-1) sysfatal("segattach: %r"); + }else{ + memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz); } - memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz); p = gmem; for(r = mmap; r != nil; r = r->next){ if(r->segname == nil) continue; @@ -365,14 +363,12 @@ mksegment(char *sn) p += r->end - r->start; r->ve = p; } - vgamem = p; - vgamemoff = p - gmem; - regptr(0xa0000)->segoff = vgamemoff; - regptr(0xa0000)->v = vgamem; + /* vga */ + r = regptr(0xa0000); + r->segoff = p - gmem; + r->v = p; p += 256*1024; - regptr(0xa0000)->ve = p; - tmp = p; - tmpoff = p - gmem; + r->ve = p; for(r = mmap; r != nil; r = r->next) modregion(r); @@ -504,7 +500,7 @@ sendnotif(void (*f)(void *), void *arg) send(notifch, ¬if); } -extern void vgainit(void); +extern void vgainit(int); extern void pciinit(void); extern void pcibusmap(void); extern void cpuidinit(void); @@ -574,7 +570,7 @@ usage(void) for(p = blanks; *p != 0; p++) *p = ' '; fprint(2, "usage: %s [ -M mem ] [ -c com1rd[,com1wr] ] [ -C com2rd[,com2r] ] [ -n nic ]\n", argv0); - fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v vga ] [ -9 srv ] kernel [ args ... ]\n", blanks); + fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v|-w vga ] [ -9 srv ] kernel [ args ... ]\n", blanks); threadexitsall("usage"); } @@ -590,6 +586,7 @@ threadmain(int argc, char **argv) static uvlong gmemsz = 64*1024*1024; static char *srvname; extern uintptr fbsz, fbaddr; + int newwin = 0; int i; quotefmtinstall(); @@ -598,7 +595,7 @@ threadmain(int argc, char **argv) waitch = chancreate(sizeof(char *), 32); sleepch = chancreate(sizeof(ulong), 32); notifch = chancreate(sizeof(VmxNotif), 16); - + ARGBEGIN { case 'm': bootmod = realloc(bootmod, (bootmodn + 1) * sizeof(char *)); @@ -633,10 +630,15 @@ threadmain(int argc, char **argv) } edevn++; break; + case 'D': + debug++; + break; case 'M': gmemsz = siparse(EARGF(usage())); if(gmemsz != (uintptr) gmemsz) sysfatal("too much memory for address space"); break; + case 'w': + newwin = 1; case 'v': vgafbparse(EARGF(usage())); break; @@ -673,7 +675,7 @@ threadmain(int argc, char **argv) loadkernel(argv[0]); pciinit(); - vgainit(); + vgainit(newwin); for(i = 0; i < edevn; i++) if(edev[i](edevaux[i]) < 0) sysfatal("%s: %r", edevt[i]); diff --git a/sys/src/cmd/vmx/x86.h b/sys/src/cmd/vmx/x86.h index da2b16847..4fe7947e1 100644 --- a/sys/src/cmd/vmx/x86.h +++ b/sys/src/cmd/vmx/x86.h @@ -22,8 +22,9 @@ enum { enum { Cr0Pg = 1<<31, - Cr4Pse = 1<<4, - Cr4Pae = 1<<5, + Cr4Pse = 1<<4, + Cr4Pae = 1<<5, + Cr4Osxsave = 1<<18, EferLme = 1<<8, }; diff --git a/sys/src/lib9p/auth.c b/sys/src/lib9p/auth.c index c67a4a481..dcd2d8de0 100644 --- a/sys/src/lib9p/auth.c +++ b/sys/src/lib9p/auth.c @@ -25,7 +25,7 @@ auth9p(Req *r) Afid *afid; afid = emalloc9p(sizeof(Afid)); - afid->afd = open("/mnt/factotum/rpc", ORDWR); + afid->afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC); if(afid->afd < 0) goto error; diff --git a/sys/src/lib9p/listen.c b/sys/src/lib9p/listen.c index be5290a3b..89b2f322d 100644 --- a/sys/src/lib9p/listen.c +++ b/sys/src/lib9p/listen.c @@ -100,7 +100,7 @@ getremotesys(char *ndir) snprint(buf, sizeof buf, "%s/remote", ndir); sys = nil; - fd = open(buf, OREAD); + fd = open(buf, OREAD|OCEXEC); if(fd >= 0){ n = read(fd, buf, sizeof(buf)-1); if(n>0){ diff --git a/sys/src/lib9p/queue.c b/sys/src/lib9p/queue.c index 478f40ddd..ff846cfd8 100644 --- a/sys/src/lib9p/queue.c +++ b/sys/src/lib9p/queue.c @@ -16,8 +16,8 @@ _reqqueueproc(void *v) q = v; rfork(RFNOTEG); - buf = smprint("/proc/%d/ctl", getpid()); - fd = open(buf, OWRITE); + buf = smprint("/proc/%lud/ctl", (ulong)getpid()); + fd = open(buf, OWRITE|OCEXEC); free(buf); for(;;){ @@ -40,6 +40,8 @@ _reqqueueproc(void *v) f(r); } + if(fd >= 0) + close(fd); free(r); free(q); threadexits(nil); diff --git a/sys/src/libauth/auth_challenge.c b/sys/src/libauth/auth_challenge.c index 5ab0ee6a1..63f670b4c 100644 --- a/sys/src/libauth/auth_challenge.c +++ b/sys/src/libauth/auth_challenge.c @@ -23,7 +23,7 @@ auth_challenge(char *fmt, ...) return nil; } - if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ + if((c->afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC)) < 0){ Error: auth_freechal(c); free(p); diff --git a/sys/src/libauth/auth_chuid.c b/sys/src/libauth/auth_chuid.c index 300e93f67..4703ea000 100644 --- a/sys/src/libauth/auth_chuid.c +++ b/sys/src/libauth/auth_chuid.c @@ -16,7 +16,7 @@ auth_chuid(AuthInfo *ai, char *ns) } /* change uid */ - fd = open("#¤/capuse", OWRITE); + fd = open("#¤/capuse", OWRITE|OCEXEC); if(fd < 0){ werrstr("opening #¤/capuse: %r"); return -1; @@ -31,8 +31,8 @@ auth_chuid(AuthInfo *ai, char *ns) /* get a link to factotum as new user */ fd = open("/srv/factotum", ORDWR); if(fd >= 0){ - mount(fd, -1, "/mnt", MREPL, ""); - close(fd); + if(mount(fd, -1, "/mnt", MREPL, "") == -1) + close(fd); } /* set up new namespace */ diff --git a/sys/src/libauth/auth_getuserpasswd.c b/sys/src/libauth/auth_getuserpasswd.c index 4d66dcecb..831ee3300 100644 --- a/sys/src/libauth/auth_getuserpasswd.c +++ b/sys/src/libauth/auth_getuserpasswd.c @@ -32,12 +32,11 @@ auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...) UserPasswd *up; up = nil; - rpc = nil; params = nil; - fd = open("/mnt/factotum/rpc", ORDWR); + fd = open("/mnt/factotum/rpc", ORDWR|OCEXEC); if(fd < 0) - goto out; + return nil; rpc = auth_allocrpc(fd); if(rpc == nil) goto out; @@ -69,7 +68,7 @@ auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...) out: free(params); - auth_freerpc(rpc); close(fd); + auth_freerpc(rpc); return up; } diff --git a/sys/src/libauth/auth_proxy.c b/sys/src/libauth/auth_proxy.c index 68987140a..3f9f03694 100644 --- a/sys/src/libauth/auth_proxy.c +++ b/sys/src/libauth/auth_proxy.c @@ -200,7 +200,7 @@ auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...) va_end(arg); ai = nil; - afd = open("/mnt/factotum/rpc", ORDWR); + afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC); if(afd < 0){ werrstr("opening /mnt/factotum/rpc: %r"); free(p); diff --git a/sys/src/libauth/auth_respond.c b/sys/src/libauth/auth_respond.c index cab4446e0..b5a362571 100644 --- a/sys/src/libauth/auth_respond.c +++ b/sys/src/libauth/auth_respond.c @@ -31,7 +31,7 @@ dorespond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp AuthRpc *rpc; Attr *a; - if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) + if((afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC)) < 0) return -1; if((rpc = auth_allocrpc(afd)) == nil){ diff --git a/sys/src/libauth/auth_userpasswd.c b/sys/src/libauth/auth_userpasswd.c index 62ed2c0da..df5b5834f 100644 --- a/sys/src/libauth/auth_userpasswd.c +++ b/sys/src/libauth/auth_userpasswd.c @@ -11,7 +11,7 @@ auth_userpasswd(char *user, char *passwd) char *s; int afd; - afd = open("/mnt/factotum/rpc", ORDWR); + afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC); if(afd < 0) return nil; ai = nil; diff --git a/sys/src/libauth/newns.c b/sys/src/libauth/newns.c index fd5d6cb59..c0f866b9b 100644 --- a/sys/src/libauth/newns.c +++ b/sys/src/libauth/newns.c @@ -41,7 +41,7 @@ buildns(int newns, char *user, char *file) rpc = nil; /* try for factotum now because later is impossible */ - afd = open("/mnt/factotum/rpc", ORDWR); + afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC); if(afd < 0 && newnsdebug) fprint(2, "open /mnt/factotum/rpc: %r\n"); if(afd >= 0){ @@ -58,8 +58,8 @@ buildns(int newns, char *user, char *file) } file = "/lib/namespace"; } - b = Bopen(file, OREAD); - if(b == 0){ + b = Bopen(file, OREAD|OCEXEC); + if(b == nil){ werrstr("can't open %s: %r", file); return freecloserpc(rpc); } @@ -135,6 +135,8 @@ famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname) auth_freeAI(ai); } ret = mount(fd, afd, mntpt, flags, aname); + if(ret == -1) + close(fd); if(afd >= 0) close(afd); return ret; @@ -151,7 +153,7 @@ nsop(char *fn, int argc, char *argv[], AuthRpc *rpc) cdroot = 0; flags = 0; - argv0 = 0; + argv0 = nil; if(newnsdebug){ for (i = 0; i < argc; i++) fprint(2, "%s ", argv[i]); @@ -176,7 +178,7 @@ nsop(char *fn, int argc, char *argv[], AuthRpc *rpc) flags |= MREPL; if(strcmp(argv0, ".") == 0 && argc == 1){ - b = Bopen(argv[0], OREAD); + b = Bopen(argv[0], OREAD|OCEXEC); if(b == nil) return 0; cdroot |= nsfile(fn, b, rpc); @@ -204,8 +206,9 @@ nsop(char *fn, int argc, char *argv[], AuthRpc *rpc) }else if(argc == 3){ if(famount(fd, rpc, argv[1], flags, argv[2]) == -1 && newnsdebug) fprint(2, "%s: mount: %s %s %s: %r\n", fn, argv[0], argv[1], argv[2]); + } else { + close(fd); } - close(fd); }else if(strcmp(argv0, "cd") == 0 && argc == 1){ if(chdir(argv[0]) == 0 && *argv[0] == '/') cdroot = 1; @@ -316,7 +319,7 @@ expandarg(char *arg, char *buf) strcpy(env, "#e/"); strncpy(env+3, p, len); env[3+len] = '\0'; - fd = open(env, OREAD); + fd = open(env, OREAD|OCEXEC); if(fd >= 0){ len = read(fd, &buf[n], ANAMELEN - 1); /* some singleton environment variables have trailing NULs */ @@ -345,7 +348,7 @@ setenv(char *name, char *val) long s; sprint(ename, "#e/%s", name); - f = create(ename, OWRITE, 0664); + f = create(ename, OWRITE|OCEXEC, 0664); if(f < 0) return -1; s = strlen(val); diff --git a/sys/src/libauth/noworld.c b/sys/src/libauth/noworld.c index c61b1463c..b8687f194 100644 --- a/sys/src/libauth/noworld.c +++ b/sys/src/libauth/noworld.c @@ -15,7 +15,7 @@ noworld(char *user) char *p; int n; - b = Bopen("/adm/users", OREAD); + b = Bopen("/adm/users", OREAD|OCEXEC); if(b == nil) return 0; while((p = Brdline(b, '\n')) != nil){ diff --git a/sys/src/libauthsrv/readcons.c b/sys/src/libauthsrv/readcons.c index 8a7a3af27..d9a9ead94 100644 --- a/sys/src/libauthsrv/readcons.c +++ b/sys/src/libauthsrv/readcons.c @@ -13,13 +13,13 @@ readcons(char *prompt, char *def, int raw) s = p = nil; fdout = ctl = -1; - if((fdin = open("/dev/cons", OREAD)) < 0) + if((fdin = open("/dev/cons", OREAD|OCEXEC)) < 0) goto Out; - if((fdout = open("/dev/cons", OWRITE)) < 0) + if((fdout = open("/dev/cons", OWRITE|OCEXEC)) < 0) goto Out; if(raw){ - if((ctl = open("/dev/consctl", OWRITE)) < 0) + if((ctl = open("/dev/consctl", OWRITE|OCEXEC)) < 0) goto Out; write(ctl, "rawon", 5); } diff --git a/sys/src/libauthsrv/readnvram.c b/sys/src/libauthsrv/readnvram.c index 1a00835cf..e13641bd6 100644 --- a/sys/src/libauthsrv/readnvram.c +++ b/sys/src/libauthsrv/readnvram.c @@ -91,9 +91,9 @@ findnvram(Nvrwhere *locp) v[0] = ""; v[1] = nil; } - fd = open(v[0], ORDWR); + fd = open(v[0], ORDWR|OCEXEC); if (fd < 0) - fd = open(v[0], OREAD); + fd = open(v[0], OREAD|OCEXEC); safelen = sizeof(Nvrsafe); if(strstr(v[0], "/9fat") == nil) safeoff = 0; @@ -120,7 +120,7 @@ findnvram(Nvrwhere *locp) for(i=0; i<nelem(nvtab); i++){ if(strcmp(cputype, nvtab[i].cputype) != 0) continue; - if((fd = open(nvtab[i].file, ORDWR)) < 0) + if((fd = open(nvtab[i].file, ORDWR|OCEXEC)) < 0) continue; safeoff = nvtab[i].off; safelen = nvtab[i].len; diff --git a/sys/src/libc/9sys/getenv.c b/sys/src/libc/9sys/getenv.c index 9535708e7..e1c89c1d1 100644 --- a/sys/src/libc/9sys/getenv.c +++ b/sys/src/libc/9sys/getenv.c @@ -18,7 +18,8 @@ getenv(char *name) snprint(s, HUNK, "/env/%s", name); n = 0; r = -1; - if((f = open(s, OREAD)) >= 0){ + f = open(s, OREAD|OCEXEC); + if(f >= 0){ while((r = read(f, s+n, HUNK)) > 0){ n += r; r = -1; diff --git a/sys/src/libc/9sys/getnetconninfo.c b/sys/src/libc/9sys/getnetconninfo.c index 8dbb95f89..e21dcc306 100644 --- a/sys/src/libc/9sys/getnetconninfo.c +++ b/sys/src/libc/9sys/getnetconninfo.c @@ -13,7 +13,7 @@ getendpoint(char *dir, char *file, char **sysp, char **servp) sys = serv = 0; snprint(buf, sizeof buf, "%s/%s", dir, file); - fd = open(buf, OREAD); + fd = open(buf, OREAD|OCEXEC); if(fd >= 0){ n = read(fd, buf, sizeof(buf)-1); if(n>0){ @@ -41,7 +41,6 @@ getnetconninfo(char *dir, int fd) NetConnInfo *nci; char *cp; Dir *d; - char spec[10]; char path[128]; char netname[128], *p; @@ -76,10 +75,8 @@ getnetconninfo(char *dir, int fd) /* figure out bind spec */ d = dirstat(nci->dir); - if(d != nil){ - sprint(spec, "#%C%d", d->type, d->dev); - nci->spec = strdup(spec); - } + if(d != nil) + nci->spec = smprint("#%C%d", d->type, d->dev); if(nci->spec == nil) nci->spec = unknown; free(d); diff --git a/sys/src/libc/9sys/getppid.c b/sys/src/libc/9sys/getppid.c index b90b57ee5..87b878927 100644 --- a/sys/src/libc/9sys/getppid.c +++ b/sys/src/libc/9sys/getppid.c @@ -8,7 +8,7 @@ getppid(void) int f; memset(b, 0, sizeof(b)); - f = open("/dev/ppid", 0); + f = open("/dev/ppid", OREAD|OCEXEC); if(f >= 0) { read(f, b, sizeof(b)); close(f); diff --git a/sys/src/libc/9sys/getwd.c b/sys/src/libc/9sys/getwd.c index ed73cb775..cef4b4796 100644 --- a/sys/src/libc/9sys/getwd.c +++ b/sys/src/libc/9sys/getwd.c @@ -1,14 +1,12 @@ #include <u.h> #include <libc.h> -static char *nsgetwd(char*, int); - char* getwd(char *buf, int nbuf) { int n, fd; - fd = open(".", OREAD); + fd = open(".", OREAD|OCEXEC); if(fd < 0) return nil; n = fd2path(fd, buf, nbuf); diff --git a/sys/src/libc/9sys/iounit.c b/sys/src/libc/9sys/iounit.c index 194b17173..02ee77ee4 100644 --- a/sys/src/libc/9sys/iounit.c +++ b/sys/src/libc/9sys/iounit.c @@ -13,7 +13,7 @@ iounit(int fd) char buf[128], *args[10]; snprint(buf, sizeof buf, "#d/%dctl", fd); - cfd = open(buf, OREAD); + cfd = open(buf, OREAD|OCEXEC); if(cfd < 0) return 0; i = read(cfd, buf, sizeof buf-1); diff --git a/sys/src/libc/9sys/postnote.c b/sys/src/libc/9sys/postnote.c index 46564e9ea..12dc7a951 100644 --- a/sys/src/libc/9sys/postnote.c +++ b/sys/src/libc/9sys/postnote.c @@ -4,21 +4,21 @@ int postnote(int group, int pid, char *note) { - char file[128]; + char file[32]; int f, r; switch(group) { case PNPROC: - sprint(file, "/proc/%d/note", pid); + snprint(file, sizeof(file), "/proc/%lud/note", (ulong)pid); break; case PNGROUP: - sprint(file, "/proc/%d/notepg", pid); + snprint(file, sizeof(file), "/proc/%lud/notepg", (ulong)pid); break; default: return -1; } - f = open(file, OWRITE); + f = open(file, OWRITE|OCEXEC); if(f < 0) return -1; diff --git a/sys/src/libc/9sys/procsetname.c b/sys/src/libc/9sys/procsetname.c index 5a75b5147..7b9d41b8e 100644 --- a/sys/src/libc/9sys/procsetname.c +++ b/sys/src/libc/9sys/procsetname.c @@ -8,8 +8,9 @@ procsetname(char *fmt, ...) char buf[128]; va_list arg; - snprint(buf, sizeof buf, "#p/%lud/args", (ulong)getpid()); - if((fd = open(buf, OWRITE)) < 0) + snprint(buf, sizeof buf, "/proc/%lud/args", (ulong)getpid()); + fd = open(buf, OWRITE|OCEXEC); + if(fd < 0) return; va_start(arg, fmt); n = vsnprint(buf, sizeof buf, fmt, arg); diff --git a/sys/src/libc/9sys/pushssl.c b/sys/src/libc/9sys/pushssl.c index 8817dd1c3..29eee92a3 100644 --- a/sys/src/libc/9sys/pushssl.c +++ b/sys/src/libc/9sys/pushssl.c @@ -11,7 +11,7 @@ int pushssl(int fd, char *alg, char *secin, char *secout, int *cfd) { char buf[8]; - char dname[64]; + char dname[32]; int n, data, ctl; ctl = open("#D/ssl/clone", ORDWR); @@ -21,7 +21,7 @@ pushssl(int fd, char *alg, char *secin, char *secout, int *cfd) if(n < 0) goto error; buf[n] = 0; - sprint(dname, "#D/ssl/%s/data", buf); + snprint(dname, sizeof(dname), "#D/ssl/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; diff --git a/sys/src/libc/9sys/pushtls.c b/sys/src/libc/9sys/pushtls.c index 345c6b030..07e6c35a4 100644 --- a/sys/src/libc/9sys/pushtls.c +++ b/sys/src/libc/9sys/pushtls.c @@ -42,14 +42,14 @@ int pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir) { char buf[8]; - char dname[64]; + char dname[32]; int n, data, ctl, hand; // open a new filter; get ctl fd data = hand = -1; // /net/tls uses decimal file descriptors to name channels, hence a // user-level file server can't stand in for #a; may as well hard-code it. - ctl = open("#a/tls/clone", ORDWR); + ctl = open("#a/tls/clone", ORDWR|OCEXEC); if(ctl < 0) goto error; n = read(ctl, buf, sizeof(buf)-1); @@ -60,14 +60,14 @@ pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *d sprint(dir, "#a/tls/%s", buf); // get application fd - sprint(dname, "#a/tls/%s/data", buf); + snprint(dname, sizeof(dname), "#a/tls/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; // get handshake fd - sprint(dname, "#a/tls/%s/hand", buf); - hand = open(dname, ORDWR); + snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); + hand = open(dname, ORDWR|OCEXEC); if(hand < 0) goto error; diff --git a/sys/src/libc/9sys/putenv.c b/sys/src/libc/9sys/putenv.c index a99aaeb5f..034bbf0a7 100644 --- a/sys/src/libc/9sys/putenv.c +++ b/sys/src/libc/9sys/putenv.c @@ -13,7 +13,7 @@ putenv(char *name, char *val) return -1; } snprint(ename, sizeof(ename), "/env/%s", name); - f = create(ename, OWRITE, 0664); + f = create(ename, OWRITE|OCEXEC, 0664); if(f < 0) return -1; n = strlen(val); diff --git a/sys/src/libc/9sys/sysname.c b/sys/src/libc/9sys/sysname.c index 1854ddceb..6d8823643 100644 --- a/sys/src/libc/9sys/sysname.c +++ b/sys/src/libc/9sys/sysname.c @@ -10,7 +10,7 @@ sysname(void) if(b[0]) return b; - f = open("#c/sysname", 0); + f = open("/dev/sysname", OREAD|OCEXEC); if(f >= 0) { n = read(f, b, sizeof(b)-1); if(n > 0) diff --git a/sys/src/libc/port/date.c b/sys/src/libc/port/date.c index 7be6cb52f..805302432 100644 --- a/sys/src/libc/port/date.c +++ b/sys/src/libc/port/date.c @@ -174,11 +174,12 @@ loadzone(Tzone *tz, char *name) else snprint(path, sizeof(path), "/adm/timezone/%s", name); memset(buf, 0, sizeof(buf)); - if((f = open(path, 0)) == -1) + f = open(path, OREAD|OCEXEC); + if(f < 0) return -1; r = read(f, buf, sizeof(buf)); close(f); - if(r == sizeof(buf) || r == -1) + if(r < 0 || r >= sizeof(buf)) return -1; buf[r] = 0; p = buf; diff --git a/sys/src/libc/port/getuser.c b/sys/src/libc/port/getuser.c index a987244ee..ff3d2e2a1 100644 --- a/sys/src/libc/port/getuser.c +++ b/sys/src/libc/port/getuser.c @@ -8,7 +8,7 @@ getuser(void) int fd; int n; - fd = open("/dev/user", OREAD); + fd = open("/dev/user", OREAD|OCEXEC); if(fd < 0) return "none"; n = read(fd, user, (sizeof user)-1); diff --git a/sys/src/libc/port/malloc.c b/sys/src/libc/port/malloc.c index 907bfa8a6..d738cc4b9 100644 --- a/sys/src/libc/port/malloc.c +++ b/sys/src/libc/port/malloc.c @@ -99,13 +99,13 @@ checkenv(void) { int n, fd; char buf[20]; - fd = open("/env/MALLOCFD", OREAD); + fd = open("/env/MALLOCFD", OREAD|OCEXEC); if(fd < 0) return -1; - if((n = read(fd, buf, sizeof buf)) < 0) { - close(fd); + n = read(fd, buf, sizeof buf); + close(fd); + if(n < 0) return -1; - } if(n >= sizeof buf) n = sizeof(buf)-1; buf[n] = 0; diff --git a/sys/src/libc/port/profile.c b/sys/src/libc/port/profile.c index 8a8cd41b3..2a81aebcf 100644 --- a/sys/src/libc/port/profile.c +++ b/sys/src/libc/port/profile.c @@ -137,7 +137,7 @@ _profdump(void) snprint(filename, sizeof filename - 1, "prof.%ld", _tos->prof.pid); else snprint(filename, sizeof filename - 1, "prof.out"); - f = create(filename, 1, 0666); + f = create(filename, OWRITE|OCEXEC, 0666); if(f < 0) { perror("create prof.out"); return; @@ -245,7 +245,7 @@ _profmain(void) khz = _tos->cyclefreq / 1000; /* Report times in milliseconds */ havecycles = 1; } - f = open("/env/profsize", OREAD); + f = open("/env/profsize", OREAD|OCEXEC); if(f >= 0) { memset(ename, 0, sizeof(ename)); read(f, ename, sizeof(ename)-1); @@ -253,7 +253,7 @@ _profmain(void) n = atol(ename); } _tos->prof.what = Profuser; - f = open("/env/proftype", OREAD); + f = open("/env/proftype", OREAD|OCEXEC); if(f >= 0) { memset(ename, 0, sizeof(ename)); read(f, ename, sizeof(ename)-1); diff --git a/sys/src/libcomplete/complete.c b/sys/src/libcomplete/complete.c index 6c7c7e67a..a50a9a66a 100644 --- a/sys/src/libcomplete/complete.c +++ b/sys/src/libcomplete/complete.c @@ -53,7 +53,7 @@ complete(char *dir, char *s) return nil; } - fd = open(dir, OREAD); + fd = open(dir, OREAD|OCEXEC); if(fd < 0) return nil; diff --git a/sys/src/libdraw/getsubfont.c b/sys/src/libdraw/getsubfont.c index 02634c466..8832aaa11 100644 --- a/sys/src/libdraw/getsubfont.c +++ b/sys/src/libdraw/getsubfont.c @@ -22,7 +22,7 @@ _getsubfont(Display *d, char *name) if(dolock) unlockdisplay(d); - fd = open(name, OREAD); + fd = open(name, OREAD|OCEXEC); if(fd < 0) { fprint(2, "getsubfont: can't open %s: %r\n", name); f = nil; diff --git a/sys/src/libdraw/init.c b/sys/src/libdraw/init.c index f6f2551db..b02ced89b 100644 --- a/sys/src/libdraw/init.c +++ b/sys/src/libdraw/init.c @@ -49,7 +49,7 @@ geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *l return -1; } if(fontname == nil){ - fd = open("/env/font", OREAD); + fd = open("/env/font", OREAD|OCEXEC); if(fd >= 0){ n = read(fd, buf, sizeof(buf)); if(n>0 && n<sizeof buf-1){ @@ -82,11 +82,11 @@ geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *l */ if(label != nil){ snprint(buf, sizeof buf, "%s/label", display->windir); - fd = open(buf, OREAD); + fd = open(buf, OREAD|OCEXEC); if(fd >= 0){ read(fd, display->oldlabel, (sizeof display->oldlabel)-1); close(fd); - fd = create(buf, OWRITE, 0666); + fd = create(buf, OWRITE|OCEXEC, 0666); if(fd >= 0){ write(fd, label, strlen(label)); close(fd); @@ -125,7 +125,7 @@ gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref) obuf[0] = 0; retry: - fd = open(winname, OREAD); + fd = open(winname, OREAD|OCEXEC); if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){ if(fd >= 0) close(fd); strcpy(buf, "noborder"); @@ -345,7 +345,7 @@ _closedisplay(Display *disp, int isshutdown) display = nil; if(disp->oldlabel[0]){ snprint(buf, sizeof buf, "%s/label", disp->windir); - fd = open(buf, OWRITE); + fd = open(buf, OWRITE|OCEXEC); if(fd >= 0){ write(fd, disp->oldlabel, strlen(disp->oldlabel)); close(fd); diff --git a/sys/src/libdraw/openfont.c b/sys/src/libdraw/openfont.c index 7e94627a4..6d4aa2d2f 100644 --- a/sys/src/libdraw/openfont.c +++ b/sys/src/libdraw/openfont.c @@ -12,7 +12,7 @@ readfile(char *name) n = 0; r = -1; if((s = malloc(HUNK)) != nil){ - if((f = open(name, OREAD)) >= 0){ + if((f = open(name, OREAD|OCEXEC)) >= 0){ while((r = read(f, s+n, HUNK)) > 0){ n += r; r = -1; diff --git a/sys/src/libdraw/readcolmap.c b/sys/src/libdraw/readcolmap.c index 6eb8ee26e..6d63dc46d 100644 --- a/sys/src/libdraw/readcolmap.c +++ b/sys/src/libdraw/readcolmap.c @@ -27,8 +27,8 @@ readcolmap(Display *d, RGB *colmap) USED(screen); sprint(buf, "/dev/draw/%d/colormap", d->dirno); - b = Bopen(buf, OREAD); - if(b == 0) + b = Bopen(buf, OREAD|OCEXEC); + if(b == nil) drawerror(d, "rdcolmap: can't open colormap device"); for(;;) { diff --git a/sys/src/libdraw/window.c b/sys/src/libdraw/window.c index 485e14652..44f067d9f 100644 --- a/sys/src/libdraw/window.c +++ b/sys/src/libdraw/window.c @@ -90,7 +90,6 @@ freescreen(Screen *s) d = s->display; a = bufimage(d, 1+4); if(a == nil){ -Error: free(s); return -1; } diff --git a/sys/src/libdraw/writecolmap.c b/sys/src/libdraw/writecolmap.c index 26c1f7f1f..30efdf64a 100644 --- a/sys/src/libdraw/writecolmap.c +++ b/sys/src/libdraw/writecolmap.c @@ -16,7 +16,7 @@ writecolmap(Display *d, RGB *m) ulong r, g, b; sprint(buf, "/dev/draw/%d/colormap", d->dirno); - fd = open(buf, OWRITE); + fd = open(buf, OWRITE|OCEXEC); if(fd < 0) drawerror(d, "writecolmap: open colormap failed"); t = malloc(8192); diff --git a/sys/src/libndb/csgetval.c b/sys/src/libndb/csgetval.c index a1f6a9052..b6e28ff6e 100644 --- a/sys/src/libndb/csgetval.c +++ b/sys/src/libndb/csgetval.c @@ -25,10 +25,10 @@ csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp) snprint(line, sizeof(line), "%s/cs", netroot); else strcpy(line, "/net/cs"); - fd = open(line, ORDWR); + fd = open(line, ORDWR|OCEXEC); if(fd < 0) return nil; - seek(fd, 0, 0); + snprint(line, sizeof(line), "!%s=%s %s=*", attr, val, rattr); if(write(fd, line, strlen(line)) < 0){ close(fd); diff --git a/sys/src/libndb/csipinfo.c b/sys/src/libndb/csipinfo.c index 53c33f328..38a927443 100644 --- a/sys/src/libndb/csipinfo.c +++ b/sys/src/libndb/csipinfo.c @@ -23,10 +23,10 @@ csipinfo(char *netroot, char *attr, char *val, char **list, int n) snprint(line, sizeof(line), "%s/cs", netroot); else strcpy(line, "/net/cs"); - fd = open(line, ORDWR); + fd = open(line, ORDWR|OCEXEC); if(fd < 0) - return 0; - seek(fd, 0, 0); + return nil; + e = line + sizeof(line); p = seprint(line, e, "!ipinfo %s=%s", attr, val); for(i = 0; i < n; i++){ @@ -37,11 +37,11 @@ csipinfo(char *netroot, char *attr, char *val, char **list, int n) if(write(fd, line, strlen(line)) < 0){ close(fd); - return 0; + return nil; } seek(fd, 0, 0); - first = last = 0; + first = last = nil; for(;;){ n = read(fd, line, sizeof(line)-2); if(n <= 0) @@ -50,15 +50,15 @@ csipinfo(char *netroot, char *attr, char *val, char **list, int n) line[n+1] = 0; t = _ndbparseline(line); - if(t == 0) + if(t == nil) continue; - if(first) + if(first != nil) last->entry = t; else first = t; last = t; - while(last->entry) + while(last->entry != nil) last = last->entry; } close(fd); diff --git a/sys/src/libndb/dnsquery.c b/sys/src/libndb/dnsquery.c index 1bf1ff8b3..da2312e4d 100644 --- a/sys/src/libndb/dnsquery.c +++ b/sys/src/libndb/dnsquery.c @@ -29,7 +29,7 @@ dnsquery(char *net, char *val, char *type) net = "/net"; snprint(buf, sizeof(buf), "%s/dns", net); - if((fd = open(buf, ORDWR)) < 0) + if((fd = open(buf, ORDWR|OCEXEC)) < 0) return nil; /* zero out the error string */ @@ -84,7 +84,6 @@ doquery(int fd, char *dn, char *type) int n; Ndbtuple *t, *first, *last; - seek(fd, 0, 0); snprint(buf, sizeof(buf), "!%s %s", dn, type); if(write(fd, buf, strlen(buf)) < 0) return nil; diff --git a/sys/src/libndb/ndbhash.c b/sys/src/libndb/ndbhash.c index 63b0839de..5987c3ea3 100644 --- a/sys/src/libndb/ndbhash.c +++ b/sys/src/libndb/ndbhash.c @@ -57,42 +57,42 @@ hfopen(Ndb *db, char *attr) /* try opening the data base if it's closed */ if(db->mtime==0 && ndbreopen(db) < 0) - return 0; + return nil; /* if the database has changed, throw out hash files and reopen db */ if((d = dirfstat(Bfildes(&db->b))) == nil || db->qid.path != d->qid.path || db->qid.vers != d->qid.vers){ if(ndbreopen(db) < 0){ free(d); - return 0; + return nil; } } free(d); if(db->nohash) - return 0; + return nil; /* see if a hash file exists for this attribute */ - for(hf = db->hf; hf; hf= hf->next){ + for(hf = db->hf; hf != nil; hf= hf->next){ if(strcmp(hf->attr, attr) == 0) return hf; } /* create a new one */ hf = (Ndbhf*)malloc(sizeof(Ndbhf)); - if(hf == 0) - return 0; + if(hf == nil) + return nil; memset(hf, 0, sizeof(Ndbhf)); /* compare it to the database file */ strncpy(hf->attr, attr, sizeof(hf->attr)-1); sprint(buf, "%s.%s", db->file, hf->attr); - hf->fd = open(buf, OREAD); + hf->fd = open(buf, OREAD|OCEXEC); if(hf->fd >= 0){ hf->len = 0; hf->off = 0; p = hfread(hf, 0, 2*NDBULLEN); - if(p){ + if(p != nil){ hf->dbmtime = NDBGETUL(p); hf->hlen = NDBGETUL(p+NDBULLEN); if(hf->dbmtime == db->mtime){ @@ -105,7 +105,7 @@ hfopen(Ndb *db, char *attr) } free(hf); - return 0; + return nil; } /* @@ -142,17 +142,6 @@ ndbsearch(Ndb *db, Ndbs *s, char *attr, char *val) } s->ptr = NDBGETP(p); s->type = Cptr1; - } else if(db->length > 128*1024){ - print("Missing or out of date hash file %s.%s.\n", db->file, attr); - syslog(0, "ndb", "Missing or out of date hash file %s.%s.", db->file, attr); - - /* advance search to next db file */ - s->ptr = NDBNAP; - _ndbcacheadd(db, s, attr, val, nil); - if(db->next == nil) - return nil; - t = ndbsearch(db->next, s, attr, val); - goto out; } else { s->ptr = 0; s->type = Dptr; @@ -173,7 +162,7 @@ match(Ndbtuple *t, char *attr, char *val) if(strcmp(attr, nt->attr) == 0 && strcmp(val, nt->val) == 0) return nt; - return 0; + return nil; } /* diff --git a/sys/src/libndb/ndbopen.c b/sys/src/libndb/ndbopen.c index 36dd9a864..cae6e7aa0 100644 --- a/sys/src/libndb/ndbopen.c +++ b/sys/src/libndb/ndbopen.c @@ -99,7 +99,7 @@ ndbreopen(Ndb *db) } /* try the open again */ - fd = open(db->file, OREAD); + fd = open(db->file, OREAD|OCEXEC); if(fd < 0) return -1; d = dirfstat(fd); diff --git a/sys/src/libsec/port/readcert.c b/sys/src/libsec/port/readcert.c index 90ed884e2..f2758ce91 100644 --- a/sys/src/libsec/port/readcert.c +++ b/sys/src/libsec/port/readcert.c @@ -8,7 +8,7 @@ readfile(char *name) char *s; Dir *d; - fd = open(name, OREAD); + fd = open(name, OREAD|OCEXEC); if(fd < 0) return nil; if((d = dirfstat(fd)) == nil) { diff --git a/sys/src/libsec/port/thumb.c b/sys/src/libsec/port/thumb.c index 73add8db1..72e7d24a8 100644 --- a/sys/src/libsec/port/thumb.c +++ b/sys/src/libsec/port/thumb.c @@ -95,7 +95,7 @@ loadThumbprints(char *file, char *tag, Thumbprint *table, Thumbprint *crltab, in } if(access(file, AEXIST) < 0) return 0; /* not an error */ - if((bin = Bopen(file, OREAD)) == nil) + if((bin = Bopen(file, OREAD|OCEXEC)) == nil) return -1; for(; (line = Brdstr(bin, '\n', 1)) != nil; free(line)){ if(tokenize(line, field, nelem(field)) < 2) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 5f5aced9a..ee1bd270f 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -459,7 +459,7 @@ tlsServer(int fd, TLSconn *conn) if(conn == nil) return -1; - ctl = open("#a/tls/clone", ORDWR); + ctl = open("#a/tls/clone", ORDWR|OCEXEC); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); @@ -470,7 +470,7 @@ tlsServer(int fd, TLSconn *conn) buf[n] = 0; snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); - hand = open(dname, ORDWR); + hand = open(dname, ORDWR|OCEXEC); if(hand < 0){ close(ctl); return -1; @@ -592,7 +592,7 @@ tlsClient(int fd, TLSconn *conn) if(conn == nil) return -1; - ctl = open("#a/tls/clone", ORDWR); + ctl = open("#a/tls/clone", ORDWR|OCEXEC); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); @@ -603,7 +603,7 @@ tlsClient(int fd, TLSconn *conn) buf[n] = 0; snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); - hand = open(dname, ORDWR); + hand = open(dname, ORDWR|OCEXEC); if(hand < 0){ close(ctl); return -1; @@ -2178,7 +2178,7 @@ initCiphers(void) unlock(&ciphLock); return nciphers; } - j = open("#a/tls/encalgs", OREAD); + j = open("#a/tls/encalgs", OREAD|OCEXEC); if(j < 0){ werrstr("can't open #a/tls/encalgs: %r"); goto out; @@ -2202,7 +2202,7 @@ initCiphers(void) cipherAlgs[i].ok = ok; } - j = open("#a/tls/hashalgs", OREAD); + j = open("#a/tls/hashalgs", OREAD|OCEXEC); if(j < 0){ werrstr("can't open #a/tls/hashalgs: %r"); goto out; @@ -2261,7 +2261,7 @@ factotum_rsa_open(RSApub *rsapub) AuthRpc *rpc; // start talking to factotum - if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) + if((afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC)) < 0) return nil; if((rpc = auth_allocrpc(afd)) == nil){ close(afd); diff --git a/sys/src/libthread/id.c b/sys/src/libthread/id.c index 22d60f423..289dc8698 100644 --- a/sys/src/libthread/id.c +++ b/sys/src/libthread/id.c @@ -59,7 +59,7 @@ void threadsetname(char *fmt, ...) { int fd; - char buf[128]; + char buf[32]; va_list arg; Proc *p; Thread *t; @@ -72,8 +72,8 @@ threadsetname(char *fmt, ...) t->cmdname = vsmprint(fmt, arg); va_end(arg); if(t->cmdname && p->nthreads == 1){ - snprint(buf, sizeof buf, "#p/%lud/args", _tos->pid); //getpid()); - if((fd = open(buf, OWRITE)) >= 0){ + snprint(buf, sizeof buf, "/proc/%lud/args", (ulong)getpid()); + if((fd = open(buf, OWRITE|OCEXEC)) >= 0){ write(fd, t->cmdname, strlen(t->cmdname)+1); close(fd); } diff --git a/sys/src/libthread/ioproc.c b/sys/src/libthread/ioproc.c index 32be31026..1ee56c4f3 100644 --- a/sys/src/libthread/ioproc.c +++ b/sys/src/libthread/ioproc.c @@ -19,6 +19,15 @@ iointerrupt(Ioproc *io) qunlock(io); } +static int +openprocctl(void) +{ + char buf[32]; + + snprint(buf, sizeof(buf), "/proc/%lud/ctl", (ulong)getpid()); + return open(buf, OWRITE|OCEXEC); +} + static void xioproc(void *a) { @@ -28,15 +37,11 @@ xioproc(void *a) c = a; if(io = mallocz(sizeof(*io), 1)){ - char buf[128]; - /* * open might fail, ignore it for programs like factotum * that don't use iointerrupt() anyway. */ - snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); - io->ctl = open(buf, OWRITE); - + io->ctl = openprocctl(); if((io->creply = chancreate(sizeof(void*), 0)) == nil){ if(io->ctl >= 0) close(io->ctl); diff --git a/sys/src/libthread/kill.c b/sys/src/libthread/kill.c index 9160df016..e7292437c 100644 --- a/sys/src/libthread/kill.c +++ b/sys/src/libthread/kill.c @@ -76,24 +76,31 @@ threadint(int id) threadxxx(id, 0); } -static void -tinterrupt(Proc *p, Thread *t) +static int +writeprocctl(int pid, char *ctl) { - char buf[64]; + char buf[32]; int fd; + snprint(buf, sizeof(buf), "/proc/%lud/ctl", (ulong)pid); + fd = open(buf, OWRITE|OCEXEC); + if(fd < 0) + return -1; + if(write(fd, ctl, strlen(ctl)) < 0){ + close(fd); + return -1; + } + close(fd); + return 0; +} + +static void +tinterrupt(Proc *p, Thread *t) +{ switch(t->state){ case Running: - snprint(buf, sizeof(buf), "/proc/%d/ctl", p->pid); - fd = open(buf, OWRITE|OCEXEC); - if(fd >= 0){ - if(write(fd, "interrupt", 9) == 9){ - close(fd); - break; - } - close(fd); - } - postnote(PNPROC, p->pid, "threadint"); + if(writeprocctl(p->pid, "interrupt") < 0) + postnote(PNPROC, p->pid, "threadint"); break; case Rendezvous: _threadflagrendez(t); |