From ecb12c87187a37a74f77aff45ffece9f7e985658 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 11:55:27 +0100 Subject: aux/status^(bar msg): few small fixes (thanks umbraticus) --- sys/man/8/statusbar | 3 ++- sys/src/cmd/aux/statusbar.c | 38 +++++++++++++++----------------------- sys/src/cmd/aux/statusmsg.c | 4 ++-- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/sys/man/8/statusbar b/sys/man/8/statusbar index 8f3b09a01..99878dd51 100644 --- a/sys/man/8/statusbar +++ b/sys/man/8/statusbar @@ -9,8 +9,9 @@ statusbar, statusmsg \- display a bar graph or status message window [ .B -w .I minx,miny,maxx,maxy -] +] [ .I title +] .br .B aux/statusmsg [ 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); -- cgit v1.2.3 From 7f7c1516876a0afacca2822e3e083c79551ad92c Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 12:17:05 +0100 Subject: rio: allow windows as small as one line of text, still scrollable --- sys/src/cmd/rio/wctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c index 59c9246c9..b4caa4ba4 100644 --- a/sys/src/cmd/rio/wctl.c +++ b/sys/src/cmd/rio/wctl.c @@ -95,7 +95,7 @@ goodrect(Rectangle r) return 0; if(Dy(r) > BIG*Dy(screen->r)) return 0; - if(Dx(r) < 100 || Dy(r) < 3*font->height) + if(Dx(r) < 100 || Dy(r) < 3*Borderwidth+font->height) return 0; /* window must be on screen */ if(!rectXrect(screen->r, r)) -- cgit v1.2.3 From a696951c6cbad354373a820ed1d14e25697d1fa3 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 13:02:33 +0100 Subject: rio: goodrect: clarify minimal height and actually use the smallest reasonable value --- sys/src/cmd/rio/wctl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c index b4caa4ba4..22f7b501c 100644 --- a/sys/src/cmd/rio/wctl.c +++ b/sys/src/cmd/rio/wctl.c @@ -95,7 +95,12 @@ goodrect(Rectangle r) return 0; if(Dy(r) > BIG*Dy(screen->r)) return 0; - if(Dx(r) < 100 || Dy(r) < 3*Borderwidth+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)) -- cgit v1.2.3 From f5d9b2222bc6194f35442894e0ca0ea9bb8e1f23 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 13:04:36 +0100 Subject: rio: handle corner selection for resizing better (thanks cinap) --- sys/src/cmd/rio/rio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index a42721fac..458d26d34 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -392,13 +392,15 @@ whichrect(Rectangle r, Point p, int which) int portion(int x, int lo, int hi) { + int t; x -= lo; hi -= lo; - if(hi < 20) + t = min(20, max(1, hi/2)); + if(hi < t) return x > 0 ? 2 : 0; - if(x < 20) + if(x < t) return 0; - if(x > hi-20) + if(x > hi-t) return 2; return 1; } -- cgit v1.2.3 From 082560fd5b48ff4b8c0f6c9b093c86ddf75052f6 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 13:20:29 +0100 Subject: rio: rewrite better portion() function --- sys/src/cmd/rio/rio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index 458d26d34..13c9e29eb 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -392,16 +392,15 @@ whichrect(Rectangle r, Point p, int which) int portion(int x, int lo, int hi) { - int t; x -= lo; hi -= lo; - t = min(20, max(1, hi/2)); - if(hi < t) - return x > 0 ? 2 : 0; - if(x < t) - return 0; - if(x > hi-t) - return 2; + if(x < hi/2){ + if(x < 20) + return 0; + } else { + if(x > hi-20) + return 2; + } return 1; } -- cgit v1.2.3 From bf2a6f786502026ce4229bc84a6a22e5e55a7c13 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 14:44:23 +0100 Subject: rio: use libdraw's badrect() to exclude some extreme cases in goodrect() --- sys/src/cmd/rio/wctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c index 22f7b501c..bef98fda9 100644 --- a/sys/src/cmd/rio/wctl.c +++ b/sys/src/cmd/rio/wctl.c @@ -88,7 +88,7 @@ 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)) -- cgit v1.2.3 From a0d12784bd6493e9e05c98a66d65837de82f8bda Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 14:50:50 +0100 Subject: rio: give visual clue during sweep and bandsizing when window is too small We color the window border with a dark red in case the window is too small. --- sys/src/cmd/rio/dat.h | 1 + sys/src/cmd/rio/data.c | 1 + sys/src/cmd/rio/rio.c | 50 +++++++++++++++++++++++++++----------------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h index edc855595..e18c34b49 100644 --- a/sys/src/cmd/rio/dat.h +++ b/sys/src/cmd/rio/dat.h @@ -325,6 +325,7 @@ Image *lightholdcol; Image *paleholdcol; Image *paletextcol; Image *sizecol; +Image *badsizecol; int reverse; /* there are no pastel paints in the dungeons and dragons world -- rob pike */ Window **window; diff --git a/sys/src/cmd/rio/data.c b/sys/src/cmd/rio/data.c index f9b9cfad0..e591255b9 100644 --- a/sys/src/cmd/rio/data.c +++ b/sys/src/cmd/rio/data.c @@ -196,6 +196,7 @@ iconinit(void) paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); paletextcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF^reverse); sizecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DRed); + badsizecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x880000FF); if(reverse == 0) holdcol = dholdcol; diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index 13c9e29eb..f1af15469 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -826,7 +826,7 @@ sweep(void) if(i == nil) goto Rescue; oi = i; - border(i, r, Selborder, sizecol, ZP); + border(i, r, Selborder, goodrect(r)?sizecol:badsizecol, ZP); draw(i, insetrect(r, Selborder), cols[BACK], nil, ZP); } } @@ -858,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)) @@ -866,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* @@ -902,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; @@ -936,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,13 +947,15 @@ bandsize(Window *w) riosetcursor(corners[which]); } r = whichrect(or, p, owhich); - if(!eqrect(r, or) && goodrect(r)){ + if(!eqrect(r, or)){ + drawborder(r, goodrect(r)?sizecol:badsizecol); 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); -- cgit v1.2.3 From 753a35b52ac098985aff5e22a069d30d16903385 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 15:08:23 +0100 Subject: rio: undo previous commit, was a stupid idea --- sys/src/cmd/rio/dat.h | 1 - sys/src/cmd/rio/data.c | 1 - sys/src/cmd/rio/rio.c | 6 +++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h index e18c34b49..edc855595 100644 --- a/sys/src/cmd/rio/dat.h +++ b/sys/src/cmd/rio/dat.h @@ -325,7 +325,6 @@ Image *lightholdcol; Image *paleholdcol; Image *paletextcol; Image *sizecol; -Image *badsizecol; int reverse; /* there are no pastel paints in the dungeons and dragons world -- rob pike */ Window **window; diff --git a/sys/src/cmd/rio/data.c b/sys/src/cmd/rio/data.c index e591255b9..f9b9cfad0 100644 --- a/sys/src/cmd/rio/data.c +++ b/sys/src/cmd/rio/data.c @@ -196,7 +196,6 @@ iconinit(void) paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); paletextcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF^reverse); sizecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DRed); - badsizecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x880000FF); if(reverse == 0) holdcol = dholdcol; diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index f1af15469..f02c278ed 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -826,7 +826,7 @@ sweep(void) if(i == nil) goto Rescue; oi = i; - border(i, r, Selborder, goodrect(r)?sizecol:badsizecol, ZP); + border(i, r, Selborder, sizecol, ZP); draw(i, insetrect(r, Selborder), cols[BACK], nil, ZP); } } @@ -947,8 +947,8 @@ bandsize(Window *w) riosetcursor(corners[which]); } r = whichrect(or, p, owhich); - if(!eqrect(r, or)){ - drawborder(r, goodrect(r)?sizecol:badsizecol); + if(!eqrect(r, or) && goodrect(r)){ + drawborder(r, sizecol); or = r; } readmouse(mousectl); -- cgit v1.2.3 From 66b6185845e85258f1408271d5f705aacfa6ffdb Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 18:48:32 +0100 Subject: amd64, vmx: support avx/avx2 for host/guest; use *noavx= in plan9.ini to disable --- sys/man/8/plan9.ini | 2 + sys/src/9/pc/cputemp.c | 4 +- sys/src/9/pc/dat.h | 2 +- sys/src/9/pc/devarch.c | 28 ++---- sys/src/9/pc/devvmx.c | 57 +++++++++-- sys/src/9/pc/fns.h | 4 +- sys/src/9/pc/fpu.c | 31 ++++++ sys/src/9/pc/l.s | 5 +- sys/src/9/pc/mkfile | 1 + sys/src/9/pc/mtrr.c | 4 +- sys/src/9/pc64/dat.h | 29 +++++- sys/src/9/pc64/fns.h | 10 +- sys/src/9/pc64/fpu.c | 51 ++++++++++ sys/src/9/pc64/l.s | 48 ++++++++- sys/src/9/pc64/main.c | 42 +++++++- sys/src/9/pc64/mem.h | 1 - sys/src/9/pc64/mkfile | 1 + sys/src/cmd/vmx/exith.c | 259 +++++++++++++++++++++++++++++++----------------- sys/src/cmd/vmx/fns.h | 1 + sys/src/cmd/vmx/x86.h | 5 +- 20 files changed, 446 insertions(+), 139 deletions(-) create mode 100644 sys/src/9/pc/fpu.c create mode 100644 sys/src/9/pc64/fpu.c diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index 765aad04b..d89cf713c 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -898,6 +898,8 @@ The main feature of the interface is the ability to watch battery life (see .IR stats (8)). It is not on by default because it causes problems on some laptops. +.SS \fL*noavx=\fP +Disables AVX and AVX2 on AMD64 CPUs. .SS USB .SS \fL*nousbprobe=\fP Disable USB host controller detection. 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..564e7e7d8 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, @@ -507,13 +502,13 @@ cpuidentify(void) ulong regs[4]; vlong mca, mct, pat; - cpuid(Highstdfunc, regs); + cpuid(Highstdfunc, 0, regs); memmove(m->cpuidid, ®s[1], BY2WD); /* bx */ memmove(m->cpuidid+4, ®s[3], BY2WD); /* dx */ memmove(m->cpuidid+8, ®s[2], BY2WD); /* cx */ m->cpuidid[12] = '\0'; - cpuid(Procsig, regs); + cpuid(Procsig, 0, regs); m->cpuidax = regs[0]; m->cpuidcx = regs[2]; m->cpuiddx = regs[3]; @@ -650,15 +645,6 @@ cpuidentify(void) if(m->cpuiddx & Mtrr) 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 +655,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 +675,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; @@ -483,6 +487,13 @@ dr7write(Vmx *vmx, char *s) return 0; } +static int +xcr0write(Vmx *vmx, char *s) +{ + vmx->xcr0 = parseval(s) & 7; + return 0; +} + static int readonly(Vmx *, char *) { @@ -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..b1c92248d 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*); @@ -138,6 +139,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..8955306f8 --- /dev/null +++ b/sys/src/9/pc/fpu.c @@ -0,0 +1,31 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +enum { + CR4Osfxsr = 1 << 9, + CR4Oxmmex = 1 << 10, +}; + +void +putxcr0(ulong) +{ +} + +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/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..7adb13a64 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; diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index 84efe9a2c..7cfc6e5c2 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,12 @@ struct Mach int havewatchpt8; int havenx; uvlong tscticks; - + u64int dr7; /* shadow copy of dr7 */ - + u64int xcr0; + u32int fpsavesz; + u32int fpalign; + void* vmx; uintptr stack[1]; @@ -270,8 +287,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..9e07b33d8 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*); @@ -40,6 +41,11 @@ void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); void fpsserestore(FPsave*); void fpssesave(FPsave*); +void fpxrestore(FPsave*); +void fpxrestores(FPsave*); +void fpxsave(FPsave*); +void fpxsaveopt(FPsave*); +void fpxsaves(FPsave*); void fpx87restore(FPsave*); void fpx87save(FPsave*); int fpusave(void); @@ -48,6 +54,7 @@ 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 +145,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..4326f51a7 --- /dev/null +++ b/sys/src/9/pc64/fpu.c @@ -0,0 +1,51 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +enum { + CR4Osfxsr = 1 << 9, + CR4Oxmmex = 1 << 10, + CR4Oxsave = 1 << 18, +}; + +void +fpuinit(void) +{ + uintptr cr4; + ulong regs[4]; + + m->fpsavesz = sizeof(FPssestate); + m->fpalign = 16; + if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ + cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; + putcr4(cr4); + fpsave = fpssesave; + fprestore = fpsserestore; + + if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ + cr4 |= CR4Oxsave; + putcr4(cr4); + m->xcr0 = 7; /* x87, sse, avx */ + putxcr0(m->xcr0); + fpsave = fpxsave; + fprestore = fpxrestore; + + cpuid(0xd, 0, regs); + m->fpsavesz = regs[1]; + m->fpalign = 64; + + cpuid(0xd, 1, regs); + if(regs[0] & Xsaveopt) + fpsave = fpxsaveopt; + if(regs[0] & Xsaves){ + fpsave = fpxsaves; + fprestore = fpxrestores; + } + } + } else { + fpsave = fpx87save; + fprestore = fpx87restore; + } +} 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..4026ee151 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -304,6 +304,9 @@ 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); @@ -333,6 +336,39 @@ fpsserestore(FPsave *s) _fxrstor(s); } +void +fpxsave(FPsave *s) +{ + _xsave(s); + _stts(); +} +void +fpxrestore(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +void +fpxsaves(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} +void +fpxrestores(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +void +fpxsaveopt(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} + static char* mathmsg[] = { nil, /* handled below */ @@ -452,7 +488,7 @@ mathemu(Ureg *ureg, void*) up->fpstate |= FPkernel; } while(up->fpslot[index] == nil) - up->fpslot[index] = mallocalign(sizeof(FPsave), FPalign, 0, 0); + up->fpslot[index] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); up->fpsave = up->fpslot[index]; up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); break; @@ -538,8 +574,8 @@ procfork(Proc *p) 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->fpslot[0] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); + memmove(p->fpsave = p->fpslot[0], up->fpslot[0], m->fpsavesz); p->fpstate = FPinactive; } splx(s); diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index c6f9bba70..f02e042a6 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -26,7 +26,6 @@ #define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) #define PGROUND(s) ROUND(s, BY2PG) #define BLOCKALIGN 8 -#define FPalign 16 #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/cmd/vmx/exith.c b/sys/src/cmd/vmx/exith.c index 48f054c01..a96646294 100644 --- a/sys/src/cmd/vmx/exith.c +++ b/sys/src/cmd/vmx/exith.c @@ -1,9 +1,8 @@ #include #include -#include -#include #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) + vmerror("unknown cpuid field eax=%#ux", ax); zero: - ax = 0; - bx = 0; - cx = 0; - dx = 0; + ax = cx = 0; break; } rset(RAX, ax); @@ -267,6 +322,9 @@ 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); @@ -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..54c9ef252 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 *); 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, }; -- cgit v1.2.3 From 334c5e1134719a02c35c72ec5435a967a74846f8 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 19:31:56 +0100 Subject: amd64: FP: always use enough to fit AVX state and align to 64 bytes --- sys/src/9/pc64/dat.h | 1 - sys/src/9/pc64/fpu.c | 4 +--- sys/src/9/pc64/main.c | 4 ++-- sys/src/9/pc64/mem.h | 1 + 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index 7cfc6e5c2..b9b9fc147 100644 --- a/sys/src/9/pc64/dat.h +++ b/sys/src/9/pc64/dat.h @@ -242,7 +242,6 @@ struct Mach u64int dr7; /* shadow copy of dr7 */ u64int xcr0; u32int fpsavesz; - u32int fpalign; void* vmx; diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c index 4326f51a7..6ac8819d7 100644 --- a/sys/src/9/pc64/fpu.c +++ b/sys/src/9/pc64/fpu.c @@ -16,8 +16,7 @@ fpuinit(void) uintptr cr4; ulong regs[4]; - m->fpsavesz = sizeof(FPssestate); - m->fpalign = 16; + m->fpsavesz = sizeof(FPsave); /* always enough to fit sse+avx */ if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; putcr4(cr4); @@ -34,7 +33,6 @@ fpuinit(void) cpuid(0xd, 0, regs); m->fpsavesz = regs[1]; - m->fpalign = 64; cpuid(0xd, 1, regs); if(regs[0] & Xsaveopt) diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 4026ee151..803799ab9 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -488,7 +488,7 @@ mathemu(Ureg *ureg, void*) up->fpstate |= FPkernel; } while(up->fpslot[index] == nil) - up->fpslot[index] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); + up->fpslot[index] = mallocalign(m->fpsavesz, FPalign, 0, 0); up->fpsave = up->fpslot[index]; up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); break; @@ -574,7 +574,7 @@ procfork(Proc *p) case FPinactive | FPpush: case FPinactive: while(p->fpslot[0] == nil) - p->fpslot[0] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); + p->fpslot[0] = mallocalign(m->fpsavesz, FPalign, 0, 0); memmove(p->fpsave = p->fpslot[0], up->fpslot[0], m->fpsavesz); p->fpstate = FPinactive; } diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index f02e042a6..4541a62a0 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -26,6 +26,7 @@ #define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) #define PGROUND(s) ROUND(s, BY2PG) #define BLOCKALIGN 8 +#define FPalign 64 #define MAXMACH 128 /* max # cpus system can run */ -- cgit v1.2.3 From 97b32915334c700a8b282888481c7f37a6ae0442 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 19:40:57 +0100 Subject: amd64: FP: back to static size for allocation and copying --- sys/src/9/pc64/dat.h | 1 - sys/src/9/pc64/fpu.c | 4 ---- sys/src/9/pc64/main.c | 6 +++--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index b9b9fc147..b597f8988 100644 --- a/sys/src/9/pc64/dat.h +++ b/sys/src/9/pc64/dat.h @@ -241,7 +241,6 @@ struct Mach u64int dr7; /* shadow copy of dr7 */ u64int xcr0; - u32int fpsavesz; void* vmx; diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c index 6ac8819d7..3af4d60e3 100644 --- a/sys/src/9/pc64/fpu.c +++ b/sys/src/9/pc64/fpu.c @@ -16,7 +16,6 @@ fpuinit(void) uintptr cr4; ulong regs[4]; - m->fpsavesz = sizeof(FPsave); /* always enough to fit sse+avx */ if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; putcr4(cr4); @@ -31,9 +30,6 @@ fpuinit(void) fpsave = fpxsave; fprestore = fpxrestore; - cpuid(0xd, 0, regs); - m->fpsavesz = regs[1]; - cpuid(0xd, 1, regs); if(regs[0] & Xsaveopt) fpsave = fpxsaveopt; diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 803799ab9..4ab9c0a31 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -488,7 +488,7 @@ mathemu(Ureg *ureg, void*) up->fpstate |= FPkernel; } while(up->fpslot[index] == nil) - up->fpslot[index] = mallocalign(m->fpsavesz, FPalign, 0, 0); + up->fpslot[index] = mallocalign(sizeof(FPsave), FPalign, 0, 0); up->fpsave = up->fpslot[index]; up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); break; @@ -574,8 +574,8 @@ procfork(Proc *p) case FPinactive | FPpush: case FPinactive: while(p->fpslot[0] == nil) - p->fpslot[0] = mallocalign(m->fpsavesz, FPalign, 0, 0); - memmove(p->fpsave = p->fpslot[0], up->fpslot[0], m->fpsavesz); + 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); -- cgit v1.2.3 From dbbae6d38405cdd817f84e2ace104bb27963a246 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Sun, 6 Dec 2020 20:28:53 +0100 Subject: xen: fix for the last avx changes --- sys/src/9/xen/fns.h | 3 ++- sys/src/9/xen/mkfile | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h index 9dd3d239e..f1e047654 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -9,7 +9,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*); 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\ -- cgit v1.2.3 From 8c1bde46f0aa97e9f018e7fb805f367e908fa379 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 21:07:30 +0100 Subject: pc, pc64: move all fpu specific code from main.c to fpu.c --- sys/src/9/pc/fns.h | 6 - sys/src/9/pc/fpu.c | 277 ++++++++++++++++++++++++++++++++++++++++ sys/src/9/pc/main.c | 266 -------------------------------------- sys/src/9/pc64/fns.h | 13 +- sys/src/9/pc64/fpu.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++ sys/src/9/pc64/main.c | 324 +---------------------------------------------- 6 files changed, 631 insertions(+), 600 deletions(-) diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index b1c92248d..7bbaeb551 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -41,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); diff --git a/sys/src/9/pc/fpu.c b/sys/src/9/pc/fpu.c index 8955306f8..c7aa47bb7 100644 --- a/sys/src/9/pc/fpu.c +++ b/sys/src/9/pc/fpu.c @@ -3,17 +3,294 @@ #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*); + 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<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) { 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 @@ -233,272 +233,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<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 */ diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 9e07b33d8..90d831e3a 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -39,15 +39,10 @@ int ecwrite(uchar addr, uchar val); void fpinit(void); void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); -void fpsserestore(FPsave*); -void fpssesave(FPsave*); -void fpxrestore(FPsave*); -void fpxrestores(FPsave*); -void fpxsave(FPsave*); -void fpxsaveopt(FPsave*); -void fpxsaves(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); diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c index 3af4d60e3..924a5752f 100644 --- a/sys/src/9/pc64/fpu.c +++ b/sys/src/9/pc64/fpu.c @@ -3,6 +3,8 @@ #include "mem.h" #include "dat.h" #include "fns.h" +#include "ureg.h" +#include "io.h" enum { CR4Osfxsr = 1 << 9, @@ -10,6 +12,252 @@ enum { 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); + +/* + * not used, AMD64 mandated SSE + */ +static void +fpx87save(FPsave*) +{ +} +static void +fpx87restore(FPsave*) +{ +} + +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<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) { @@ -43,3 +291,100 @@ fpuinit(void) fprestore = fpx87restore; } } + +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/main.c b/sys/src/9/pc64/main.c index 4ab9c0a31..4083e33f6 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -293,254 +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 _xrstor(void*); -extern void _xsave(void*); -extern void _xsaveopt(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); -} - -void -fpxsave(FPsave *s) -{ - _xsave(s); - _stts(); -} -void -fpxrestore(FPsave *s) -{ - _clts(); - _xrstor(s); -} - -void -fpxsaves(FPsave *s) -{ - _xsaveopt(s); - _stts(); -} -void -fpxrestores(FPsave *s) -{ - _clts(); - _xrstor(s); -} - -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<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)); @@ -556,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 @@ -594,6 +331,8 @@ procrestore(Proc *p) if(p->vmx != nil) vmxprocrestore(p); + fpuprocrestore(p); + if(p->kp) return; @@ -618,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 @@ -653,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; -} -- cgit v1.2.3 From dcdb2bfb9ab915b9f18c36dc951ca421d97496a2 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 21:28:11 +0100 Subject: xen: use pc/fpu.c --- sys/src/9/xen/archxen.c | 15 ------ sys/src/9/xen/fns.h | 8 --- sys/src/9/xen/l.s | 26 ++++++---- sys/src/9/xen/main.c | 127 ------------------------------------------------ 4 files changed, 17 insertions(+), 159 deletions(-) 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 f1e047654..bc87a60ef 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -17,18 +17,10 @@ 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<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 */ -- cgit v1.2.3 From cd38d4135633fd2dd9ce544aa3c2c86cf5078f8d Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 21:44:26 +0100 Subject: pc64: AMD64 mandates SSE support, remove the check in fpuinit() --- sys/src/9/pc64/fpu.c | 53 ++++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c index 924a5752f..2b9a377b7 100644 --- a/sys/src/9/pc64/fpu.c +++ b/sys/src/9/pc64/fpu.c @@ -30,18 +30,6 @@ extern void _fwait(void); extern void _ldmxcsr(u32int); extern void _stts(void); -/* - * not used, AMD64 mandated SSE - */ -static void -fpx87save(FPsave*) -{ -} -static void -fpx87restore(FPsave*) -{ -} - static void fpssesave(FPsave *s) { @@ -261,34 +249,29 @@ mathinit(void) void fpuinit(void) { - uintptr cr4; + u64int cr4; ulong regs[4]; - if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ - cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; - putcr4(cr4); - fpsave = fpssesave; - fprestore = fpsserestore; + cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; + putcr4(cr4); + fpsave = fpssesave; + fprestore = fpsserestore; - if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ - cr4 |= CR4Oxsave; - putcr4(cr4); - m->xcr0 = 7; /* x87, sse, avx */ - putxcr0(m->xcr0); - fpsave = fpxsave; - fprestore = fpxrestore; + if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ + cr4 |= CR4Oxsave; + putcr4(cr4); + m->xcr0 = 7; /* x87, sse, avx */ + putxcr0(m->xcr0); + fpsave = fpxsave; + fprestore = fpxrestore; - cpuid(0xd, 1, regs); - if(regs[0] & Xsaveopt) - fpsave = fpxsaveopt; - if(regs[0] & Xsaves){ - fpsave = fpxsaves; - fprestore = fpxrestores; - } + cpuid(0xd, 1, regs); + if(regs[0] & Xsaveopt) + fpsave = fpxsaveopt; + if(regs[0] & Xsaves){ + fpsave = fpxsaves; + fprestore = fpxrestores; } - } else { - fpsave = fpx87save; - fprestore = fpx87restore; } } -- cgit v1.2.3 From d15439ee765ec027db49777ebd9760be20ba3b31 Mon Sep 17 00:00:00 2001 From: kvik Date: Sun, 6 Dec 2020 21:52:01 +0100 Subject: ptrap: implement filtering on plumb attributes --- sys/man/4/ptrap | 42 ++++++++++++++++++++---------------- sys/src/cmd/ptrap.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 27 deletions(-) diff --git a/sys/man/4/ptrap b/sys/man/4/ptrap index 5c29956ad..35238b4c9 100644 --- a/sys/man/4/ptrap +++ b/sys/man/4/ptrap @@ -7,10 +7,7 @@ filter .B ptrap .I port [\fB!\fR]\fIregexp\fR -[ -.I port -[\fB!\fR]\fIregexp\fR ... -] +[ +\fIattr\fR [\fB!\fR]\fIregexp\fR ... ] ... .SH DESCRIPTION .I Ptrap is a program that mounts itself over a @@ -20,20 +17,20 @@ service mounted at and filters incoming messages according to the rules provided on the command line. .PP .I Ptrap -accepts an arbitrary number of argument pairs; each pair consists of a port name -.I port -and a regular expression -.I regexp -(see -.IR regexp (6)). -Each incoming message that does not match -.I regexp -is discarded. -The -.I regexp -can be optionally prefixed by -.B ! -to indicate logical inversion (i.e. messages matching the regexp are discarded). +accepts an arbitrary number of filters; +each filter applies to a port, and may match over both the data and attributes of plumb messages. +.PP +A filter is formatted as a port name, a data filter, and a list of attribute filters. +.PP +The data filter is a +.IR regex (6) +that matches the plumbed data. +The attribute filter consists of the attribute name prefixed with a '+', followed by a +.IR regex (6) +that matches the contents of the attribute. +Any regex may be prefixed with a '!' in order to negate a match, +causing all matches for that regex to be discarded. +All parts of a filter must match in order for a plumb message to be forwarded. .SH EXAMPLES Start a .IR sam (1) @@ -52,6 +49,15 @@ instance for all other editing jobs: ptrap edit '!^/sys/src/9/' sam .EE +.PP +Start an +.IR acme (1) +instance instance dedicated to reading plumbed manual pages: +.IP +.EX +ptrap edit '.*' +action '^showdata' +filename '^/man/' +acme -c1 +.EE .SH SOURCE .B /sys/src/cmd/ptrap.c .SH SEE ALSO 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; @@ -161,13 +170,33 @@ ptrapopen(Req *r) respond(r, nil); } +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); -- cgit v1.2.3 From 23b52bbf23bcc3f7f64b4d3496993bee83f5f2eb Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 6 Dec 2020 22:05:00 +0100 Subject: pc64: assign fpsave/fprestore only once in fpuinit() --- sys/src/9/pc64/fpu.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c index 2b9a377b7..1a5f31251 100644 --- a/sys/src/9/pc64/fpu.c +++ b/sys/src/9/pc64/fpu.c @@ -253,25 +253,26 @@ fpuinit(void) ulong regs[4]; cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; - putcr4(cr4); - fpsave = fpssesave; - fprestore = fpsserestore; - if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ cr4 |= CR4Oxsave; putcr4(cr4); m->xcr0 = 7; /* x87, sse, avx */ putxcr0(m->xcr0); - fpsave = fpxsave; - fprestore = fpxrestore; - cpuid(0xd, 1, regs); - if(regs[0] & Xsaveopt) - fpsave = fpxsaveopt; 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; } } -- cgit v1.2.3 From a92ffdbbfb3157d6fef23e3a8901c7ecdea68f1b Mon Sep 17 00:00:00 2001 From: kvik Date: Mon, 7 Dec 2020 00:36:41 +0100 Subject: libndb: remove db file size limit Removes the 128 kB limit for files making up the database. We used to skip over and complain about files that exceeded the limit, forcing the user to generate hash files. This caused things to inexplicably stop working after a file hit the hidden limit, which is unreasonable behaviour considering that libndb happily, albeit slowly, works with bigger files. --- sys/src/libndb/ndbhash.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/sys/src/libndb/ndbhash.c b/sys/src/libndb/ndbhash.c index 63b0839de..ff481231f 100644 --- a/sys/src/libndb/ndbhash.c +++ b/sys/src/libndb/ndbhash.c @@ -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; -- cgit v1.2.3 From c86a9608806b7d6bc95b68f1baa2e32451fd6ca8 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:22:30 +0100 Subject: rio: simplify filsysinit() by using getuser(), format pid's as ulongs --- sys/src/cmd/rio/fsys.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) 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; -- cgit v1.2.3 From ed3ae3faa3cbb9171890d6c963a8d86cdeffd96b Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:23:23 +0100 Subject: rio: open /dev/snarf with OCEXEC flag when writing --- sys/src/cmd/rio/rio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index f02c278ed..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 */ -- cgit v1.2.3 From 544bca0290df1dc512641a1ab23e184ccc2406b3 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:23:41 +0100 Subject: rio: format pid's as ulongs --- sys/src/cmd/rio/wind.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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) -- cgit v1.2.3 From f1e15da8f550b12196d57e245437251f6eb289b5 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:24:51 +0100 Subject: libc: open internal file-descriptor with OCEXEC flag --- sys/src/libc/9sys/access.c | 2 +- sys/src/libc/9sys/getenv.c | 3 ++- sys/src/libc/9sys/getnetconninfo.c | 9 +++------ sys/src/libc/9sys/getppid.c | 2 +- sys/src/libc/9sys/getwd.c | 4 +--- sys/src/libc/9sys/iounit.c | 2 +- sys/src/libc/9sys/postnote.c | 8 ++++---- sys/src/libc/9sys/procsetname.c | 5 +++-- sys/src/libc/9sys/pushssl.c | 4 ++-- sys/src/libc/9sys/pushtls.c | 10 +++++----- sys/src/libc/9sys/putenv.c | 2 +- sys/src/libc/9sys/sysname.c | 2 +- sys/src/libc/port/date.c | 5 +++-- sys/src/libc/port/getuser.c | 2 +- sys/src/libc/port/malloc.c | 8 ++++---- sys/src/libc/port/profile.c | 6 +++--- 16 files changed, 36 insertions(+), 38 deletions(-) diff --git a/sys/src/libc/9sys/access.c b/sys/src/libc/9sys/access.c index c9fee3432..86e459955 100644 --- a/sys/src/libc/9sys/access.c +++ b/sys/src/libc/9sys/access.c @@ -24,7 +24,7 @@ access(char *name, int mode) return 0; return -1; } - fd = open(name, omode[mode&7]); + fd = open(name, omode[mode&7]|OCEXEC); if(fd >= 0){ close(fd); return 0; 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 #include -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); -- cgit v1.2.3 From 1e2657ee9726e5dd9b8b1f39fa94bb02c1f5cdb7 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:27:46 +0100 Subject: libthread: simplify threadsetname() - open /proc/n/args with OCEXEC flag - reduce stack usage by using smaller buffer for path - format pid as ulong --- sys/src/libthread/id.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); } -- cgit v1.2.3 From e45bd6814a125e7a175ff19e23252608a060d847 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:29:45 +0100 Subject: libthread: reduce stack usage for ioprocs, open /proc/n/ctl with OCEXEC flag --- sys/src/libthread/ioproc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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); -- cgit v1.2.3 From c10e21b491937315a096e3e83840886fd7ba9ae8 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:31:02 +0100 Subject: libthread: reduce stack usage of threadkill*(), open /proc/n/ctl with OCEXEC flag --- sys/src/libthread/kill.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) 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); -- cgit v1.2.3 From e8b871ef5af74187a17b068e8fc2c1b44384a782 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:32:12 +0100 Subject: libdraw: remove unused Error label in freescreen() --- sys/src/libdraw/window.c | 1 - 1 file changed, 1 deletion(-) 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; } -- cgit v1.2.3 From 4d22dbb0f5a0cd4d3202a01a8cc18b632b5c9b01 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:32:34 +0100 Subject: libdraw: open internal file-descriptors with OCEXEC flag --- sys/src/libdraw/getsubfont.c | 2 +- sys/src/libdraw/init.c | 10 +++++----- sys/src/libdraw/newwindow.c | 2 +- sys/src/libdraw/openfont.c | 2 +- sys/src/libdraw/writecolmap.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) 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 && nwindir); - 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/newwindow.c b/sys/src/libdraw/newwindow.c index 2fb708bef..73306be03 100644 --- a/sys/src/libdraw/newwindow.c +++ b/sys/src/libdraw/newwindow.c @@ -13,7 +13,7 @@ newwindow(char *str) wsys = getenv("wsys"); if(wsys == nil) return -1; - fd = open(wsys, ORDWR); + fd = open(wsys, ORDWR|OCEXEC); if(fd < 0){ free(wsys); return -1; 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/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); -- cgit v1.2.3 From d570229e8268c96e97858f021b84bf00305f1daa Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:49:12 +0100 Subject: lib9p: improve reqqueuecreate() - open /proc/n/ctl with OCEXEC flag - format pid as ulong - don't leak the fd --- sys/src/lib9p/queue.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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); -- cgit v1.2.3 From 4d4b6a19de040a111cca42d518fe0d26c255ceec Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:51:53 +0100 Subject: lib9p: open /mnt/factotum/rpc with OCEXEC flag in auth9p() --- sys/src/lib9p/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; -- cgit v1.2.3 From 5e59c57bb110403f83a41ad88415e108c6cb1f6a Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 14:54:27 +0100 Subject: lib9p: open internal file-descriptor with OCEXEC flag in getremotesys() --- sys/src/lib9p/listen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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){ -- cgit v1.2.3 From 1a900513fb137143e1c1f8177975952bc404f5a9 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 15:15:02 +0100 Subject: libndb: open internal file-descriptors with OCEXEC flag --- sys/src/libndb/csgetval.c | 4 ++-- sys/src/libndb/csipinfo.c | 16 ++++++++-------- sys/src/libndb/dnsquery.c | 3 +-- sys/src/libndb/ndbhash.c | 20 ++++++++++---------- sys/src/libndb/ndbopen.c | 2 +- 5 files changed, 22 insertions(+), 23 deletions(-) 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 ff481231f..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; } /* @@ -162,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); -- cgit v1.2.3 From f341ae8c777dda2876beb4d4a1c67c4e920595ca Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 16:30:27 +0100 Subject: libdraw: open file-descriptor with OCEXEC flag in readcolmap() --- sys/src/libdraw/readcolmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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(;;) { -- cgit v1.2.3 From 6c29cf79f073c71b1e0db1a9f713c52803ba32f7 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Mon, 7 Dec 2020 16:42:56 +0100 Subject: aux/kbdfs, kbmaps: enable Kmod4 for other layouts, not just neo2 --- sys/lib/kbmap/ascii | 2 +- sys/lib/kbmap/by | 2 +- sys/lib/kbmap/de | 2 +- sys/lib/kbmap/hr | 2 +- sys/lib/kbmap/hu | 2 +- sys/lib/kbmap/it | 2 +- sys/lib/kbmap/pl | 2 +- sys/lib/kbmap/ru | 2 +- sys/lib/kbmap/sg | 2 +- sys/lib/kbmap/sr | 2 +- sys/lib/kbmap/sr-latin | 2 +- sys/lib/kbmap/ua | 2 +- sys/lib/kbmap/us | 2 +- sys/src/cmd/aux/kbdfs/kbdfs.c | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sys/lib/kbmap/ascii b/sys/lib/kbmap/ascii index 705d4e8f1..75b259426 100644 --- a/sys/lib/kbmap/ascii +++ b/sys/lib/kbmap/ascii @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/by b/sys/lib/kbmap/by index ed66ca4ee..6409ccf6e 100644 --- a/sys/lib/kbmap/by +++ b/sys/lib/kbmap/by @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/de b/sys/lib/kbmap/de index 1df7d01ab..cdcfef393 100644 --- a/sys/lib/kbmap/de +++ b/sys/lib/kbmap/de @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/hr b/sys/lib/kbmap/hr index c2e362644..248c191e8 100644 --- a/sys/lib/kbmap/hr +++ b/sys/lib/kbmap/hr @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/hu b/sys/lib/kbmap/hu index 9bb9d32bf..ed1607b54 100644 --- a/sys/lib/kbmap/hu +++ b/sys/lib/kbmap/hu @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/it b/sys/lib/kbmap/it index e537b36d1..7163411c8 100644 --- a/sys/lib/kbmap/it +++ b/sys/lib/kbmap/it @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/pl b/sys/lib/kbmap/pl index 4e8cd93f2..d0f99c75e 100644 --- a/sys/lib/kbmap/pl +++ b/sys/lib/kbmap/pl @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/ru b/sys/lib/kbmap/ru index 8b142de4e..0c6e4d880 100644 --- a/sys/lib/kbmap/ru +++ b/sys/lib/kbmap/ru @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/sg b/sys/lib/kbmap/sg index 68d0d1f80..f36391bc7 100644 --- a/sys/lib/kbmap/sg +++ b/sys/lib/kbmap/sg @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/sr b/sys/lib/kbmap/sr index bf5a55eb7..7c19249b1 100644 --- a/sys/lib/kbmap/sr +++ b/sys/lib/kbmap/sr @@ -345,7 +345,7 @@ _1 53 '_ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/sr-latin b/sys/lib/kbmap/sr-latin index 7007dbba7..60d397754 100644 --- a/sys/lib/kbmap/sr-latin +++ b/sys/lib/kbmap/sr-latin @@ -345,7 +345,7 @@ _1 53 '_ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/ua b/sys/lib/kbmap/ua index 1dbb378cc..04d314820 100644 --- a/sys/lib/kbmap/ua +++ b/sys/lib/kbmap/ua @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 diff --git a/sys/lib/kbmap/us b/sys/lib/kbmap/us index 705d4e8f1..75b259426 100644 --- a/sys/lib/kbmap/us +++ b/sys/lib/kbmap/us @@ -345,7 +345,7 @@ 2 88 0 2 89 0 2 90 0 -2 91 0 +2 91 0xf868 2 92 0 2 93 0 2 94 0 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, -- cgit v1.2.3 From f433f1426b10dc7bdd313ee72b842e27089f88f1 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 16:46:34 +0100 Subject: libauth: open internal file-descriptors with OCEXEC flag --- sys/src/libauth/auth_challenge.c | 2 +- sys/src/libauth/auth_chuid.c | 8 ++++---- sys/src/libauth/auth_getuserpasswd.c | 7 +++---- sys/src/libauth/auth_proxy.c | 2 +- sys/src/libauth/auth_respond.c | 2 +- sys/src/libauth/auth_userpasswd.c | 2 +- sys/src/libauth/newns.c | 21 ++++++++++++--------- sys/src/libauth/noworld.c | 2 +- 8 files changed, 24 insertions(+), 22 deletions(-) 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..6b3819e86 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; @@ -29,10 +29,10 @@ auth_chuid(AuthInfo *ai, char *ns) } /* get a link to factotum as new user */ - fd = open("/srv/factotum", ORDWR); + fd = open("/srv/factotum", ORDWR|OCEXEC); 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..91bf5f802 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); @@ -192,7 +194,7 @@ nsop(char *fn, int argc, char *argv[], AuthRpc *rpc) else if(argc == 2) unmount(argv[0], argv[1]); }else if(strcmp(argv0, "mount") == 0){ - fd = open(argv[0], ORDWR); + fd = open(argv[0], ORDWR|OCEXEC); if(fd < 0){ if(newnsdebug) fprint(2, "%s: mount: %s: %r\n", fn, argv[0]); @@ -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){ -- cgit v1.2.3 From f7e21d7692e619e9a926f29f2d59906c0d7ef072 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 16:47:06 +0100 Subject: libauthsrv: open internal file-descriptors with OCEXEC flag --- sys/src/libauthsrv/readcons.c | 6 +++--- sys/src/libauthsrv/readnvram.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) 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 Date: Mon, 7 Dec 2020 17:14:34 +0100 Subject: libsec: open internal file-descriptors with OCEXEC flag --- sys/src/libsec/port/readcert.c | 2 +- sys/src/libsec/port/thumb.c | 2 +- sys/src/libsec/port/tlshand.c | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) 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); -- cgit v1.2.3 From 1bb96d542cd43a027934ca372e0ab8c87f523db9 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 17:18:33 +0100 Subject: libcomplete: open internal file-descriptor with OCEXEC flag --- sys/src/libcomplete/complete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; -- cgit v1.2.3 From c74458c98b3cba6ed33a63b9f02a10e9828f9097 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 7 Dec 2020 18:59:54 +0100 Subject: vmx: add -v|-w flag to control window creation behaviour The -v flag now does not create a new rio window, while -w flag does (restores the old behaviour). This allows vmx to run under vncs and is in general mode aligned to other emulators and programs. --- sys/man/1/vmx | 7 ++++++- sys/src/cmd/vmx/vga.c | 4 ++-- sys/src/cmd/vmx/vmx.c | 9 ++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/sys/man/1/vmx b/sys/man/1/vmx index 8d014c294..fef51735c 100644 --- a/sys/man/1/vmx +++ b/sys/man/1/vmx @@ -24,7 +24,7 @@ vmx \- virtual PC .I blockfile ] [ -.B -v +.BR -v | -w .I vga ] [ @@ -61,6 +61,11 @@ argument. If .B -v is specified, a graphics device, PS/2 keyboard and mouse are simulated. +The +.B -w +flag behaves the same as +.B -v +but also creates a new window for the screen. Clicking on the screen "grabs" the mouse; pressing Ctrl and Alt simultaneously releases the grab. Valid values for the argument are .TP diff --git a/sys/src/cmd/vmx/vga.c b/sys/src/cmd/vmx/vga.c index 9fadff15e..eea5c8deb 100644 --- a/sys/src/cmd/vmx/vga.c +++ b/sys/src/cmd/vmx/vga.c @@ -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..64536c522 100644 --- a/sys/src/cmd/vmx/vmx.c +++ b/sys/src/cmd/vmx/vmx.c @@ -504,7 +504,7 @@ sendnotif(void (*f)(void *), void *arg) send(notifch, ¬if); } -extern void vgainit(void); +extern void vgainit(int); extern void pciinit(void); extern void pcibusmap(void); extern void cpuidinit(void); @@ -574,7 +574,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 +590,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(); @@ -637,6 +638,8 @@ threadmain(int argc, char **argv) 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 +676,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]); -- cgit v1.2.3 From 96850d8bb40e282217776e17977dd8ac10d0d10f Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 10:01:44 +0100 Subject: vmx: add -D option to enable debug messages, use vmdebug for non-fatal "errors" --- sys/man/1/vmx | 6 ++++++ sys/src/cmd/vmx/exith.c | 6 +++--- sys/src/cmd/vmx/fns.h | 2 +- sys/src/cmd/vmx/io.c | 6 +++--- sys/src/cmd/vmx/vga.c | 14 +++++++------- sys/src/cmd/vmx/vmx.c | 25 +++++++++++++++++++++++-- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/sys/man/1/vmx b/sys/man/1/vmx index fef51735c..ac07769f8 100644 --- a/sys/man/1/vmx +++ b/sys/man/1/vmx @@ -4,6 +4,9 @@ vmx \- virtual PC .SH SYNOPSIS .B vmx [ +.B -D +] +[ .B -M .I mem ] @@ -58,6 +61,9 @@ Boot modules can be specified with the .B -m argument. .PP +.B -D +enables debug messages. +.PP If .B -v is specified, a graphics device, PS/2 keyboard and mouse are simulated. diff --git a/sys/src/cmd/vmx/exith.c b/sys/src/cmd/vmx/exith.c index a96646294..1a6afc634 100644 --- a/sys/src/cmd/vmx/exith.c +++ b/sys/src/cmd/vmx/exith.c @@ -294,7 +294,7 @@ cpuid(ExitInfo *ei) break; default: if((ax & 0xf0000000) != 0x40000000) - vmerror("unknown cpuid field eax=%#ux", ax); + vmdebug("unknown cpuid field eax=%#ux", ax); zero: ax = cx = 0; break; @@ -327,10 +327,10 @@ rdwrmsr(ExitInfo *ei) 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){ diff --git a/sys/src/cmd/vmx/fns.h b/sys/src/cmd/vmx/fns.h index 54c9ef252..61336d83c 100644 --- a/sys/src/cmd/vmx/fns.h +++ b/sys/src/cmd/vmx/fns.h @@ -11,7 +11,7 @@ void pitadvance(void); void rtcadvance(void); void settimer(vlong targ); void vmerror(char *, ...); -#define vmdebug vmerror +void vmdebug(char *, ...); int ctl(char *, ...); void registermmio(uvlong, uvlong, uvlong (*)(int, uvlong, uvlong)); void irqline(int, int); diff --git a/sys/src/cmd/vmx/io.c b/sys/src/cmd/vmx/io.c index 2de8fe605..e3125ab51 100644 --- a/sys/src/cmd/vmx/io.c +++ b/sys/src/cmd/vmx/io.c @@ -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/vga.c b/sys/src/cmd/vmx/vga.c index eea5c8deb..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; diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c index 64536c522..8b71ecfd1 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 *); @@ -48,6 +48,23 @@ vmerror(char *fmt, ...) fmtfdflush(&f); } +void +vmdebug(char *fmt, ...) +{ + Fmt f; + char buf[256]; + va_list arg; + + if(debug == 0) + return; + fmtfdinit(&f, 2, buf, sizeof buf); + va_start(arg, fmt); + fmtvprint(&f, fmt, arg); + va_end(arg); + fmtprint(&f, "\n"); + fmtfdflush(&f); +} + int ctl(char *fmt, ...) { @@ -599,7 +616,8 @@ threadmain(int argc, char **argv) waitch = chancreate(sizeof(char *), 32); sleepch = chancreate(sizeof(ulong), 32); notifch = chancreate(sizeof(VmxNotif), 16); - + debug = 0; + ARGBEGIN { case 'm': bootmod = realloc(bootmod, (bootmodn + 1) * sizeof(char *)); @@ -634,6 +652,9 @@ 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"); -- cgit v1.2.3 From 8f9d4d7c27c5a26962c122c185549be24716571f Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 10:08:49 +0100 Subject: vesa: make unsupported function not an error, set return status --- sys/src/cmd/vmx/vesa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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); } } } -- cgit v1.2.3 From 014bf3fe7c78abb0fbd59f4da88fda7cb8ae2674 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 10:21:17 +0100 Subject: mouse(3): document "scrollswap" ctl message, fix style a bit (thanks umbraticus) --- sys/man/3/mouse | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/man/3/mouse b/sys/man/3/mouse index 078faff9a..2078caeb1 100644 --- a/sys/man/3/mouse +++ b/sys/man/3/mouse @@ -147,17 +147,20 @@ messages are idempotent, unlike .BR swap . .TP +.B scrollswap +inverts the scroll wheel. +.TP .B reset clears the mouse to its default state. .TP .B blank -Blank the screen. +blank the screen. The screen also blanks after 30 minutes of inactivity. The screen can be unblanked by moving the mouse. .TP .BI blanktime " minutes" -Set the timeout before the +set the timeout before the screen blanks; the default is 30 minutes. If .I minutes -- cgit v1.2.3 From e812aa617f70b43ba6d17ff6ed3b4fe324cdc853 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 10:34:10 +0100 Subject: mouse(3): blankS, setS to follow the convention (thanks umbraticus) --- sys/man/3/mouse | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/man/3/mouse b/sys/man/3/mouse index 2078caeb1..57772eab9 100644 --- a/sys/man/3/mouse +++ b/sys/man/3/mouse @@ -155,12 +155,12 @@ clears the mouse to its default state. .TP .B blank -blank the screen. +blanks the screen. The screen also blanks after 30 minutes of inactivity. The screen can be unblanked by moving the mouse. .TP .BI blanktime " minutes" -set the timeout before the +sets the timeout before the screen blanks; the default is 30 minutes. If .I minutes -- cgit v1.2.3 From 3d9abd96aea42e7e1134e0f241cb57275a29bc71 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 11:21:18 +0100 Subject: devmouse: remove redundant check --- sys/src/9/port/devmouse.c | 2 -- 1 file changed, 2 deletions(-) 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); -- cgit v1.2.3 From 07805ac8927ca8034a2e1bc39ef1b6a20f80806c Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 11:47:15 +0100 Subject: nusb/kb: update button state if event was actually received, fix typos (thanks umbraticus) --- sys/src/cmd/nusb/kb/kb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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; ivalid) *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; -- cgit v1.2.3 From de5770c3523e8ecb4f639417bf6f7592ed703c37 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 12:40:28 +0100 Subject: vmx: add fmt checking, fix fmt errors, remove duplication for vmdebug --- sys/src/cmd/vmx/dat.h | 1 + sys/src/cmd/vmx/exith.c | 6 +++--- sys/src/cmd/vmx/fns.h | 3 ++- sys/src/cmd/vmx/ide.c | 10 +++++----- sys/src/cmd/vmx/io.c | 8 ++++---- sys/src/cmd/vmx/vmx.c | 18 ------------------ 6 files changed, 15 insertions(+), 31 deletions(-) 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 1a6afc634..185c22e07 100644 --- a/sys/src/cmd/vmx/exith.c +++ b/sys/src/cmd/vmx/exith.c @@ -368,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; @@ -390,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; @@ -405,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); } } diff --git a/sys/src/cmd/vmx/fns.h b/sys/src/cmd/vmx/fns.h index 61336d83c..06643a9aa 100644 --- a/sys/src/cmd/vmx/fns.h +++ b/sys/src/cmd/vmx/fns.h @@ -11,7 +11,8 @@ void pitadvance(void); void rtcadvance(void); void settimer(vlong targ); void vmerror(char *, ...); -void vmdebug(char *, ...); +#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 e3125ab51..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); diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c index 8b71ecfd1..c82ba0d1c 100644 --- a/sys/src/cmd/vmx/vmx.c +++ b/sys/src/cmd/vmx/vmx.c @@ -48,23 +48,6 @@ vmerror(char *fmt, ...) fmtfdflush(&f); } -void -vmdebug(char *fmt, ...) -{ - Fmt f; - char buf[256]; - va_list arg; - - if(debug == 0) - return; - fmtfdinit(&f, 2, buf, sizeof buf); - va_start(arg, fmt); - fmtvprint(&f, fmt, arg); - va_end(arg); - fmtprint(&f, "\n"); - fmtfdflush(&f); -} - int ctl(char *fmt, ...) { @@ -616,7 +599,6 @@ threadmain(int argc, char **argv) waitch = chancreate(sizeof(char *), 32); sleepch = chancreate(sizeof(ulong), 32); notifch = chancreate(sizeof(VmxNotif), 16); - debug = 0; ARGBEGIN { case 'm': -- cgit v1.2.3 From 01eb04060b0de65eca044566381e214fab99fea3 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 12:42:36 +0100 Subject: pc: move ldmxcsr() prototype to fpu.c --- sys/src/9/pc/fns.h | 1 - sys/src/9/pc/fpu.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 7bbaeb551..b107707ae 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -78,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]); diff --git a/sys/src/9/pc/fpu.c b/sys/src/9/pc/fpu.c index c7aa47bb7..e9467fc52 100644 --- a/sys/src/9/pc/fpu.c +++ b/sys/src/9/pc/fpu.c @@ -16,6 +16,7 @@ extern void fpsserestore(FPsave*); extern void fpssesave(FPsave*); extern void fpx87restore0(FPsave*); extern void fpx87save0(FPsave*); +extern void ldmxcsr(ulong); void putxcr0(ulong) -- cgit v1.2.3 From 4ba5cb6c6abc5ffa988c0b3d78e3151efddac4f5 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 13:04:52 +0100 Subject: vmx: nanosec(): fix non-interruptable temporary, assign fasthz only once after xstart --- sys/src/cmd/vmx/nanosec.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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); -- cgit v1.2.3 From 93c6f8cb0dbd4386aea73773933d917848922a1b Mon Sep 17 00:00:00 2001 From: Sigrid Date: Tue, 8 Dec 2020 13:18:10 +0100 Subject: vmx(1): build vmxgdb by default, clean it up as well --- sys/src/cmd/vmx/mkfile | 5 +++++ 1 file changed, 5 insertions(+) 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=\ Date: Tue, 8 Dec 2020 14:32:28 +0100 Subject: vncv: do NOT map Kaltgr to meta, introduce Mod4 (Super) as an extra key to use instead --- sys/src/cmd/vnc/kbdv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/src/cmd/vnc/kbdv.c b/sys/src/cmd/vnc/kbdv.c index 967843b0c..4da3eafa5 100644 --- a/sys/src/cmd/vnc/kbdv.c +++ b/sys/src/cmd/vnc/kbdv.c @@ -6,7 +6,8 @@ enum { Xshift = 0xFFE1, Xctl = 0xFFE3, Xmeta = 0xFFE7, - Xalt = 0xFFE9 + Xalt = 0xFFE9, + Xsuper = 0xFFEB, }; static struct { @@ -41,10 +42,11 @@ static struct { {KF|10, 0xffc7}, {KF|11, 0xffc8}, {KF|12, 0xffc9}, + {Kaltgr, 0xfe03}, {Kshift, Xshift}, {Kalt, Xalt}, - {Kaltgr, Xmeta}, + {Kmod4, Xsuper}, {Kctl, Xctl}, }; @@ -95,7 +97,7 @@ readcons(Vnc *v) { char buf[256], k[10]; ulong ks; - int ctlfd, fd, kr, kn, w, shift, ctl, alt; + int ctlfd, fd, kr, kn, w, shift, ctl, alt, mod4; Rune r; snprint(buf, sizeof buf, "%s/cons", display->devdir); @@ -108,7 +110,7 @@ readcons(Vnc *v) write(ctlfd, "rawon", 5); kn = 0; - shift = alt = ctl = 0; + shift = alt = ctl = mod4 = 0; for(;;){ while(!fullrune(k, kn)){ kr = read(fd, k+kn, sizeof k - kn); @@ -134,6 +136,10 @@ readcons(Vnc *v) shift = !shift; keyevent(v, Xshift, shift); break; + case Kmod4: + mod4 = !mod4; + keyevent(v, Xsuper, alt); + break; default: if(r == ks && r < 0x1A){ /* control key */ keyevent(v, Xctl, 1); @@ -176,6 +182,10 @@ readcons(Vnc *v) keyevent(v, Xshift, 0); shift = 0; } + if(mod4){ + keyevent(v, Xsuper, 0); + shift = 0; + } break; } } @@ -228,7 +238,7 @@ readkbd(Vnc *v) if((r == Kshift) || utfrune(buf+1, Kctl) || utfrune(buf+1, Kalt) || - utfrune(buf+1, Kaltgr)) + utfrune(buf+1, Kmod4)) keyevent(v, runetovnc(r), 1); } break; @@ -241,7 +251,7 @@ readkbd(Vnc *v) } break; case 'c': - if(utfrune(buf2+1, Kctl) || utfrune(buf2+1, Kalt) || utfrune(buf2+1, Kaltgr)) + if(utfrune(buf2+1, Kctl) || utfrune(buf2+1, Kalt) || utfrune(buf2+1, Kmod4)) continue; chartorune(&r, buf+1); keyevent(v, runetovnc(r), 1); -- cgit v1.2.3 From 4db8a82f5a5afbd72abb6d251f67edb0b251d556 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 15:15:13 +0100 Subject: vncv: backing out previous change, this needs another revision --- sys/src/cmd/vnc/kbdv.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/sys/src/cmd/vnc/kbdv.c b/sys/src/cmd/vnc/kbdv.c index 4da3eafa5..967843b0c 100644 --- a/sys/src/cmd/vnc/kbdv.c +++ b/sys/src/cmd/vnc/kbdv.c @@ -6,8 +6,7 @@ enum { Xshift = 0xFFE1, Xctl = 0xFFE3, Xmeta = 0xFFE7, - Xalt = 0xFFE9, - Xsuper = 0xFFEB, + Xalt = 0xFFE9 }; static struct { @@ -42,11 +41,10 @@ static struct { {KF|10, 0xffc7}, {KF|11, 0xffc8}, {KF|12, 0xffc9}, - {Kaltgr, 0xfe03}, {Kshift, Xshift}, {Kalt, Xalt}, - {Kmod4, Xsuper}, + {Kaltgr, Xmeta}, {Kctl, Xctl}, }; @@ -97,7 +95,7 @@ readcons(Vnc *v) { char buf[256], k[10]; ulong ks; - int ctlfd, fd, kr, kn, w, shift, ctl, alt, mod4; + int ctlfd, fd, kr, kn, w, shift, ctl, alt; Rune r; snprint(buf, sizeof buf, "%s/cons", display->devdir); @@ -110,7 +108,7 @@ readcons(Vnc *v) write(ctlfd, "rawon", 5); kn = 0; - shift = alt = ctl = mod4 = 0; + shift = alt = ctl = 0; for(;;){ while(!fullrune(k, kn)){ kr = read(fd, k+kn, sizeof k - kn); @@ -136,10 +134,6 @@ readcons(Vnc *v) shift = !shift; keyevent(v, Xshift, shift); break; - case Kmod4: - mod4 = !mod4; - keyevent(v, Xsuper, alt); - break; default: if(r == ks && r < 0x1A){ /* control key */ keyevent(v, Xctl, 1); @@ -182,10 +176,6 @@ readcons(Vnc *v) keyevent(v, Xshift, 0); shift = 0; } - if(mod4){ - keyevent(v, Xsuper, 0); - shift = 0; - } break; } } @@ -238,7 +228,7 @@ readkbd(Vnc *v) if((r == Kshift) || utfrune(buf+1, Kctl) || utfrune(buf+1, Kalt) || - utfrune(buf+1, Kmod4)) + utfrune(buf+1, Kaltgr)) keyevent(v, runetovnc(r), 1); } break; @@ -251,7 +241,7 @@ readkbd(Vnc *v) } break; case 'c': - if(utfrune(buf2+1, Kctl) || utfrune(buf2+1, Kalt) || utfrune(buf2+1, Kmod4)) + if(utfrune(buf2+1, Kctl) || utfrune(buf2+1, Kalt) || utfrune(buf2+1, Kaltgr)) continue; chartorune(&r, buf+1); keyevent(v, runetovnc(r), 1); -- cgit v1.2.3 From 263dc8093d7eeece36160515b3a4f76a95352050 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 16:00:57 +0100 Subject: pc64: preserve reserved bits in CR0/CR4 for amd64 in mtrr setstate() On AMD64, CR0/CR4 are 64-bit registers, with the upper half reserved. So use uintptr type to store the register values to get 32 bit on 386 and 64 bit on AMD64. --- sys/src/9/pc/mtrr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index 7adb13a64..a2dd475b0 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -354,7 +354,7 @@ enum { static void putstate(State *s) { - ulong cr0, cr4; + uintptr cr0, cr4; int i, x; x = splhi(); -- cgit v1.2.3 From b2ffb6ccc5a5a4fcc996cc5db14ea7e2da13a411 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 16:34:36 +0100 Subject: pc, pc64: add *nomtrr= kernel parameter --- sys/src/9/pc/devarch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 564e7e7d8..bd72cd07f 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -642,7 +642,7 @@ cpuidentify(void) } #endif - if(m->cpuiddx & Mtrr) + if((m->cpuiddx & Mtrr) != 0 && getconf("*nomtrr") == nil) mtrrsync(); if(strcmp(m->cpuidid, "GenuineIntel") == 0 && (m->cpuidcx & Rdrnd) != 0) -- cgit v1.2.3 From 8efbd243e1934288fe6a57d3f168d370f6c04493 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 16:58:41 +0100 Subject: pc, pc64: cleanup cpuidentify() and some comments --- sys/src/9/pc/devarch.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index bd72cd07f..4058808f5 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -491,16 +491,19 @@ 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, 0, regs); memmove(m->cpuidid, ®s[1], BY2WD); /* bx */ @@ -567,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; @@ -626,7 +628,6 @@ cpuidentify(void) cr4 |= 0x80; /* page global enable bit */ m->havepge = 1; } - putcr4(cr4); if((m->cpuiddx & (Mca|Mce)) == Mce) @@ -635,10 +636,14 @@ 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 -- cgit v1.2.3 From 5149f204b78b7969c0cb865ff376fc21a2c50297 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 8 Dec 2020 17:16:12 +0100 Subject: plan9.ini(8): document *nomtrr= and order the table --- sys/man/8/plan9.ini | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index d89cf713c..039935f45 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -815,11 +815,13 @@ This deprecated option is rarely necessary in newer kernels. This limits the maximum amount of memory (in megabytes) the graphics image memory pool can grow. The default is unlimited for terminals and cpu servers. -.SS \fL*nomce=\fIvalue\fP +.SS \fL*noavx=\fP +Disables AVX and AVX2 on AMD64 CPUs. +.SS \fL*nomce=\fP If machine check exceptions are supported by the processor, then they are enabled by default. -Setting this variable to -.B 1 +Setting +.B *nomce causes them to be disabled even when available. .SS \fL*nomp=\fP A multiprocessor machine will enable all processors by default. @@ -836,7 +838,12 @@ processors. .SS \fL*apicdebug=\fP Prints a summary of the multiprocessor APIC interrupt configuration. .SS \fL*nomsi=\fP -Disables message signaled interrupts. +Disables message signaled interrupts for PCI devices. +This option has no effect when +.B *nomp +is set. +.SS \fL*nomtrr=\fP +Disables memory type range register (MTRR) support when set. (debug) .SS \fL*notsc=\fP Disables the use of the per processor timestamp counter registers as high resolution clock. @@ -898,8 +905,6 @@ The main feature of the interface is the ability to watch battery life (see .IR stats (8)). It is not on by default because it causes problems on some laptops. -.SS \fL*noavx=\fP -Disables AVX and AVX2 on AMD64 CPUs. .SS USB .SS \fL*nousbprobe=\fP Disable USB host controller detection. -- cgit v1.2.3 From 07d3d9bf0c69d4beb4555c9054f455f7181c34c5 Mon Sep 17 00:00:00 2001 From: kvik Date: Tue, 8 Dec 2020 21:20:13 +0100 Subject: sega(1): fix keys (thanks bigato) --- sys/man/1/sega | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/man/1/sega b/sys/man/1/sega index 9e3dfd21a..b23437baf 100644 --- a/sys/man/1/sega +++ b/sys/man/1/sega @@ -14,7 +14,7 @@ md \- emulator .I Md is an emulator for the Sega Megadrive/Genesis. It executes the romfile given as an argument. -The \fBz\fR, \fBx\fR, \fBa\fR, return and shift keys correspond to A, B, C, Start and Select, respectively. +The \fBz\fR, \fBx\fR, \fBc\fR, return and shift keys correspond to A, B, C, Start and Select, respectively. Other keys: .TP F1 -- cgit v1.2.3 From eb3d055eb376cb930a15ea85f594185f754223e9 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Wed, 9 Dec 2020 01:04:03 +0100 Subject: backout OCEXEC changes when potentially opening /srv files Opening a /srv file sets the close-on-exec flag on the shared channel breaking the exportfs openmount() hack. The devsrv tries to prevent posting a channel with the close-on-exec or remove-on-close flags. but nothing currently prevents this poisoning on open. Until this gets fixed in eigther exportfs or devsrv, i'll back out the changes that could have potential side effects like this. --- sys/src/libauth/auth_chuid.c | 2 +- sys/src/libauth/newns.c | 2 +- sys/src/libc/9sys/access.c | 2 +- sys/src/libdraw/newwindow.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/src/libauth/auth_chuid.c b/sys/src/libauth/auth_chuid.c index 6b3819e86..4703ea000 100644 --- a/sys/src/libauth/auth_chuid.c +++ b/sys/src/libauth/auth_chuid.c @@ -29,7 +29,7 @@ auth_chuid(AuthInfo *ai, char *ns) } /* get a link to factotum as new user */ - fd = open("/srv/factotum", ORDWR|OCEXEC); + fd = open("/srv/factotum", ORDWR); if(fd >= 0){ if(mount(fd, -1, "/mnt", MREPL, "") == -1) close(fd); diff --git a/sys/src/libauth/newns.c b/sys/src/libauth/newns.c index 91bf5f802..c0f866b9b 100644 --- a/sys/src/libauth/newns.c +++ b/sys/src/libauth/newns.c @@ -194,7 +194,7 @@ nsop(char *fn, int argc, char *argv[], AuthRpc *rpc) else if(argc == 2) unmount(argv[0], argv[1]); }else if(strcmp(argv0, "mount") == 0){ - fd = open(argv[0], ORDWR|OCEXEC); + fd = open(argv[0], ORDWR); if(fd < 0){ if(newnsdebug) fprint(2, "%s: mount: %s: %r\n", fn, argv[0]); diff --git a/sys/src/libc/9sys/access.c b/sys/src/libc/9sys/access.c index 86e459955..c9fee3432 100644 --- a/sys/src/libc/9sys/access.c +++ b/sys/src/libc/9sys/access.c @@ -24,7 +24,7 @@ access(char *name, int mode) return 0; return -1; } - fd = open(name, omode[mode&7]|OCEXEC); + fd = open(name, omode[mode&7]); if(fd >= 0){ close(fd); return 0; diff --git a/sys/src/libdraw/newwindow.c b/sys/src/libdraw/newwindow.c index 73306be03..2fb708bef 100644 --- a/sys/src/libdraw/newwindow.c +++ b/sys/src/libdraw/newwindow.c @@ -13,7 +13,7 @@ newwindow(char *str) wsys = getenv("wsys"); if(wsys == nil) return -1; - fd = open(wsys, ORDWR|OCEXEC); + fd = open(wsys, ORDWR); if(fd < 0){ free(wsys); return -1; -- cgit v1.2.3 From cef91f23e787a9e01916b35cf35347b964f03a3b Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Thu, 10 Dec 2020 01:47:19 +0100 Subject: pc, pc64: work around bhyve all uncached MTRR's --- sys/src/9/pc/memory.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c index 6df499728..f15f6e776 100644 --- a/sys/src/9/pc/memory.c +++ b/sys/src/9/pc/memory.c @@ -383,8 +383,16 @@ e820scan(void) } } - /* RAM needs to be writeback */ - mtrrexclude(MemRAM, "wb"); + /* + * Make sure RAM is set to writeback, + * but do a sanity check first checking + * that the kernel text is writeback. + * This is needed as some emulators (bhyve) + * set everything to uncached. + */ + s = mtrrattr(PADDR(KTZERO), nil); + if(s != nil && strcmp(s, "wb") == 0) + mtrrexclude(MemRAM, "wb"); for(base = memmapnext(-1, MemRAM); base != -1; base = memmapnext(base, MemRAM)){ size = memmapsize(base, BY2PG) & ~(BY2PG-1); -- cgit v1.2.3 From d7120ecb77c22496678e2352ed3782b411215118 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Thu, 10 Dec 2020 10:33:42 +0100 Subject: src: work on awk scripts too, see "src valley" (thanks phil9) --- rc/bin/src | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rc/bin/src b/rc/bin/src index b2de4dc4c..1855a6044 100755 --- a/rc/bin/src +++ b/rc/bin/src @@ -13,6 +13,8 @@ fn dbsrc{ fn go{ type=`{file <$1 | sed 's/stdin: //'} switch($type){ + case 'Ascii' + plumbit $1 '(ascii file)' case 'rc executable file' plumbit $1 '(rc executable)' case *executable* *'plan 9 boot image'* -- cgit v1.2.3 From f5d1fce9b56143ac90ef0c1c4388ee502f44cfed Mon Sep 17 00:00:00 2001 From: Sigrid Date: Thu, 10 Dec 2020 12:19:45 +0100 Subject: vmx: clean up mksegment, memset only if segment existed (devsegment clears new ones) --- sys/src/cmd/vmx/vmx.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c index c82ba0d1c..b3b73d845 100644 --- a/sys/src/cmd/vmx/vmx.c +++ b/sys/src/cmd/vmx/vmx.c @@ -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); -- cgit v1.2.3 From 345e93dd4c5879655686edd282b859cf958360c4 Mon Sep 17 00:00:00 2001 From: Sigrid Date: Fri, 11 Dec 2020 15:18:41 +0100 Subject: update Finnish kbmap: fix ¤ on shift+4 and add more AltGr variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/lib/kbmap/fi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sys/lib/kbmap/fi b/sys/lib/kbmap/fi index 0e73fe385..0892608c4 100644 --- a/sys/lib/kbmap/fi +++ b/sys/lib/kbmap/fi @@ -13,7 +13,7 @@ 1 2 '! 1 3 '" 1 4 '# -1 5 '$ +1 5 '¤ 1 6 '% 1 7 '& 1 8 '/ @@ -40,7 +40,13 @@ 3 10 '] 3 11 '} 3 12 '\ +3 13 '¸ 3 18 '€ 3 27 '~ 3 46 '¢ 3 86 '| +3 39 'ø +3 40 'æ +7 13 'Ë› +7 39 'Ø +7 40 'Æ -- cgit v1.2.3 From 658c994cfff444e0d473dbd312638c4f609fcc81 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 11 Dec 2020 15:21:44 +0100 Subject: pc, pc64: ignore MTRR's when MTRRCap.vcnt and MTRRCap.fix are zero Bhyve returns 0 in MTRRCap register, so we can use that instead on relying on cpuid only to see if MTRR's are supported. That way we can get rid of the sanity check in memory.c. --- sys/src/9/pc/memory.c | 12 ++---------- sys/src/9/pc/mtrr.c | 10 +++++++--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c index f15f6e776..6df499728 100644 --- a/sys/src/9/pc/memory.c +++ b/sys/src/9/pc/memory.c @@ -383,16 +383,8 @@ e820scan(void) } } - /* - * Make sure RAM is set to writeback, - * but do a sanity check first checking - * that the kernel text is writeback. - * This is needed as some emulators (bhyve) - * set everything to uncached. - */ - s = mtrrattr(PADDR(KTZERO), nil); - if(s != nil && strcmp(s, "wb") == 0) - mtrrexclude(MemRAM, "wb"); + /* RAM needs to be writeback */ + mtrrexclude(MemRAM, "wb"); for(base = memmapnext(-1, MemRAM); base != -1; base = memmapnext(base, MemRAM)){ size = memmapsize(base, BY2PG) & ~(BY2PG-1); diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index a2dd475b0..7601ef543 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -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 -- cgit v1.2.3 From fc0f08c65112e50a75d77042d8249b6bd15a3b76 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 11 Dec 2020 15:23:03 +0100 Subject: pc, pc64: make sure write combining is supported in MTRR's before setting it --- sys/src/9/pc/mtrr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index 7601ef543..f840b159d 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -678,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); -- cgit v1.2.3 From 5ea540e75def56d3c2b5ef16f0f4e91d5f5c0ad1 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 12 Dec 2020 18:00:41 +0100 Subject: sdiahci: enable pci busmaster before ahciconfigdrive() (fix qemu crash) enable pci busmaster before set the fis-receive-enable bit in the port command register. not doing so triggers a crash in qemu like: address_space_unmap: Assertion `mr != NULL' failed. as qemu tries to process the dma command list as soon as we set that flag and busmaster dma needs to be enabled at this point. --- sys/src/9/pc/sdiahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 63ac8559b..1c243908e 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1553,7 +1553,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 +2227,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]); -- cgit v1.2.3 From b2b2d2cb4c5cb3153760084a55584817a2c58a24 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 12 Dec 2020 18:16:06 +0100 Subject: sdiahci: assume 64-bit PCIWADDR() --- sys/src/9/pc/sdiahci.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 1c243908e..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; -- cgit v1.2.3 From 0b33b3b8adf95bcf6cf0764fe425169ee0b8be0e Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Dec 2020 16:04:09 +0100 Subject: kernel: implement per file descriptor OCEXEC flag, reject ORCLOSE when opening /fd, /srv and /shr The OCEXEC flag used to be maintained per channel, making it shared between all the file desciptors. This has a unexpected side effects with regard to channel passing drivers such as devdup (/fd), devsrv (/srv) and devshr (/shr). For example, opening a /srv file with OCEXEC makes it impossible to be remounted by exportfs as it internally does a exec() to mount and re-export it. There is no way to reset the flag. This change makes the OCEXEC flag per file descriptor, so a open with the OCEXEC flag only affects the fd group of the calling process, and not the channel itself. On rfork(RFFDG), the per file descriptor flags get copied. On dup(), the per file descriptor flags are reset. The second modification is that /fd, /srv and /shr should reject the ORCLOSE flag, as the files that are returned have already been opend. --- sys/man/2/dup | 13 +++++++++++++ sys/src/9/port/auth.c | 5 ++--- sys/src/9/port/chan.c | 7 +------ sys/src/9/port/devdup.c | 2 ++ sys/src/9/port/devshr.c | 2 ++ sys/src/9/port/devsrv.c | 4 ++-- sys/src/9/port/lib.h | 2 +- sys/src/9/port/pgrp.c | 14 ++++++++++++-- sys/src/9/port/portdat.h | 3 ++- sys/src/9/port/portfns.h | 2 +- sys/src/9/port/sysfile.c | 50 ++++++++++++++++++++++++++++++++++-------------- 11 files changed, 74 insertions(+), 30 deletions(-) diff --git a/sys/man/2/dup b/sys/man/2/dup index cd3414106..1eca0a713 100644 --- a/sys/man/2/dup +++ b/sys/man/2/dup @@ -32,6 +32,19 @@ requires that .I newfd be no greater than 20 more than the highest file descriptor ever used by the program. +.PP +.I Dup +does not copy the per file descriptor +.B OCEXEC +flag, +meaning that +.I newfd +will not be closed on +.IR exec(2) +syscall, +when +.I oldfd +had been previously opend with it. .SH SOURCE .B /sys/src/libc/9syscall .SH SEE ALSO 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/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(); -- cgit v1.2.3 From 27a83106f4b5b68d77afa8f800d92398163a7043 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Dec 2020 20:09:03 +0100 Subject: oexportfs: move legacy code for cpu and import to separate program The initial protocol handling in exportfs for cpu and import services is a huge mess. Saparate the code out into its own program with its own oexportfs(4) manpage. --- rc/bin/service/!tcp17007 | 2 +- sys/man/4/exportfs | 124 +----- sys/man/4/oexportfs | 146 +++++++ sys/src/cmd/cpu.c | 2 +- sys/src/cmd/exportfs/exportfs.c | 850 +-------------------------------------- sys/src/cmd/exportfs/exportfs.h | 3 + sys/src/cmd/exportfs/exportsrv.c | 8 - sys/src/cmd/exportfs/io.c | 503 +++++++++++++++++++++++ sys/src/cmd/exportfs/mkfile | 6 +- sys/src/cmd/exportfs/oexportfs.c | 443 ++++++++++++++++++++ sys/src/cmd/srvfs.c | 45 +-- 11 files changed, 1146 insertions(+), 986 deletions(-) create mode 100644 sys/man/4/oexportfs create mode 100644 sys/src/cmd/exportfs/io.c create mode 100644 sys/src/cmd/exportfs/oexportfs.c diff --git a/rc/bin/service/!tcp17007 b/rc/bin/service/!tcp17007 index 915d78ae7..3b18002b6 100755 --- a/rc/bin/service/!tcp17007 +++ b/rc/bin/service/!tcp17007 @@ -1,3 +1,3 @@ #!/bin/rc netdir=`{echo $3 | sed 's;/[0-9]+$;!*!0;'} -exec /bin/exportfs -a -A $netdir +exec /bin/oexportfs -a -A $netdir diff --git a/sys/man/4/exportfs b/sys/man/4/exportfs index b7cbeb979..b6108c1ab 100644 --- a/sys/man/4/exportfs +++ b/sys/man/4/exportfs @@ -1,6 +1,6 @@ .TH EXPORTFS 4 .SH NAME -exportfs, srvfs \- network file server plumbing +exportfs, srvfs \- file server plumbing .SH SYNOPSIS .B exportfs [ @@ -26,17 +26,11 @@ exportfs, srvfs \- network file server plumbing .I path .SH DESCRIPTION .I Exportfs -is a user level file server that allows Plan 9 compute servers, rather -than file servers, to export portions of a name space across networks. -The service is started either by the -.IR cpu (1) -command or by a network listener process. An initial protocol -establishes a root directory for the exported name space. -The -connection to -.I exportfs -is then mounted, typically on -.BR /mnt/term . +is a user level file server that allows Plan 9 cpu servers, rather +than file servers, to export portions of a name space. +It is usually started by other programs such as +.IR rcpu (1) +after a secure channel has been established. .I Exportfs then acts as a relay file server: operations in the imported file tree are executed on the remote server and the results returned. This @@ -44,49 +38,6 @@ gives the appearance of exporting a name space from a remote machine into a local file tree. .PP The options are: -.TF "-A \fIaddress" -.PD -.TP -.B -A \fIaddress -Use the network -.I address -to announce -.IR aan (8) -connections, -if requested by the initial protocol. -.TP -.B -a -Authenticate the user with the -.I p9any -protocol before running the regular -.I exportfs -session; used when -.I exportfs -is invoked to handle an incoming network connection. -.I Exportfs -creates a new name space for each connection, using -.B /lib/namespace -by default (see -.IR namespace (6)). -.TP -.B -B \fIaddress -Dial -.IR address , -authenticate as a -.I p9any -client, and then -serve that network connection. -Requires setting the root of the name space with -.B -r -or -.BR -s . -The remote system should run -.B import -.B -B -to handle the call. -See -.IR import (4) -for an example. .TP .B -d -f \fIdbgfile Log all 9P traffic to @@ -94,31 +45,6 @@ Log all 9P traffic to (default .BR /tmp/exportdb ). .TP -.B -e '\fIenc auth\fL' -Set the encryption and authentication algorithms to use for -encrypting the wire traffic (see -.IR ssl (3)). -The defaults are -.B rc4_256 -and -.BR sha1 . -.TP -.B -m \fImsize -Set the maximum message size that -.I exportfs -should offer to send (see -.IR version (5)); -this helps tunneled -9P connections to avoid unnecessary fragmentation. -.TP -.B -N \fInsfile -Serve the name space described by -.IR nsfile . -.TP -.B -n -Disallow mounts by user -.BR none . -.TP .B -P \fIpatternfile Restrict the set of exported files. .I Patternfile @@ -137,11 +63,11 @@ must not match. Make the served name space read only. .TP .B -r \fIroot -Bypass the initial protocol, serving the name space rooted at +Serve the name space rooted at .IR root . .TP .B -S \fIservice -bypass the initial protocol, serving the result of mounting +Serve the result of mounting .IR service . A separate mount is used for each .IR attach (5) @@ -156,28 +82,15 @@ equivalent to .B -r .BR / ; kept for compatibility. -.PD -.PP -The -.B cpu -command uses -.I exportfs -to serve device files in the terminal. The -.IR import (4) -command calls -.I exportfs -on a remote machine, permitting users to access arbitrary pieces of -name space on other systems. -.PP -Because the kernel disallows reads and writes on mounted pipes -(as might be found in -.BR /srv ), +.TP +.B -m \fImsize +Set the maximum message size that .I exportfs -calls itself (with appropriate -.B -m -and -.B -S -options) to simulate reads and writes on such files. +should offer to send (see +.IR version (5)); +this helps tunneled +9P connections to avoid unnecessary fragmentation. +.PD .PP .I Srvfs invokes @@ -251,7 +164,4 @@ cd /n/spy; ls .br .B /sys/src/cmd/srvfs.c .SH SEE ALSO -.IR dial (2), -.IR import (4), -.IR aan (8), -.IR listen (8) +.IR rcpu (1) diff --git a/sys/man/4/oexportfs b/sys/man/4/oexportfs new file mode 100644 index 000000000..180ad204f --- /dev/null +++ b/sys/man/4/oexportfs @@ -0,0 +1,146 @@ +.TH OEXPORTFS 4 +.SH NAME +oexportfs \- legacy exportfs for cpu and import +.SH SYNOPSIS +.PP +.B oexportfs +[ +.I options +] +.SH DESCRIPTION +.I Oexportfs +is older version of the +.IR exportfs (4) +program that handles an initial protocol to establish a root directory +for the exported name space. +It also provides authentication and encryption using +the +.IR ssl (3) +device. +.PP +It is used exclusively by the deprecated +.IR cpu (1) +and +.IR import (4) +services. +.PP +The options are: +.TP +.B -d -f \fIdbgfile +Log all 9P traffic to +.I dbgfile +(default +.BR /tmp/exportdb ). +.TP +.B -P \fIpatternfile +Restrict the set of exported files. +.I Patternfile +contains one regular expression per line, +to be matched against path names +relative to the current working directory +and starting with +.BR / . +For a file to be exported, all lines with a prefix +.B + +must match and all those with prefix +.B - +must not match. +.TP +.B -R +Make the served name space read only. +.TP +.B -r \fIroot +Serve the name space rooted at +.IR root . +.TP +.B -S \fIservice +Serve the result of mounting +.IR service . +A separate mount is used for each +.IR attach (5) +message, +to correctly handle servers in which each mount +corresponds to a different client +.IR e.g. , ( +.IR rio (4)). +.TP +.B -s +equivalent to +.B -r +.BR / ; +kept for compatibility. +.TP +.B -m \fImsize +Set the maximum message size that +.I oexportfs +should offer to send (see +.IR version (5)); +this helps tunneled +9P connections to avoid unnecessary fragmentation. +.TP +.B -A \fIaddress +Use the network +.I address +to announce +.IR aan (8) +connections, +if requested by the initial protocol. +.TP +.B -a +Authenticate the user with the +.I p9any +protocol before running the regular +.I oexportfs +session; used when +.I oexportfs +is invoked to handle an incoming network connection. +.I Exportfs +creates a new name space for each connection, using +.B /lib/namespace +by default (see +.IR namespace (6)). +.TP +.B -B \fIaddress +Dial +.IR address , +authenticate as a +.I p9any +client, and then +serve that network connection. +Requires setting the root of the name space with +.B -r +or +.BR -s . +The remote system should run +.B import +.B -B +to handle the call. +See +.IR import (4) +for an example. +.TP +.B -e '\fIenc auth\fL' +Set the encryption and authentication algorithms to use for +encrypting the wire traffic (see +.IR ssl (3)). +The defaults are +.B rc4_256 +and +.BR sha1 . +.TP +.B -N \fInsfile +Serve the name space described by +.IR nsfile . +.TP +.B -n +Disallow mounts by user +.BR none . +.EE +.SH SOURCE +.B /sys/src/cmd/exportfs/oexportfs.c +.SH SEE ALSO +.IR dial (2), +.IR exportfs (4), +.IR import (4), +.IR aan (8), +.IR listen (8) 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 #include -#include #include -#include #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; hnext) - 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 +#include +#include +#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; hnext) + 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 @@ +#include +#include +#include +#include +#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/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); } -- cgit v1.2.3 From 6f932de718a740ac4676c14b739f1ce74f8d85c9 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Dec 2020 20:11:30 +0100 Subject: import(4): refer to oexportfs(4) --- sys/man/4/import | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/man/4/import b/sys/man/4/import index 88be8145c..9c6511dfc 100644 --- a/sys/man/4/import +++ b/sys/man/4/import @@ -45,7 +45,7 @@ A process is started on the remote machine, with authority of the user of .IR import , to perform work for the local machine using the -.IR exportfs (4) +.IR oexportfs (4) service. The default port used is TCP 17007. If @@ -76,7 +76,7 @@ This is useful for connecting to foreign systems like Inferno. .B -z Bypass the initial protocol request for which remote tree to serve. This is necessary when the remote -.IR exportfs (4) +.IR oexportfs (4) is running with the .B -r or @@ -144,7 +144,7 @@ runs a .I p9any authentication (as server) over its file descriptor 0 (expected to be an incoming network connection from -.B exportfs +.B oexportfs .BR -B ), mounts the connection onto .IR mntpt , @@ -189,7 +189,7 @@ When boots, it runs .IP .EX -exportfs -R -r /usr/web -B tcp!webvax!999 +oexportfs -R -r /usr/web -B tcp!webvax!999 .EE .PP to serve a read-only copy of @@ -212,7 +212,7 @@ to restart .IR rcpu (1), .IR bind (1), .IR ssl (3), -.IR exportfs (4), +.IR oexportfs (4), .IR srv (4), .IR aan (8), .IR listen (8), -- cgit v1.2.3 From 08a9a6952dfa9ace5b4ae6fa1614c97d4a945ece Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Dec 2020 20:11:44 +0100 Subject: cpu(1): refer to oexportfs(4) --- sys/man/1/cpu | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/man/1/cpu b/sys/man/1/cpu index 046560d88..41b60a015 100644 --- a/sys/man/1/cpu +++ b/sys/man/1/cpu @@ -99,7 +99,7 @@ If a argument is present, the .I patternfile is passed to -.IR exportfs (4) +.IR oexportfs (4) to control how much of the local name space will be exported to the remote system. .PP @@ -210,7 +210,7 @@ connections, if requested by the initial protocol. The name space of the terminal side of the .I cpu command is mounted, via -.IR exportfs (4), +.IR oexportfs (4), on the CPU side on directory .BR /mnt/term . The files such as @@ -222,7 +222,7 @@ are bound to their standard locations from there. .IR rcpu (1) , .IR rc (1) , .IR rio (1) , -.IR exportfs (4) , +.IR oexportfs (4) , .IR aan (8) .SH BUGS Binds and mounts done after the terminal -- cgit v1.2.3 From 32291b52bcbd6976051acff1692b571e321ac859 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 13 Dec 2020 20:23:03 +0100 Subject: iostats: dup 9p pipe to both fd 0 and fd 1 for exportfs --- sys/src/cmd/iostats.c | 1 + 1 file changed, 1 insertion(+) 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]); -- cgit v1.2.3