summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar archshift2015-05-10 18:07:44 -0700
committerGravatar archshift2015-05-10 18:07:44 -0700
commite98fbadf4a49eecc6d39c082cba683d5d88ea2c5 (patch)
tree7901b6ad673f8950d4f36d731eaa45b195cac763 /src
parentMerge pull request #741 from Subv/tls (diff)
parentfixup! GSP: Small tweaks to shared memory initialization (diff)
downloadyuzu-e98fbadf4a49eecc6d39c082cba683d5d88ea2c5.tar.gz
yuzu-e98fbadf4a49eecc6d39c082cba683d5d88ea2c5.tar.xz
yuzu-e98fbadf4a49eecc6d39c082cba683d5d88ea2c5.zip
Merge pull request #740 from yuriks/gsp-shmem
Fix crashes due to un-initialized GSP shared memory
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/shared_memory.cpp28
-rw-r--r--src/core/hle/kernel/shared_memory.h25
-rw-r--r--src/core/hle/service/apt/apt.cpp4
-rw-r--r--src/core/hle/service/gsp_gpu.cpp30
-rw-r--r--src/core/hle/service/hid/hid.cpp6
-rw-r--r--src/core/hle/service/ir/ir.cpp4
-rw-r--r--src/core/hle/svc.cpp4
7 files changed, 67 insertions, 34 deletions
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index cb5c16696..0c59f4876 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6
5#include "common/logging/log.h" 7#include "common/logging/log.h"
6 8
7#include "core/mem_map.h" 9#include "core/mem_map.h"
@@ -12,11 +14,15 @@ namespace Kernel {
12SharedMemory::SharedMemory() {} 14SharedMemory::SharedMemory() {}
13SharedMemory::~SharedMemory() {} 15SharedMemory::~SharedMemory() {}
14 16
15SharedPtr<SharedMemory> SharedMemory::Create(std::string name) { 17SharedPtr<SharedMemory> SharedMemory::Create(u32 size, MemoryPermission permissions,
18 MemoryPermission other_permissions, std::string name) {
16 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 19 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
17 20
18 shared_memory->name = std::move(name); 21 shared_memory->name = std::move(name);
19 shared_memory->base_address = 0x0; 22 shared_memory->base_address = 0x0;
23 shared_memory->size = size;
24 shared_memory->permissions = permissions;
25 shared_memory->other_permissions = other_permissions;
20 26
21 return shared_memory; 27 return shared_memory;
22} 28}
@@ -24,7 +30,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(std::string name) {
24ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, 30ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
25 MemoryPermission other_permissions) { 31 MemoryPermission other_permissions) {
26 32
27 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 33 if (address < Memory::SHARED_MEMORY_VADDR || address + size >= Memory::SHARED_MEMORY_VADDR_END) {
28 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!", 34 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!",
29 GetObjectId(), address); 35 GetObjectId(), address);
30 // TODO: Verify error code with hardware 36 // TODO: Verify error code with hardware
@@ -32,21 +38,25 @@ ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
32 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 38 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
33 } 39 }
34 40
41 // TODO: Test permissions
42
43 // HACK: Since there's no way to write to the memory block without mapping it onto the game
44 // process yet, at least initialize memory the first time it's mapped.
45 if (address != this->base_address) {
46 std::memset(Memory::GetPointer(address), 0, size);
47 }
48
35 this->base_address = address; 49 this->base_address = address;
36 this->permissions = permissions;
37 this->other_permissions = other_permissions;
38 50
39 return RESULT_SUCCESS; 51 return RESULT_SUCCESS;
40} 52}
41 53
42ResultVal<u8*> SharedMemory::GetPointer(u32 offset) { 54u8* SharedMemory::GetPointer(u32 offset) {
43 if (base_address != 0) 55 if (base_address != 0)
44 return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); 56 return Memory::GetPointer(base_address + offset);
45 57
46 LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId()); 58 LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId());
47 // TODO(yuriks): Verify error code. 59 return nullptr;
48 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
49 ErrorSummary::InvalidState, ErrorLevel::Permanent);
50} 60}
51 61
52} // namespace 62} // namespace
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 5833b411c..204266896 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -27,11 +27,16 @@ class SharedMemory final : public Object {
27public: 27public:
28 /** 28 /**
29 * Creates a shared memory object 29 * Creates a shared memory object
30 * @param name Optional object name, used only for debugging purposes. 30 * @param size Size of the memory block. Must be page-aligned.
31 * @param permissions Permission restrictions applied to the process which created the block.
32 * @param other_permissions Permission restrictions applied to other processes mapping the block.
33 * @param name Optional object name, used for debugging purposes.
31 */ 34 */
32 static SharedPtr<SharedMemory> Create(std::string name = "Unknown"); 35 static SharedPtr<SharedMemory> Create(u32 size, MemoryPermission permissions,
36 MemoryPermission other_permissions, std::string name = "Unknown");
33 37
34 std::string GetTypeName() const override { return "SharedMemory"; } 38 std::string GetTypeName() const override { return "SharedMemory"; }
39 std::string GetName() const override { return name; }
35 40
36 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 41 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
37 HandleType GetHandleType() const override { return HANDLE_TYPE; } 42 HandleType GetHandleType() const override { return HANDLE_TYPE; }
@@ -49,12 +54,18 @@ public:
49 * @param offset Offset from the start of the shared memory block to get pointer 54 * @param offset Offset from the start of the shared memory block to get pointer
50 * @return Pointer to the shared memory block from the specified offset 55 * @return Pointer to the shared memory block from the specified offset
51 */ 56 */
52 ResultVal<u8*> GetPointer(u32 offset = 0); 57 u8* GetPointer(u32 offset = 0);
53 58
54 VAddr base_address; ///< Address of shared memory block in RAM 59 /// Address of shared memory block in the process.
55 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 60 VAddr base_address;
56 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field) 61 /// Size of the memory block. Page-aligned.
57 std::string name; ///< Name of shared memory object (optional) 62 u32 size;
63 /// Permission restrictions applied to the process which created the block.
64 MemoryPermission permissions;
65 /// Permission restrictions applied to other processes mapping the block.
66 MemoryPermission other_permissions;
67 /// Name of shared memory object.
68 std::string name;
58 69
59private: 70private:
60 SharedMemory(); 71 SharedMemory();
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 560c9dcf6..09d463dd5 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -304,7 +304,9 @@ void Init() {
304 file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); 304 file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
305 305
306 // Create shared font memory object 306 // Create shared font memory object
307 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem"); 307 using Kernel::MemoryPermission;
308 shared_font_mem = Kernel::SharedMemory::Create(3 * 1024 * 1024, // 3MB
309 MemoryPermission::ReadWrite, MemoryPermission::Read, "APT_U:shared_font_mem");
308 } else { 310 } else {
309 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); 311 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
310 shared_font_mem = nullptr; 312 shared_font_mem = nullptr;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 8da063bd2..c6252a03b 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -30,13 +30,12 @@ namespace GSP_GPU {
30Kernel::SharedPtr<Kernel::Event> g_interrupt_event; 30Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
31/// GSP shared memoryings 31/// GSP shared memoryings
32Kernel::SharedPtr<Kernel::SharedMemory> g_shared_memory; 32Kernel::SharedPtr<Kernel::SharedMemory> g_shared_memory;
33/// Thread index into interrupt relay queue, 1 is arbitrary 33/// Thread index into interrupt relay queue
34u32 g_thread_id = 1; 34u32 g_thread_id = 0;
35 35
36/// Gets a pointer to a thread command buffer in GSP shared memory 36/// Gets a pointer to a thread command buffer in GSP shared memory
37static inline u8* GetCommandBuffer(u32 thread_id) { 37static inline u8* GetCommandBuffer(u32 thread_id) {
38 ResultVal<u8*> ptr = g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer))); 38 return g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer)));
39 return ptr.ValueOr(nullptr);
40} 39}
41 40
42static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { 41static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) {
@@ -44,14 +43,14 @@ static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_in
44 43
45 // For each thread there are two FrameBufferUpdate fields 44 // For each thread there are two FrameBufferUpdate fields
46 u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); 45 u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate);
47 ResultVal<u8*> ptr = g_shared_memory->GetPointer(offset); 46 u8* ptr = g_shared_memory->GetPointer(offset);
48 return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr)); 47 return reinterpret_cast<FrameBufferUpdate*>(ptr);
49} 48}
50 49
51/// Gets a pointer to the interrupt relay queue for a given thread index 50/// Gets a pointer to the interrupt relay queue for a given thread index
52static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { 51static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
53 ResultVal<u8*> ptr = g_shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id); 52 u8* ptr = g_shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id);
54 return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); 53 return reinterpret_cast<InterruptRelayQueue*>(ptr);
55} 54}
56 55
57/** 56/**
@@ -278,7 +277,7 @@ static void FlushDataCache(Service::Interface* self) {
278 * 1 : "Flags" field, purpose is unknown 277 * 1 : "Flags" field, purpose is unknown
279 * 3 : Handle to GSP synchronization event 278 * 3 : Handle to GSP synchronization event
280 * Outputs: 279 * Outputs:
281 * 0 : Result of function, 0 on success, otherwise error code 280 * 1 : Result of function, 0x2A07 on success, otherwise error code
282 * 2 : Thread index into GSP command buffer 281 * 2 : Thread index into GSP command buffer
283 * 4 : Handle to GSP shared memory 282 * 4 : Handle to GSP shared memory
284 */ 283 */
@@ -288,11 +287,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
288 287
289 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]); 288 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
290 ASSERT_MSG((g_interrupt_event != nullptr), "handle is not valid!"); 289 ASSERT_MSG((g_interrupt_event != nullptr), "handle is not valid!");
291 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem");
292 290
293 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); 291 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
294 292
295 cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init 293 // This specific code is required for a successful initialization, rather than 0
294 cmd_buff[1] = ResultCode((ErrorDescription)519, ErrorModule::GX,
295 ErrorSummary::Success, ErrorLevel::Success).raw;
296 cmd_buff[2] = g_thread_id++; // Thread ID 296 cmd_buff[2] = g_thread_id++; // Thread ID
297 cmd_buff[4] = shmem_handle; // GSP shared memory 297 cmd_buff[4] = shmem_handle; // GSP shared memory
298 298
@@ -527,8 +527,12 @@ Interface::Interface() {
527 Register(FunctionTable); 527 Register(FunctionTable);
528 528
529 g_interrupt_event = 0; 529 g_interrupt_event = 0;
530 g_shared_memory = 0; 530
531 g_thread_id = 1; 531 using Kernel::MemoryPermission;
532 g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite,
533 MemoryPermission::ReadWrite, "GSPSharedMem");
534
535 g_thread_id = 0;
532} 536}
533 537
534} // namespace 538} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index dd85848d0..9695f7e56 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -48,7 +48,7 @@ static u32 next_touch_index;
48// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41 48// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41
49 49
50void Update() { 50void Update() {
51 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer().ValueOr(nullptr)); 51 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
52 const PadState state = VideoCore::g_emu_window->GetPadState(); 52 const PadState state = VideoCore::g_emu_window->GetPadState();
53 53
54 if (mem == nullptr) { 54 if (mem == nullptr) {
@@ -163,7 +163,9 @@ void Init() {
163 AddService(new HID_U_Interface); 163 AddService(new HID_U_Interface);
164 AddService(new HID_SPVR_Interface); 164 AddService(new HID_SPVR_Interface);
165 165
166 shared_mem = SharedMemory::Create("HID:SharedMem"); 166 using Kernel::MemoryPermission;
167 shared_mem = SharedMemory::Create(0x1000, MemoryPermission::ReadWrite,
168 MemoryPermission::Read, "HID:SharedMem");
167 169
168 next_pad_index = 0; 170 next_pad_index = 0;
169 next_touch_index = 0; 171 next_touch_index = 0;
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index 15ac477ef..adfbb258d 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -34,7 +34,9 @@ void Init() {
34 AddService(new IR_U_Interface); 34 AddService(new IR_U_Interface);
35 AddService(new IR_User_Interface); 35 AddService(new IR_User_Interface);
36 36
37 shared_memory = SharedMemory::Create("IR:SharedMemory"); 37 using Kernel::MemoryPermission;
38 shared_memory = SharedMemory::Create(0x1000, Kernel::MemoryPermission::ReadWrite,
39 Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory");
38 40
39 // Create event handle(s) 41 // Create event handle(s)
40 handle_event = Event::Create(RESETTYPE_ONESHOT, "IR:HandleEvent"); 42 handle_event = Event::Create(RESETTYPE_ONESHOT, "IR:HandleEvent");
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 393cfbe79..1ec6599c7 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -601,7 +601,9 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
601 using Kernel::SharedMemory; 601 using Kernel::SharedMemory;
602 // TODO(Subv): Implement this function 602 // TODO(Subv): Implement this function
603 603
604 SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(); 604 using Kernel::MemoryPermission;
605 SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(size,
606 (MemoryPermission)my_permission, (MemoryPermission)other_permission);
605 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 607 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
606 608
607 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 609 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);