From cfa9a322c723619c60e12d4630044ee79fea5718 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 10 Nov 2018 11:14:29 -0500 Subject: [PATCH 1/2] Kernel/SharedMemory: set and reset source memory state --- src/core/hle/kernel/kernel.h | 12 ++++++------ src/core/hle/kernel/shared_memory.cpp | 21 ++++++++++++++------- src/core/hle/kernel/svc.cpp | 7 ++++--- src/core/hle/service/apt/apt.cpp | 9 +++++---- src/core/hle/service/csnd/csnd_snd.cpp | 8 +++++--- src/core/hle/service/gsp/gsp_gpu.cpp | 8 +++++--- src/core/hle/service/hid/hid.cpp | 8 +++++--- src/core/hle/service/ir/ir_rst.cpp | 8 +++++--- 8 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index a6db1eb39..cf6e95fe4 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -170,12 +170,12 @@ public: * linear heap. * @param name Optional object name, used for debugging purposes. */ - SharedPtr CreateSharedMemory(Process* owner_process, u32 size, - MemoryPermission permissions, - MemoryPermission other_permissions, - VAddr address = 0, - MemoryRegion region = MemoryRegion::BASE, - std::string name = "Unknown"); + ResultVal> CreateSharedMemory(Process* owner_process, u32 size, + MemoryPermission permissions, + MemoryPermission other_permissions, + VAddr address = 0, + MemoryRegion region = MemoryRegion::BASE, + std::string name = "Unknown"); /** * Creates a shared memory object from a block of memory managed by an HLE applet. diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index f32651d49..eec74bfde 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -17,13 +17,16 @@ SharedMemory::~SharedMemory() { kernel.GetMemoryRegion(MemoryRegion::SYSTEM) ->Free(interval.lower(), interval.upper() - interval.lower()); } + if (base_address != 0 && owner_process != nullptr) { + owner_process->vm_manager.ChangeMemoryState(base_address, size, MemoryState::Locked, + VMAPermission::None, MemoryState::Private, + VMAPermission::ReadWrite); + } } -SharedPtr KernelSystem::CreateSharedMemory(Process* owner_process, u32 size, - MemoryPermission permissions, - MemoryPermission other_permissions, - VAddr address, MemoryRegion region, - std::string name) { +ResultVal> KernelSystem::CreateSharedMemory( + Process* owner_process, u32 size, MemoryPermission permissions, + MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { SharedPtr shared_memory(new SharedMemory(*this)); shared_memory->owner_process = owner_process; @@ -53,13 +56,17 @@ SharedPtr KernelSystem::CreateSharedMemory(Process* owner_process, auto& vm_manager = shared_memory->owner_process->vm_manager; // The memory is already available and mapped in the owner process. + CASCADE_CODE(vm_manager.ChangeMemoryState(address, size, MemoryState::Private, + VMAPermission::ReadWrite, MemoryState::Locked, + SharedMemory::ConvertPermissions(permissions))); + auto backing_blocks = vm_manager.GetBackingBlocksForRange(address, size); - ASSERT_MSG(backing_blocks.Succeeded(), "Trying to share freed memory"); + ASSERT(backing_blocks.Succeeded()); // should success after verifying memory state above shared_memory->backing_blocks = std::move(backing_blocks).Unwrap(); } shared_memory->base_address = address; - return shared_memory; + return MakeResult(shared_memory); } SharedPtr KernelSystem::CreateSharedMemoryForApplet( diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 53728a66d..ab341a6bf 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1250,9 +1250,10 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my if (addr == 0 && current_process->flags.shared_device_mem) region = current_process->flags.memory_region; - shared_memory = kernel.CreateSharedMemory( - current_process.get(), size, static_cast(my_permission), - static_cast(other_permission), addr, region); + CASCADE_RESULT(shared_memory, + kernel.CreateSharedMemory( + current_process.get(), size, static_cast(my_permission), + static_cast(other_permission), addr, region)); CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory))); LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr); diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 44b81a0fd..db8247a2a 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -861,10 +861,11 @@ Module::Module(Core::System& system) : system(system) { applet_manager = std::make_shared(system); using Kernel::MemoryPermission; - shared_font_mem = - system.Kernel().CreateSharedMemory(nullptr, 0x332000, // 3272 KB - MemoryPermission::ReadWrite, MemoryPermission::Read, 0, - Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); + shared_font_mem = system.Kernel() + .CreateSharedMemory(nullptr, 0x332000, // 3272 KB + MemoryPermission::ReadWrite, MemoryPermission::Read, + 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont") + .Unwrap(); lock = system.Kernel().CreateMutex(false, "APT_U:Lock"); } diff --git a/src/core/hle/service/csnd/csnd_snd.cpp b/src/core/hle/service/csnd/csnd_snd.cpp index ec4f55c0d..432a405c6 100644 --- a/src/core/hle/service/csnd/csnd_snd.cpp +++ b/src/core/hle/service/csnd/csnd_snd.cpp @@ -20,9 +20,11 @@ void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) { using Kernel::MemoryPermission; mutex = system.Kernel().CreateMutex(false, "CSND:mutex"); - shared_memory = system.Kernel().CreateSharedMemory( - nullptr, size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, - Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); + shared_memory = system.Kernel() + .CreateSharedMemory(nullptr, size, MemoryPermission::ReadWrite, + MemoryPermission::ReadWrite, 0, + Kernel::MemoryRegion::BASE, "CSND:SharedMemory") + .Unwrap(); IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 8ed79ebca..6e6d0e585 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -787,9 +787,11 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 2), system RegisterHandlers(functions); using Kernel::MemoryPermission; - shared_memory = system.Kernel().CreateSharedMemory( - nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0, - Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); + shared_memory = system.Kernel() + .CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite, + MemoryPermission::ReadWrite, 0, + Kernel::MemoryRegion::BASE, "GSP:SharedMemory") + .Unwrap(); first_initialization = true; }; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 805cc6c91..e42b265df 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -361,9 +361,11 @@ std::shared_ptr Module::Interface::GetModule() const { Module::Module(Core::System& system) : system(system) { using namespace Kernel; - shared_mem = system.Kernel().CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite, - MemoryPermission::Read, 0, MemoryRegion::BASE, - "HID:SharedMemory"); + shared_mem = + system.Kernel() + .CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite, + MemoryPermission::Read, 0, MemoryRegion::BASE, "HID:SharedMemory") + .Unwrap(); // Create event handles event_pad_or_touch_1 = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventPadOrTouch1"); diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp index 33e4fc0ff..7b7849afd 100644 --- a/src/core/hle/service/ir/ir_rst.cpp +++ b/src/core/hle/service/ir/ir_rst.cpp @@ -149,9 +149,11 @@ IR_RST::IR_RST(Core::System& system) : ServiceFramework("ir:rst", 1), system(sys using namespace Kernel; // Note: these two kernel objects are even available before Initialize service function is // called. - shared_memory = system.Kernel().CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite, - MemoryPermission::Read, 0, - MemoryRegion::BASE, "IRRST:SharedMemory"); + shared_memory = + system.Kernel() + .CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite, + MemoryPermission::Read, 0, MemoryRegion::BASE, "IRRST:SharedMemory") + .Unwrap(); update_event = system.Kernel().CreateEvent(ResetType::OneShot, "IRRST:UpdateEvent"); update_callback_id = system.CoreTiming().RegisterEvent( From d90094e8a722b9e35bda2fef33670b02345b7dd6 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 10 Nov 2018 11:27:15 -0500 Subject: [PATCH 2/2] Service: release shared memory object when finalize Since last commit SharedMemory only reset source memory set on dtor, service should always release the ref as soon as possible to make the reset happen --- src/core/hle/applets/swkbd.cpp | 1 + src/core/hle/service/http_c.cpp | 13 ++++++++++++- src/core/hle/service/http_c.h | 7 +++++++ src/core/hle/service/mic_u.cpp | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 750a20849..0de0555c0 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -136,6 +136,7 @@ void SoftwareKeyboard::Finalize() { SendParameter(message); is_running = false; + text_memory = nullptr; } Frontend::KeyboardConfig SoftwareKeyboard::ToFrontendConfig( diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 869a3602d..f55d6ed0e 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -443,6 +443,17 @@ void HTTP_C::CloseClientCertContext(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HTTP, "called, cert_handle={}", cert_handle); } +void HTTP_C::Finalize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x39, 0, 0); + + shared_memory = nullptr; + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_HTTP, "(STUBBED) called"); +} + void HTTP_C::DecryptClCertA() { static constexpr u32 iv_length = 16; @@ -575,7 +586,7 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) { {0x00360000, nullptr, "ClearDNSCache"}, {0x00370080, nullptr, "SetKeepAlive"}, {0x003800C0, nullptr, "SetPostDataTypeSize"}, - {0x00390000, nullptr, "Finalize"}, + {0x00390000, &HTTP_C::Finalize, "Finalize"}, }; RegisterHandlers(functions); diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h index 64dc4703b..515572a10 100644 --- a/src/core/hle/service/http_c.h +++ b/src/core/hle/service/http_c.h @@ -240,6 +240,13 @@ private: */ void CloseClientCertContext(Kernel::HLERequestContext& ctx); + /** + * HTTP_C::Finalize service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void Finalize(Kernel::HLERequestContext& ctx); + void DecryptClCertA(); Kernel::SharedPtr shared_memory = nullptr; diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index b2c24bd17..ce9594751 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp @@ -52,6 +52,7 @@ struct MIC_U::Impl { void UnmapSharedMem(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx, 0x02, 0, 0}; IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + shared_memory = nullptr; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_MIC, "called"); }