k_capabilities.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/hardware_properties.h"
  4. #include "core/hle/kernel/k_capabilities.h"
  5. #include "core/hle/kernel/k_memory_layout.h"
  6. #include "core/hle/kernel/k_process_page_table.h"
  7. #include "core/hle/kernel/k_trace.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/svc_results.h"
  10. #include "core/hle/kernel/svc_version.h"
  11. namespace Kernel {
  12. Result KCapabilities::InitializeForKip(std::span<const u32> kern_caps,
  13. KProcessPageTable* page_table) {
  14. // We're initializing an initial process.
  15. m_svc_access_flags.reset();
  16. m_irq_access_flags.reset();
  17. m_debug_capabilities = 0;
  18. m_handle_table_size = 0;
  19. m_intended_kernel_version = 0;
  20. m_program_type = 0;
  21. // Initial processes may run on all cores.
  22. constexpr u64 VirtMask = Core::Hardware::VirtualCoreMask;
  23. constexpr u64 PhysMask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(VirtMask);
  24. m_core_mask = VirtMask;
  25. m_phys_core_mask = PhysMask;
  26. // Initial processes may use any user priority they like.
  27. m_priority_mask = ~0xFULL;
  28. // Here, Nintendo sets the kernel version to the current kernel version.
  29. // We will follow suit and set the version to the highest supported kernel version.
  30. KernelVersion intended_kernel_version{};
  31. intended_kernel_version.major_version.Assign(Svc::SupportedKernelMajorVersion);
  32. intended_kernel_version.minor_version.Assign(Svc::SupportedKernelMinorVersion);
  33. m_intended_kernel_version = intended_kernel_version.raw;
  34. // Parse the capabilities array.
  35. R_RETURN(this->SetCapabilities(kern_caps, page_table));
  36. }
  37. Result KCapabilities::InitializeForUser(std::span<const u32> user_caps,
  38. KProcessPageTable* page_table) {
  39. // We're initializing a user process.
  40. m_svc_access_flags.reset();
  41. m_irq_access_flags.reset();
  42. m_debug_capabilities = 0;
  43. m_handle_table_size = 0;
  44. m_intended_kernel_version = 0;
  45. m_program_type = 0;
  46. // User processes must specify what cores/priorities they can use.
  47. m_core_mask = 0;
  48. m_priority_mask = 0;
  49. // Parse the user capabilities array.
  50. R_RETURN(this->SetCapabilities(user_caps, page_table));
  51. }
  52. Result KCapabilities::SetCorePriorityCapability(const u32 cap) {
  53. // We can't set core/priority if we've already set them.
  54. R_UNLESS(m_core_mask == 0, ResultInvalidArgument);
  55. R_UNLESS(m_priority_mask == 0, ResultInvalidArgument);
  56. // Validate the core/priority.
  57. CorePriority pack{cap};
  58. const u32 min_core = pack.minimum_core_id;
  59. const u32 max_core = pack.maximum_core_id;
  60. const u32 max_prio = pack.lowest_thread_priority;
  61. const u32 min_prio = pack.highest_thread_priority;
  62. R_UNLESS(min_core <= max_core, ResultInvalidCombination);
  63. R_UNLESS(min_prio <= max_prio, ResultInvalidCombination);
  64. R_UNLESS(max_core < Core::Hardware::NumVirtualCores, ResultInvalidCoreId);
  65. ASSERT(max_prio < Common::BitSize<u64>());
  66. // Set core mask.
  67. for (auto core_id = min_core; core_id <= max_core; core_id++) {
  68. m_core_mask |= (1ULL << core_id);
  69. }
  70. ASSERT((m_core_mask & Core::Hardware::VirtualCoreMask) == m_core_mask);
  71. // Set physical core mask.
  72. m_phys_core_mask = Core::Hardware::ConvertVirtualCoreMaskToPhysical(m_core_mask);
  73. // Set priority mask.
  74. for (auto prio = min_prio; prio <= max_prio; prio++) {
  75. m_priority_mask |= (1ULL << prio);
  76. }
  77. // We must have some core/priority we can use.
  78. R_UNLESS(m_core_mask != 0, ResultInvalidArgument);
  79. R_UNLESS(m_priority_mask != 0, ResultInvalidArgument);
  80. // Processes must not have access to kernel thread priorities.
  81. R_UNLESS((m_priority_mask & 0xF) == 0, ResultInvalidArgument);
  82. R_SUCCEED();
  83. }
  84. Result KCapabilities::SetSyscallMaskCapability(const u32 cap, u32& set_svc) {
  85. // Validate the index.
  86. SyscallMask pack{cap};
  87. const u32 mask = pack.mask;
  88. const u32 index = pack.index;
  89. const u32 index_flag = (1U << index);
  90. R_UNLESS((set_svc & index_flag) == 0, ResultInvalidCombination);
  91. set_svc |= index_flag;
  92. // Set SVCs.
  93. for (size_t i = 0; i < decltype(SyscallMask::mask)::bits; i++) {
  94. const u32 svc_id = static_cast<u32>(decltype(SyscallMask::mask)::bits * index + i);
  95. if (mask & (1U << i)) {
  96. R_UNLESS(this->SetSvcAllowed(svc_id), ResultOutOfRange);
  97. }
  98. }
  99. R_SUCCEED();
  100. }
  101. Result KCapabilities::MapRange_(const u32 cap, const u32 size_cap, KProcessPageTable* page_table) {
  102. const auto range_pack = MapRange{cap};
  103. const auto size_pack = MapRangeSize{size_cap};
  104. // Get/validate address/size
  105. const u64 phys_addr = range_pack.address.Value() * PageSize;
  106. // Validate reserved bits are unused.
  107. R_UNLESS(size_pack.reserved.Value() == 0, ResultOutOfRange);
  108. const size_t num_pages = size_pack.pages;
  109. const size_t size = num_pages * PageSize;
  110. R_UNLESS(num_pages != 0, ResultInvalidSize);
  111. R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress);
  112. R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress);
  113. // Do the mapping.
  114. [[maybe_unused]] const KMemoryPermission perm = range_pack.read_only.Value()
  115. ? KMemoryPermission::UserRead
  116. : KMemoryPermission::UserReadWrite;
  117. if (MapRangeSize{size_cap}.normal) {
  118. R_RETURN(page_table->MapStatic(phys_addr, size, perm));
  119. } else {
  120. R_RETURN(page_table->MapIo(phys_addr, size, perm));
  121. }
  122. }
  123. Result KCapabilities::MapIoPage_(const u32 cap, KProcessPageTable* page_table) {
  124. // Get/validate address/size
  125. const u64 phys_addr = MapIoPage{cap}.address.Value() * PageSize;
  126. const size_t num_pages = 1;
  127. const size_t size = num_pages * PageSize;
  128. R_UNLESS(phys_addr < phys_addr + size, ResultInvalidAddress);
  129. R_UNLESS(((phys_addr + size - 1) & ~PhysicalMapAllowedMask) == 0, ResultInvalidAddress);
  130. // Do the mapping.
  131. R_RETURN(page_table->MapIo(phys_addr, size, KMemoryPermission::UserReadWrite));
  132. }
  133. template <typename F>
  134. Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) {
  135. // Define the allowed memory regions.
  136. constexpr std::array<KMemoryRegionType, 4> MemoryRegions{
  137. KMemoryRegionType_None,
  138. KMemoryRegionType_KernelTraceBuffer,
  139. KMemoryRegionType_OnMemoryBootImage,
  140. KMemoryRegionType_DTB,
  141. };
  142. // Extract regions/read only.
  143. const MapRegion pack{cap};
  144. const std::array<RegionType, 3> types{pack.region0, pack.region1, pack.region2};
  145. const std::array<u32, 3> ro{pack.read_only0, pack.read_only1, pack.read_only2};
  146. for (size_t i = 0; i < types.size(); i++) {
  147. const auto type = types[i];
  148. const auto perm = ro[i] ? KMemoryPermission::UserRead : KMemoryPermission::UserReadWrite;
  149. switch (type) {
  150. case RegionType::NoMapping:
  151. break;
  152. case RegionType::KernelTraceBuffer:
  153. if constexpr (!IsKTraceEnabled) {
  154. break;
  155. }
  156. [[fallthrough]];
  157. case RegionType::OnMemoryBootImage:
  158. case RegionType::DTB:
  159. R_TRY(f(MemoryRegions[static_cast<u32>(type)], perm));
  160. break;
  161. default:
  162. R_THROW(ResultNotFound);
  163. }
  164. }
  165. R_SUCCEED();
  166. }
  167. Result KCapabilities::MapRegion_(const u32 cap, KProcessPageTable* page_table) {
  168. // Map each region into the process's page table.
  169. return ProcessMapRegionCapability(
  170. cap, [page_table](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
  171. R_RETURN(page_table->MapRegion(region_type, perm));
  172. });
  173. }
  174. Result KCapabilities::CheckMapRegion(KernelCore& kernel, const u32 cap) {
  175. // Check that each region has a physical backing store.
  176. return ProcessMapRegionCapability(
  177. cap, [&](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
  178. R_UNLESS(kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(
  179. region_type) != nullptr,
  180. ResultOutOfRange);
  181. R_SUCCEED();
  182. });
  183. }
  184. Result KCapabilities::SetInterruptPairCapability(const u32 cap) {
  185. // Extract interrupts.
  186. const InterruptPair pack{cap};
  187. const std::array<u32, 2> ids{pack.interrupt_id0, pack.interrupt_id1};
  188. for (size_t i = 0; i < ids.size(); i++) {
  189. if (ids[i] != PaddingInterruptId) {
  190. UNIMPLEMENTED();
  191. // R_UNLESS(Kernel::GetInterruptManager().IsInterruptDefined(ids[i]), ResultOutOfRange);
  192. // R_UNLESS(this->SetInterruptPermitted(ids[i]), ResultOutOfRange);
  193. }
  194. }
  195. R_SUCCEED();
  196. }
  197. Result KCapabilities::SetProgramTypeCapability(const u32 cap) {
  198. // Validate.
  199. const ProgramType pack{cap};
  200. R_UNLESS(pack.reserved == 0, ResultReservedUsed);
  201. m_program_type = pack.type;
  202. R_SUCCEED();
  203. }
  204. Result KCapabilities::SetKernelVersionCapability(const u32 cap) {
  205. // Ensure we haven't set our version before.
  206. R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version == 0, ResultInvalidArgument);
  207. // Set, ensure that we set a valid version.
  208. m_intended_kernel_version = cap;
  209. R_UNLESS(KernelVersion{m_intended_kernel_version}.major_version != 0, ResultInvalidArgument);
  210. R_SUCCEED();
  211. }
  212. Result KCapabilities::SetHandleTableCapability(const u32 cap) {
  213. // Validate.
  214. const HandleTable pack{cap};
  215. R_UNLESS(pack.reserved == 0, ResultReservedUsed);
  216. m_handle_table_size = pack.size;
  217. R_SUCCEED();
  218. }
  219. Result KCapabilities::SetDebugFlagsCapability(const u32 cap) {
  220. // Validate.
  221. const DebugFlags pack{cap};
  222. R_UNLESS(pack.reserved == 0, ResultReservedUsed);
  223. DebugFlags debug_capabilities{m_debug_capabilities};
  224. debug_capabilities.allow_debug.Assign(pack.allow_debug);
  225. debug_capabilities.force_debug.Assign(pack.force_debug);
  226. m_debug_capabilities = debug_capabilities.raw;
  227. R_SUCCEED();
  228. }
  229. Result KCapabilities::SetCapability(const u32 cap, u32& set_flags, u32& set_svc,
  230. KProcessPageTable* page_table) {
  231. // Validate this is a capability we can act on.
  232. const auto type = GetCapabilityType(cap);
  233. R_UNLESS(type != CapabilityType::Invalid, ResultInvalidArgument);
  234. // If the type is padding, we have no work to do.
  235. R_SUCCEED_IF(type == CapabilityType::Padding);
  236. // Check that we haven't already processed this capability.
  237. const auto flag = GetCapabilityFlag(type);
  238. R_UNLESS(((set_flags & InitializeOnceFlags) & flag) == 0, ResultInvalidCombination);
  239. set_flags |= flag;
  240. // Process the capability.
  241. switch (type) {
  242. case CapabilityType::CorePriority:
  243. R_RETURN(this->SetCorePriorityCapability(cap));
  244. case CapabilityType::SyscallMask:
  245. R_RETURN(this->SetSyscallMaskCapability(cap, set_svc));
  246. case CapabilityType::MapIoPage:
  247. R_RETURN(this->MapIoPage_(cap, page_table));
  248. case CapabilityType::MapRegion:
  249. R_RETURN(this->MapRegion_(cap, page_table));
  250. case CapabilityType::InterruptPair:
  251. R_RETURN(this->SetInterruptPairCapability(cap));
  252. case CapabilityType::ProgramType:
  253. R_RETURN(this->SetProgramTypeCapability(cap));
  254. case CapabilityType::KernelVersion:
  255. R_RETURN(this->SetKernelVersionCapability(cap));
  256. case CapabilityType::HandleTable:
  257. R_RETURN(this->SetHandleTableCapability(cap));
  258. case CapabilityType::DebugFlags:
  259. R_RETURN(this->SetDebugFlagsCapability(cap));
  260. default:
  261. R_THROW(ResultInvalidArgument);
  262. }
  263. }
  264. Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTable* page_table) {
  265. u32 set_flags = 0, set_svc = 0;
  266. for (size_t i = 0; i < caps.size(); i++) {
  267. const u32 cap{caps[i]};
  268. if (GetCapabilityType(cap) == CapabilityType::MapRange) {
  269. // Check that the pair cap exists.
  270. R_UNLESS((++i) < caps.size(), ResultInvalidCombination);
  271. // Check the pair cap is a map range cap.
  272. const u32 size_cap{caps[i]};
  273. R_UNLESS(GetCapabilityType(size_cap) == CapabilityType::MapRange,
  274. ResultInvalidCombination);
  275. // Map the range.
  276. R_TRY(this->MapRange_(cap, size_cap, page_table));
  277. } else {
  278. R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table));
  279. }
  280. }
  281. R_SUCCEED();
  282. }
  283. Result KCapabilities::CheckCapabilities(KernelCore& kernel, std::span<const u32> caps) {
  284. for (auto cap : caps) {
  285. // Check the capability refers to a valid region.
  286. if (GetCapabilityType(cap) == CapabilityType::MapRegion) {
  287. R_TRY(CheckMapRegion(kernel, cap));
  288. }
  289. }
  290. R_SUCCEED();
  291. }
  292. } // namespace Kernel