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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
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);
        }
Beispiel #12
0
        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));
        }
Beispiel #14
0
        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);
        }
Beispiel #15
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);
        }
Beispiel #16
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);
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        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);
        }
Beispiel #20
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);
        }
Beispiel #21
0
        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);
        }
Beispiel #22
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);
        }
Beispiel #23
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);
        }
Beispiel #24
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);
        }
Beispiel #25
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);
        }
Beispiel #26
0
        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;
        }
Beispiel #27
0
 internal void SaveState(ref Arch.ExceptionRegisters pt_regs)
 {
     regs = pt_regs;
 }
Beispiel #28
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;
        }
Beispiel #29
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;
        }
Beispiel #30
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);
        }
Beispiel #31
0
 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));
 }
Beispiel #32
0
        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);
        }
Beispiel #33
0
        // 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);
        }
Beispiel #34
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);
        }