Merge pull request #9496 from liamwhite/shm3
kernel: workaround static shared memory initialization
This commit is contained in:
		| @@ -6,6 +6,7 @@ | |||||||
| #include "core/hle/kernel/k_page_table.h" | #include "core/hle/kernel/k_page_table.h" | ||||||
| #include "core/hle/kernel/k_scoped_resource_reservation.h" | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||||||
| #include "core/hle/kernel/k_shared_memory.h" | #include "core/hle/kernel/k_shared_memory.h" | ||||||
|  | #include "core/hle/kernel/k_system_resource.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/svc_results.h" | #include "core/hle/kernel/svc_results.h" | ||||||
|  |  | ||||||
| @@ -18,19 +19,19 @@ KSharedMemory::~KSharedMemory() { | |||||||
| } | } | ||||||
|  |  | ||||||
| Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | ||||||
|                                  KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_, |                                  Svc::MemoryPermission owner_permission_, | ||||||
|                                  Svc::MemoryPermission user_permission_, PAddr physical_address_, |                                  Svc::MemoryPermission user_permission_, std::size_t size_, | ||||||
|                                  std::size_t size_, std::string name_) { |                                  std::string name_) { | ||||||
|     // Set members. |     // Set members. | ||||||
|     owner_process = owner_process_; |     owner_process = owner_process_; | ||||||
|     device_memory = &device_memory_; |     device_memory = &device_memory_; | ||||||
|     page_list = std::move(page_list_); |  | ||||||
|     owner_permission = owner_permission_; |     owner_permission = owner_permission_; | ||||||
|     user_permission = user_permission_; |     user_permission = user_permission_; | ||||||
|     physical_address = physical_address_; |     size = Common::AlignUp(size_, PageSize); | ||||||
|     size = size_; |  | ||||||
|     name = std::move(name_); |     name = std::move(name_); | ||||||
|  |  | ||||||
|  |     const size_t num_pages = Common::DivideUp(size, PageSize); | ||||||
|  |  | ||||||
|     // Get the resource limit. |     // Get the resource limit. | ||||||
|     KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); |     KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); | ||||||
|  |  | ||||||
| @@ -39,6 +40,17 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o | |||||||
|                                                   size_); |                                                   size_); | ||||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||||
|  |  | ||||||
|  |     // Allocate the memory. | ||||||
|  |  | ||||||
|  |     //! HACK: Open continuous mapping from sysmodule pool. | ||||||
|  |     auto option = KMemoryManager::EncodeOption(KMemoryManager::Pool::Secure, | ||||||
|  |                                                KMemoryManager::Direction::FromBack); | ||||||
|  |     physical_address = kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); | ||||||
|  |     R_UNLESS(physical_address != 0, ResultOutOfMemory); | ||||||
|  |  | ||||||
|  |     //! Insert the result into our page group. | ||||||
|  |     page_group.emplace(physical_address, num_pages); | ||||||
|  |  | ||||||
|     // Commit our reservation. |     // Commit our reservation. | ||||||
|     memory_reservation.Commit(); |     memory_reservation.Commit(); | ||||||
|  |  | ||||||
| @@ -50,12 +62,23 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o | |||||||
|     is_initialized = true; |     is_initialized = true; | ||||||
|  |  | ||||||
|     // Clear all pages in the memory. |     // Clear all pages in the memory. | ||||||
|     std::memset(device_memory_.GetPointer<void>(physical_address_), 0, size_); |     for (const auto& block : page_group->Nodes()) { | ||||||
|  |         std::memset(device_memory_.GetPointer<void>(block.GetAddress()), 0, block.GetSize()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
| void KSharedMemory::Finalize() { | void KSharedMemory::Finalize() { | ||||||
|  |     // Close and finalize the page group. | ||||||
|  |     // page_group->Close(); | ||||||
|  |     // page_group->Finalize(); | ||||||
|  |  | ||||||
|  |     //! HACK: Manually close. | ||||||
|  |     for (const auto& block : page_group->Nodes()) { | ||||||
|  |         kernel.MemoryManager().Close(block.GetAddress(), block.GetNumPages()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Release the memory reservation. |     // Release the memory reservation. | ||||||
|     resource_limit->Release(LimitableResource::PhysicalMemoryMax, size); |     resource_limit->Release(LimitableResource::PhysicalMemoryMax, size); | ||||||
|     resource_limit->Close(); |     resource_limit->Close(); | ||||||
| @@ -65,32 +88,28 @@ void KSharedMemory::Finalize() { | |||||||
| } | } | ||||||
|  |  | ||||||
| Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, | Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, | ||||||
|                           Svc::MemoryPermission permissions) { |                           Svc::MemoryPermission map_perm) { | ||||||
|     const u64 page_count{(map_size + PageSize - 1) / PageSize}; |     // Validate the size. | ||||||
|  |     R_UNLESS(size == map_size, ResultInvalidSize); | ||||||
|  |  | ||||||
|     if (page_list.GetNumPages() != page_count) { |     // Validate the permission. | ||||||
|         UNIMPLEMENTED_MSG("Page count does not match"); |     const Svc::MemoryPermission test_perm = | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const Svc::MemoryPermission expected = |  | ||||||
|         &target_process == owner_process ? owner_permission : user_permission; |         &target_process == owner_process ? owner_permission : user_permission; | ||||||
|  |     if (test_perm == Svc::MemoryPermission::DontCare) { | ||||||
|     if (permissions != expected) { |         ASSERT(map_perm == Svc::MemoryPermission::Read || map_perm == Svc::MemoryPermission::Write); | ||||||
|         UNIMPLEMENTED_MSG("Permission does not match"); |     } else { | ||||||
|  |         R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared, |     return target_process.PageTable().MapPages(address, *page_group, KMemoryState::Shared, | ||||||
|                                                ConvertToKMemoryPermission(permissions)); |                                                ConvertToKMemoryPermission(map_perm)); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { | Result KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { | ||||||
|     const u64 page_count{(unmap_size + PageSize - 1) / PageSize}; |     // Validate the size. | ||||||
|  |     R_UNLESS(size == unmap_size, ResultInvalidSize); | ||||||
|  |  | ||||||
|     if (page_list.GetNumPages() != page_count) { |     return target_process.PageTable().UnmapPages(address, *page_group, KMemoryState::Shared); | ||||||
|         UNIMPLEMENTED_MSG("Page count does not match"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return target_process.PageTable().UnmapPages(address, page_list, KMemoryState::Shared); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Kernel | } // namespace Kernel | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <optional> | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| @@ -26,9 +27,8 @@ public: | |||||||
|     ~KSharedMemory() override; |     ~KSharedMemory() override; | ||||||
|  |  | ||||||
|     Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, |     Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | ||||||
|                       KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_, |                       Svc::MemoryPermission owner_permission_, | ||||||
|                       Svc::MemoryPermission user_permission_, PAddr physical_address_, |                       Svc::MemoryPermission user_permission_, std::size_t size_, std::string name_); | ||||||
|                       std::size_t size_, std::string name_); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Maps a shared memory block to an address in the target process' address space |      * Maps a shared memory block to an address in the target process' address space | ||||||
| @@ -76,7 +76,7 @@ public: | |||||||
| private: | private: | ||||||
|     Core::DeviceMemory* device_memory{}; |     Core::DeviceMemory* device_memory{}; | ||||||
|     KProcess* owner_process{}; |     KProcess* owner_process{}; | ||||||
|     KPageGroup page_list; |     std::optional<KPageGroup> page_group{}; | ||||||
|     Svc::MemoryPermission owner_permission{}; |     Svc::MemoryPermission owner_permission{}; | ||||||
|     Svc::MemoryPermission user_permission{}; |     Svc::MemoryPermission user_permission{}; | ||||||
|     PAddr physical_address{}; |     PAddr physical_address{}; | ||||||
|   | |||||||
| @@ -94,6 +94,7 @@ struct KernelCore::Impl { | |||||||
|                                        pt_heap_region.GetSize()); |                                        pt_heap_region.GetSize()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         InitializeHackSharedMemory(); | ||||||
|         RegisterHostThread(nullptr); |         RegisterHostThread(nullptr); | ||||||
|  |  | ||||||
|         default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); |         default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); | ||||||
| @@ -726,14 +727,14 @@ struct KernelCore::Impl { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void InitializeMemoryLayout() { |     void InitializeMemoryLayout() { | ||||||
|         const auto system_pool = memory_layout->GetKernelSystemPoolRegionPhysicalExtents(); |  | ||||||
|  |  | ||||||
|         // Initialize the memory manager. |         // Initialize the memory manager. | ||||||
|         memory_manager = std::make_unique<KMemoryManager>(system); |         memory_manager = std::make_unique<KMemoryManager>(system); | ||||||
|         const auto& management_region = memory_layout->GetPoolManagementRegion(); |         const auto& management_region = memory_layout->GetPoolManagementRegion(); | ||||||
|         ASSERT(management_region.GetEndAddress() != 0); |         ASSERT(management_region.GetEndAddress() != 0); | ||||||
|         memory_manager->Initialize(management_region.GetAddress(), management_region.GetSize()); |         memory_manager->Initialize(management_region.GetAddress(), management_region.GetSize()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void InitializeHackSharedMemory() { | ||||||
|         // Setup memory regions for emulated processes |         // Setup memory regions for emulated processes | ||||||
|         // TODO(bunnei): These should not be hardcoded regions initialized within the kernel |         // TODO(bunnei): These should not be hardcoded regions initialized within the kernel | ||||||
|         constexpr std::size_t hid_size{0x40000}; |         constexpr std::size_t hid_size{0x40000}; | ||||||
| @@ -742,39 +743,23 @@ struct KernelCore::Impl { | |||||||
|         constexpr std::size_t time_size{0x1000}; |         constexpr std::size_t time_size{0x1000}; | ||||||
|         constexpr std::size_t hidbus_size{0x1000}; |         constexpr std::size_t hidbus_size{0x1000}; | ||||||
|  |  | ||||||
|         const PAddr hid_phys_addr{system_pool.GetAddress()}; |  | ||||||
|         const PAddr font_phys_addr{system_pool.GetAddress() + hid_size}; |  | ||||||
|         const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size}; |  | ||||||
|         const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size}; |  | ||||||
|         const PAddr hidbus_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size + |  | ||||||
|                                      time_size}; |  | ||||||
|  |  | ||||||
|         hid_shared_mem = KSharedMemory::Create(system.Kernel()); |         hid_shared_mem = KSharedMemory::Create(system.Kernel()); | ||||||
|         font_shared_mem = KSharedMemory::Create(system.Kernel()); |         font_shared_mem = KSharedMemory::Create(system.Kernel()); | ||||||
|         irs_shared_mem = KSharedMemory::Create(system.Kernel()); |         irs_shared_mem = KSharedMemory::Create(system.Kernel()); | ||||||
|         time_shared_mem = KSharedMemory::Create(system.Kernel()); |         time_shared_mem = KSharedMemory::Create(system.Kernel()); | ||||||
|         hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); |         hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); | ||||||
|  |  | ||||||
|         hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, |         hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | ||||||
|                                    {hid_phys_addr, hid_size / PageSize}, |                                    Svc::MemoryPermission::Read, hid_size, "HID:SharedMemory"); | ||||||
|                                    Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |         font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | ||||||
|                                    hid_phys_addr, hid_size, "HID:SharedMemory"); |                                     Svc::MemoryPermission::Read, font_size, "Font:SharedMemory"); | ||||||
|         font_shared_mem->Initialize(system.DeviceMemory(), nullptr, |         irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | ||||||
|                                     {font_phys_addr, font_size / PageSize}, |                                    Svc::MemoryPermission::Read, irs_size, "IRS:SharedMemory"); | ||||||
|                                     Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |         time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | ||||||
|                                     font_phys_addr, font_size, "Font:SharedMemory"); |                                     Svc::MemoryPermission::Read, time_size, "Time:SharedMemory"); | ||||||
|         irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, |         hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | ||||||
|                                    {irs_phys_addr, irs_size / PageSize}, |                                       Svc::MemoryPermission::Read, hidbus_size, | ||||||
|                                    Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |                                       "HidBus:SharedMemory"); | ||||||
|                                    irs_phys_addr, irs_size, "IRS:SharedMemory"); |  | ||||||
|         time_shared_mem->Initialize(system.DeviceMemory(), nullptr, |  | ||||||
|                                     {time_phys_addr, time_size / PageSize}, |  | ||||||
|                                     Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |  | ||||||
|                                     time_phys_addr, time_size, "Time:SharedMemory"); |  | ||||||
|         hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, |  | ||||||
|                                       {hidbus_phys_addr, hidbus_size / PageSize}, |  | ||||||
|                                       Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |  | ||||||
|                                       hidbus_phys_addr, hidbus_size, "HidBus:SharedMemory"); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     KClientPort* CreateNamedServicePort(std::string name) { |     KClientPort* CreateNamedServicePort(std::string name) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user