diff options
| author | 2018-04-23 15:23:55 -0400 | |
|---|---|---|
| committer | 2018-04-23 15:23:55 -0400 | |
| commit | bf25299272b210c11e68036e2e8b22f25256429b (patch) | |
| tree | ca070bc9b2493d4291a1c556eb82d600a4cd8334 /src/core | |
| parent | Merge pull request #385 from Subv/unimpl_ioctls (diff) | |
| parent | NvDrv/nvhost-as-gpu: Ensure that the object passed to MapBufferEx has already... (diff) | |
| download | yuzu-bf25299272b210c11e68036e2e8b22f25256429b.tar.gz yuzu-bf25299272b210c11e68036e2e8b22f25256429b.tar.xz yuzu-bf25299272b210c11e68036e2e8b22f25256429b.zip | |
Merge pull request #384 from Subv/nvhost-remap
Nvdrv/nvhost-as-gpu: Implemented the ioctl REMAP command.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 45 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 12 |
2 files changed, 57 insertions, 0 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 71e844959..8e7ca6123 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -27,6 +27,11 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto | |||
| 27 | case IoctlCommand::IocGetVaRegionsCommand: | 27 | case IoctlCommand::IocGetVaRegionsCommand: |
| 28 | return GetVARegions(input, output); | 28 | return GetVARegions(input, output); |
| 29 | } | 29 | } |
| 30 | |||
| 31 | if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand) | ||
| 32 | return Remap(input, output); | ||
| 33 | |||
| 34 | UNIMPLEMENTED_MSG("Unimplemented ioctl command"); | ||
| 30 | return 0; | 35 | return 0; |
| 31 | } | 36 | } |
| 32 | 37 | ||
| @@ -56,6 +61,36 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& | |||
| 56 | return 0; | 61 | return 0; |
| 57 | } | 62 | } |
| 58 | 63 | ||
| 64 | u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 65 | size_t num_entries = input.size() / sizeof(IoctlRemapEntry); | ||
| 66 | |||
| 67 | NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, num_entries=0x{:X}", num_entries); | ||
| 68 | |||
| 69 | std::vector<IoctlRemapEntry> entries(num_entries); | ||
| 70 | std::memcpy(entries.data(), input.data(), input.size()); | ||
| 71 | |||
| 72 | auto& gpu = Core::System::GetInstance().GPU(); | ||
| 73 | |||
| 74 | for (const auto& entry : entries) { | ||
| 75 | NGLOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}", | ||
| 76 | entry.offset, entry.nvmap_handle, entry.pages); | ||
| 77 | Tegra::GPUVAddr offset = static_cast<Tegra::GPUVAddr>(entry.offset) << 0x10; | ||
| 78 | |||
| 79 | auto object = nvmap_dev->GetObject(entry.nvmap_handle); | ||
| 80 | ASSERT(object); | ||
| 81 | |||
| 82 | ASSERT(object->status == nvmap::Object::Status::Allocated); | ||
| 83 | |||
| 84 | u64 size = static_cast<u64>(entry.pages) << 0x10; | ||
| 85 | ASSERT(size <= object->size); | ||
| 86 | |||
| 87 | Tegra::GPUVAddr returned = gpu.memory_manager->MapBufferEx(object->addr, offset, size); | ||
| 88 | ASSERT(returned == offset); | ||
| 89 | } | ||
| 90 | std::memcpy(output.data(), entries.data(), output.size()); | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 59 | u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | 94 | u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { |
| 60 | IoctlMapBufferEx params{}; | 95 | IoctlMapBufferEx params{}; |
| 61 | std::memcpy(¶ms, input.data(), input.size()); | 96 | std::memcpy(¶ms, input.data(), input.size()); |
| @@ -73,6 +108,16 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 73 | auto object = nvmap_dev->GetObject(params.nvmap_handle); | 108 | auto object = nvmap_dev->GetObject(params.nvmap_handle); |
| 74 | ASSERT(object); | 109 | ASSERT(object); |
| 75 | 110 | ||
| 111 | // We can only map objects that have already been assigned a CPU address. | ||
| 112 | ASSERT(object->status == nvmap::Object::Status::Allocated); | ||
| 113 | |||
| 114 | ASSERT(params.buffer_offset == 0); | ||
| 115 | |||
| 116 | // The real nvservices doesn't make a distinction between handles and ids, and | ||
| 117 | // object can only have one handle and it will be the same as its id. Assert that this is the | ||
| 118 | // case to prevent unexpected behavior. | ||
| 119 | ASSERT(object->id == params.nvmap_handle); | ||
| 120 | |||
| 76 | auto& gpu = Core::System::GetInstance().GPU(); | 121 | auto& gpu = Core::System::GetInstance().GPU(); |
| 77 | 122 | ||
| 78 | if (params.flags & 1) { | 123 | if (params.flags & 1) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index d86c3ebd9..f2dd0c3b3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -26,6 +26,7 @@ private: | |||
| 26 | enum class IoctlCommand : u32_le { | 26 | enum class IoctlCommand : u32_le { |
| 27 | IocInitalizeExCommand = 0x40284109, | 27 | IocInitalizeExCommand = 0x40284109, |
| 28 | IocAllocateSpaceCommand = 0xC0184102, | 28 | IocAllocateSpaceCommand = 0xC0184102, |
| 29 | IocRemapCommand = 0x00000014, | ||
| 29 | IocMapBufferExCommand = 0xC0284106, | 30 | IocMapBufferExCommand = 0xC0284106, |
| 30 | IocBindChannelCommand = 0x40044101, | 31 | IocBindChannelCommand = 0x40044101, |
| 31 | IocGetVaRegionsCommand = 0xC0404108, | 32 | IocGetVaRegionsCommand = 0xC0404108, |
| @@ -54,6 +55,16 @@ private: | |||
| 54 | }; | 55 | }; |
| 55 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); | 56 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); |
| 56 | 57 | ||
| 58 | struct IoctlRemapEntry { | ||
| 59 | u16_le flags; | ||
| 60 | u16_le kind; | ||
| 61 | u32_le nvmap_handle; | ||
| 62 | INSERT_PADDING_WORDS(1); | ||
| 63 | u32_le offset; | ||
| 64 | u32_le pages; | ||
| 65 | }; | ||
| 66 | static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size"); | ||
| 67 | |||
| 57 | struct IoctlMapBufferEx { | 68 | struct IoctlMapBufferEx { |
| 58 | u32_le flags; // bit0: fixed_offset, bit2: cacheable | 69 | u32_le flags; // bit0: fixed_offset, bit2: cacheable |
| 59 | u32_le kind; // -1 is default | 70 | u32_le kind; // -1 is default |
| @@ -91,6 +102,7 @@ private: | |||
| 91 | 102 | ||
| 92 | u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); | 103 | u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); |
| 93 | u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); | 104 | u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); |
| 105 | u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 94 | u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | 106 | u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); |
| 95 | u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); | 107 | u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); |
| 96 | u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); | 108 | u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); |