ref: 3749e92cdb88a157f99c0709a264bd508603be9b
parent: 404c901f299c4d93cb159a3c44c2977a25408319
parent: 32291b52bcbd6976051acff1692b571e321ac859
author: Alex Musolino <[email protected]>
date: Tue Dec 15 15:55:41 EST 2020
merge
--- 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
--- a/rc/bin/src
+++ b/rc/bin/src
@@ -13,6 +13,8 @@
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'*
--- 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
--- 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
--- 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
--- 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 'Æ
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- a/sys/lib/kbmap/sr
+++ b/sys/lib/kbmap/sr
@@ -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
--- a/sys/lib/kbmap/sr-latin
+++ b/sys/lib/kbmap/sr-latin
@@ -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
--- 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
--- 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
--- a/sys/man/1/cpu
+++ b/sys/man/1/cpu
@@ -99,7 +99,7 @@
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 @@
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 @@
.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
--- a/sys/man/1/sega
+++ b/sys/man/1/sega
@@ -14,7 +14,7 @@
.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
--- a/sys/man/1/vmx
+++ b/sys/man/1/vmx
@@ -4,6 +4,9 @@
.SH SYNOPSIS
.B vmx
[
+.B -D
+]
+[
.B -M
.I mem
]
@@ -24,7 +27,7 @@
.I blockfile
]
[
-.B -v
+.BR -v | -w
.I vga
]
[
@@ -58,9 +61,17 @@
.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
--- a/sys/man/2/dup
+++ b/sys/man/2/dup
@@ -32,6 +32,19 @@
.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
--- a/sys/man/3/mouse
+++ b/sys/man/3/mouse
@@ -147,17 +147,20 @@
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
--- 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 @@
.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,50 +38,7 @@
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
.I dbgfile
@@ -94,31 +45,6 @@
(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 @@
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,29 +82,16 @@
.B -r
.BR / ;
kept for compatibility.
+.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.
.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 ),
-.I exportfs
-calls itself (with appropriate
-.B -m
-and
-.B -S
-options) to simulate reads and writes on such files.
-.PP
.I Srvfs
invokes
.I exportprog
@@ -251,7 +164,4 @@
.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)
--- a/sys/man/4/import
+++ b/sys/man/4/import
@@ -45,7 +45,7 @@
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 @@
.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 @@
.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 @@
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 @@
.IR rcpu (1),
.IR bind (1),
.IR ssl (3),
-.IR exportfs (4),
+.IR oexportfs (4),
.IR srv (4),
.IR aan (8),
.IR listen (8),
--- /dev/null
+++ b/sys/man/4/oexportfs
@@ -1,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)
--- a/sys/man/4/ptrap
+++ b/sys/man/4/ptrap
@@ -7,10 +7,7 @@
.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 @@
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)
@@ -51,6 +48,15 @@
.EX
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
--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -815,11 +815,13 @@
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 @@
.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.
--- a/sys/man/8/statusbar
+++ b/sys/man/8/statusbar
@@ -9,8 +9,9 @@
[
.B -w
.I minx,miny,maxx,maxy
-]
+] [
.I title
+]
.br
.B aux/statusmsg
[
--- a/sys/src/9/pc/cputemp.c
+++ b/sys/src/9/pc/cputemp.c
@@ -13,7 +13,7 @@
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 @@
ulong regs[4];
static ulong tj;
- cpuid(6, regs);
+ cpuid(6, 0, regs);
if((regs[0] & 1) == 0)
goto unsup;
if(tj == 0){
--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -250,7 +250,7 @@
int pdbfree;
u32int dr7; /* shadow copy of dr7 */
-
+ u32int xcr0;
void* vmx;
int stack[1];
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -18,11 +18,6 @@
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 @@
* (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 @@
* 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 @@
cr4 |= 0x80; /* page global enable bit */
m->havepge = 1;
}
-
putcr4(cr4);
if((m->cpuiddx & (Mca|Mce)) == Mce)
@@ -640,25 +636,20 @@
#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 @@
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,13 +680,15 @@
|| 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;
--- a/sys/src/9/pc/devvmx.c
+++ b/sys/src/9/pc/devvmx.c
@@ -44,6 +44,7 @@
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 @@
VMENTRY_INTRCODE = 0x4018,
VMENTRY_INTRILEN = 0x401a,
+ VMCS_TSC_OFFSET = 0x2010,
VMCS_LINK = 0x2800,
GUEST_ES = 0x800,
@@ -264,7 +266,9 @@
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 @@
}
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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
free(vmx);
nexterror();
}
+ memset(vmx, 0, sizeof(Vmx));
vmx->state = VMXINIT;
vmx->lastcmd = &vmx->firstcmd;
vmx->mem.next = &vmx->mem;
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -15,7 +15,8 @@
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 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 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 putcr2(ulong);
void putcr3(ulong);
void putcr4(ulong);
+void putxcr0(ulong);
void putdr(u32int*);
void putdr01236(uintptr*);
void putdr6(u32int);
--- /dev/null
+++ b/sys/src/9/pc/fpu.c
@@ -1,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;
+ }
+}
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -520,7 +520,7 @@
* 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 @@
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 @@
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)
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -234,272 +234,6 @@
}
/*
- * 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
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -49,6 +49,7 @@
OBJ=\
l.$O\
cga.$O\
+ fpu.$O\
i8253.$O\
i8259.$O\
main.$O\
--- a/sys/src/9/pc/mtrr.c
+++ b/sys/src/9/pc/mtrr.c
@@ -289,9 +289,9 @@
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,12 +305,14 @@
vlong v;
int i;
- s->mask = physmask();
+ if(rdmsr(MTRRCap, &s->cap) < 0)
+ return -1;
+ if((s->cap & (Capfix|Capvcnt)) == 0)
+ return -1;
+
if(rdmsr(MTRRDefaultType, &s->def) < 0)
return -1;
- if(rdmsr(MTRRCap, &s->cap) < 0)
- return -1;
if(s->cap & Capfix){
for(i = 0; i < nelem(fixreg); i++){
@@ -332,6 +334,8 @@
return -1;
}
+ s->mask = physmask();
+
if(strcmp(m->cpuidid, "AuthenticAMD") != 0
|| m->cpuidfamily < 15
|| rdmsr(AMDK8SysCfg, &v) < 0
@@ -354,7 +358,7 @@
static void
putstate(State *s)
{
- ulong cr0, cr4;
+ uintptr cr0, cr4;
int i, x;
x = splhi();
@@ -673,6 +677,10 @@
new.size = size;
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;
--- 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 @@
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 @@
static int
ahciconfigdrive(Ahba *h, Aportc *c, int mode)
{
+ uvlong pa;
Aportm *m;
Aport *p;
int i;
@@ -618,10 +621,12 @@
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 @@
}
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 @@
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]);
--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -2,6 +2,8 @@
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 @@
uintptr pc;
};
-struct FPsave
+struct FPssestate
{
u16int fcw; /* x87 control word */
u16int fsw; /* x87 status word */
@@ -65,6 +67,18 @@
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 @@
int havewatchpt8;
int havenx;
uvlong tscticks;
-
+
u64int dr7; /* shadow copy of dr7 */
-
+ u64int xcr0;
+
void* vmx;
uintptr stack[1];
@@ -270,8 +285,14 @@
/* 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,
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -15,7 +15,8 @@
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,10 +39,10 @@
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);
@@ -48,6 +49,7 @@
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 putcr2(u64int);
void putcr3(u64int);
void putcr4(u64int);
+void putxcr0(u64int);
void putdr(u64int*);
void putdr01236(u64int*);
void putdr6(u64int);
--- /dev/null
+++ b/sys/src/9/pc64/fpu.c
@@ -1,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;
+}
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -249,9 +249,10 @@
*/
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 @@
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
@@ -624,6 +640,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
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -293,218 +293,10 @@
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 @@
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 @@
if(p->vmx != nil)
vmxprocrestore(p);
+ fpuprocrestore(p);
+
if(p->kp)
return;
@@ -582,27 +357,7 @@
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
@@ -616,37 +371,4 @@
* especially on VMware, but it turns out not to matter.
*/
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;
}
--- 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 */
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -47,6 +47,7 @@
OBJ=\
l.$O\
cga.$O\
+ fpu.$O\
i8253.$O\
i8259.$O\
main.$O\
--- a/sys/src/9/port/auth.c
+++ b/sys/src/9/port/auth.c
@@ -97,13 +97,12 @@
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;
}
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -1468,9 +1468,6 @@
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 @@
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;
--- a/sys/src/9/port/devdup.c
+++ b/sys/src/9/port/devdup.c
@@ -63,6 +63,8 @@
Chan *f;
int fd, twicefd;
+ if(omode & ORCLOSE)
+ error(Eperm);
if(c->qid.type & QTDIR){
if(omode != 0)
error(Eisdir);
--- a/sys/src/9/port/devmouse.c
+++ b/sys/src/9/port/devmouse.c
@@ -304,8 +304,6 @@
one = two = three = 0;
for(i = 0; i < 3; i++){
- if(map[i] == 0)
- error(Ebadarg);
if(map[i] == '1'){
if(one)
error(Ebadarg);
--- a/sys/src/9/port/devshr.c
+++ b/sys/src/9/port/devshr.c
@@ -396,6 +396,8 @@
case Qcmpt:
if(omode&OTRUNC)
error(Eexist);
+ if(omode&ORCLOSE)
+ error(Eperm);
shr = sch->shr;
mpt = sch->mpt;
devpermcheck(mpt->owner, mpt->perm, mode);
--- a/sys/src/9/port/devsrv.c
+++ b/sys/src/9/port/devsrv.c
@@ -135,6 +135,8 @@
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 @@
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);
--- a/sys/src/9/port/lib.h
+++ b/sys/src/9/port/lib.h
@@ -176,7 +176,7 @@
#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 */
--- a/sys/src/9/port/pgrp.c
+++ b/sys/src/9/port/pgrp.c
@@ -140,7 +140,8 @@
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 @@
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 @@
if((c = f->fd[i]) != nil){
incref(c);
new->fd[i] = c;
+ new->flag[i] = f->flag[i];
}
}
unlock(f);
@@ -194,6 +203,7 @@
up->closingfgrp = nil;
free(f->fd);
+ free(f->flag);
free(f);
}
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -125,7 +125,7 @@
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 @@
Ref;
Lock;
Chan **fd;
+ uchar *flag; /* per file-descriptor flags (CCEXEC) */
int nfd; /* number allocated */
int maxfd; /* highest fd in use */
int exceed; /* debugging */
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -201,7 +201,7 @@
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);
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -25,33 +25,45 @@
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 @@
}
int
-newfd(Chan *c)
+newfd(Chan *c, int mode)
{
- int fd;
+ int fd, flag;
Fgrp *f;
f = up->fgrp;
@@ -87,6 +99,13 @@
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 @@
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 @@
oc = f->fd[fd];
f->fd[fd] = c;
+ f->flag[fd] = 0;
unlockfgrp(f);
if(oc != nil)
cclose(oc);
@@ -255,7 +277,7 @@
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, 0);
if(fd < 0)
error(Enofd);
poperror();
@@ -280,7 +302,7 @@
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, mode);
if(fd < 0)
error(Enofd);
poperror();
@@ -295,7 +317,7 @@
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 @@
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, mode);
if(fd < 0)
error(Enofd);
poperror();
--- a/sys/src/9/xen/archxen.c
+++ b/sys/src/9/xen/archxen.c
@@ -83,18 +83,3 @@
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);
-}
--- a/sys/src/9/xen/fns.h
+++ b/sys/src/9/xen/fns.h
@@ -9,7 +9,8 @@
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*);
@@ -16,18 +17,10 @@
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);
--- a/sys/src/9/xen/l.s
+++ b/sys/src/9/xen/l.s
@@ -163,13 +163,13 @@
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)
@@ -176,19 +176,27 @@
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
/*
--- a/sys/src/9/xen/main.c
+++ b/sys/src/9/xen/main.c
@@ -322,133 +322,6 @@
}
}
-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
*/
--- a/sys/src/9/xen/mkfile
+++ b/sys/src/9/xen/mkfile
@@ -68,6 +68,7 @@
plan9l.$O\
xen.$O\
main.$O\
+ fpu.$O\
mmu.$O\
random.$O\
rdb.$O\
--- a/sys/src/cmd/aux/kbdfs/kbdfs.c
+++ b/sys/src/cmd/aux/kbdfs/kbdfs.c
@@ -179,7 +179,7 @@
[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,
--- a/sys/src/cmd/aux/statusbar.c
+++ b/sys/src/cmd/aux/statusbar.c
@@ -21,10 +21,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/sys/src/cmd/aux/statusmsg.c
+++ b/sys/src/cmd/aux/statusmsg.c
@@ -22,6 +22,7 @@
{
text = display->black;
light = allocimagemix(display, DPalegreen, DWhite);
+ if(light == nil) sysfatal("initcolor: %r");
}
void
@@ -136,7 +137,6 @@
usage();
case 1:
title = argv[0];
- break;
case 0:
break;
}
@@ -153,7 +153,7 @@
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);
--- a/sys/src/cmd/cpu.c
+++ b/sys/src/cmd/cpu.c
@@ -37,7 +37,7 @@
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 */
--- 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 @@
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,53 +70,16 @@
}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);
- }
+ } else if(srv == nil)
+ usage();
- 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);
- }
-
exclusions();
if(dbg) {
@@ -228,11 +88,6 @@
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 @@
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();
}
--- a/sys/src/cmd/exportfs/exportfs.h
+++ b/sys/src/cmd/exportfs/exportfs.h
@@ -112,7 +112,10 @@
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);
--- 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 @@
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);
--- /dev/null
+++ b/sys/src/cmd/exportfs/io.c
@@ -1,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;
+}
--- 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 @@
$HFILES\
${OFILES:%.$O=%.c}\
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany
--- /dev/null
+++ b/sys/src/cmd/exportfs/oexportfs.c
@@ -1,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();
+}
--- a/sys/src/cmd/iostats.c
+++ b/sys/src/cmd/iostats.c
@@ -354,6 +354,7 @@
sysfatal("fork: %r");
case 0:
dup(efd[0], 0);
+ dup(efd[0], 1);
close(efd[0]);
close(efd[1]);
close(pfd[1]);
--- a/sys/src/cmd/nusb/kb/kb.c
+++ b/sys/src/cmd/nusb/kb/kb.c
@@ -637,7 +637,7 @@
s->h = v;
break;
- case 0x0D0051: /* Conteact identifier */
+ case 0x0D0051: /* Contact identifier */
s->id = v;
break;
@@ -684,7 +684,7 @@
{
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 @@
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 @@
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 @@
b |= 2;
if(s->b & 2)
b |= 4;
+ bpress |= s->m;
/* X/Y are absolute? */
if((s->abs & 3) == 3){
@@ -825,7 +826,9 @@
y += s->y;
}
}
-
+
+ if(bpress == 0)
+ b = lastb & 7;
if(z != 0)
b |= z > 0 ? 8 : 16;
--- 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 @@
};
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 @@
}
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 @@
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 @@
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 @@
threadmain(int argc, char **argv)
{
PFilter *f;
+ FAttr *fa;
char *p;
int i;
@@ -357,19 +387,33 @@
}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);
--- a/sys/src/cmd/rio/fsys.c
+++ b/sys/src/cmd/rio/fsys.c
@@ -118,10 +118,9 @@
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)
@@ -128,20 +127,11 @@
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
@@ -148,7 +138,7 @@
*/
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 @@
/*
* 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 @@
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;
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -244,7 +244,7 @@
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 @@
{
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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);
--- a/sys/src/cmd/rio/wctl.c
+++ b/sys/src/cmd/rio/wctl.c
@@ -88,7 +88,7 @@
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))
@@ -95,7 +95,12 @@
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))
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -1420,7 +1420,7 @@
void
wsetpid(Window *w, int pid, int dolabel)
{
- char buf[64];
+ char buf[32];
int ofd;
ofd = w->notefd;
@@ -1428,11 +1428,11 @@
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)
--- a/sys/src/cmd/srvfs.c
+++ b/sys/src/cmd/srvfs.c
@@ -12,7 +12,7 @@
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 @@
*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,7 +69,6 @@
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");
@@ -63,32 +75,5 @@
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);
}
--- a/sys/src/cmd/vmx/dat.h
+++ b/sys/src/cmd/vmx/dat.h
@@ -11,6 +11,7 @@
VMDEAD,
};
extern int state;
+extern int debug;
enum {
BY2PG = 4096
--- 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 @@
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);
+ CPUID r;
+ int f;
+
+ 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);
}
- Bterm(bp);
- close(pfd[1]);
}
-CPUID *
-getcpuid(ulong idx)
-{
- CPUID *cp;
-
- for(cp = cpuidf; cp < cpuidf + ncpuidf; cp++)
- if(cp->idx == idx)
- return cp;
- return nil;
-}
+static int xsavesz[] = {
+ [1] = 512+64,
+ [3] = 512+64,
+ [7] = 512+64+256,
+};
-int maxcpuid = 7;
-
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
{".movdr", movdr},
{"#db", dbgexc},
{"movcr", movcr},
+ {".xsetbv", xsetbv},
};
void
--- 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 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);
--- a/sys/src/cmd/vmx/ide.c
+++ b/sys/src/cmd/vmx/ide.c
@@ -118,7 +118,7 @@
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 @@
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 @@
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 @@
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 @@
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;
}
--- a/sys/src/cmd/vmx/io.c
+++ b/sys/src/cmd/vmx/io.c
@@ -292,7 +292,7 @@
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 @@
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 @@
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 @@
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 @@
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;
}
--- 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 \
@@ -18,6 +19,10 @@
nanosec.$O \
</sys/src/cmd/mkone
+
+default:V: all
+
+all:V: $O.out $O.vmxgdb
install:V: $BIN/vmxgdb
--- a/sys/src/cmd/vmx/nanosec.c
+++ b/sys/src/cmd/vmx/nanosec.c
@@ -17,14 +17,15 @@
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);
--- a/sys/src/cmd/vmx/vesa.c
+++ b/sys/src/cmd/vmx/vesa.c
@@ -622,7 +622,8 @@
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);
}
}
}
--- a/sys/src/cmd/vmx/vga.c
+++ b/sys/src/cmd/vmx/vga.c
@@ -178,7 +178,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
void
-vgainit(void)
+vgainit(int new)
{
char buf[512];
int i;
@@ -760,7 +760,7 @@
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);
--- a/sys/src/cmd/vmx/vmx.c
+++ b/sys/src/cmd/vmx/vmx.c
@@ -11,7 +11,7 @@
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 @@
return (u8int *) v + gavail(v);
}
-void *tmp, *vgamem;
-uvlong tmpoff, vgamemoff;
-
static void
mksegment(char *sn)
{
@@ -355,8 +352,9 @@
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 @@
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 @@
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 @@
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 @@
static uvlong gmemsz = 64*1024*1024;
static char *srvname;
extern uintptr fbsz, fbaddr;
+ int newwin = 0;
int i;
quotefmtinstall();
@@ -598,7 +595,7 @@
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 @@
}
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 @@
loadkernel(argv[0]);
pciinit();
- vgainit();
+ vgainit(newwin);
for(i = 0; i < edevn; i++)
if(edev[i](edevaux[i]) < 0)
sysfatal("%s: %r", edevt[i]);
--- a/sys/src/cmd/vmx/x86.h
+++ b/sys/src/cmd/vmx/x86.h
@@ -22,8 +22,9 @@
enum {
Cr0Pg = 1<<31,
- Cr4Pse = 1<<4,
- Cr4Pae = 1<<5,
+ Cr4Pse = 1<<4,
+ Cr4Pae = 1<<5,
+ Cr4Osxsave = 1<<18,
EferLme = 1<<8,
};
--- a/sys/src/lib9p/auth.c
+++ b/sys/src/lib9p/auth.c
@@ -25,7 +25,7 @@
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;
--- a/sys/src/lib9p/listen.c
+++ b/sys/src/lib9p/listen.c
@@ -100,7 +100,7 @@
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){
--- a/sys/src/lib9p/queue.c
+++ b/sys/src/lib9p/queue.c
@@ -16,8 +16,8 @@
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 @@
f(r);
}
+ if(fd >= 0)
+ close(fd);
free(r);
free(q);
threadexits(nil);
--- a/sys/src/libauth/auth_challenge.c
+++ b/sys/src/libauth/auth_challenge.c
@@ -23,7 +23,7 @@
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);
--- a/sys/src/libauth/auth_chuid.c
+++ b/sys/src/libauth/auth_chuid.c
@@ -16,7 +16,7 @@
}
/* change uid */
- fd = open("#¤/capuse", OWRITE);
+ fd = open("#¤/capuse", OWRITE|OCEXEC);
if(fd < 0){
werrstr("opening #¤/capuse: %r");
return -1;
@@ -31,8 +31,8 @@
/* 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 */
--- a/sys/src/libauth/auth_getuserpasswd.c
+++ b/sys/src/libauth/auth_getuserpasswd.c
@@ -32,12 +32,11 @@
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 @@
out:
free(params);
- auth_freerpc(rpc);
close(fd);
+ auth_freerpc(rpc);
return up;
}
--- a/sys/src/libauth/auth_proxy.c
+++ b/sys/src/libauth/auth_proxy.c
@@ -200,7 +200,7 @@
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);
--- a/sys/src/libauth/auth_respond.c
+++ b/sys/src/libauth/auth_respond.c
@@ -31,7 +31,7 @@
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){
--- a/sys/src/libauth/auth_userpasswd.c
+++ b/sys/src/libauth/auth_userpasswd.c
@@ -11,7 +11,7 @@
char *s;
int afd;
- afd = open("/mnt/factotum/rpc", ORDWR);
+ afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC);
if(afd < 0)
return nil;
ai = nil;
--- a/sys/src/libauth/newns.c
+++ b/sys/src/libauth/newns.c
@@ -41,7 +41,7 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}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 @@
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 @@
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);
--- a/sys/src/libauth/noworld.c
+++ b/sys/src/libauth/noworld.c
@@ -15,7 +15,7 @@
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){
--- a/sys/src/libauthsrv/readcons.c
+++ b/sys/src/libauthsrv/readcons.c
@@ -13,13 +13,13 @@
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);
}
--- a/sys/src/libauthsrv/readnvram.c
+++ b/sys/src/libauthsrv/readnvram.c
@@ -91,9 +91,9 @@
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 @@
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;
--- a/sys/src/libc/9sys/getenv.c
+++ b/sys/src/libc/9sys/getenv.c
@@ -18,7 +18,8 @@
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;
--- a/sys/src/libc/9sys/getnetconninfo.c
+++ b/sys/src/libc/9sys/getnetconninfo.c
@@ -13,7 +13,7 @@
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 @@
NetConnInfo *nci;
char *cp;
Dir *d;
- char spec[10];
char path[128];
char netname[128], *p;
@@ -76,10 +75,8 @@
/* 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);
--- a/sys/src/libc/9sys/getppid.c
+++ b/sys/src/libc/9sys/getppid.c
@@ -8,7 +8,7 @@
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);
--- 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);
--- a/sys/src/libc/9sys/iounit.c
+++ b/sys/src/libc/9sys/iounit.c
@@ -13,7 +13,7 @@
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);
--- 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;
--- a/sys/src/libc/9sys/procsetname.c
+++ b/sys/src/libc/9sys/procsetname.c
@@ -8,8 +8,9 @@
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);
--- a/sys/src/libc/9sys/pushssl.c
+++ b/sys/src/libc/9sys/pushssl.c
@@ -11,7 +11,7 @@
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 @@
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;
--- a/sys/src/libc/9sys/pushtls.c
+++ b/sys/src/libc/9sys/pushtls.c
@@ -42,7 +42,7 @@
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
@@ -49,7 +49,7 @@
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 @@
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;
--- a/sys/src/libc/9sys/putenv.c
+++ b/sys/src/libc/9sys/putenv.c
@@ -13,7 +13,7 @@
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);
--- a/sys/src/libc/9sys/sysname.c
+++ b/sys/src/libc/9sys/sysname.c
@@ -10,7 +10,7 @@
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)
--- a/sys/src/libc/port/date.c
+++ b/sys/src/libc/port/date.c
@@ -174,11 +174,12 @@
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;
--- a/sys/src/libc/port/getuser.c
+++ b/sys/src/libc/port/getuser.c
@@ -8,7 +8,7 @@
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);
--- a/sys/src/libc/port/malloc.c
+++ b/sys/src/libc/port/malloc.c
@@ -99,13 +99,13 @@
{
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;
--- a/sys/src/libc/port/profile.c
+++ b/sys/src/libc/port/profile.c
@@ -137,7 +137,7 @@
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 @@
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 @@
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);
--- a/sys/src/libcomplete/complete.c
+++ b/sys/src/libcomplete/complete.c
@@ -53,7 +53,7 @@
return nil;
}
- fd = open(dir, OREAD);
+ fd = open(dir, OREAD|OCEXEC);
if(fd < 0)
return nil;
--- a/sys/src/libdraw/getsubfont.c
+++ b/sys/src/libdraw/getsubfont.c
@@ -22,7 +22,7 @@
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;
--- a/sys/src/libdraw/init.c
+++ b/sys/src/libdraw/init.c
@@ -49,7 +49,7 @@
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 @@
*/
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 @@
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 @@
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);
--- a/sys/src/libdraw/openfont.c
+++ b/sys/src/libdraw/openfont.c
@@ -12,7 +12,7 @@
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;
--- a/sys/src/libdraw/readcolmap.c
+++ b/sys/src/libdraw/readcolmap.c
@@ -27,8 +27,8 @@
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(;;) {
--- a/sys/src/libdraw/window.c
+++ b/sys/src/libdraw/window.c
@@ -90,7 +90,6 @@
d = s->display;
a = bufimage(d, 1+4);
if(a == nil){
-Error:
free(s);
return -1;
}
--- a/sys/src/libdraw/writecolmap.c
+++ b/sys/src/libdraw/writecolmap.c
@@ -16,7 +16,7 @@
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);
--- a/sys/src/libndb/csgetval.c
+++ b/sys/src/libndb/csgetval.c
@@ -25,10 +25,10 @@
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);
--- a/sys/src/libndb/csipinfo.c
+++ b/sys/src/libndb/csipinfo.c
@@ -23,10 +23,10 @@
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 @@
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 @@
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);
--- a/sys/src/libndb/dnsquery.c
+++ b/sys/src/libndb/dnsquery.c
@@ -29,7 +29,7 @@
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 @@
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;
--- a/sys/src/libndb/ndbhash.c
+++ b/sys/src/libndb/ndbhash.c
@@ -57,7 +57,7 @@
/* 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
@@ -64,16 +64,16 @@
|| 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;
}
@@ -80,19 +80,19 @@
/* 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 @@
}
free(hf);
- return 0;
+ return nil;
}
/*
@@ -142,17 +142,6 @@
}
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 @@
if(strcmp(attr, nt->attr) == 0
&& strcmp(val, nt->val) == 0)
return nt;
- return 0;
+ return nil;
}
/*
--- a/sys/src/libndb/ndbopen.c
+++ b/sys/src/libndb/ndbopen.c
@@ -99,7 +99,7 @@
}
/* try the open again */
- fd = open(db->file, OREAD);
+ fd = open(db->file, OREAD|OCEXEC);
if(fd < 0)
return -1;
d = dirfstat(fd);
--- a/sys/src/libsec/port/readcert.c
+++ b/sys/src/libsec/port/readcert.c
@@ -8,7 +8,7 @@
char *s;
Dir *d;
- fd = open(name, OREAD);
+ fd = open(name, OREAD|OCEXEC);
if(fd < 0)
return nil;
if((d = dirfstat(fd)) == nil) {
--- a/sys/src/libsec/port/thumb.c
+++ b/sys/src/libsec/port/thumb.c
@@ -95,7 +95,7 @@
}
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)
--- a/sys/src/libsec/port/tlshand.c
+++ b/sys/src/libsec/port/tlshand.c
@@ -459,7 +459,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/sys/src/libthread/id.c
+++ b/sys/src/libthread/id.c
@@ -59,7 +59,7 @@
threadsetname(char *fmt, ...)
{
int fd;
- char buf[128];
+ char buf[32];
va_list arg;
Proc *p;
Thread *t;
@@ -72,8 +72,8 @@
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);
}
--- a/sys/src/libthread/ioproc.c
+++ b/sys/src/libthread/ioproc.c
@@ -19,6 +19,15 @@
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 @@
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);
--- a/sys/src/libthread/kill.c
+++ b/sys/src/libthread/kill.c
@@ -76,24 +76,31 @@
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);