mem_map.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <map>
  5. #include "common/common_types.h"
  6. #include "common/logging/log.h"
  7. #include "core/hle/config_mem.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/shared_memory.h"
  10. #include "core/hle/kernel/vm_manager.h"
  11. #include "core/hle/result.h"
  12. #include "core/hle/shared_page.h"
  13. #include "core/mem_map.h"
  14. #include "core/memory.h"
  15. #include "core/memory_setup.h"
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////
  17. namespace Memory {
  18. namespace {
  19. struct MemoryArea {
  20. u32 base;
  21. u32 size;
  22. const char* name;
  23. };
  24. // We don't declare the IO regions in here since its handled by other means.
  25. static MemoryArea memory_areas[] = {
  26. {PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE, "Process Image"}, // ExeFS:/.code is loaded here
  27. {HEAP_VADDR, HEAP_SIZE, "Heap"}, // Application heap (main memory)
  28. {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory
  29. {LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE, "Linear Heap"}, // Linear heap (main memory)
  30. {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
  31. {DSP_RAM_VADDR, DSP_RAM_SIZE, "DSP RAM"}, // DSP memory
  32. {TLS_AREA_VADDR, TLS_AREA_SIZE, "TLS Area"}, // TLS memory
  33. };
  34. /// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
  35. struct MemoryBlock {
  36. MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) {
  37. }
  38. u32 handle;
  39. u32 base_address;
  40. u32 address;
  41. u32 size;
  42. u32 operation;
  43. u32 permissions;
  44. const u32 GetVirtualAddress() const{
  45. return base_address + address;
  46. }
  47. };
  48. static std::map<u32, MemoryBlock> heap_map;
  49. static std::map<u32, MemoryBlock> heap_linear_map;
  50. }
  51. u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
  52. MemoryBlock block;
  53. block.base_address = HEAP_VADDR;
  54. block.size = size;
  55. block.operation = operation;
  56. block.permissions = permissions;
  57. if (heap_map.size() > 0) {
  58. const MemoryBlock last_block = heap_map.rbegin()->second;
  59. block.address = last_block.address + last_block.size;
  60. }
  61. heap_map[block.GetVirtualAddress()] = block;
  62. return block.GetVirtualAddress();
  63. }
  64. u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
  65. MemoryBlock block;
  66. block.base_address = LINEAR_HEAP_VADDR;
  67. block.size = size;
  68. block.operation = operation;
  69. block.permissions = permissions;
  70. if (heap_linear_map.size() > 0) {
  71. const MemoryBlock last_block = heap_linear_map.rbegin()->second;
  72. block.address = last_block.address + last_block.size;
  73. }
  74. heap_linear_map[block.GetVirtualAddress()] = block;
  75. return block.GetVirtualAddress();
  76. }
  77. PAddr VirtualToPhysicalAddress(const VAddr addr) {
  78. if (addr == 0) {
  79. return 0;
  80. } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
  81. return addr - VRAM_VADDR + VRAM_PADDR;
  82. } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
  83. return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
  84. } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
  85. return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
  86. } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
  87. return addr - IO_AREA_VADDR + IO_AREA_PADDR;
  88. }
  89. LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
  90. // To help with debugging, set bit on address so that it's obviously invalid.
  91. return addr | 0x80000000;
  92. }
  93. VAddr PhysicalToVirtualAddress(const PAddr addr) {
  94. if (addr == 0) {
  95. return 0;
  96. } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
  97. return addr - VRAM_PADDR + VRAM_VADDR;
  98. } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
  99. return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR;
  100. } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
  101. return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
  102. } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
  103. return addr - IO_AREA_PADDR + IO_AREA_VADDR;
  104. }
  105. LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
  106. // To help with debugging, set bit on address so that it's obviously invalid.
  107. return addr | 0x80000000;
  108. }
  109. // TODO(yuriks): Move this into Process
  110. static Kernel::VMManager address_space;
  111. void Init() {
  112. using namespace Kernel;
  113. InitMemoryMap();
  114. for (MemoryArea& area : memory_areas) {
  115. auto block = std::make_shared<std::vector<u8>>(area.size);
  116. address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap();
  117. }
  118. auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR,
  119. (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom();
  120. address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
  121. auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR,
  122. (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom();
  123. address_space.Reprotect(shared_page_vma, VMAPermission::Read);
  124. LOG_DEBUG(HW_Memory, "initialized OK");
  125. }
  126. void Shutdown() {
  127. heap_map.clear();
  128. heap_linear_map.clear();
  129. address_space.Reset();
  130. LOG_DEBUG(HW_Memory, "shutdown OK");
  131. }
  132. } // namespace