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