summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar VonChenPlus2022-06-27 12:39:57 +0800
committerGravatar Fernando Sahmkow2022-10-06 21:00:53 +0200
commit9982cff98b4db38565715cc515ea496b6195725b (patch)
tree08ac644dcb6d51b4deda281133fa31b40b7cc3d7
parentGeneral: Fix clang format. (diff)
downloadyuzu-9982cff98b4db38565715cc515ea496b6195725b.tar.gz
yuzu-9982cff98b4db38565715cc515ea496b6195725b.tar.xz
yuzu-9982cff98b4db38565715cc515ea496b6195725b.zip
Core: Fix get nvmap object random crash
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp15
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h5
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h3
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.cpp9
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.h8
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp10
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.h9
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp16
-rw-r--r--src/core/hle/service/vi/display/vi_display.h7
12 files changed, 66 insertions, 35 deletions
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index b02dbb9c9..dd30e156e 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -207,6 +207,19 @@ void NvMap::UnpinHandle(Handle::Id handle) {
207 } 207 }
208} 208}
209 209
210void NvMap::DuplicateHandle(Handle::Id handle) {
211 auto handle_description{GetHandle(handle)};
212 if (!handle_description) {
213 LOG_CRITICAL(Service_NVDRV, "Unregistered handle!");
214 return;
215 }
216
217 auto result = handle_description->Duplicate(false);
218 if (result != NvResult::Success) {
219 LOG_CRITICAL(Service_NVDRV, "Could not duplicate handle!");
220 }
221}
222
210std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) { 223std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
211 std::weak_ptr<Handle> hWeak{GetHandle(handle)}; 224 std::weak_ptr<Handle> hWeak{GetHandle(handle)};
212 FreeInfo freeInfo; 225 FreeInfo freeInfo;
@@ -254,7 +267,7 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
254 267
255 // Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed 268 // Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed
256 if (!hWeak.expired()) { 269 if (!hWeak.expired()) {
257 LOG_ERROR(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle); 270 LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
258 freeInfo.address = 0; 271 freeInfo.address = 0;
259 } 272 }
260 273
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h
index 1082bb58d..b6613a521 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.h
+++ b/src/core/hle/service/nvdrv/core/nvmap.h
@@ -163,6 +163,11 @@ public:
163 void UnpinHandle(Handle::Id handle); 163 void UnpinHandle(Handle::Id handle);
164 164
165 /** 165 /**
166 * @brief Tries to duplicate a handle
167 */
168 void DuplicateHandle(Handle::Id handle);
169
170 /**
166 * @brief Tries to free a handle and remove a single dupe 171 * @brief Tries to free a handle and remove a single dupe
167 * @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned 172 * @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned
168 * describing the prior state of the handle 173 * describing the prior state of the handle
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index f84fc8c37..ddf273b5e 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -69,18 +69,6 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
69void nvmap::OnOpen(DeviceFD fd) {} 69void nvmap::OnOpen(DeviceFD fd) {}
70void nvmap::OnClose(DeviceFD fd) {} 70void nvmap::OnClose(DeviceFD fd) {}
71 71
72VAddr nvmap::GetObjectAddress(u32 handle) const {
73 auto obj = file.GetHandle(handle);
74 if (obj) {
75 return obj->address;
76 }
77 return 0;
78}
79
80std::shared_ptr<NvCore::NvMap::Handle> nvmap::GetObject(u32 handle) const {
81 return file.GetHandle(handle);
82}
83
84NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { 72NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
85 IocCreateParams params; 73 IocCreateParams params;
86 std::memcpy(&params, input.data(), sizeof(params)); 74 std::memcpy(&params, input.data(), sizeof(params));
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index c22eb57a4..52e1d7cff 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -36,11 +36,6 @@ public:
36 void OnOpen(DeviceFD fd) override; 36 void OnOpen(DeviceFD fd) override;
37 void OnClose(DeviceFD fd) override; 37 void OnClose(DeviceFD fd) override;
38 38
39 /// Returns the allocated address of an nvmap object given its handle.
40 VAddr GetObjectAddress(u32 handle) const;
41
42 std::shared_ptr<NvCore::NvMap::Handle> GetObject(u32 handle) const;
43
44 enum class HandleParameterType : u32_le { 39 enum class HandleParameterType : u32_le {
45 Size = 1, 40 Size = 1,
46 Alignment = 2, 41 Alignment = 2,
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index b26254753..22836529d 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -96,6 +96,7 @@ public:
96 96
97private: 97private:
98 friend class EventInterface; 98 friend class EventInterface;
99 friend class Service::NVFlinger::NVFlinger;
99 100
100 /// Id to use for the next open file descriptor. 101 /// Id to use for the next open file descriptor.
101 DeviceFD next_fd = 1; 102 DeviceFD next_fd = 1;
@@ -111,8 +112,6 @@ private:
111 /// Manages syncpoints on the host 112 /// Manages syncpoints on the host
112 NvCore::Container container; 113 NvCore::Container container;
113 114
114 void CreateEvent(u32 event_id);
115 void FreeEvent(u32 event_id);
116 std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; 115 std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
117}; 116};
118 117
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
index 4b3d5efd6..a0330ab4a 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
@@ -5,15 +5,18 @@
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp 5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/service/nvdrv/core/nvmap.h"
8#include "core/hle/service/nvflinger/buffer_item.h" 9#include "core/hle/service/nvflinger/buffer_item.h"
9#include "core/hle/service/nvflinger/buffer_queue_consumer.h" 10#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
10#include "core/hle/service/nvflinger/buffer_queue_core.h" 11#include "core/hle/service/nvflinger/buffer_queue_core.h"
11#include "core/hle/service/nvflinger/producer_listener.h" 12#include "core/hle/service/nvflinger/producer_listener.h"
13#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
12 14
13namespace Service::android { 15namespace Service::android {
14 16
15BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_) 17BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
16 : core{std::move(core_)}, slots{core->slots} {} 18 Service::Nvidia::NvCore::NvMap& nvmap_)
19 : core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
17 20
18BufferQueueConsumer::~BufferQueueConsumer() = default; 21BufferQueueConsumer::~BufferQueueConsumer() = default;
19 22
@@ -133,6 +136,8 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
133 136
134 slots[slot].buffer_state = BufferState::Free; 137 slots[slot].buffer_state = BufferState::Free;
135 138
139 nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), false);
140
136 listener = core->connected_producer_listener; 141 listener = core->connected_producer_listener;
137 142
138 LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot); 143 LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.h b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
index b598c314f..4ec06ca13 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
@@ -13,6 +13,10 @@
13#include "core/hle/service/nvflinger/buffer_queue_defs.h" 13#include "core/hle/service/nvflinger/buffer_queue_defs.h"
14#include "core/hle/service/nvflinger/status.h" 14#include "core/hle/service/nvflinger/status.h"
15 15
16namespace Service::Nvidia::NvCore {
17class NvMap;
18} // namespace Service::Nvidia::NvCore
19
16namespace Service::android { 20namespace Service::android {
17 21
18class BufferItem; 22class BufferItem;
@@ -21,7 +25,8 @@ class IConsumerListener;
21 25
22class BufferQueueConsumer final { 26class BufferQueueConsumer final {
23public: 27public:
24 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); 28 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
29 Service::Nvidia::NvCore::NvMap& nvmap_);
25 ~BufferQueueConsumer(); 30 ~BufferQueueConsumer();
26 31
27 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); 32 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
@@ -32,6 +37,7 @@ public:
32private: 37private:
33 std::shared_ptr<BufferQueueCore> core; 38 std::shared_ptr<BufferQueueCore> core;
34 BufferQueueDefs::SlotsType& slots; 39 BufferQueueDefs::SlotsType& slots;
40 Service::Nvidia::NvCore::NvMap& nvmap;
35}; 41};
36 42
37} // namespace Service::android 43} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index 337431488..a4e46964c 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -14,7 +14,7 @@
14#include "core/hle/kernel/k_writable_event.h" 14#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
16#include "core/hle/service/kernel_helpers.h" 16#include "core/hle/service/kernel_helpers.h"
17#include "core/hle/service/nvdrv/nvdrv.h" 17#include "core/hle/service/nvdrv/core/nvmap.h"
18#include "core/hle/service/nvflinger/buffer_queue_core.h" 18#include "core/hle/service/nvflinger/buffer_queue_core.h"
19#include "core/hle/service/nvflinger/buffer_queue_producer.h" 19#include "core/hle/service/nvflinger/buffer_queue_producer.h"
20#include "core/hle/service/nvflinger/consumer_listener.h" 20#include "core/hle/service/nvflinger/consumer_listener.h"
@@ -26,8 +26,10 @@
26namespace Service::android { 26namespace Service::android {
27 27
28BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, 28BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
29 std::shared_ptr<BufferQueueCore> buffer_queue_core_) 29 std::shared_ptr<BufferQueueCore> buffer_queue_core_,
30 : service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots) { 30 Service::Nvidia::NvCore::NvMap& nvmap_)
31 : service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots),
32 nvmap(nvmap_) {
31 buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent"); 33 buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
32} 34}
33 35
@@ -530,6 +532,8 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
530 item.is_droppable = core->dequeue_buffer_cannot_block || async; 532 item.is_droppable = core->dequeue_buffer_cannot_block || async;
531 item.swap_interval = swap_interval; 533 item.swap_interval = swap_interval;
532 534
535 nvmap.DuplicateHandle(item.graphic_buffer->BufferId());
536
533 sticky_transform = sticky_transform_; 537 sticky_transform = sticky_transform_;
534 538
535 if (core->queue.empty()) { 539 if (core->queue.empty()) {
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h
index 42d4722dc..0ba03a568 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h
@@ -31,6 +31,10 @@ namespace Service::KernelHelpers {
31class ServiceContext; 31class ServiceContext;
32} // namespace Service::KernelHelpers 32} // namespace Service::KernelHelpers
33 33
34namespace Service::Nvidia::NvCore {
35class NvMap;
36} // namespace Service::Nvidia::NvCore
37
34namespace Service::android { 38namespace Service::android {
35 39
36class BufferQueueCore; 40class BufferQueueCore;
@@ -39,7 +43,8 @@ class IProducerListener;
39class BufferQueueProducer final : public IBinder { 43class BufferQueueProducer final : public IBinder {
40public: 44public:
41 explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, 45 explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
42 std::shared_ptr<BufferQueueCore> buffer_queue_core_); 46 std::shared_ptr<BufferQueueCore> buffer_queue_core_,
47 Service::Nvidia::NvCore::NvMap& nvmap_);
43 ~BufferQueueProducer(); 48 ~BufferQueueProducer();
44 49
45 void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override; 50 void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
@@ -78,6 +83,8 @@ private:
78 s32 next_callback_ticket{}; 83 s32 next_callback_ticket{};
79 s32 current_callback_ticket{}; 84 s32 current_callback_ticket{};
80 std::condition_variable_any callback_condition; 85 std::condition_variable_any callback_condition;
86
87 Service::Nvidia::NvCore::NvMap& nvmap;
81}; 88};
82 89
83} // namespace Service::android 90} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 4658f1e8b..aa14d2cbc 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -149,7 +149,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
149 149
150void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { 150void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
151 const auto buffer_id = next_buffer_queue_id++; 151 const auto buffer_id = next_buffer_queue_id++;
152 display.CreateLayer(layer_id, buffer_id); 152 display.CreateLayer(layer_id, buffer_id, nvdrv->container);
153} 153}
154 154
155void NVFlinger::CloseLayer(u64 layer_id) { 155void NVFlinger::CloseLayer(u64 layer_id) {
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index aa49aa775..288aafaaf 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/k_readable_event.h" 12#include "core/hle/kernel/k_readable_event.h"
13#include "core/hle/kernel/k_writable_event.h" 13#include "core/hle/kernel/k_writable_event.h"
14#include "core/hle/service/kernel_helpers.h" 14#include "core/hle/service/kernel_helpers.h"
15#include "core/hle/service/nvdrv/core/container.h"
15#include "core/hle/service/nvflinger/buffer_item_consumer.h" 16#include "core/hle/service/nvflinger/buffer_item_consumer.h"
16#include "core/hle/service/nvflinger/buffer_queue_consumer.h" 17#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
17#include "core/hle/service/nvflinger/buffer_queue_core.h" 18#include "core/hle/service/nvflinger/buffer_queue_core.h"
@@ -29,11 +30,13 @@ struct BufferQueue {
29 std::unique_ptr<android::BufferQueueConsumer> consumer; 30 std::unique_ptr<android::BufferQueueConsumer> consumer;
30}; 31};
31 32
32static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context) { 33static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
34 Service::Nvidia::NvCore::NvMap& nvmap) {
33 auto buffer_queue_core = std::make_shared<android::BufferQueueCore>(); 35 auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
34 return {buffer_queue_core, 36 return {
35 std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core), 37 buffer_queue_core,
36 std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; 38 std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
39 std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)};
37} 40}
38 41
39Display::Display(u64 id, std::string name_, 42Display::Display(u64 id, std::string name_,
@@ -74,10 +77,11 @@ void Display::SignalVSyncEvent() {
74 vsync_event->GetWritableEvent().Signal(); 77 vsync_event->GetWritableEvent().Signal();
75} 78}
76 79
77void Display::CreateLayer(u64 layer_id, u32 binder_id) { 80void Display::CreateLayer(u64 layer_id, u32 binder_id,
81 Service::Nvidia::NvCore::Container& nv_core) {
78 ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); 82 ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
79 83
80 auto [core, producer, consumer] = CreateBufferQueue(service_context); 84 auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
81 85
82 auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer)); 86 auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
83 buffer_item_consumer->Connect(false); 87 buffer_item_consumer->Connect(false);
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 8dbb0ef80..33d5f398c 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -27,6 +27,11 @@ namespace Service::NVFlinger {
27class HosBinderDriverServer; 27class HosBinderDriverServer;
28} 28}
29 29
30namespace Service::Nvidia::NvCore {
31class Container;
32class NvMap;
33} // namespace Service::Nvidia::NvCore
34
30namespace Service::VI { 35namespace Service::VI {
31 36
32class Layer; 37class Layer;
@@ -93,7 +98,7 @@ public:
93 /// @param layer_id The ID to assign to the created layer. 98 /// @param layer_id The ID to assign to the created layer.
94 /// @param binder_id The ID assigned to the buffer queue. 99 /// @param binder_id The ID assigned to the buffer queue.
95 /// 100 ///
96 void CreateLayer(u64 layer_id, u32 binder_id); 101 void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
97 102
98 /// Closes and removes a layer from this display with the given ID. 103 /// Closes and removes a layer from this display with the given ID.
99 /// 104 ///