コード例 #1
0
        private static int UnmapBuffer(ServiceCtx context)
        {
            long inputPosition = context.Request.GetBufferType0x21().Position;

            NvHostChannelMapBuffer args = MemoryHelper.Read <NvHostChannelMapBuffer>(context.Memory, inputPosition);

            NvGpuVmm vmm = NvGpuASIoctl.GetASCtx(context).Vmm;

            for (int index = 0; index < args.NumEntries; index++)
            {
                int handle = context.Memory.ReadInt32(inputPosition + 0xc + index * 8);

                NvMapHandle map = NvMapIoctl.GetNvMap(context, handle);

                if (map == null)
                {
                    Logger.PrintWarning(LogClass.ServiceNv, $"Invalid handle 0x{handle:x8}!");

                    return(NvResult.InvalidInput);
                }

                lock (map)
                {
                    if (map.DmaMapAddress != 0)
                    {
                        vmm.Free(map.DmaMapAddress, map.Size);

                        map.DmaMapAddress = 0;
                    }
                }
            }

            return(NvResult.Success);
        }
コード例 #2
0
        private static int Remap(ServiceCtx Context, int Cmd)
        {
            int Count = ((Cmd >> 16) & 0xff) / 0x14;

            long InputPosition = Context.Request.GetBufferType0x21().Position;

            for (int Index = 0; Index < Count; Index++, InputPosition += 0x14)
            {
                NvGpuASRemap Args = AMemoryHelper.Read <NvGpuASRemap>(Context.Memory, InputPosition);

                NvGpuVmm Vmm = GetASCtx(Context).Vmm;

                NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

                if (Map == null)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                    return(NvResult.InvalidInput);
                }

                long Result = Vmm.Map(Map.Address, (long)(uint)Args.Offset << 16,
                                      (long)(uint)Args.Pages << 16);

                if (Result < 0)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv,
                                                $"Page 0x{Args.Offset:x16} size 0x{Args.Pages:x16} not allocated!");

                    return(NvResult.InvalidInput);
                }
            }

            return(NvResult.Success);
        }
コード例 #3
0
        private static int Submit(ServiceCtx context)
        {
            long inputPosition  = context.Request.GetBufferType0x21().Position;
            long outputPosition = context.Request.GetBufferType0x22().Position;

            NvHostChannelSubmit args = MemoryHelper.Read <NvHostChannelSubmit>(context.Memory, inputPosition);

            NvGpuVmm vmm = NvGpuASIoctl.GetASCtx(context).Vmm;

            for (int index = 0; index < args.CmdBufsCount; index++)
            {
                long cmdBufOffset = inputPosition + 0x10 + index * 0xc;

                NvHostChannelCmdBuf cmdBuf = MemoryHelper.Read <NvHostChannelCmdBuf>(context.Memory, cmdBufOffset);

                NvMapHandle map = NvMapIoctl.GetNvMap(context, cmdBuf.MemoryId);

                int[] cmdBufData = new int[cmdBuf.WordsCount];

                for (int offset = 0; offset < cmdBufData.Length; offset++)
                {
                    cmdBufData[offset] = context.Memory.ReadInt32(map.Address + cmdBuf.Offset + offset * 4);
                }

                context.Device.Gpu.PushCommandBuffer(vmm, cmdBufData);
            }

            // TODO: Relocation, waitchecks, etc.

            return(NvResult.Success);
        }
コード例 #4
0
        private static int Remap(ServiceCtx context, int cmd)
        {
            int count = ((cmd >> 16) & 0xff) / 0x14;

            long inputPosition = context.Request.GetBufferType0x21().Position;

            for (int index = 0; index < count; index++, inputPosition += 0x14)
            {
                NvGpuASRemap args = MemoryHelper.Read <NvGpuASRemap>(context.Memory, inputPosition);

                NvGpuVmm vmm = GetASCtx(context).Vmm;

                NvMapHandle map = NvMapIoctl.GetNvMapWithFb(context, args.NvMapHandle);

                if (map == null)
                {
                    Logger.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{args.NvMapHandle:x8}!");

                    return(NvResult.InvalidInput);
                }

                long result = vmm.Map(map.Address, (long)(uint)args.Offset << 16,
                                      (long)(uint)args.Pages << 16);

                if (result < 0)
                {
                    Logger.PrintWarning(LogClass.ServiceNv,
                                        $"Page 0x{args.Offset:x16} size 0x{args.Pages:x16} not allocated!");

                    return(NvResult.InvalidInput);
                }
            }

            return(NvResult.Success);
        }
コード例 #5
0
        private static int Submit(ServiceCtx Context)
        {
            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

            NvHostChannelSubmit Args = MemoryHelper.Read <NvHostChannelSubmit>(Context.Memory, InputPosition);

            NvGpuVmm Vmm = NvGpuASIoctl.GetASCtx(Context).Vmm;

            for (int Index = 0; Index < Args.CmdBufsCount; Index++)
            {
                long CmdBufOffset = InputPosition + 0x10 + Index * 0xc;

                NvHostChannelCmdBuf CmdBuf = MemoryHelper.Read <NvHostChannelCmdBuf>(Context.Memory, CmdBufOffset);

                NvMapHandle Map = NvMapIoctl.GetNvMap(Context, CmdBuf.MemoryId);

                int[] CmdBufData = new int[CmdBuf.WordsCount];

                for (int Offset = 0; Offset < CmdBufData.Length; Offset++)
                {
                    CmdBufData[Offset] = Context.Memory.ReadInt32(Map.Address + CmdBuf.Offset + Offset * 4);
                }

                Context.Device.Gpu.PushCommandBuffer(Vmm, CmdBufData);
            }

            //TODO: Relocation, waitchecks, etc.

            return(NvResult.Success);
        }
コード例 #6
0
        private static int UnmapBuffer(ServiceCtx Context)
        {
            long InputPosition = Context.Request.GetBufferType0x21().Position;

            NvHostChannelMapBuffer Args = MemoryHelper.Read <NvHostChannelMapBuffer>(Context.Memory, InputPosition);

            NvGpuVmm Vmm = NvGpuASIoctl.GetASCtx(Context).Vmm;

            for (int Index = 0; Index < Args.NumEntries; Index++)
            {
                int Handle = Context.Memory.ReadInt32(InputPosition + 0xc + Index * 8);

                NvMapHandle Map = NvMapIoctl.GetNvMap(Context, Handle);

                if (Map == null)
                {
                    Logger.PrintWarning(LogClass.ServiceNv, $"Invalid handle 0x{Handle:x8}!");

                    return(NvResult.InvalidInput);
                }

                lock (Map)
                {
                    if (Map.DmaMapAddress != 0)
                    {
                        Vmm.Free(Map.DmaMapAddress, Map.Size);

                        Map.DmaMapAddress = 0;
                    }
                }
            }

            return(NvResult.Success);
        }
コード例 #7
0
        public static void UnloadProcess(Process Process)
        {
            Fds.DeleteProcess(Process);

            NvGpuASIoctl.UnloadProcess(Process);

            NvHostCtrlIoctl.UnloadProcess(Process);

            NvMapIoctl.UnloadProcess(Process);
        }
コード例 #8
0
        public long Initialize(ServiceCtx Context)
        {
            long TransferMemSize   = Context.RequestData.ReadInt64();
            int  TransferMemHandle = Context.Request.HandleDesc.ToCopy[0];

            NvMapIoctl.InitializeNvMap(Context);

            Context.ResponseData.Write(0);

            return(0);
        }
コード例 #9
0
ファイル: INvDrvServices.cs プロジェクト: woxihuanjia/Ryujinx
        // Initialize(u32 transfer_memory_size, handle<copy, process> current_process, handle<copy, transfer_memory> transfer_memory) -> u32 error_code
        public ResultCode Initialize(ServiceCtx context)
        {
            long transferMemSize   = context.RequestData.ReadInt64();
            int  transferMemHandle = context.Request.HandleDesc.ToCopy[0];

            NvMapIoctl.InitializeNvMap(context);

            context.ResponseData.Write(0);

            return(ResultCode.Success);
        }
コード例 #10
0
ファイル: INvDrvServices.cs プロジェクト: woxihuanjia/Ryujinx
        public static void UnloadProcess(KProcess process)
        {
            Fds.DeleteProcess(process);

            NvGpuASIoctl.UnloadProcess(process);

            NvHostChannelIoctl.UnloadProcess(process);

            NvHostCtrlIoctl.UnloadProcess(process);

            NvMapIoctl.UnloadProcess(process);
        }
コード例 #11
0
        private static int Remap(ServiceCtx Context)
        {
            long InputPosition = Context.Request.GetBufferType0x21().Position;

            NvGpuASRemap Args = AMemoryHelper.Read <NvGpuASRemap>(Context.Memory, InputPosition);

            NvGpuVmm Vmm = GetVmm(Context);

            NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

            if (Map == null)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            //FIXME: This is most likely wrong...
            Vmm.Map(Map.Address, (long)(uint)Args.Offset << 16,
                    (long)(uint)Args.Pages << 16);

            return(NvResult.Success);
        }
コード例 #12
0
        private static int MapBufferEx(ServiceCtx Context)
        {
            const string MapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!";

            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

            NvGpuASMapBufferEx Args = AMemoryHelper.Read <NvGpuASMapBufferEx>(Context.Memory, InputPosition);

            NvGpuASCtx ASCtx = GetASCtx(Context);

            NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

            if (Map == null)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            long PA;

            if ((Args.Flags & FlagRemapSubRange) != 0)
            {
                lock (ASCtx)
                {
                    if (ASCtx.TryGetMapPhysicalAddress(Args.Offset, out PA))
                    {
                        long VA = Args.Offset + Args.BufferOffset;

                        PA += Args.BufferOffset;

                        if (ASCtx.Vmm.Map(PA, VA, Args.MappingSize) < 0)
                        {
                            string Msg = string.Format(MapErrorMsg, VA, Args.MappingSize);

                            Context.Ns.Log.PrintWarning(LogClass.ServiceNv, Msg);

                            return(NvResult.InvalidInput);
                        }

                        return(NvResult.Success);
                    }
                    else
                    {
                        Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Address 0x{Args.Offset:x16} not mapped!");

                        return(NvResult.InvalidInput);
                    }
                }
            }

            PA = Map.Address + Args.BufferOffset;

            long Size = Args.MappingSize;

            if (Size == 0)
            {
                Size = (uint)Map.Size;
            }

            int Result = NvResult.Success;

            lock (ASCtx)
            {
                //Note: When the fixed offset flag is not set,
                //the Offset field holds the alignment size instead.
                bool VaAllocated = (Args.Flags & FlagFixedOffset) == 0;

                if (!VaAllocated)
                {
                    if (ASCtx.ValidateFixedBuffer(Args.Offset, Size))
                    {
                        Args.Offset = ASCtx.Vmm.Map(PA, Args.Offset, Size);
                    }
                    else
                    {
                        string Msg = string.Format(MapErrorMsg, Args.Offset, Size);

                        Context.Ns.Log.PrintWarning(LogClass.ServiceNv, Msg);

                        Result = NvResult.InvalidInput;
                    }
                }
                else
                {
                    Args.Offset = ASCtx.Vmm.Map(PA, Size);
                }

                if (Args.Offset < 0)
                {
                    Args.Offset = 0;

                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Failed to map size 0x{Size:x16}!");

                    Result = NvResult.InvalidInput;
                }
                else
                {
                    ASCtx.AddMap(Args.Offset, Size, PA, VaAllocated);
                }
            }

            AMemoryHelper.Write(Context.Memory, OutputPosition, Args);

            return(Result);
        }
コード例 #13
0
        private static int MapBufferEx(ServiceCtx Context)
        {
            long InputPosition  = Context.Request.GetBufferType0x21().Position;
            long OutputPosition = Context.Request.GetBufferType0x22().Position;

            NvGpuASMapBufferEx Args = AMemoryHelper.Read <NvGpuASMapBufferEx>(Context.Memory, InputPosition);

            NvGpuVmm Vmm = GetVmm(Context);

            NvMapHandle Map = NvMapIoctl.GetNvMapWithFb(Context, Args.NvMapHandle);

            if (Map == null)
            {
                Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{Args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            long PA = Map.Address + Args.BufferOffset;

            long Size = Args.MappingSize;

            if (Size == 0)
            {
                Size = (uint)Map.Size;
            }

            int Result = NvResult.Success;

            //Note: When the fixed offset flag is not set,
            //the Offset field holds the alignment size instead.
            if ((Args.Flags & FlagFixedOffset) != 0)
            {
                long MapEnd = Args.Offset + Args.MappingSize;

                if ((ulong)MapEnd <= (ulong)Args.Offset)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Offset 0x{Args.Offset:x16} and size 0x{Args.MappingSize:x16} results in a overflow!");

                    return(NvResult.InvalidInput);
                }

                if ((Args.Offset & NvGpuVmm.PageMask) != 0)
                {
                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"Offset 0x{Args.Offset:x16} is not page aligned!");

                    return(NvResult.InvalidInput);
                }

                Args.Offset = Vmm.Map(PA, Args.Offset, Size);
            }
            else
            {
                Args.Offset = Vmm.Map(PA, Size);

                if (Args.Offset < 0)
                {
                    Args.Offset = 0;

                    Context.Ns.Log.PrintWarning(LogClass.ServiceNv, $"No memory to map size {Args.MappingSize:x16}!");

                    Result = NvResult.InvalidInput;
                }
            }

            AMemoryHelper.Write(Context.Memory, OutputPosition, Args);

            return(Result);
        }
コード例 #14
0
        private static int MapBufferEx(ServiceCtx context)
        {
            const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!";

            long inputPosition  = context.Request.GetBufferType0x21().Position;
            long outputPosition = context.Request.GetBufferType0x22().Position;

            NvGpuASMapBufferEx args = MemoryHelper.Read <NvGpuASMapBufferEx>(context.Memory, inputPosition);

            NvGpuASCtx asCtx = GetASCtx(context);

            NvMapHandle map = NvMapIoctl.GetNvMapWithFb(context, args.NvMapHandle);

            if (map == null)
            {
                Logger.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{args.NvMapHandle:x8}!");

                return(NvResult.InvalidInput);
            }

            long pa;

            if ((args.Flags & FlagRemapSubRange) != 0)
            {
                lock (asCtx)
                {
                    if (asCtx.TryGetMapPhysicalAddress(args.Offset, out pa))
                    {
                        long va = args.Offset + args.BufferOffset;

                        pa += args.BufferOffset;

                        if (asCtx.Vmm.Map(pa, va, args.MappingSize) < 0)
                        {
                            string msg = string.Format(mapErrorMsg, va, args.MappingSize);

                            Logger.PrintWarning(LogClass.ServiceNv, msg);

                            return(NvResult.InvalidInput);
                        }

                        return(NvResult.Success);
                    }
                    else
                    {
                        Logger.PrintWarning(LogClass.ServiceNv, $"Address 0x{args.Offset:x16} not mapped!");

                        return(NvResult.InvalidInput);
                    }
                }
            }

            pa = map.Address + args.BufferOffset;

            long size = args.MappingSize;

            if (size == 0)
            {
                size = (uint)map.Size;
            }

            int result = NvResult.Success;

            lock (asCtx)
            {
                // Note: When the fixed offset flag is not set,
                // the Offset field holds the alignment size instead.
                bool vaAllocated = (args.Flags & FlagFixedOffset) == 0;

                if (!vaAllocated)
                {
                    if (asCtx.ValidateFixedBuffer(args.Offset, size))
                    {
                        args.Offset = asCtx.Vmm.Map(pa, args.Offset, size);
                    }
                    else
                    {
                        string msg = string.Format(mapErrorMsg, args.Offset, size);

                        Logger.PrintWarning(LogClass.ServiceNv, msg);

                        result = NvResult.InvalidInput;
                    }
                }
                else
                {
                    args.Offset = asCtx.Vmm.Map(pa, size);
                }

                if (args.Offset < 0)
                {
                    args.Offset = 0;

                    Logger.PrintWarning(LogClass.ServiceNv, $"Failed to map size 0x{size:x16}!");

                    result = NvResult.InvalidInput;
                }
                else
                {
                    asCtx.AddMap(args.Offset, size, pa, vaAllocated);
                }
            }

            MemoryHelper.Write(context.Memory, outputPosition, args);

            return(result);
        }