public override int GetHashCode() { return(_value.ToInt32()); }
public static int mmap2(Thread current, UserPtr addr, int length, int prot, int flags, int fd, int pgoffset) { Contract.Requires(current.Parent == current.Parent.Space.GhostOwner); Pointer targetAddr = new Pointer(Arch.ArchDefinition.PageAlign(addr.Value.ToUInt32())); //Arch.Console.Write("mmap2:"); //Arch.Console.Write(addr.Value.ToInt32()); //Arch.Console.Write(" sz="); //Arch.Console.Write(length); //Arch.Console.Write(" prot="); //Arch.Console.Write(prot); //Arch.Console.WriteLine(); var proc = current.Parent; var space = proc.Space; Contract.Assert(proc == space.GhostOwner); if ((flags & MAP_FIXED) == 0) { if (targetAddr == Pointer.Zero || space.ContainRegion(targetAddr, length)) targetAddr = space.FindFreeRegion(length); } else if (Arch.ArchDefinition.PageOffset(addr.Value.ToInt32()) != 0) { return -ErrorCode.EINVAL; } targetAddr = new Pointer(Arch.ArchDefinition.PageIndex(targetAddr.ToUInt32())); if (targetAddr == Pointer.Zero || length == 0) return -ErrorCode.EINVAL; File file = null; GenericINode inode = null; if ((flags & MAP_ANONYMOUS) == 0) { file = proc.LookupFile(fd); if (file == null) return -ErrorCode.EBADF; inode = file.inode; } int memorySize = Arch.ArchDefinition.PageAlign(length); // fix for code contract if (length > memorySize) length = memorySize; if ((file != null && length == 0) || length < 0) return -ErrorCode.EINVAL; if (file == null) { pgoffset = 0; length = 0; } // // Be careful for shared mapping -- which could be a shared memory region coming from Linux. // In this case we'll need to (1) call mmap() in the shadow process to obtain a valid mapping // (2) when a page fault happens, grabs the physical page from linux. // if ((flags & MAP_SHARED) != 0 && SharedWithLinux(inode)) { // Don't know how to deal with it... if (addr != UserPtr.Zero) return -ErrorCode.EINVAL; var vaddr = Arch.IPCStubs.linux_sys_alien_mmap2(current.Parent.helperPid, addr.Value, length, prot, flags, inode.LinuxFd, pgoffset); if (vaddr > AddressSpace.KERNEL_OFFSET) return -ErrorCode.EINVAL; switch (inode.kind) { case GenericINode.INodeKind.BinderSharedINodeKind: case GenericINode.INodeKind.AshmemINodeKind: case GenericINode.INodeKind.ScreenBufferINodeKind: inode.AlienSharedMemoryINode.vaddrInShadowProcess = new Pointer(vaddr); break; default: // UNIMPLEMENTED... let's return EINVAL to make sure we can catch it. return -ErrorCode.EINVAL; } } var r = space.AddMapping(ProtToAccessFlag(prot), flags, file, (uint)pgoffset * Arch.ArchDefinition.PageSize, length, targetAddr, memorySize); if (r < 0) return r; // // HACK for binder IPC // if (inode != null && inode.kind == GenericINode.INodeKind.BinderINodeKind) { proc.binderVMStart = new UserPtr(targetAddr); proc.binderVMSize = length; } return targetAddr.ToInt32(); }
public static int mmap2(Thread current, UserPtr addr, int length, int prot, int flags, int fd, int pgoffset) { Contract.Requires(current.Parent == current.Parent.Space.GhostOwner); Pointer targetAddr = new Pointer(Arch.ArchDefinition.PageAlign(addr.Value.ToUInt32())); //Arch.Console.Write("mmap2:"); //Arch.Console.Write(addr.Value.ToInt32()); //Arch.Console.Write(" sz="); //Arch.Console.Write(length); //Arch.Console.Write(" prot="); //Arch.Console.Write(prot); //Arch.Console.WriteLine(); var proc = current.Parent; var space = proc.Space; Contract.Assert(proc == space.GhostOwner); if ((flags & MAP_FIXED) == 0) { if (targetAddr == Pointer.Zero || space.ContainRegion(targetAddr, length)) { targetAddr = space.FindFreeRegion(length); } } else if (Arch.ArchDefinition.PageOffset(addr.Value.ToInt32()) != 0) { return(-ErrorCode.EINVAL); } targetAddr = new Pointer(Arch.ArchDefinition.PageIndex(targetAddr.ToUInt32())); if (targetAddr == Pointer.Zero || length == 0) { return(-ErrorCode.EINVAL); } File file = null; GenericINode inode = null; if ((flags & MAP_ANONYMOUS) == 0) { file = proc.LookupFile(fd); if (file == null) { return(-ErrorCode.EBADF); } inode = file.inode; } int memorySize = Arch.ArchDefinition.PageAlign(length); // fix for code contract if (length > memorySize) { length = memorySize; } if ((file != null && length == 0) || length < 0) { return(-ErrorCode.EINVAL); } if (file == null) { pgoffset = 0; length = 0; } // // Be careful for shared mapping -- which could be a shared memory region coming from Linux. // In this case we'll need to (1) call mmap() in the shadow process to obtain a valid mapping // (2) when a page fault happens, grabs the physical page from linux. // if ((flags & MAP_SHARED) != 0 && SharedWithLinux(inode)) { // Don't know how to deal with it... if (addr != UserPtr.Zero) { return(-ErrorCode.EINVAL); } var vaddr = Arch.IPCStubs.linux_sys_alien_mmap2(current.Parent.helperPid, addr.Value, length, prot, flags, inode.LinuxFd, pgoffset); if (vaddr > AddressSpace.KERNEL_OFFSET) { return(-ErrorCode.EINVAL); } switch (inode.kind) { case GenericINode.INodeKind.BinderSharedINodeKind: case GenericINode.INodeKind.AshmemINodeKind: case GenericINode.INodeKind.ScreenBufferINodeKind: inode.AlienSharedMemoryINode.vaddrInShadowProcess = new Pointer(vaddr); break; default: // UNIMPLEMENTED... let's return EINVAL to make sure we can catch it. return(-ErrorCode.EINVAL); } } var r = space.AddMapping(ProtToAccessFlag(prot), flags, file, (uint)pgoffset * Arch.ArchDefinition.PageSize, length, targetAddr, memorySize); if (r < 0) { return(r); } // // HACK for binder IPC // if (inode != null && inode.kind == GenericINode.INodeKind.BinderINodeKind) { proc.binderVMStart = new UserPtr(targetAddr); proc.binderVMSize = length; } return(targetAddr.ToInt32()); }