process.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <memory>
  6. #include "common/assert.h"
  7. #include "common/common_funcs.h"
  8. #include "common/logging/log.h"
  9. #include "core/hle/kernel/errors.h"
  10. #include "core/hle/kernel/kernel.h"
  11. #include "core/hle/kernel/process.h"
  12. #include "core/hle/kernel/resource_limit.h"
  13. #include "core/hle/kernel/thread.h"
  14. #include "core/hle/kernel/vm_manager.h"
  15. #include "core/memory.h"
  16. namespace Kernel {
  17. SharedPtr<CodeSet> CodeSet::Create(KernelCore& kernel, std::string name) {
  18. SharedPtr<CodeSet> codeset(new CodeSet(kernel));
  19. codeset->name = std::move(name);
  20. return codeset;
  21. }
  22. CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {}
  23. CodeSet::~CodeSet() = default;
  24. SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) {
  25. SharedPtr<Process> process(new Process(kernel));
  26. process->name = std::move(name);
  27. process->flags.raw = 0;
  28. process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
  29. process->status = ProcessStatus::Created;
  30. process->program_id = 0;
  31. process->process_id = kernel.CreateNewProcessID();
  32. kernel.AppendNewProcess(process);
  33. return process;
  34. }
  35. void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) {
  36. for (std::size_t i = 0; i < len; ++i) {
  37. u32 descriptor = kernel_caps[i];
  38. u32 type = descriptor >> 20;
  39. if (descriptor == 0xFFFFFFFF) {
  40. // Unused descriptor entry
  41. continue;
  42. } else if ((type & 0xF00) == 0xE00) { // 0x0FFF
  43. // Allowed interrupts list
  44. LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
  45. } else if ((type & 0xF80) == 0xF00) { // 0x07FF
  46. // Allowed syscalls mask
  47. unsigned int index = ((descriptor >> 24) & 7) * 24;
  48. u32 bits = descriptor & 0xFFFFFF;
  49. while (bits && index < svc_access_mask.size()) {
  50. svc_access_mask.set(index, bits & 1);
  51. ++index;
  52. bits >>= 1;
  53. }
  54. } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
  55. // Handle table size
  56. handle_table_size = descriptor & 0x3FF;
  57. } else if ((type & 0xFF8) == 0xFF0) { // 0x007F
  58. // Misc. flags
  59. flags.raw = descriptor & 0xFFFF;
  60. } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
  61. // Mapped memory range
  62. if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
  63. LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
  64. continue;
  65. }
  66. u32 end_desc = kernel_caps[i + 1];
  67. ++i; // Skip over the second descriptor on the next iteration
  68. AddressMapping mapping;
  69. mapping.address = descriptor << 12;
  70. VAddr end_address = end_desc << 12;
  71. if (mapping.address < end_address) {
  72. mapping.size = end_address - mapping.address;
  73. } else {
  74. mapping.size = 0;
  75. }
  76. mapping.read_only = (descriptor & (1 << 20)) != 0;
  77. mapping.unk_flag = (end_desc & (1 << 20)) != 0;
  78. address_mappings.push_back(mapping);
  79. } else if ((type & 0xFFF) == 0xFFE) { // 0x000F
  80. // Mapped memory page
  81. AddressMapping mapping;
  82. mapping.address = descriptor << 12;
  83. mapping.size = Memory::PAGE_SIZE;
  84. mapping.read_only = false;
  85. mapping.unk_flag = false;
  86. address_mappings.push_back(mapping);
  87. } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
  88. // Kernel version
  89. kernel_version = descriptor & 0xFFFF;
  90. int minor = kernel_version & 0xFF;
  91. int major = (kernel_version >> 8) & 0xFF;
  92. LOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
  93. } else {
  94. LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x{:08X}", descriptor);
  95. }
  96. }
  97. }
  98. void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
  99. // Allocate and map the main thread stack
  100. // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part
  101. // of the user address space.
  102. vm_manager
  103. .MapMemoryBlock(Memory::STACK_AREA_VADDR_END - stack_size,
  104. std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
  105. MemoryState::Mapped)
  106. .Unwrap();
  107. vm_manager.LogLayout();
  108. status = ProcessStatus::Running;
  109. Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, this);
  110. }
  111. void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
  112. const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
  113. MemoryState memory_state) {
  114. auto vma = vm_manager
  115. .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset,
  116. segment.size, memory_state)
  117. .Unwrap();
  118. vm_manager.Reprotect(vma, permissions);
  119. };
  120. // Map CodeSet segments
  121. MapSegment(module_->CodeSegment(), VMAPermission::ReadExecute, MemoryState::CodeStatic);
  122. MapSegment(module_->RODataSegment(), VMAPermission::Read, MemoryState::CodeMutable);
  123. MapSegment(module_->DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeMutable);
  124. }
  125. ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) {
  126. if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
  127. target + size < target) {
  128. return ERR_INVALID_ADDRESS;
  129. }
  130. if (heap_memory == nullptr) {
  131. // Initialize heap
  132. heap_memory = std::make_shared<std::vector<u8>>();
  133. heap_start = heap_end = target;
  134. } else {
  135. vm_manager.UnmapRange(heap_start, heap_end - heap_start);
  136. }
  137. // If necessary, expand backing vector to cover new heap extents.
  138. if (target < heap_start) {
  139. heap_memory->insert(begin(*heap_memory), heap_start - target, 0);
  140. heap_start = target;
  141. vm_manager.RefreshMemoryBlockMappings(heap_memory.get());
  142. }
  143. if (target + size > heap_end) {
  144. heap_memory->insert(end(*heap_memory), (target + size) - heap_end, 0);
  145. heap_end = target + size;
  146. vm_manager.RefreshMemoryBlockMappings(heap_memory.get());
  147. }
  148. ASSERT(heap_end - heap_start == heap_memory->size());
  149. CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start,
  150. size, MemoryState::Heap));
  151. vm_manager.Reprotect(vma, perms);
  152. heap_used = size;
  153. return MakeResult<VAddr>(heap_end - size);
  154. }
  155. ResultCode Process::HeapFree(VAddr target, u32 size) {
  156. if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
  157. target + size < target) {
  158. return ERR_INVALID_ADDRESS;
  159. }
  160. if (size == 0) {
  161. return RESULT_SUCCESS;
  162. }
  163. ResultCode result = vm_manager.UnmapRange(target, size);
  164. if (result.IsError())
  165. return result;
  166. heap_used -= size;
  167. return RESULT_SUCCESS;
  168. }
  169. ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
  170. auto vma = vm_manager.FindVMA(src_addr);
  171. ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
  172. ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
  173. // The returned VMA might be a bigger one encompassing the desired address.
  174. auto vma_offset = src_addr - vma->first;
  175. ASSERT_MSG(vma_offset + size <= vma->second.size,
  176. "Shared memory exceeds bounds of mapped block");
  177. const std::shared_ptr<std::vector<u8>>& backing_block = vma->second.backing_block;
  178. std::size_t backing_block_offset = vma->second.offset + vma_offset;
  179. CASCADE_RESULT(auto new_vma,
  180. vm_manager.MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size,
  181. MemoryState::Mapped));
  182. // Protect mirror with permissions from old region
  183. vm_manager.Reprotect(new_vma, vma->second.permissions);
  184. // Remove permissions from old region
  185. vm_manager.Reprotect(vma, VMAPermission::None);
  186. return RESULT_SUCCESS;
  187. }
  188. ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
  189. return vm_manager.UnmapRange(dst_addr, size);
  190. }
  191. Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {}
  192. Kernel::Process::~Process() {}
  193. } // namespace Kernel