Exemple #1
0
 internal NeuralTuringMachine(NeuralTuringMachine oldMachine)
 {
     _controller     = oldMachine._controller.Clone();
     _memory         = oldMachine._memory;
     _newMemoryState = oldMachine._newMemoryState;
     _oldMemoryState = oldMachine._oldMemoryState;
 }
 public KBufferDescriptor(ulong src, ulong dst, ulong size, MemoryState state)
 {
     ClientAddress = src;
     ServerAddress = dst;
     Size          = size;
     State         = state;
 }
Exemple #3
0
 public void SetState(KMemoryPermission permission, MemoryState state, MemoryAttribute attribute)
 {
     Permission = permission;
     State      = state;
     Attribute &= MemoryAttribute.IpcAndDeviceMapped;
     Attribute |= attribute;
 }
Exemple #4
0
        public KernelResult UnmapFromProcess(
            KPageTableBase memoryManager,
            ulong address,
            ulong size,
            KProcess process)
        {
            if (_storage == null)
            {
                throw new NotImplementedException();
            }

            ulong pagesCountRounded = BitUtils.DivRoundUp(size, KPageTableBase.PageSize);

            var   pageList   = _storage.GetPageList();
            ulong pagesCount = pageList.GetPagesCount();

            if (pagesCount != pagesCountRounded)
            {
                return(KernelResult.InvalidSize);
            }

            var ranges = _storage.GetRanges();

            MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;

            KernelResult result = memoryManager.UnmapPages(address, pagesCount, ranges, state);

            if (result == KernelResult.Success)
            {
                _isMapped = false;
            }

            return(result);
        }
        public KernelResult MapIntoProcess(
            KPageTableBase memoryManager,
            ulong address,
            ulong size,
            KProcess process,
            KMemoryPermission permission)
        {
            if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize))
            {
                return(KernelResult.InvalidSize);
            }

            if (permission != Permission || _isMapped)
            {
                return(KernelResult.InvalidState);
            }

            MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;

            KernelResult result = memoryManager.MapPages(address, _pageList, state, KMemoryPermission.ReadAndWrite);

            if (result == KernelResult.Success)
            {
                _isMapped = true;
            }

            return(result);
        }
Exemple #6
0
        public void Process(double[] input)
        {
            _lastInput      = input;
            _oldMemoryState = _newMemoryState;

            _controller.Process(input, _oldMemoryState.ReadData);
            _newMemoryState = _oldMemoryState.Process(GetHeads());
        }
 public NativeMemoryInfo(ulong baseAddress, ulong allocationBase, MemoryProtection allocationProtect, ulong regionSize, MemoryState state, MemoryProtection protect, MemoryType type)
 {
     BaseAddress       = baseAddress;
     AllocationBase    = allocationBase;
     AllocationProtect = allocationProtect;
     RegionSize        = regionSize;
     State             = state;
     Protect           = protect;
     Type = type;
 }
Exemple #8
0
        public void InsertBlock(
            ulong baseAddress,
            ulong pagesCount,
            MemoryState state,
            KMemoryPermission permission = KMemoryPermission.None,
            MemoryAttribute attribute    = MemoryAttribute.None)
        {
            // Inserts new block at the list, replacing and splitting
            // existing blocks as needed.
            int oldCount = _blocks.Count;

            ulong endAddr = baseAddress + pagesCount * PageSize;

            LinkedListNode <KMemoryBlock> node = _blocks.First;

            while (node != null)
            {
                LinkedListNode <KMemoryBlock> newNode = node;

                KMemoryBlock currBlock = node.Value;

                ulong currBaseAddr = currBlock.BaseAddress;
                ulong currEndAddr  = currBlock.PagesCount * PageSize + currBaseAddr;

                if (baseAddress < currEndAddr && currBaseAddr < endAddr)
                {
                    if (baseAddress > currBaseAddr)
                    {
                        _blocks.AddBefore(node, currBlock.SplitRightAtAddress(baseAddress));
                    }

                    if (endAddr < currEndAddr)
                    {
                        newNode = _blocks.AddBefore(node, currBlock.SplitRightAtAddress(endAddr));
                    }

                    newNode.Value.SetState(permission, state, attribute);

                    newNode = MergeEqualStateNeighbors(newNode);
                }

                if (currEndAddr - 1 >= endAddr - 1)
                {
                    break;
                }

                node = newNode.Next;
            }

            _slabManager.Count += _blocks.Count - oldCount;

            ValidateInternalState();
        }
Exemple #9
0
        public void InsertBlock(
            ulong baseAddress,
            ulong pagesCount,
            MemoryState state,
            KMemoryPermission permission = KMemoryPermission.None,
            MemoryAttribute attribute    = MemoryAttribute.None)
        {
            // Inserts new block at the list, replacing and splitting
            // existing blocks as needed.

            int oldCount = _blockTree.Count;

            ulong endAddr = baseAddress + pagesCount * PageSize;

            KMemoryBlock currBlock = FindBlock(baseAddress);

            while (currBlock != null)
            {
                ulong currBaseAddr = currBlock.BaseAddress;
                ulong currEndAddr  = currBlock.PagesCount * PageSize + currBaseAddr;

                if (baseAddress < currEndAddr && currBaseAddr < endAddr)
                {
                    if (baseAddress > currBaseAddr)
                    {
                        KMemoryBlock newBlock = currBlock.SplitRightAtAddress(baseAddress);
                        _blockTree.Add(newBlock);
                    }

                    if (endAddr < currEndAddr)
                    {
                        KMemoryBlock newBlock = currBlock.SplitRightAtAddress(endAddr);
                        _blockTree.Add(newBlock);
                        currBlock = newBlock;
                    }

                    currBlock.SetState(permission, state, attribute);

                    currBlock = MergeEqualStateNeighbors(currBlock);
                }

                if (currEndAddr - 1 >= endAddr - 1)
                {
                    break;
                }

                currBlock = currBlock.Successor;
            }

            _slabManager.Count += _blockTree.Count - oldCount;

            ValidateInternalState();
        }
Exemple #10
0
 public KMemoryBlock(
     ulong baseAddress,
     ulong pagesCount,
     MemoryState state,
     MemoryPermission permission,
     MemoryAttribute attribute)
 {
     BaseAddress = baseAddress;
     PagesCount  = pagesCount;
     State       = state;
     Attribute   = attribute;
     Permission  = permission;
 }
Exemple #11
0
 public KMemoryBlock(
     long BasePosition,
     long PagesCount,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute)
 {
     this.BasePosition = BasePosition;
     this.PagesCount   = PagesCount;
     this.State        = State;
     this.Attribute    = Attribute;
     this.Permission   = Permission;
 }
Exemple #12
0
 public KMemoryBlock(
     ulong BaseAddress,
     ulong PagesCount,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute)
 {
     this.BaseAddress = BaseAddress;
     this.PagesCount  = PagesCount;
     this.State       = State;
     this.Attribute   = Attribute;
     this.Permission  = Permission;
 }
Exemple #13
0
        public void HleMapCustom(long Position, long Size, MemoryState State, MemoryPermission Permission)
        {
            long PagesCount = Size / PageSize;

            if (!Allocator.TryAllocate(Size, out long PA))
            {
                throw new InvalidOperationException();
            }

            lock (Blocks)
            {
                InsertBlock(Position, PagesCount, State, Permission);

                CpuMemory.Map(Position, PA, Size);
            }
        }
Exemple #14
0
 public KMemoryInfo(
     long Position,
     long Size,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute,
     int IpcRefCount,
     int DeviceRefCount)
 {
     this.Position       = Position;
     this.Size           = Size;
     this.State          = State;
     this.Attribute      = Attribute;
     this.Permission     = Permission;
     this.IpcRefCount    = IpcRefCount;
     this.DeviceRefCount = DeviceRefCount;
 }
Exemple #15
0
 public KMemoryInfo(
     ulong address,
     ulong size,
     MemoryState state,
     MemoryPermission permission,
     MemoryAttribute attribute,
     int ipcRefCount,
     int deviceRefCount)
 {
     Address        = address;
     Size           = size;
     State          = state;
     Attribute      = attribute;
     Permission     = permission;
     IpcRefCount    = ipcRefCount;
     DeviceRefCount = deviceRefCount;
 }
Exemple #16
0
 public KMemoryInfo(
     ulong Address,
     ulong Size,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute,
     int IpcRefCount,
     int DeviceRefCount)
 {
     this.Address        = Address;
     this.Size           = Size;
     this.State          = State;
     this.Attribute      = Attribute;
     this.Permission     = Permission;
     this.IpcRefCount    = IpcRefCount;
     this.DeviceRefCount = DeviceRefCount;
 }
Exemple #17
0
 public KMemoryBlock(
     ulong baseAddress,
     ulong pagesCount,
     MemoryState state,
     KMemoryPermission permission,
     MemoryAttribute attribute,
     int ipcRefCount    = 0,
     int deviceRefCount = 0)
 {
     BaseAddress    = baseAddress;
     PagesCount     = pagesCount;
     State          = state;
     Attribute      = attribute;
     Permission     = permission;
     IpcRefCount    = ipcRefCount;
     DeviceRefCount = deviceRefCount;
 }
        private bool AnalyzePointerFromStack(out PointerInfo info, ulong address, KThread thread)
        {
            info = default;

            ulong       sp          = thread.Context.GetX(31);
            var         memoryInfo  = _owner.MemoryManager.QueryMemory(address);
            MemoryState memoryState = memoryInfo.State;

            if (!memoryState.HasFlag(MemoryState.Stack)) // Is this pointer within the stack?
            {
                return(false);
            }

            info.SubOffset = address - sp;

            return(true);
        }
Exemple #19
0
        /// <summary>
        /// Gets the bookmark for a particular cycle type.
        /// </summary>
        private BookmarkEntry GetBookmarkEntry(int book, MemoryState state)
        {
            //
            // Index into the "bookmark" table:
            //		bits	value
            //		7:4		bookmark (cycle type)
            //		3:2		current state
            //		1:0		current Tstate
            //
            int lookup = (((int)book & 0x0f) << 4) | ((int)state << 2) | Tstate;

#if TRACING_ENABLED
            if (Trace.TraceOn)
            {
                Trace.Log(LogType.MemoryState, "{0} Bookmark[{1:x3}]: {2}", _name, lookup, _bkmTable[lookup]);
            }
#endif
            return(_bkmTable[lookup]);
        }
Exemple #20
0
        public KernelResult MapIntoProcess(
            KPageTableBase memoryManager,
            ulong address,
            ulong size,
            KProcess process,
            KMemoryPermission permission)
        {
            if (_storage == null)
            {
                throw new NotImplementedException();
            }

            ulong pagesCountRounded = BitUtils.DivRoundUp(size, KPageTableBase.PageSize);

            var pageList = _storage.GetPageList();

            if (pageList.GetPagesCount() != pagesCountRounded)
            {
                return(KernelResult.InvalidSize);
            }

            if (permission != Permission || _isMapped)
            {
                return(KernelResult.InvalidState);
            }

            MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;

            KernelResult result = memoryManager.MapPages(address, pageList, state, KMemoryPermission.ReadAndWrite);

            if (result == KernelResult.Success)
            {
                _isMapped = true;

                if (!memoryManager.SupportsMemoryAliasing)
                {
                    _storage.Borrow(process, address);
                }
            }

            return(result);
        }
Exemple #21
0
        private string GetStateStr(MemoryState state)
        {
            switch (state)
            {
            case MemoryState.Commit:
                return("Commit");

            case MemoryState.Free:
                return("Free");

            case MemoryState.Reserve:
                return("Reserve");

            case MemoryState.Reset:
                return("Reset");

            default:
                return("Unknown");
            }
        }
        public KernelResult UnmapFromProcess(
            KPageTableBase memoryManager,
            ulong address,
            ulong size,
            KProcess process)
        {
            if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize))
            {
                return(KernelResult.InvalidSize);
            }

            MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;

            KernelResult result = memoryManager.UnmapPages(address, _pageList, state);

            if (result == KernelResult.Success)
            {
                _isMapped = false;
            }

            return(result);
        }
Exemple #23
0
        private bool CheckRange(
            long Position,
            long Size,
            MemoryState StateMask,
            MemoryState StateExpected,
            MemoryPermission PermissionMask,
            MemoryPermission PermissionExpected,
            MemoryAttribute AttributeMask,
            MemoryAttribute AttributeExpected,
            MemoryAttribute AttributeIgnoreMask,
            out MemoryState OutState,
            out MemoryPermission OutPermission,
            out MemoryAttribute OutAttribute)
        {
            KMemoryInfo BlkInfo = FindBlock(Position).GetInfo();

            ulong Start = (ulong)Position;
            ulong End   = (ulong)Size + Start;

            if (End <= (ulong)(BlkInfo.Position + BlkInfo.Size))
            {
                if ((BlkInfo.Attribute & AttributeMask) == AttributeExpected &&
                    (BlkInfo.State & StateMask) == StateExpected &&
                    (BlkInfo.Permission & PermissionMask) == PermissionExpected)
                {
                    OutState      = BlkInfo.State;
                    OutPermission = BlkInfo.Permission;
                    OutAttribute  = BlkInfo.Attribute & ~AttributeIgnoreMask;

                    return(true);
                }
            }

            OutState      = MemoryState.Unmapped;
            OutPermission = MemoryPermission.None;
            OutAttribute  = MemoryAttribute.None;

            return(false);
        }
Exemple #24
0
 private string GetStateStr(MemoryState state)
 {
     if (state == MemoryState.Commit)
     {
         return("Commit");
     }
     else if (state == MemoryState.Free)
     {
         return("Free");
     }
     else if (state == MemoryState.Reserve)
     {
         return("Reserve");
     }
     else if (state == MemoryState.Reset)
     {
         return("Reset");
     }
     else
     {
         return("Unknown");
     }
 }
Exemple #25
0
 public KernelResult AddReceiveBuffer(ulong src, ulong dst, ulong size, MemoryState state)
 {
     return(Add(_receiveBufferDescriptors, src, dst, size, state));
 }
Exemple #26
0
 private string GetStateStr(MemoryState state)
 {
     if (state == MemoryState.Commit)
         return "Commit";
     else if (state == MemoryState.Free)
         return "Free";
     else if (state == MemoryState.Reserve)
         return "Reserve";
     else if (state == MemoryState.Reset)
         return "Reset";
     else
         return "Unknown";
 }
 private string GetStateStr(MemoryState state)
 {
     switch (state)
     {
         case MemoryState.Commit:
             return "Commit";
         case MemoryState.Free:
             return "Free";
         case MemoryState.Reserve:
             return "Reserve";
         case MemoryState.Reset:
             return "Reset";
         default:
             return "Unknown";
     }
 }
Exemple #28
0
        private void InsertBlock(
            long BasePosition,
            long PagesCount,
            MemoryState OldState,
            MemoryPermission OldPermission,
            MemoryAttribute OldAttribute,
            MemoryState NewState,
            MemoryPermission NewPermission,
            MemoryAttribute NewAttribute)
        {
            //Insert new block on the list only on areas where the state
            //of the block matches the state specified on the Old* state
            //arguments, otherwise leave it as is.
            OldAttribute |= MemoryAttribute.IpcAndDeviceMapped;

            ulong Start = (ulong)BasePosition;
            ulong End   = (ulong)PagesCount * PageSize + Start;

            LinkedListNode <KMemoryBlock> Node = Blocks.First;

            while (Node != null)
            {
                LinkedListNode <KMemoryBlock> NewNode  = Node;
                LinkedListNode <KMemoryBlock> NextNode = Node.Next;

                KMemoryBlock CurrBlock = Node.Value;

                ulong CurrStart = (ulong)CurrBlock.BasePosition;
                ulong CurrEnd   = (ulong)CurrBlock.PagesCount * PageSize + CurrStart;

                if (Start < CurrEnd && CurrStart < End)
                {
                    MemoryAttribute CurrBlockAttr = CurrBlock.Attribute | MemoryAttribute.IpcAndDeviceMapped;

                    if (CurrBlock.State != OldState ||
                        CurrBlock.Permission != OldPermission ||
                        CurrBlockAttr != OldAttribute)
                    {
                        Node = NextNode;

                        continue;
                    }

                    if (CurrStart >= Start && CurrEnd <= End)
                    {
                        CurrBlock.State      = NewState;
                        CurrBlock.Permission = NewPermission;
                        CurrBlock.Attribute &= ~MemoryAttribute.IpcAndDeviceMapped;
                        CurrBlock.Attribute |= NewAttribute;
                    }
                    else if (CurrStart >= Start)
                    {
                        CurrBlock.BasePosition = (long)End;

                        CurrBlock.PagesCount = (long)((CurrEnd - End) / PageSize);

                        long NewPagesCount = (long)((End - CurrStart) / PageSize);

                        NewNode = Blocks.AddBefore(Node, new KMemoryBlock(
                                                       (long)CurrStart,
                                                       NewPagesCount,
                                                       NewState,
                                                       NewPermission,
                                                       NewAttribute));
                    }
                    else if (CurrEnd <= End)
                    {
                        CurrBlock.PagesCount = (long)((Start - CurrStart) / PageSize);

                        long NewPagesCount = (long)((CurrEnd - Start) / PageSize);

                        NewNode = Blocks.AddAfter(Node, new KMemoryBlock(
                                                      BasePosition,
                                                      NewPagesCount,
                                                      NewState,
                                                      NewPermission,
                                                      NewAttribute));
                    }
                    else
                    {
                        CurrBlock.PagesCount = (long)((Start - CurrStart) / PageSize);

                        long NextPagesCount = (long)((CurrEnd - End) / PageSize);

                        NewNode = Blocks.AddAfter(Node, new KMemoryBlock(
                                                      BasePosition,
                                                      PagesCount,
                                                      NewState,
                                                      NewPermission,
                                                      NewAttribute));

                        Blocks.AddAfter(NewNode, new KMemoryBlock(
                                            (long)End,
                                            NextPagesCount,
                                            CurrBlock.State,
                                            CurrBlock.Permission,
                                            CurrBlock.Attribute));

                        NextNode = null;
                    }

                    MergeEqualStateNeighbours(NewNode);
                }

                Node = NextNode;
            }
        }
Exemple #29
0
 internal void InitializeMemoryState()
 {
     _newMemoryState = new MemoryState(_memory);
     _newMemoryState.DoInitialReading();
     _oldMemoryState = null;
 }
Exemple #30
0
 public KernelResult AddExchangeBuffer(ulong src, ulong dst, ulong size, MemoryState state)
 {
     return Add(_exchangeBufferDescriptors, src, dst, size, state);
 }
Exemple #31
0
        private KernelResult Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
        {
            if (list.Count < MaxInternalBuffersCount)
            {
                list.Add(new KBufferDescriptor(src, dst, size, state));

                return KernelResult.Success;
            }

            return KernelResult.OutOfMemory;
        }
Exemple #32
0
        public KernelResult Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
        {
            KThread  serverThread  = KernelContext.Scheduler.GetCurrentThread();
            KProcess serverProcess = serverThread.Owner;

            KernelContext.CriticalSection.Enter();

            if (_parent.ClientSession.State != ChannelState.Open)
            {
                KernelContext.CriticalSection.Leave();

                return(KernelResult.PortRemoteClosed);
            }

            if (_activeRequest != null || !DequeueRequest(out KSessionRequest request))
            {
                KernelContext.CriticalSection.Leave();

                return(KernelResult.NotFound);
            }

            if (request.ClientThread == null)
            {
                KernelContext.CriticalSection.Leave();

                return(KernelResult.PortRemoteClosed);
            }

            KThread  clientThread  = request.ClientThread;
            KProcess clientProcess = clientThread.Owner;

            KernelContext.CriticalSection.Leave();

            _activeRequest = request;

            request.ServerProcess = serverProcess;

            Message clientMsg = new Message(request);
            Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize);

            MessageHeader clientHeader = GetClientMessageHeader(clientMsg);
            MessageHeader serverHeader = GetServerMessageHeader(serverMsg);

            KernelResult serverResult = KernelResult.NotFound;
            KernelResult clientResult = KernelResult.Success;

            void CleanUpForError()
            {
                if (request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager) == KernelResult.Success)
                {
                    request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager);
                }

                CloseAllHandles(serverMsg, clientHeader, serverProcess);

                KernelContext.CriticalSection.Enter();

                _activeRequest = null;

                if (_requests.Count != 0)
                {
                    Signal();
                }

                KernelContext.CriticalSection.Leave();

                WakeClientThread(request, clientResult);
            }

            if (clientHeader.ReceiveListType < 2 &&
                clientHeader.ReceiveListOffset > clientMsg.Size)
            {
                CleanUpForError();

                return(KernelResult.InvalidCombination);
            }
            else if (clientHeader.ReceiveListType == 2 &&
                     clientHeader.ReceiveListOffset + 8 > clientMsg.Size)
            {
                CleanUpForError();

                return(KernelResult.InvalidCombination);
            }
            else if (clientHeader.ReceiveListType > 2 &&
                     clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size)
            {
                CleanUpForError();

                return(KernelResult.InvalidCombination);
            }

            if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords)
            {
                CleanUpForError();

                return(KernelResult.InvalidCombination);
            }

            if (clientHeader.MessageSizeInWords * 4 > clientMsg.Size)
            {
                CleanUpForError();

                return(KernelResult.CmdBufferTooSmall);
            }

            ulong[] receiveList = GetReceiveList(
                serverMsg,
                serverHeader.ReceiveListType,
                serverHeader.ReceiveListOffset);

            serverProcess.CpuMemory.Write(serverMsg.Address + 0, clientHeader.Word0);
            serverProcess.CpuMemory.Write(serverMsg.Address + 4, clientHeader.Word1);

            uint offset;

            // Copy handles.
            if (clientHeader.HasHandles)
            {
                if (clientHeader.MoveHandlesCount != 0)
                {
                    CleanUpForError();

                    return(KernelResult.InvalidCombination);
                }

                serverProcess.CpuMemory.Write(serverMsg.Address + 8, clientHeader.Word2);

                offset = 3;

                if (clientHeader.HasPid)
                {
                    serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, clientProcess.Pid);

                    offset += 2;
                }

                for (int index = 0; index < clientHeader.CopyHandlesCount; index++)
                {
                    int newHandle = 0;
                    int handle    = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4);

                    if (clientResult == KernelResult.Success && handle != 0)
                    {
                        clientResult = GetCopyObjectHandle(clientThread, serverProcess, handle, out newHandle);
                    }

                    serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle);

                    offset++;
                }

                for (int index = 0; index < clientHeader.MoveHandlesCount; index++)
                {
                    int newHandle = 0;
                    int handle    = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4);

                    if (handle != 0)
                    {
                        if (clientResult == KernelResult.Success)
                        {
                            clientResult = GetMoveObjectHandle(clientProcess, serverProcess, handle, out newHandle);
                        }
                        else
                        {
                            clientProcess.HandleTable.CloseHandle(handle);
                        }
                    }

                    serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle);

                    offset++;
                }

                if (clientResult != KernelResult.Success)
                {
                    CleanUpForError();

                    return(serverResult);
                }
            }
            else
            {
                offset = 2;
            }

            // Copy pointer/receive list buffers.
            uint recvListDstOffset = 0;

            for (int index = 0; index < clientHeader.PointerBuffersCount; index++)
            {
                ulong pointerDesc = KernelContext.Memory.Read <ulong>(clientMsg.DramAddress + offset * 4);

                PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc);

                if (descriptor.BufferSize != 0)
                {
                    clientResult = GetReceiveListAddress(
                        descriptor,
                        serverMsg,
                        serverHeader.ReceiveListType,
                        clientHeader.MessageSizeInWords,
                        receiveList,
                        ref recvListDstOffset,
                        out ulong recvListBufferAddress);

                    if (clientResult != KernelResult.Success)
                    {
                        CleanUpForError();

                        return(serverResult);
                    }

                    clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess(
                        recvListBufferAddress,
                        descriptor.BufferSize,
                        descriptor.BufferAddress,
                        MemoryState.IsPoolAllocated,
                        MemoryState.IsPoolAllocated,
                        MemoryPermission.Read,
                        MemoryAttribute.Uncached,
                        MemoryAttribute.None);

                    if (clientResult != KernelResult.Success)
                    {
                        CleanUpForError();

                        return(serverResult);
                    }

                    descriptor.BufferAddress = recvListBufferAddress;
                }
                else
                {
                    descriptor.BufferAddress = 0;
                }

                serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, descriptor.Pack());

                offset += 2;
            }

            // Copy send, receive and exchange buffers.
            uint totalBuffersCount =
                clientHeader.SendBuffersCount +
                clientHeader.ReceiveBuffersCount +
                clientHeader.ExchangeBuffersCount;

            for (int index = 0; index < totalBuffersCount; index++)
            {
                ulong clientDescAddress = clientMsg.DramAddress + offset * 4;

                uint descWord0 = KernelContext.Memory.Read <uint>(clientDescAddress + 0);
                uint descWord1 = KernelContext.Memory.Read <uint>(clientDescAddress + 4);
                uint descWord2 = KernelContext.Memory.Read <uint>(clientDescAddress + 8);

                bool isSendDesc     = index < clientHeader.SendBuffersCount;
                bool isExchangeDesc = index >= clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount;

                bool notReceiveDesc = isSendDesc || isExchangeDesc;
                bool isReceiveDesc  = !notReceiveDesc;

                MemoryPermission permission = index >= clientHeader.SendBuffersCount
                    ? MemoryPermission.ReadAndWrite
                    : MemoryPermission.Read;

                uint sizeHigh4 = (descWord2 >> 24) & 0xf;

                ulong bufferSize = descWord0 | (ulong)sizeHigh4 << 32;

                ulong dstAddress = 0;

                if (bufferSize != 0)
                {
                    ulong bufferAddress;

                    bufferAddress  = descWord2 >> 28;
                    bufferAddress |= ((descWord2 >> 2) & 7) << 4;

                    bufferAddress = (bufferAddress << 32) | descWord1;

                    MemoryState state = IpcMemoryStates[(descWord2 + 1) & 3];

                    clientResult = serverProcess.MemoryManager.MapBufferFromClientProcess(
                        bufferSize,
                        bufferAddress,
                        clientProcess.MemoryManager,
                        permission,
                        state,
                        notReceiveDesc,
                        out dstAddress);

                    if (clientResult != KernelResult.Success)
                    {
                        CleanUpForError();

                        return(serverResult);
                    }

                    if (isSendDesc)
                    {
                        clientResult = request.BufferDescriptorTable.AddSendBuffer(bufferAddress, dstAddress, bufferSize, state);
                    }
                    else if (isReceiveDesc)
                    {
                        clientResult = request.BufferDescriptorTable.AddReceiveBuffer(bufferAddress, dstAddress, bufferSize, state);
                    }
                    else /* if (isExchangeDesc) */
                    {
                        clientResult = request.BufferDescriptorTable.AddExchangeBuffer(bufferAddress, dstAddress, bufferSize, state);
                    }

                    if (clientResult != KernelResult.Success)
                    {
                        CleanUpForError();

                        return(serverResult);
                    }
                }

                descWord1 = (uint)dstAddress;

                descWord2 &= 3;

                descWord2 |= sizeHigh4 << 24;

                descWord2 |= (uint)(dstAddress >> 34) & 0x3ffffffc;
                descWord2 |= (uint)(dstAddress >> 4) & 0xf0000000;

                ulong serverDescAddress = serverMsg.Address + offset * 4;

                serverProcess.CpuMemory.Write(serverDescAddress + 0, descWord0);
                serverProcess.CpuMemory.Write(serverDescAddress + 4, descWord1);
                serverProcess.CpuMemory.Write(serverDescAddress + 8, descWord2);

                offset += 3;
            }

            // Copy raw data.
            if (clientHeader.RawDataSizeInWords != 0)
            {
                ulong copySrc = clientMsg.Address + offset * 4;
                ulong copyDst = serverMsg.Address + offset * 4;

                ulong copySize = clientHeader.RawDataSizeInWords * 4;

                if (serverMsg.IsCustom || clientMsg.IsCustom)
                {
                    MemoryPermission permission = clientMsg.IsCustom
                        ? MemoryPermission.None
                        : MemoryPermission.Read;

                    clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess(
                        copyDst,
                        copySize,
                        copySrc,
                        MemoryState.IsPoolAllocated,
                        MemoryState.IsPoolAllocated,
                        permission,
                        MemoryAttribute.Uncached,
                        MemoryAttribute.None);
                }
                else
                {
                    copySrc = clientProcess.MemoryManager.GetDramAddressFromVa(copySrc);
                    copyDst = serverProcess.MemoryManager.GetDramAddressFromVa(copyDst);

                    KernelContext.Memory.Copy(copyDst, copySrc, copySize);
                }

                if (clientResult != KernelResult.Success)
                {
                    CleanUpForError();

                    return(serverResult);
                }
            }

            return(KernelResult.Success);
        }