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 a6db1eb395..cf6e95fe44 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 f32651d49a..eec74bfde7 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 53728a66d6..ab341a6bf1 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 44b81a0fd5..db8247a2aa 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 ec4f55c0d4..432a405c61 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 8ed79ebca7..6e6d0e5859 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 805cc6c919..e42b265dfc 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 33e4fc0ff3..7b7849afdb 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 750a208496..0de0555c0b 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 869a3602d5..f55d6ed0e2 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 64dc4703b1..515572a10b 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 b2c24bd17d..ce95947510 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"); }