diff options
| author | 2023-11-30 09:20:55 -0500 | |
|---|---|---|
| committer | 2023-11-30 09:20:55 -0500 | |
| commit | 57a391e71db13ade7a3d96f59d53781eff18d2ac (patch) | |
| tree | 0b4223de40a2d77598ac9095b1374353c2e9da7c /src/core/hle/kernel | |
| parent | Merge pull request #12223 from liamwhite/fruit-company (diff) | |
| parent | core: Rename patcher file (diff) | |
| download | yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.gz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.xz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.zip | |
Merge pull request #12074 from GPUCode/yuwu-on-the-metal
Implement Native Code Execution (NCE)
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/code_set.h | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_address_space_info.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 33 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process_page_table.h | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 14 |
9 files changed, 109 insertions, 21 deletions
diff --git a/src/core/hle/kernel/code_set.h b/src/core/hle/kernel/code_set.h index af1af2b78..4d2d0098e 100644 --- a/src/core/hle/kernel/code_set.h +++ b/src/core/hle/kernel/code_set.h | |||
| @@ -75,12 +75,26 @@ struct CodeSet final { | |||
| 75 | return segments[2]; | 75 | return segments[2]; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | #ifdef HAS_NCE | ||
| 79 | Segment& PatchSegment() { | ||
| 80 | return patch_segment; | ||
| 81 | } | ||
| 82 | |||
| 83 | const Segment& PatchSegment() const { | ||
| 84 | return patch_segment; | ||
| 85 | } | ||
| 86 | #endif | ||
| 87 | |||
| 78 | /// The overall data that backs this code set. | 88 | /// The overall data that backs this code set. |
| 79 | Kernel::PhysicalMemory memory; | 89 | Kernel::PhysicalMemory memory; |
| 80 | 90 | ||
| 81 | /// The segments that comprise this code set. | 91 | /// The segments that comprise this code set. |
| 82 | std::array<Segment, 3> segments; | 92 | std::array<Segment, 3> segments; |
| 83 | 93 | ||
| 94 | #ifdef HAS_NCE | ||
| 95 | Segment patch_segment; | ||
| 96 | #endif | ||
| 97 | |||
| 84 | /// The entry point address for this code set. | 98 | /// The entry point address for this code set. |
| 85 | KProcessAddress entrypoint = 0; | 99 | KProcessAddress entrypoint = 0; |
| 86 | }; | 100 | }; |
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 32173e52b..23258071e 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp | |||
| @@ -25,8 +25,8 @@ constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ | |||
| 25 | { .bit_width = 36, .address = 2_GiB , .size = 64_GiB - 2_GiB , .type = KAddressSpaceInfo::Type::MapLarge, }, | 25 | { .bit_width = 36, .address = 2_GiB , .size = 64_GiB - 2_GiB , .type = KAddressSpaceInfo::Type::MapLarge, }, |
| 26 | { .bit_width = 36, .address = Size_Invalid, .size = 8_GiB , .type = KAddressSpaceInfo::Type::Heap, }, | 26 | { .bit_width = 36, .address = Size_Invalid, .size = 8_GiB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 27 | { .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, }, | 27 | { .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 28 | #ifdef ANDROID | 28 | #ifdef HAS_NCE |
| 29 | // With Android, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region. | 29 | // With NCE, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region. |
| 30 | { .bit_width = 39, .address = 128_MiB , .size = 256_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, | 30 | { .bit_width = 39, .address = 128_MiB , .size = 256_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, |
| 31 | #else | 31 | #else |
| 32 | { .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, | 32 | { .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, |
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 47dc8fd35..6691586ed 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -88,6 +88,22 @@ Result FlushDataCache(AddressType addr, u64 size) { | |||
| 88 | R_SUCCEED(); | 88 | R_SUCCEED(); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission perm) { | ||
| 92 | Common::MemoryPermission perms{}; | ||
| 93 | if (True(perm & KMemoryPermission::UserRead)) { | ||
| 94 | perms |= Common::MemoryPermission::Read; | ||
| 95 | } | ||
| 96 | if (True(perm & KMemoryPermission::UserWrite)) { | ||
| 97 | perms |= Common::MemoryPermission::Write; | ||
| 98 | } | ||
| 99 | #ifdef HAS_NCE | ||
| 100 | if (True(perm & KMemoryPermission::UserExecute)) { | ||
| 101 | perms |= Common::MemoryPermission::Execute; | ||
| 102 | } | ||
| 103 | #endif | ||
| 104 | return perms; | ||
| 105 | } | ||
| 106 | |||
| 91 | } // namespace | 107 | } // namespace |
| 92 | 108 | ||
| 93 | void KPageTableBase::MemoryRange::Open() { | 109 | void KPageTableBase::MemoryRange::Open() { |
| @@ -170,7 +186,8 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool | |||
| 170 | KMemoryManager::Pool pool, KProcessAddress code_address, | 186 | KMemoryManager::Pool pool, KProcessAddress code_address, |
| 171 | size_t code_size, KSystemResource* system_resource, | 187 | size_t code_size, KSystemResource* system_resource, |
| 172 | KResourceLimit* resource_limit, | 188 | KResourceLimit* resource_limit, |
| 173 | Core::Memory::Memory& memory) { | 189 | Core::Memory::Memory& memory, |
| 190 | KProcessAddress aslr_space_start) { | ||
| 174 | // Calculate region extents. | 191 | // Calculate region extents. |
| 175 | const size_t as_width = GetAddressSpaceWidth(as_type); | 192 | const size_t as_width = GetAddressSpaceWidth(as_type); |
| 176 | const KProcessAddress start = 0; | 193 | const KProcessAddress start = 0; |
| @@ -211,7 +228,8 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool | |||
| 211 | heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Heap); | 228 | heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Heap); |
| 212 | stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Stack); | 229 | stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Stack); |
| 213 | kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type::MapSmall); | 230 | kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type::MapSmall); |
| 214 | m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type::Map39Bit); | 231 | m_code_region_start = m_address_space_start + aslr_space_start + |
| 232 | GetSpaceStart(KAddressSpaceInfo::Type::Map39Bit); | ||
| 215 | m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit); | 233 | m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit); |
| 216 | m_alias_code_region_start = m_code_region_start; | 234 | m_alias_code_region_start = m_code_region_start; |
| 217 | m_alias_code_region_end = m_code_region_end; | 235 | m_alias_code_region_end = m_code_region_end; |
| @@ -5643,7 +5661,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5643 | case OperationType::Map: { | 5661 | case OperationType::Map: { |
| 5644 | ASSERT(virt_addr != 0); | 5662 | ASSERT(virt_addr != 0); |
| 5645 | ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); | 5663 | ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); |
| 5646 | m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr); | 5664 | m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr, |
| 5665 | ConvertToMemoryPermission(properties.perm)); | ||
| 5647 | 5666 | ||
| 5648 | // Open references to pages, if we should. | 5667 | // Open references to pages, if we should. |
| 5649 | if (this->IsHeapPhysicalAddress(phys_addr)) { | 5668 | if (this->IsHeapPhysicalAddress(phys_addr)) { |
| @@ -5658,8 +5677,11 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5658 | } | 5677 | } |
| 5659 | case OperationType::ChangePermissions: | 5678 | case OperationType::ChangePermissions: |
| 5660 | case OperationType::ChangePermissionsAndRefresh: | 5679 | case OperationType::ChangePermissionsAndRefresh: |
| 5661 | case OperationType::ChangePermissionsAndRefreshAndFlush: | 5680 | case OperationType::ChangePermissionsAndRefreshAndFlush: { |
| 5681 | m_memory->ProtectRegion(*m_impl, virt_addr, num_pages * PageSize, | ||
| 5682 | ConvertToMemoryPermission(properties.perm)); | ||
| 5662 | R_SUCCEED(); | 5683 | R_SUCCEED(); |
| 5684 | } | ||
| 5663 | default: | 5685 | default: |
| 5664 | UNREACHABLE(); | 5686 | UNREACHABLE(); |
| 5665 | } | 5687 | } |
| @@ -5687,7 +5709,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a | |||
| 5687 | const size_t size{node.GetNumPages() * PageSize}; | 5709 | const size_t size{node.GetNumPages() * PageSize}; |
| 5688 | 5710 | ||
| 5689 | // Map the pages. | 5711 | // Map the pages. |
| 5690 | m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress()); | 5712 | m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(), |
| 5713 | ConvertToMemoryPermission(properties.perm)); | ||
| 5691 | 5714 | ||
| 5692 | virt_addr += size; | 5715 | virt_addr += size; |
| 5693 | } | 5716 | } |
diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index ee2c41e67..556d230b3 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h | |||
| @@ -235,7 +235,8 @@ public: | |||
| 235 | bool enable_device_address_space_merge, bool from_back, | 235 | bool enable_device_address_space_merge, bool from_back, |
| 236 | KMemoryManager::Pool pool, KProcessAddress code_address, | 236 | KMemoryManager::Pool pool, KProcessAddress code_address, |
| 237 | size_t code_size, KSystemResource* system_resource, | 237 | size_t code_size, KSystemResource* system_resource, |
| 238 | KResourceLimit* resource_limit, Core::Memory::Memory& memory); | 238 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, |
| 239 | KProcessAddress aslr_space_start); | ||
| 239 | 240 | ||
| 240 | void Finalize(); | 241 | void Finalize(); |
| 241 | 242 | ||
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 3cfb414e5..6c29eb72c 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -300,7 +300,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa | |||
| 300 | False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); | 300 | False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); |
| 301 | R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, | 301 | R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, |
| 302 | params.code_address, params.code_num_pages * PageSize, | 302 | params.code_address, params.code_num_pages * PageSize, |
| 303 | m_system_resource, res_limit, this->GetMemory())); | 303 | m_system_resource, res_limit, this->GetMemory(), 0)); |
| 304 | } | 304 | } |
| 305 | ON_RESULT_FAILURE_2 { | 305 | ON_RESULT_FAILURE_2 { |
| 306 | m_page_table.Finalize(); | 306 | m_page_table.Finalize(); |
| @@ -332,7 +332,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa | |||
| 332 | 332 | ||
| 333 | Result KProcess::Initialize(const Svc::CreateProcessParameter& params, | 333 | Result KProcess::Initialize(const Svc::CreateProcessParameter& params, |
| 334 | std::span<const u32> user_caps, KResourceLimit* res_limit, | 334 | std::span<const u32> user_caps, KResourceLimit* res_limit, |
| 335 | KMemoryManager::Pool pool) { | 335 | KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { |
| 336 | ASSERT(res_limit != nullptr); | 336 | ASSERT(res_limit != nullptr); |
| 337 | 337 | ||
| 338 | // Set members. | 338 | // Set members. |
| @@ -393,7 +393,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, | |||
| 393 | False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); | 393 | False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); |
| 394 | R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, | 394 | R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, |
| 395 | params.code_address, code_size, m_system_resource, res_limit, | 395 | params.code_address, code_size, m_system_resource, res_limit, |
| 396 | this->GetMemory())); | 396 | this->GetMemory(), aslr_space_start)); |
| 397 | } | 397 | } |
| 398 | ON_RESULT_FAILURE_2 { | 398 | ON_RESULT_FAILURE_2 { |
| 399 | m_page_table.Finalize(); | 399 | m_page_table.Finalize(); |
| @@ -1128,7 +1128,7 @@ KProcess::KProcess(KernelCore& kernel) | |||
| 1128 | KProcess::~KProcess() = default; | 1128 | KProcess::~KProcess() = default; |
| 1129 | 1129 | ||
| 1130 | Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, | 1130 | Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, |
| 1131 | bool is_hbl) { | 1131 | KProcessAddress aslr_space_start, bool is_hbl) { |
| 1132 | // Create a resource limit for the process. | 1132 | // Create a resource limit for the process. |
| 1133 | const auto physical_memory_size = | 1133 | const auto physical_memory_size = |
| 1134 | m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application); | 1134 | m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application); |
| @@ -1179,7 +1179,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 1179 | .name = {}, | 1179 | .name = {}, |
| 1180 | .version = {}, | 1180 | .version = {}, |
| 1181 | .program_id = metadata.GetTitleID(), | 1181 | .program_id = metadata.GetTitleID(), |
| 1182 | .code_address = code_address, | 1182 | .code_address = code_address + GetInteger(aslr_space_start), |
| 1183 | .code_num_pages = static_cast<s32>(code_size / PageSize), | 1183 | .code_num_pages = static_cast<s32>(code_size / PageSize), |
| 1184 | .flags = flag, | 1184 | .flags = flag, |
| 1185 | .reslimit = Svc::InvalidHandle, | 1185 | .reslimit = Svc::InvalidHandle, |
| @@ -1193,7 +1193,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||
| 1193 | 1193 | ||
| 1194 | // Initialize for application process. | 1194 | // Initialize for application process. |
| 1195 | R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, | 1195 | R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, |
| 1196 | KMemoryManager::Pool::Application)); | 1196 | KMemoryManager::Pool::Application, aslr_space_start)); |
| 1197 | 1197 | ||
| 1198 | // Assign remaining properties. | 1198 | // Assign remaining properties. |
| 1199 | m_is_hbl = is_hbl; | 1199 | m_is_hbl = is_hbl; |
| @@ -1214,6 +1214,17 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { | |||
| 1214 | ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute); | 1214 | ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute); |
| 1215 | ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read); | 1215 | ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read); |
| 1216 | ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); | 1216 | ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); |
| 1217 | |||
| 1218 | #ifdef HAS_NCE | ||
| 1219 | if (Settings::IsNceEnabled()) { | ||
| 1220 | auto& buffer = m_kernel.System().DeviceMemory().buffer; | ||
| 1221 | const auto& code = code_set.CodeSegment(); | ||
| 1222 | const auto& patch = code_set.PatchSegment(); | ||
| 1223 | buffer.Protect(GetInteger(base_addr + code.addr), code.size, true, true, true); | ||
| 1224 | buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, true, true, true); | ||
| 1225 | ReprotectSegment(code_set.PatchSegment(), Svc::MemoryPermission::None); | ||
| 1226 | } | ||
| 1227 | #endif | ||
| 1217 | } | 1228 | } |
| 1218 | 1229 | ||
| 1219 | bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { | 1230 | bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 8339465fd..d8cd0fdde 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -120,6 +120,9 @@ private: | |||
| 120 | std::atomic<s64> m_num_ipc_messages{}; | 120 | std::atomic<s64> m_num_ipc_messages{}; |
| 121 | std::atomic<s64> m_num_ipc_replies{}; | 121 | std::atomic<s64> m_num_ipc_replies{}; |
| 122 | std::atomic<s64> m_num_ipc_receives{}; | 122 | std::atomic<s64> m_num_ipc_receives{}; |
| 123 | #ifdef HAS_NCE | ||
| 124 | std::unordered_map<u64, u64> m_post_handlers{}; | ||
| 125 | #endif | ||
| 123 | 126 | ||
| 124 | private: | 127 | private: |
| 125 | Result StartTermination(); | 128 | Result StartTermination(); |
| @@ -150,7 +153,8 @@ public: | |||
| 150 | std::span<const u32> caps, KResourceLimit* res_limit, | 153 | std::span<const u32> caps, KResourceLimit* res_limit, |
| 151 | KMemoryManager::Pool pool, bool immortal); | 154 | KMemoryManager::Pool pool, bool immortal); |
| 152 | Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, | 155 | Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, |
| 153 | KResourceLimit* res_limit, KMemoryManager::Pool pool); | 156 | KResourceLimit* res_limit, KMemoryManager::Pool pool, |
| 157 | KProcessAddress aslr_space_start); | ||
| 154 | void Exit(); | 158 | void Exit(); |
| 155 | 159 | ||
| 156 | const char* GetName() const { | 160 | const char* GetName() const { |
| @@ -466,6 +470,12 @@ public: | |||
| 466 | 470 | ||
| 467 | static void Switch(KProcess* cur_process, KProcess* next_process); | 471 | static void Switch(KProcess* cur_process, KProcess* next_process); |
| 468 | 472 | ||
| 473 | #ifdef HAS_NCE | ||
| 474 | std::unordered_map<u64, u64>& GetPostHandlers() noexcept { | ||
| 475 | return m_post_handlers; | ||
| 476 | } | ||
| 477 | #endif | ||
| 478 | |||
| 469 | public: | 479 | public: |
| 470 | // Attempts to insert a watchpoint into a free slot. Returns false if none are available. | 480 | // Attempts to insert a watchpoint into a free slot. Returns false if none are available. |
| 471 | bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); | 481 | bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); |
| @@ -479,7 +489,7 @@ public: | |||
| 479 | 489 | ||
| 480 | public: | 490 | public: |
| 481 | Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, | 491 | Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, |
| 482 | bool is_hbl); | 492 | KProcessAddress aslr_space_start, bool is_hbl); |
| 483 | 493 | ||
| 484 | void LoadModule(CodeSet code_set, KProcessAddress base_addr); | 494 | void LoadModule(CodeSet code_set, KProcessAddress base_addr); |
| 485 | 495 | ||
diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h index b7ae5abd0..9e40f68bc 100644 --- a/src/core/hle/kernel/k_process_page_table.h +++ b/src/core/hle/kernel/k_process_page_table.h | |||
| @@ -23,10 +23,11 @@ public: | |||
| 23 | Result Initialize(Svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, | 23 | Result Initialize(Svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, |
| 24 | bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, | 24 | bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, |
| 25 | size_t code_size, KSystemResource* system_resource, | 25 | size_t code_size, KSystemResource* system_resource, |
| 26 | KResourceLimit* resource_limit, Core::Memory::Memory& memory) { | 26 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, |
| 27 | R_RETURN(m_page_table.InitializeForProcess(as_type, enable_aslr, enable_das_merge, | 27 | KProcessAddress aslr_space_start) { |
| 28 | from_back, pool, code_address, code_size, | 28 | R_RETURN(m_page_table.InitializeForProcess( |
| 29 | system_resource, resource_limit, memory)); | 29 | as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, |
| 30 | system_resource, resource_limit, memory, aslr_space_start)); | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | void Finalize() { | 33 | void Finalize() { |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e1f80b04f..e9ca5dfca 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -655,6 +655,21 @@ public: | |||
| 655 | return m_stack_top; | 655 | return m_stack_top; |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | public: | ||
| 659 | // TODO: This shouldn't be defined in kernel namespace | ||
| 660 | struct NativeExecutionParameters { | ||
| 661 | u64 tpidr_el0{}; | ||
| 662 | u64 tpidrro_el0{}; | ||
| 663 | void* native_context{}; | ||
| 664 | std::atomic<u32> lock{1}; | ||
| 665 | bool is_running{}; | ||
| 666 | u32 magic{Common::MakeMagic('Y', 'U', 'Z', 'U')}; | ||
| 667 | }; | ||
| 668 | |||
| 669 | NativeExecutionParameters& GetNativeExecutionParameters() { | ||
| 670 | return m_native_execution_parameters; | ||
| 671 | } | ||
| 672 | |||
| 658 | private: | 673 | private: |
| 659 | KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, | 674 | KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, |
| 660 | bool is_kernel_address_key); | 675 | bool is_kernel_address_key); |
| @@ -914,6 +929,7 @@ private: | |||
| 914 | ThreadWaitReasonForDebugging m_wait_reason_for_debugging{}; | 929 | ThreadWaitReasonForDebugging m_wait_reason_for_debugging{}; |
| 915 | uintptr_t m_argument{}; | 930 | uintptr_t m_argument{}; |
| 916 | KProcessAddress m_stack_top{}; | 931 | KProcessAddress m_stack_top{}; |
| 932 | NativeExecutionParameters m_native_execution_parameters{}; | ||
| 917 | 933 | ||
| 918 | public: | 934 | public: |
| 919 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; | 935 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; |
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 5ee869fa2..073039825 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp | |||
| @@ -1,8 +1,12 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/settings.h" | ||
| 4 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | 5 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
| 5 | #include "core/arm/dynarmic/arm_dynarmic_64.h" | 6 | #include "core/arm/dynarmic/arm_dynarmic_64.h" |
| 7 | #ifdef HAS_NCE | ||
| 8 | #include "core/arm/nce/arm_nce.h" | ||
| 9 | #endif | ||
| 6 | #include "core/core.h" | 10 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_scheduler.h" | 11 | #include "core/hle/kernel/k_scheduler.h" |
| 8 | #include "core/hle/kernel/kernel.h" | 12 | #include "core/hle/kernel/kernel.h" |
| @@ -14,7 +18,8 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu | |||
| 14 | : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { | 18 | : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { |
| 15 | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | 19 | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) |
| 16 | // TODO(bunnei): Initialization relies on a core being available. We may later replace this with | 20 | // TODO(bunnei): Initialization relies on a core being available. We may later replace this with |
| 17 | // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. | 21 | // an NCE interface or a 32-bit instance of Dynarmic. This should be abstracted out to a CPU |
| 22 | // manager. | ||
| 18 | auto& kernel = system.Kernel(); | 23 | auto& kernel = system.Kernel(); |
| 19 | m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( | 24 | m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( |
| 20 | system, kernel.IsMulticore(), | 25 | system, kernel.IsMulticore(), |
| @@ -28,6 +33,13 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu | |||
| 28 | PhysicalCore::~PhysicalCore() = default; | 33 | PhysicalCore::~PhysicalCore() = default; |
| 29 | 34 | ||
| 30 | void PhysicalCore::Initialize(bool is_64_bit) { | 35 | void PhysicalCore::Initialize(bool is_64_bit) { |
| 36 | #if defined(HAS_NCE) | ||
| 37 | if (Settings::IsNceEnabled()) { | ||
| 38 | m_arm_interface = std::make_unique<Core::ARM_NCE>(m_system, m_system.Kernel().IsMulticore(), | ||
| 39 | m_core_index); | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | #endif | ||
| 31 | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | 43 | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) |
| 32 | auto& kernel = m_system.Kernel(); | 44 | auto& kernel = m_system.Kernel(); |
| 33 | if (!is_64_bit) { | 45 | if (!is_64_bit) { |