X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2FRuntime.java;h=bfe1aaba8c3393f582dcd97da78ce458781d1a6c;hp=fc97e71ecf3984b5e631ceeab207e3fcde3aa400;hb=ab9be117467f7459965c61e49749b333678b6e4c;hpb=98f786ce8ee1fcd9568d1c367160851d32e1c786 diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index fc97e71..bfe1aab 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -2,13 +2,20 @@ // Based on org.xwt.imp.MIPS by Adam Megacz // Portions Copyright 2003 Adam Megacz +// FEATURE: Add a patch to gcc that enabled -Wall -Werror by default +// FIXME: Get a hotel for IVME :) + package org.ibex.nestedvm; import org.ibex.nestedvm.util.*; import java.io.*; -import java.util.Arrays; public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { + public static final String VERSION = "1.0"; + + /** True to write useful diagnostic information to stderr when things go wrong */ + final static boolean STDERR_DIAG = true; + /** Number of bits to shift to get the page number (1<<>> pageShift; - heapStart = (heapStart + pageSize) & ~(pageSize-1); + heapStart = (heapStart + pageSize - 1) & ~(pageSize-1); if(stackPages + STACK_GUARD_PAGES + (heapStart >>> pageShift) >= totalPages) throw new IllegalArgumentException("total pages too small"); } else { @@ -149,14 +156,15 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { if(totalPages == 1) { readPages[0] = writePages[0] = new int[pageSize>>2]; } else { - for(int i=(stackBottom >>> pageShift);i>2]; + for(int i=(stackBottom >>> pageShift);i>2]; } } - addFD(new StdinFD(System.in)); - addFD(new StdoutFD(System.out)); - addFD(new StdoutFD(System.err)); + InputStream stdin = Boolean.valueOf(getSystemProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in; + addFD(new TerminalFD(stdin)); + addFD(new TerminalFD(System.out)); + addFD(new TerminalFD(System.err)); } /** Copy everything from src to addr initializing uninitialized pages if required. @@ -353,7 +361,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { if(page == null) throw new WriteFaultException(a<<2); int index = a&pageWordMask; int n = min(c,pageWords-index); - Arrays.fill(page,index,index+n,fourBytes); + /* Arrays.fill(page,index,index+n,fourBytes);*/ + for(int i=index;i ARG_MAX) throw new IllegalArgumentException("args/environ too big"); + // HACK: heapStart() isn't always available when the constructor + // is run and this sometimes doesn't get initialized + if(heapEnd == 0) { + heapEnd = heapStart(); + if(heapEnd == 0) throw new Error("heapEnd == 0"); + int pageSize = writePages.length == 1 ? 4096 : (1<fdn and returns the new fs */ public final int dupFD(int fdn) { - int i; - if(fdn < 0 || fdn >= OPEN_MAX) return -1; - if(fds[fdn] == null) return -1; - for(i=0;i= OPEN_MAX) return -1; + if(fds[fdn] == null) return -1; + for(i=0;i= 0) throw new ErrnoException(EACCES); return null; @@ -735,7 +755,13 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** The open syscall */ private int sys_open(int addr, int flags, int mode) throws ErrnoException, FaultException { - FD fd = _open(cstring(addr),flags,mode); + String name = cstring(addr); + + // HACK: TeX, or GPC, or something really sucks + if(name.length() == 1024 && getClass().getName().equals("tests.TeX")) name = name.trim(); + + flags &= ~O_NOCTTY; // this is meaningless under nestedvm + FD fd = _open(name,flags,mode); if(fd == null) return -ENOENT; int fdn = addFD(fd); if(fdn == -1) { fd.close(); return -ENFILE; } @@ -744,14 +770,18 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** The write syscall */ - // FIXME: Handle pipe closed exception private int sys_write(int fdn, int addr, int count) throws FaultException, ErrnoException { count = Math.min(count,MAX_CHUNK); if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; if(fds[fdn] == null) return -EBADFD; byte[] buf = byteBuf(count); copyin(addr,buf,count); - return fds[fdn].write(buf,0,count); + try { + return fds[fdn].write(buf,0,count); + } catch(ErrnoException e) { + if(e.errno == EPIPE) sys_exit(128+13); + throw e; + } } /** The read syscall */ @@ -784,8 +814,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { int stat(FStat fs, int addr) throws FaultException { memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16) memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // st_mode - memWrite(addr+8,1<<16); // st_nlink (top 16) // st_uid (bottom 16) - memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16) + memWrite(addr+8,fs.nlink()<<16|fs.uid()&0xffff); // st_nlink (top 16) // st_uid (bottom 16) + memWrite(addr+12,fs.gid()<<16|0); // st_gid (top 16) // st_rdev (bottom 16) memWrite(addr+16,fs.size()); // st_size memWrite(addr+20,fs.atime()); // st_atime // memWrite(addr+24,0) // st_spare1 @@ -863,8 +893,10 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { private int sys_sysconf(int n) { switch(n) { case _SC_CLK_TCK: return 1000; + case _SC_PAGESIZE: return writePages.length == 1 ? 4096 : (1<syscall should be the contents of V0 and a, b, c, and d should be the contenst of A0, A1, A2, and A3. The call MAY change the state @see Runtime#state state */ - protected final int syscall(int syscall, int a, int b, int c, int d) { + protected final int syscall(int syscall, int a, int b, int c, int d, int e, int f) { try { - return _syscall(syscall,a,b,c,d); - } catch(ErrnoException e) { - e.printStackTrace(); - return -e.errno; - } catch(FaultException e) { - return -EFAULT; - } catch(RuntimeException e) { - e.printStackTrace(); - throw new Error("Internal Error in _syscall()"); + int n = _syscall(syscall,a,b,c,d,e,f); + //if(n < 0) System.err.println("syscall: " + syscall + " returned " + n); + return n; + } catch(ErrnoException ex) { + //ex.printStackTrace(); + return -ex.errno; + } catch(FaultException ex) { + return -EFAULT; + } catch(RuntimeException ex) { + ex.printStackTrace(); + throw new Error("Internal Error in _syscall()"); } } - int _syscall(int syscall, int a, int b, int c, int d) throws ErrnoException, FaultException { + int _syscall(int syscall, int a, int b, int c, int d, int e, int f) throws ErrnoException, FaultException { switch(syscall) { case SYS_null: return 0; case SYS_exit: return sys_exit(a); @@ -1018,10 +1052,10 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { case SYS_mkdir: case SYS_getcwd: case SYS_chdir: - System.err.println("Attempted to use a UnixRuntime syscall in Runtime (" + syscall + ")"); + if(STDERR_DIAG) System.err.println("Attempted to use a UnixRuntime syscall in Runtime (" + syscall + ")"); return -ENOSYS; default: - System.err.println("Attempted to use unknown syscall: " + syscall); + if(STDERR_DIAG) System.err.println("Attempted to use unknown syscall: " + syscall); return -ENOSYS; } } @@ -1113,16 +1147,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public int seek(int n, int whence) throws ErrnoException { try { - switch(whence) { - case SEEK_SET: break; - case SEEK_CUR: n += data.pos(); break; - case SEEK_END: n += data.length(); break; - default: return -1; - } - data.seek(n); - return n; + switch(whence) { + case SEEK_SET: break; + case SEEK_CUR: n += data.pos(); break; + case SEEK_END: n += data.length(); break; + default: return -1; + } + data.seek(n); + return n; } catch(IOException e) { - throw new ErrnoException(ESPIPE); + throw new ErrnoException(ESPIPE); } } @@ -1131,67 +1165,114 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { // NOTE: There is race condition here but we can't fix it in pure java if((flags&O_APPEND) != 0) seek(0,SEEK_END); try { - return data.write(a,off,length); + return data.write(a,off,length); } catch(IOException e) { - throw new ErrnoException(EIO); + throw new ErrnoException(EIO); } } public int read(byte[] a, int off, int length) throws ErrnoException { if((flags&3) == WR_ONLY) throw new ErrnoException(EBADFD); try { - int n = data.read(a,off,length); - return n < 0 ? 0 : n; + int n = data.read(a,off,length); + return n < 0 ? 0 : n; } catch(IOException e) { - throw new ErrnoException(EIO); + throw new ErrnoException(EIO); } } protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } } } - public static class OutputStreamFD extends FD { - private OutputStream os; - public int flags() { return O_WRONLY; } - public OutputStreamFD(OutputStream os) { this.os = os; } - public int write(byte[] a, int off, int length) throws ErrnoException { - try { - os.write(a,off,length); - return length; - } catch(IOException e) { - throw new ErrnoException(EIO); - } + public static class InputOutputStreamFD extends FD { + private final InputStream is; + private final OutputStream os; + + public InputOutputStreamFD(InputStream is) { this(is,null); } + public InputOutputStreamFD(OutputStream os) { this(null,os); } + public InputOutputStreamFD(InputStream is, OutputStream os) { + this.is = is; + this.os = os; + if(is == null && os == null) throw new IllegalArgumentException("at least one stream must be supplied"); } - public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ } } - public FStat _fstat() { return new FStat(); } - } - - public static class InputStreamFD extends FD { - private InputStream is; - public int flags() { return O_RDONLY; } - public InputStreamFD(InputStream is) { this.is = is; } + + public int flags() { + if(is != null && os != null) return O_RDWR; + if(is != null) return O_RDONLY; + if(os != null) return O_WRONLY; + throw new Error("should never happen"); + } + + public void _close() { + if(is != null) try { is.close(); } catch(IOException e) { /*ignore*/ } + if(os != null) try { os.close(); } catch(IOException e) { /*ignore*/ } + } + public int read(byte[] a, int off, int length) throws ErrnoException { + if(is == null) return super.read(a,off,length); try { int n = is.read(a,off,length); return n < 0 ? 0 : n; } catch(IOException e) { throw new ErrnoException(EIO); } + } + + public int write(byte[] a, int off, int length) throws ErrnoException { + if(os == null) return super.write(a,off,length); + try { + os.write(a,off,length); + return length; + } catch(IOException e) { + throw new ErrnoException(EIO); + } } - public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } } + public FStat _fstat() { return new FStat(); } } - static class StdinFD extends InputStreamFD { - public StdinFD(InputStream is) { super(is); } + static class TerminalFD extends InputOutputStreamFD { + public TerminalFD(InputStream is) { this(is,null); } + public TerminalFD(OutputStream os) { this(null,os); } + public TerminalFD(InputStream is, OutputStream os) { super(is,os); } public void _close() { /* noop */ } - public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } - } - - static class StdoutFD extends OutputStreamFD { - public StdoutFD(OutputStream os) { super(os); } - public void _close() { /* noop */ } - public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } + public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } public int mode() { return 0600; } }; } + } + + // This is pretty inefficient but it is only used for reading from the console on win32 + static class TextInputStream extends InputStream { + private int pushedBack = -1; + private final InputStream parent; + public TextInputStream(InputStream parent) { this.parent = parent; } + public int read() throws IOException { + if(pushedBack != -1) { int c = pushedBack; pushedBack = -1; return c; } + int c = parent.read(); + if(c == '\r' && (c = parent.read()) != '\n') { pushedBack = c; return '\r'; } + return c; + } + public int read(byte[] buf, int pos, int len) throws IOException { + boolean pb = false; + if(pushedBack != -1 && len > 0) { + buf[0] = (byte) pushedBack; + pushedBack = -1; + pos++; len--; pb = true; + } + int n = parent.read(buf,pos,len); + if(n == -1) return -1; + for(int i=0;i b ? a : b; }