public static int Access(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int mode) { // XXX: This is vfs related, now let's assume that we're dealing with pass through fs. var buf = Globals.AllocateAlignedCompletionBuffer(PATH_MAX); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var ret = filenamePtr.ReadString(current, buf); var accessCompletion = new BridgeCompletion(current, buf); ret = Arch.IPCStubs.AccessAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), mode); if (ret < 0) { accessCompletion.Dispose(); return(ret); } Globals.CompletionQueue.Enqueue(accessCompletion); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
public static int Write(Thread current, ref Arch.ExceptionRegisters regs, int fd, UserPtr userBuf, int len) { if (len == 0) { return(0); } if (len < 0) { return(-ErrorCode.EINVAL); } var proc = current.Parent; var file = proc.LookupFile(fd); if (file == null) { return(-ErrorCode.EBADF); } var mode = file.flags & FileFlags.ReadWriteMask; if (mode == FileFlags.ReadOnly) { return(-ErrorCode.EPERM); } int ret = file.Write(current, ref regs, userBuf, len); return(ret); }
internal int Write(Thread current, ref Arch.ExceptionRegisters regs, ref ByteBufferRef buf, int len) { Contract.Requires(GhostOwner == current.Parent); var ret = inode.Write(current, ref regs, ref buf, len, position, this); return(ret); }
public int Read(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos) { Contract.Requires(GhostOwner == current.Parent); var ret = inode.Read(current, ref regs, userBuf, len, pos, null); return(ret); }
private static int Recv(Thread current, ref Arch.ExceptionRegisters regs, UserPtr ptr_label, UserPtr userBuf, uint size) { Contract.Requires(current.VBinderState.Owner == current); if (!current.Parent.Space.VerifyWrite(userBuf, size) || !current.Parent.Space.VerifyWrite(ptr_label, sizeof(int))) { return(-ErrorCode.EFAULT); } var b = current.VBinderState.NoPendingMessages(); if (b) { var entry = new VBinderCompletion(current, ptr_label, userBuf, size); current.VBinderState.Completion = entry; current.SaveState(ref regs); current.AsyncReturn = true; return(0); } else { var msg = current.VBinderState.TakeMessage(); Contract.Assert(msg.GhostTarget == current); var length = msg.Length; ptr_label.Write(current.Parent, msg.label); userBuf.Write(current, new Pointer(msg.payload.Location), length); msg.Recycle(); return(length); } }
private static bool IsLinuxSyscall(Msgtag tag, ref ExceptionRegisters exc) { const uint GP_TRAP_NO = 0xd; const uint LINUX_SYSCALL_GATE = 0x80; return(tag.Label == Msgtag.L4_PROTO_EXCEPTION && exc.trapno == GP_TRAP_NO && exc.err == LINUX_SYSCALL_GATE * 8 + 2); }
internal int SFSWrite(Thread current, ref Arch.ExceptionRegisters regs, ByteBufferRef buf, int len, uint pos, File file) { var writtenBytes = Write(current, buf, len, pos); if (writtenBytes <= 0) { return(writtenBytes); } file.position = (uint)(pos + writtenBytes); return(writtenBytes); }
private static int Socket(Thread current, ref Arch.ExceptionRegisters regs, int domain, int type, int protocol) { var proc = current.Parent; Arch.IPCStubs.SocketAsync(proc.helperPid, current.impl._value.thread._value, domain, type, protocol); var completion = new SocketCompletion(current); Globals.CompletionQueue.Enqueue(completion); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
internal int Read(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file) { switch (kind) { case INodeKind.ArchINodeKind: case INodeKind.SocketINodeKind: return(ArchINode.ArchRead(current, ref regs, userBuf, len, pos, file)); case INodeKind.SecureFSINodeKind: return(SFSINode.SFSRead(current, ref regs, userBuf, len, pos, file)); } return(-ErrorCode.EINVAL); }
private static int BindOrConnect(int type, Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen) { Contract.Requires(type == SYS_BIND || type == SYS_CONNECT); var proc = current.Parent; var file = proc.LookupFile(sockfd); if (file == null) { return(-ErrorCode.EBADF); } if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind) { return(-ErrorCode.ENOTSOCK); } if (addrlen > Globals.LinuxIPCBuffer.Length) { return(-ErrorCode.EINVAL); } var buf = Globals.AllocateAlignedCompletionBuffer(addrlen); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var completion = new BridgeCompletion(current, buf); if (sockaddr.Read(current, buf, addrlen) != 0) { completion.Dispose(); return(-ErrorCode.EFAULT); } if (type == SYS_BIND) { Arch.IPCStubs.BindAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen); } else if (type == SYS_CONNECT) { Arch.IPCStubs.ConnectAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen); } Globals.CompletionQueue.Enqueue(completion); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
internal int SFSRead(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file) { var readBytes = Read(current, userBuf, len, pos); if (readBytes <= 0) { return(readBytes); } if (file != null) { file.position = (uint)(pos + readBytes); } return(readBytes); }
internal int Ioctl(Thread current, ref Arch.ExceptionRegisters regs, int arg0, int arg1) { switch (kind) { case INodeKind.BinderINodeKind: return(BinderINode.Ioctl(current, ref regs, (uint)arg0, new UserPtr(arg1))); // There's no good way to figure out the type of a bindersharednode is. // So we have to guess a little bit.. case INodeKind.AshmemINodeKind: case INodeKind.BinderSharedINodeKind: case INodeKind.ArchINodeKind: case INodeKind.SocketINodeKind: return(Ioctl(current, (uint)arg0, new UserPtr(arg1))); } return(-ErrorCode.EINVAL); }
public static int Ioctl(Thread current, ref Arch.ExceptionRegisters regs, int fd, int arg0, int arg1) { Contract.Requires(current.Parent != null); var proc = current.Parent; var file = proc.LookupFile(fd); if (file == null) { Arch.Console.Write("Ioctl: invalid fd="); Arch.Console.Write(fd); Arch.Console.WriteLine(); return(-ErrorCode.EBADF); } return(file.Ioctl(current, ref regs, arg0, arg1)); }
private static int Getsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, UserPtr p_optlen) { var proc = current.Parent; var file = proc.LookupFile(sockfd); if (file == null) { return(-ErrorCode.EBADF); } if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind) { return(-ErrorCode.ENOTSOCK); } uint optlen = 0; if (p_optlen.Read(current, out optlen) != 0) { return(-ErrorCode.EFAULT); } if (optlen > Globals.LinuxIPCBuffer.Length) { return(-ErrorCode.EINVAL); } var buf = Globals.AllocateAlignedCompletionBuffer((int)optlen); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var completion = new GetSockParamCompletion(current, optval, p_optlen, buf); Arch.IPCStubs.GetSockoptAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, level, optname, (int)optlen); Globals.CompletionQueue.Enqueue(completion); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
public const int SYS_SENDMMSG = 20; /* sys_sendmmsg(2) */ public static int Poll(Thread current, ref Arch.ExceptionRegisters regs, UserPtr fds, int nfds, int timeout) { if (nfds < 0) { return(-ErrorCode.EINVAL); } var pollfd_size = pollfd.Size * nfds; var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var poll_entry = new PollCompletion(current, fds, nfds, buf); if (fds.Read(current, buf, pollfd_size) != 0) { poll_entry.Dispose(); return(-ErrorCode.EFAULT); } Contract.Assert(buf.Length >= pollfd_size); if (!TranslateToLinuxFd(current, poll_entry, buf)) { poll_entry.Dispose(); return(-ErrorCode.EBADF); } var ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout); if (ret < 0) { poll_entry.Dispose(); return(ret); } Globals.CompletionQueue.Enqueue(poll_entry); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
/* * Write a segment buffer. * * The buffer itself is passed as a reference, because some inode might take the ownership * of the buffer and put it as a part of its completion. In this case the buf is set to empty */ internal int Write(Thread current, ref Arch.ExceptionRegisters regs, ref ByteBufferRef buf, int len, uint pos, File file) { switch (kind) { case INodeKind.ConsoleINodeKind: { uint dummy = 0; return(ConsoleINode.WriteImpl(current, buf, len, ref dummy)); } case INodeKind.ArchINodeKind: case INodeKind.SocketINodeKind: return(ArchINode.ArchWrite(current, ref regs, ref buf, len, pos, file)); case INodeKind.SecureFSINodeKind: return(SFSINode.SFSWrite(current, ref regs, buf, len, pos, file)); } return(-ErrorCode.EINVAL); }
public static int DoFutex(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3) { var cmd = op & FUTEX_CMD_MASK; var flags = ToFlags(op, cmd); timespec ts; ts.tv_sec = ts.tv_nsec = 0; // Don't care about shared mutex if ((flags & FLAGS_SHARED) != 0) { return(DoFutexShared(current, ref regs, uaddr, op, val, timeoutPtr, uaddr2, val3)); } bool hasTimeout = timeoutPtr != UserPtr.Zero; if (hasTimeout && timeoutPtr.Read(current, out ts) != 0) { return(-ErrorCode.EFAULT); } switch (cmd) { case FUTEX_WAIT: return(Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, FUTEX_BITSET_MATCH_ANY)); case FUTEX_WAIT_BITSET: return(Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, val3)); case FUTEX_WAKE: return(Wake(current, uaddr, flags, val, FUTEX_BITSET_MATCH_ANY)); case FUTEX_WAKE_BITSET: return(Wake(current, uaddr, flags, val, val3)); default: Arch.Console.Write("futex: unknown primitives "); Arch.Console.Write(cmd); Arch.Console.WriteLine(); return(-ErrorCode.ENOSYS); } }
public static int Dispatch(Thread current, ref Arch.ExceptionRegisters regs, int cmd, int arg1, int arg2, int arg3) { Contract.Requires(current != null && current.VBinderState.Owner == current); switch (cmd) { case VBINDER_REGISTER_CHANNEL: return(CreateChannel(current, arg1, arg2)); case VBINDER_ACQUIRE_CHANNEL: return(AcquireChannel(current, arg1, arg2)); case VBINDER_SEND: return(Send(current, arg1, new UserPtr(arg2), (uint)arg3)); case VBINDER_RECV: return(Recv(current, ref regs, new UserPtr(arg1), new UserPtr(arg2), (uint)arg3)); } return(-ErrorCode.ENOSYS); }
public static int Nanosleep(Thread current, ref Arch.ExceptionRegisters regs, UserPtr rqtp, UserPtr rmtp) { timespec ts; timespec trem; trem.tv_sec = 0; trem.tv_nsec = 0; if (rqtp.Read(current, out ts) != 0 || rmtp.Write(current, ref trem) != 0) { return(-ErrorCode.EFAULT); } Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current); var c = new SleepCompletion(current); Globals.CompletionQueue.Enqueue(c); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
internal int Write(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file) { var buf = Globals.AllocateAlignedCompletionBuffer(len); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var l = userBuf.Read(current, buf, len); var bytesToBeWritten = len - l; var ret = Write(current, ref regs, ref buf, bytesToBeWritten, pos, file); // Buffer hasn't been taken by write(), free it here if (buf.isValid) { Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift); } return(ret); }
private static int HandleSyscall(L4Handle src, Thread thr, ref Msgtag pt_tag, ref ExceptionRegisters pt_regs) { /* * Make a copy of the registers, as other IPC calls can override * the same area. */ ExceptionRegisters exc = pt_regs; var scno = exc.eax; SyscallProfiler.EnterSyscall(scno); var ret = SyscallDispatcher.Dispatch(thr, ref exc); if (thr.AsyncReturn) { return(REPLY_DEFERRED); } ArchAPI.ReturnFromSyscall(src, ref exc, ret); SyscallProfiler.ExitSyscall(scno); return(REPLY_DEFERRED); }
internal int ArchRead(Thread current, ref ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file) { var buf = Globals.AllocateAlignedCompletionBuffer(len); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var iocp = IOCompletion.CreateReadIOCP(current, userBuf, len, file, buf); var r = IPCStubs.ReadAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos); if (r < 0) { iocp.Dispose(); return(r); } Globals.CompletionQueue.Enqueue(iocp); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
internal int ArchWrite(Thread current, ref ExceptionRegisters regs, ref ByteBufferRef buf, int len, uint pos, File file) { if (!Globals.CompletionQueueAllocator.Contains(buf)) { Arch.Console.WriteLine("inode-write: unimplemented"); Arch.ArchDefinition.Panic(); } var iocp = IOCompletion.CreateWriteIOCP(current, file, buf); var r = IPCStubs.WriteAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos); if (r < 0) { iocp.Dispose(); return(r); } Globals.CompletionQueue.Enqueue(iocp); current.SaveState(ref regs); current.AsyncReturn = true; // Take the buffer buf = ByteBufferRef.Empty; return(0); }
private static int Wait(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int flags, int val, bool hasTimeout, timespec ts, uint bitset) { int old_val; if (uaddr.Read(current, out old_val) != 0) { return(-ErrorCode.EFAULT); } if (old_val != val) { return(-ErrorCode.EWOULDBLOCK); } //Arch.Console.Write("wait: addr="); //Arch.Console.Write(uaddr.Value.ToUInt32()); //Arch.Console.Write(" thr="); //Arch.Console.Write(current.Tid); //Arch.Console.WriteLine(); TimerQueueNode node; var futex_entry = new FutexCompletionEntry(current, uaddr, bitset); Globals.FutexLists.InsertAtTail(futex_entry); if (hasTimeout) { node = Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current); futex_entry.timeoutNode = node; } Globals.CompletionQueue.Enqueue(futex_entry); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
private static int HandleMessage(L4Handle src, ref Msgtag tag, ref ExceptionRegisters pt_regs, ref MessageRegisters mr) { Thread thr; if (tag.Label == Msgtag.L4_PROTO_PAGE_FAULT || IsLinuxSyscall(tag, ref pt_regs)) { thr = Globals.Threads.Lookup(src); if (thr == null) { Console.Write("HandleMessage: Unknown thread "); Console.Write(src._value); Console.Write(" tag="); Console.Write(tag.raw); Console.WriteLine(); return(REPLY_DEFERRED); } thr.AsyncReturn = false; if (tag.Label == Msgtag.L4_PROTO_PAGE_FAULT) { return(HandlePageFault(src, thr, ref tag, ref mr)); } else { return(HandleSyscall(src, thr, ref tag, ref pt_regs)); } } else if (tag.Label == (int)Arch.IPCStubs.IPCTag.EXPRESSOS_IPC) { HandleAsyncCall(ref mr); return(REPLY_DEFERRED); } else if (tag.Label == (int)Arch.IPCStubs.IPCTag.EXPRESSOS_IPC_CMD) { switch ((IPCCommand)mr.mr0) { case IPCCommand.EXPRESSOS_CMD_DUMP_PROFILE: SyscallProfiler.Dump(); break; case IPCCommand.EXPRESSOS_CMD_ENABLE_PROFILER: SyscallProfiler.Enable = true; break; case IPCCommand.EXPRESSOS_CMD_DISABLE_PROFILER: SyscallProfiler.Enable = false; break; case IPCCommand.EXPRESSOS_CMD_FLUSH_CONSOLE: Console.Flush(); break; } return(REPLY_DEFERRED); } else { Console.Write("Unhandled exception tag="); Console.Write(tag.raw); Console.Write(" exc_trapno="); Console.Write(pt_regs.trapno); Console.Write(" err="); Console.Write(pt_regs.err); Console.Write(" eip="); Console.Write(pt_regs.ip); Console.Write(" sp="); Console.Write(pt_regs.sp); Console.WriteLine(); } return(REPLY_DEFERRED); }
internal static int Dispatch(Thread current, ref ExceptionRegisters regs) { int scno, arg0, arg1, arg2, arg3, arg4, arg5; ArchAPI.GetSyscallParameters(regs, out scno, out arg0, out arg1, out arg2, out arg3, out arg4, out arg5); current.AsyncReturn = false; int retval = 0; switch (scno) { case __NR_exit: Console.Write("Thread "); Console.Write(current.Tid); Console.WriteLine(" Exited"); current.Exit(); current.AsyncReturn = true; break; case __NR_read: retval = FileSystem.Read(current, ref regs, arg0, new UserPtr(arg1), arg2); break; case __NR_write: retval = FileSystem.Write(current, ref regs, arg0, new UserPtr(arg1), arg2); break; case __NR_open: retval = FileSystem.Open(current, ref regs, new UserPtr(arg0), arg1, arg2); break; case __NR_close: retval = FileSystem.Close(current, arg0); break; case __NR_unlink: retval = FileSystem.Unlink(current, new UserPtr(arg0)); break; case __NR_lseek: retval = FileSystem.Lseek(current, arg0, arg1, arg2); break; case __NR_getpid: retval = ExpressOS.Kernel.Misc.Getpid(current); break; case __NR_access: retval = FileSystem.Access(current, ref regs, new UserPtr(arg0), arg1); break; case __NR_mkdir: retval = FileSystem.Mkdir(current, new UserPtr(arg0), arg1); break; case __NR_clone: retval = ExpressOS.Kernel.Exec.Clone(current, (uint)arg0, new UserPtr(arg1), new UserPtr(arg2), new UserPtr(arg3), ref regs); break; case __NR_mprotect: retval = ExpressOS.Kernel.Memory.mprotect(current, new UserPtr(arg0), arg1, arg2); break; case __NR__newselect: retval = ExpressOS.Kernel.Net.Select(current, ref regs, arg0, new UserPtr(arg1), new UserPtr(arg2), new UserPtr(arg3), new UserPtr(arg4)); break; case __NR_writev: retval = FileSystem.Writev(current, ref regs, arg0, new UserPtr(arg1), arg2); break; case __NR_uname: retval = ExpressOS.Kernel.Misc.UName(current, new UserPtr(arg0)); break; case __NR_fcntl64: retval = FileSystem.Fcntl64(current, arg0, arg1, arg2); break; case __NR_gettid: retval = ExpressOS.Kernel.Misc.Gettid(current); break; case __NR_dup: retval = FileSystem.Dup(current, arg0); break; case __NR_pipe: retval = FileSystem.Pipe(current, new UserPtr(arg0)); break; case __NR_brk: retval = ExpressOS.Kernel.Memory.Brk(current, (uint)arg0); break; case __NR_ioctl: retval = FileSystem.Ioctl(current, ref regs, arg0, arg1, arg2); break; case __NR_setgid32: case __NR_setuid32: case __NR_flock: case __NR_sigaction: case __NR_sigprocmask: case __NR_sched_setscheduler: case __NR_setpriority: case __NR_fsync: //Console.Write("Mock syscall "); //Console.Write(scno); //Console.WriteLine(); retval = 0; break; case __NR_futex: retval = ExpressOS.Kernel.Futex.DoFutex(current, ref regs, new UserPtr(arg0), arg1, arg2, new UserPtr(arg3), new UserPtr(arg4), (uint)arg5); break; case __NR_dup2: retval = FileSystem.Dup2(current, arg0, arg1); break; case __NR_gettimeofday: retval = ExpressOS.Kernel.Misc.Gettimeofday(current, new UserPtr(arg0)); break; case __NR_munmap: retval = ExpressOS.Kernel.Memory.munmap(current, new UserPtr(arg0), arg1); break; case __NR_ftruncate: retval = FileSystem.ftruncate(current, arg0, arg1); break; case __NR_socketcall: retval = ExpressOS.Kernel.Net.socketcall(current, ref regs, arg0, new UserPtr(arg1)); break; case __NR_getpriority: retval = ExpressOS.Kernel.Misc.Getpriority(current, arg0, arg1); break; case __NR_pread64: retval = FileSystem.Pread64(current, ref regs, arg0, new UserPtr(arg1), arg2, (uint)arg3); break; case __NR_getcwd: retval = FileSystem.Getcwd(current, new UserPtr(arg0), arg1); break; case __NR_mmap2: retval = ExpressOS.Kernel.Memory.mmap2(current, new UserPtr(arg0), arg1, arg2, arg3, arg4, arg5); break; case __NR_stat64: retval = FileSystem.Stat64(current, new UserPtr(arg0), new UserPtr(arg1)); break; case __NR_fstat64: retval = FileSystem.FStat64(current, arg0, new UserPtr(arg1)); break; case __NR_lstat64: retval = FileSystem.LStat64(current, new UserPtr(arg0), new UserPtr(arg1)); break; case __NR_getuid32: case __NR_geteuid32: retval = ExpressOS.Kernel.Misc.Getuid32(current); break; case __NR_madvise: retval = ExpressOS.Kernel.Memory.madvise(current, (uint)arg0, arg1, arg2); break; case __NR_nanosleep: retval = ExpressOS.Kernel.Misc.Nanosleep(current, ref regs, new UserPtr(arg0), new UserPtr(arg1)); break; case __NR_sched_yield: retval = ExpressOS.Kernel.Misc.Yield(current, ref regs); break; case __NR_poll: retval = ExpressOS.Kernel.Net.Poll(current, ref regs, new UserPtr(arg0), arg1, arg2); break; case __NR_set_thread_area: retval = ExpressOS.Kernel.TLS.SetThreadArea(current, new UserPtr(arg0)); break; case __NR_clock_gettime: retval = ExpressOS.Kernel.Misc.ClockGetTime(current, arg0, new UserPtr(arg1)); break; case __NR_exit_group: Console.WriteLine("Process exited"); Console.Flush(); //Misc.DumpStackTrace(current, new UserPtr(pt_regs->ebp)); //current.Parent.Space.Regions.DumpAll(); current.AsyncReturn = true; break; case __NR_vbinder: retval = ExpressOS.Kernel.VBinder.Dispatch(current, ref regs, arg0, arg1, arg2, arg3); break; default: Console.Write("Unknown syscall "); Console.Write(scno); Console.Write('@'); Console.Write(regs.ip); Console.Write(" tid="); Console.Write(current.Tid); Console.WriteLine(); retval = -ErrorCode.ENOSYS; break; } return retval; }
internal void SaveState(ref Arch.ExceptionRegisters pt_regs) { regs = pt_regs; }
internal int ArchWrite(Thread current, ref ExceptionRegisters regs, ref ByteBufferRef buf, int len, uint pos, File file) { if (!Globals.CompletionQueueAllocator.Contains(buf)) { Arch.Console.WriteLine("inode-write: unimplemented"); Arch.ArchDefinition.Panic(); } var iocp = IOCompletion.CreateWriteIOCP(current, file, buf); var r = IPCStubs.WriteAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos); if (r < 0) { iocp.Dispose(); return r; } Globals.CompletionQueue.Enqueue(iocp); current.SaveState(ref regs); current.AsyncReturn = true; // Take the buffer buf = ByteBufferRef.Empty; return 0; }
internal int ArchRead(Thread current, ref ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file) { var buf = Globals.AllocateAlignedCompletionBuffer(len); if (!buf.isValid) return -ErrorCode.ENOMEM; var iocp = IOCompletion.CreateReadIOCP(current, userBuf, len, file, buf); var r = IPCStubs.ReadAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos); if (r < 0) { iocp.Dispose(); return r; } Globals.CompletionQueue.Enqueue(iocp); current.SaveState(ref regs); current.AsyncReturn = true; return 0; }
public static int socketcall(Thread current, ref Arch.ExceptionRegisters regs, int call, UserPtr argPtr) { int err = 0; int a0, a1, a2, a3, a4, a5; SyscallProfiler.EnterSocketcall(call); switch (call) { case SYS_SOCKET: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0) { return(-ErrorCode.EFAULT); } err = Socket(current, ref regs, a0, a1, a2); break; case SYS_BIND: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0) { return(-ErrorCode.EFAULT); } err = Bind(current, ref regs, a0, new UserPtr(a1), a2); break; case SYS_CONNECT: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0) { return(-ErrorCode.EFAULT); } err = Connect(current, ref regs, a0, new UserPtr(a1), a2); break; case SYS_GETSOCKNAME: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0) { return(-ErrorCode.EFAULT); } err = Getsockname(current, ref regs, a0, new UserPtr(a1), new UserPtr(a2)); break; case SYS_SENDTO: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0) { return(-ErrorCode.EFAULT); } err = Sendto(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), a5); break; case SYS_RECVFROM: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0) { return(-ErrorCode.EFAULT); } err = RecvFrom(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), new UserPtr(a5)); break; case SYS_SHUTDOWN: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0) { return(-ErrorCode.EFAULT); } err = Shutdown(current, a0, a1); break; case SYS_SETSOCKOPT: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0) { return(-ErrorCode.EFAULT); } err = Setsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), a4); break; case SYS_GETSOCKOPT: if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0) { return(-ErrorCode.EFAULT); } err = Getsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), new UserPtr(a4)); break; default: Arch.Console.Write("Unimplemented socketcall "); Arch.Console.Write(call); Arch.Console.WriteLine(); err = -1; break; } SyscallProfiler.ExitSocketcall(call); return(err); }
private static int Connect(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen) { return(BindOrConnect(SYS_CONNECT, current, ref regs, sockfd, sockaddr, addrlen)); }
public static int Clone(Thread current, uint flags, UserPtr newsp, UserPtr parent_tidptr, UserPtr child_tidptr, ref Arch.ExceptionRegisters pt_regs) { // Only support pthread_create right now if (flags != (CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED)) { return(-ErrorCode.EINVAL); } var proc = current.Parent; var thr = Thread.Create(proc); if (thr == null) { Arch.Console.WriteLine("Failed to create thread"); return(-ErrorCode.EINVAL); } // Start the main thread // Skipping the int $0x80 thr.Start(new Pointer(pt_regs.ip + 2), newsp.Value); // There's no need to set eax for thr as they are zero by default.. return(thr.Tid); }
// Forward the futex request to Linux helper private static int DoFutexShared(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3) { // Some local test var cmd = op & FUTEX_CMD_MASK; timespec ts = new timespec(); bool hasTimeout = timeoutPtr != UserPtr.Zero; if (hasTimeout && timeoutPtr.Read(current, out ts) != 0) { return(-ErrorCode.EFAULT); } if (cmd == FUTEX_WAIT || cmd == FUTEX_WAIT_BITSET) { int old_val; if (uaddr.Read(current, out old_val) != 0) { return(-ErrorCode.EFAULT); } if (old_val != val) { return(-ErrorCode.EWOULDBLOCK); } var bitset = cmd == FUTEX_WAIT ? FUTEX_BITSET_MATCH_ANY : val3; var shadowAddr = FindShadowAddr(current, uaddr); if (shadowAddr == Pointer.Zero) { Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wait"); return(0); } var futex_entry = new FutexCompletionEntry(current, uaddr, bitset); Arch.IPCStubs.linux_sys_futex_wait(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, val, ts, bitset); Globals.CompletionQueue.Enqueue(futex_entry); current.SaveState(ref regs); current.AsyncReturn = true; return(0); } else if (cmd == FUTEX_WAKE || cmd == FUTEX_WAKE_BITSET) { var bitset = cmd == FUTEX_WAKE ? FUTEX_BITSET_MATCH_ANY : val3; if (bitset == 0) { return(-ErrorCode.EINVAL); } var shadowAddr = FindShadowAddr(current, uaddr); if (shadowAddr == Pointer.Zero) { Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wake"); return(0); } var c = new BridgeCompletion(current, new ByteBufferRef()); Arch.IPCStubs.linux_sys_futex_wake(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, bitset); Globals.CompletionQueue.Enqueue(c); current.SaveState(ref regs); current.AsyncReturn = true; return(0); } return(0); }
public static int Select(Thread current, ref Arch.ExceptionRegisters regs, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, UserPtr tvp) { var helper = new SelectHelper(); int ret = 0; ret = helper.AddUserFdList(current, inp, maxfds, POLLIN); if (ret < 0) { return(ret); } ret = helper.AddUserFdList(current, outp, maxfds, POLLOUT); if (ret < 0) { return(ret); } ret = helper.AddUserFdList(current, exp, maxfds, POLLERR); if (ret < 0) { return(ret); } int timeout = 0; timeval tv; if (tvp == UserPtr.Zero) { timeout = -1; } else if (tvp.Read(current, out tv) != 0) { return(-ErrorCode.EFAULT); } else { timeout = (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } var nfds = helper.TotalFds; var pollfd_size = pollfd.Size * nfds; var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } helper.WritePollFds(buf); var select_entry = new SelectCompletion(current, maxfds, inp, outp, exp, helper, buf); ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout); if (ret < 0) { select_entry.Dispose(); return(ret); } Globals.CompletionQueue.Enqueue(select_entry); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }