summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorAlex Musolino <alex@musolino.id.au>2020-12-15 20:55:41 +1030
committerAlex Musolino <alex@musolino.id.au>2020-12-15 20:55:41 +1030
commit3749e92cdb88a157f99c0709a264bd508603be9b (patch)
tree49ce703965ba4114490729c5aeabd9ba120d9b78 /sys/src
parent404c901f299c4d93cb159a3c44c2977a25408319 (diff)
parent32291b52bcbd6976051acff1692b571e321ac859 (diff)
merge
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/9/pc/cputemp.c4
-rw-r--r--sys/src/9/pc/dat.h2
-rw-r--r--sys/src/9/pc/devarch.c63
-rw-r--r--sys/src/9/pc/devvmx.c57
-rw-r--r--sys/src/9/pc/fns.h11
-rw-r--r--sys/src/9/pc/fpu.c309
-rw-r--r--sys/src/9/pc/l.s5
-rw-r--r--sys/src/9/pc/main.c266
-rw-r--r--sys/src/9/pc/mkfile1
-rw-r--r--sys/src/9/pc/mtrr.c20
-rw-r--r--sys/src/9/pc/sdiahci.c25
-rw-r--r--sys/src/9/pc64/dat.h27
-rw-r--r--sys/src/9/pc64/fns.h13
-rw-r--r--sys/src/9/pc64/fpu.c374
-rw-r--r--sys/src/9/pc64/l.s48
-rw-r--r--sys/src/9/pc64/main.c288
-rw-r--r--sys/src/9/pc64/mem.h2
-rw-r--r--sys/src/9/pc64/mkfile1
-rw-r--r--sys/src/9/port/auth.c5
-rw-r--r--sys/src/9/port/chan.c7
-rw-r--r--sys/src/9/port/devdup.c2
-rw-r--r--sys/src/9/port/devmouse.c2
-rw-r--r--sys/src/9/port/devshr.c2
-rw-r--r--sys/src/9/port/devsrv.c4
-rw-r--r--sys/src/9/port/lib.h2
-rw-r--r--sys/src/9/port/pgrp.c14
-rw-r--r--sys/src/9/port/portdat.h3
-rw-r--r--sys/src/9/port/portfns.h2
-rw-r--r--sys/src/9/port/sysfile.c50
-rw-r--r--sys/src/9/xen/archxen.c15
-rw-r--r--sys/src/9/xen/fns.h11
-rw-r--r--sys/src/9/xen/l.s26
-rw-r--r--sys/src/9/xen/main.c127
-rw-r--r--sys/src/9/xen/mkfile1
-rw-r--r--sys/src/cmd/aux/kbdfs/kbdfs.c2
-rw-r--r--sys/src/cmd/aux/statusbar.c38
-rw-r--r--sys/src/cmd/aux/statusmsg.c4
-rw-r--r--sys/src/cmd/cpu.c2
-rw-r--r--sys/src/cmd/exportfs/exportfs.c850
-rw-r--r--sys/src/cmd/exportfs/exportfs.h3
-rw-r--r--sys/src/cmd/exportfs/exportsrv.c8
-rw-r--r--sys/src/cmd/exportfs/io.c503
-rw-r--r--sys/src/cmd/exportfs/mkfile6
-rw-r--r--sys/src/cmd/exportfs/oexportfs.c443
-rw-r--r--sys/src/cmd/iostats.c1
-rw-r--r--sys/src/cmd/nusb/kb/kb.c13
-rw-r--r--sys/src/cmd/ptrap.c62
-rw-r--r--sys/src/cmd/rio/fsys.c20
-rw-r--r--sys/src/cmd/rio/rio.c61
-rw-r--r--sys/src/cmd/rio/wctl.c9
-rw-r--r--sys/src/cmd/rio/wind.c6
-rw-r--r--sys/src/cmd/srvfs.c45
-rw-r--r--sys/src/cmd/vmx/dat.h1
-rw-r--r--sys/src/cmd/vmx/exith.c269
-rw-r--r--sys/src/cmd/vmx/fns.h4
-rw-r--r--sys/src/cmd/vmx/ide.c10
-rw-r--r--sys/src/cmd/vmx/io.c14
-rw-r--r--sys/src/cmd/vmx/mkfile5
-rw-r--r--sys/src/cmd/vmx/nanosec.c9
-rw-r--r--sys/src/cmd/vmx/vesa.c3
-rw-r--r--sys/src/cmd/vmx/vga.c18
-rw-r--r--sys/src/cmd/vmx/vmx.c34
-rw-r--r--sys/src/cmd/vmx/x86.h5
-rw-r--r--sys/src/lib9p/auth.c2
-rw-r--r--sys/src/lib9p/listen.c2
-rw-r--r--sys/src/lib9p/queue.c6
-rw-r--r--sys/src/libauth/auth_challenge.c2
-rw-r--r--sys/src/libauth/auth_chuid.c6
-rw-r--r--sys/src/libauth/auth_getuserpasswd.c7
-rw-r--r--sys/src/libauth/auth_proxy.c2
-rw-r--r--sys/src/libauth/auth_respond.c2
-rw-r--r--sys/src/libauth/auth_userpasswd.c2
-rw-r--r--sys/src/libauth/newns.c19
-rw-r--r--sys/src/libauth/noworld.c2
-rw-r--r--sys/src/libauthsrv/readcons.c6
-rw-r--r--sys/src/libauthsrv/readnvram.c6
-rw-r--r--sys/src/libc/9sys/getenv.c3
-rw-r--r--sys/src/libc/9sys/getnetconninfo.c9
-rw-r--r--sys/src/libc/9sys/getppid.c2
-rw-r--r--sys/src/libc/9sys/getwd.c4
-rw-r--r--sys/src/libc/9sys/iounit.c2
-rw-r--r--sys/src/libc/9sys/postnote.c8
-rw-r--r--sys/src/libc/9sys/procsetname.c5
-rw-r--r--sys/src/libc/9sys/pushssl.c4
-rw-r--r--sys/src/libc/9sys/pushtls.c10
-rw-r--r--sys/src/libc/9sys/putenv.c2
-rw-r--r--sys/src/libc/9sys/sysname.c2
-rw-r--r--sys/src/libc/port/date.c5
-rw-r--r--sys/src/libc/port/getuser.c2
-rw-r--r--sys/src/libc/port/malloc.c8
-rw-r--r--sys/src/libc/port/profile.c6
-rw-r--r--sys/src/libcomplete/complete.c2
-rw-r--r--sys/src/libdraw/getsubfont.c2
-rw-r--r--sys/src/libdraw/init.c10
-rw-r--r--sys/src/libdraw/openfont.c2
-rw-r--r--sys/src/libdraw/readcolmap.c4
-rw-r--r--sys/src/libdraw/window.c1
-rw-r--r--sys/src/libdraw/writecolmap.c2
-rw-r--r--sys/src/libndb/csgetval.c4
-rw-r--r--sys/src/libndb/csipinfo.c16
-rw-r--r--sys/src/libndb/dnsquery.c3
-rw-r--r--sys/src/libndb/ndbhash.c31
-rw-r--r--sys/src/libndb/ndbopen.c2
-rw-r--r--sys/src/libsec/port/readcert.c2
-rw-r--r--sys/src/libsec/port/thumb.c2
-rw-r--r--sys/src/libsec/port/tlshand.c14
-rw-r--r--sys/src/libthread/id.c6
-rw-r--r--sys/src/libthread/ioproc.c15
-rw-r--r--sys/src/libthread/kill.c33
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, &regs[1], BY2WD); /* bx */
memmove(m->cpuidid+4, &regs[3], BY2WD); /* dx */
memmove(m->cpuidid+8, &regs[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, &notif);
}
-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);