1 // Copyright 2014 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <array> 8 #include <cstddef> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 #include <boost/serialization/array.hpp> 13 #include <boost/serialization/vector.hpp> 14 #include "common/common_types.h" 15 #include "common/memory_ref.h" 16 #include "core/mmio.h" 17 18 class ARM_Interface; 19 20 namespace Kernel { 21 class Process; 22 } 23 24 namespace AudioCore { 25 class DspInterface; 26 } 27 28 namespace Memory { 29 30 // Are defined in a system header 31 #undef PAGE_SIZE 32 #undef PAGE_MASK 33 /** 34 * Page size used by the ARM architecture. This is the smallest granularity with which memory can 35 * be mapped. 36 */ 37 const u32 PAGE_SIZE = 0x1000; 38 const u32 PAGE_MASK = PAGE_SIZE - 1; 39 const int PAGE_BITS = 12; 40 const std::size_t PAGE_TABLE_NUM_ENTRIES = 1 << (32 - PAGE_BITS); 41 42 enum class PageType { 43 /// Page is unmapped and should cause an access error. 44 Unmapped, 45 /// Page is mapped to regular memory. This is the only type you can get pointers to. 46 Memory, 47 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and 48 /// invalidation 49 RasterizerCachedMemory, 50 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. 51 Special, 52 }; 53 54 struct SpecialRegion { 55 VAddr base; 56 u32 size; 57 MMIORegionPointer handler; 58 59 private: 60 template <class Archive> serializeSpecialRegion61 void serialize(Archive& ar, const unsigned int file_version) { 62 ar& base; 63 ar& size; 64 ar& handler; 65 } 66 friend class boost::serialization::access; 67 }; 68 69 /** 70 * A (reasonably) fast way of allowing switchable and remappable process address spaces. It loosely 71 * mimics the way a real CPU page table works, but instead is optimized for minimal decoding and 72 * fetching requirements when accessing. In the usual case of an access to regular memory, it only 73 * requires an indexed fetch and a check for NULL. 74 */ 75 struct PageTable { 76 /** 77 * Array of memory pointers backing each page. An entry can only be non-null if the 78 * corresponding entry in the `attributes` array is of type `Memory`. 79 */ 80 81 // The reason for this rigmarole is to keep the 'raw' and 'refs' arrays in sync. 82 // We need 'raw' for dynarmic and 'refs' for serialization 83 struct Pointers { 84 85 struct Entry { EntryPageTable::Pointers::Entry86 Entry(Pointers& pointers_, VAddr idx_) : pointers(pointers_), idx(idx_) {} 87 88 Entry& operator=(MemoryRef value) { 89 pointers.raw[idx] = value.GetPtr(); 90 pointers.refs[idx] = std::move(value); 91 return *this; 92 } 93 94 operator u8*() { 95 return pointers.raw[idx]; 96 } 97 98 private: 99 Pointers& pointers; 100 VAddr idx; 101 }; 102 103 Entry operator[](std::size_t idx) { 104 return Entry(*this, static_cast<VAddr>(idx)); 105 } 106 107 private: 108 std::array<u8*, PAGE_TABLE_NUM_ENTRIES> raw; 109 110 std::array<MemoryRef, PAGE_TABLE_NUM_ENTRIES> refs; 111 112 friend struct PageTable; 113 }; 114 Pointers pointers; 115 116 /** 117 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of 118 * type `Special`. 119 */ 120 std::vector<SpecialRegion> special_regions; 121 122 /** 123 * Array of fine grained page attributes. If it is set to any value other than `Memory`, then 124 * the corresponding entry in `pointers` MUST be set to null. 125 */ 126 std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; 127 GetPointerArrayPageTable128 std::array<u8*, PAGE_TABLE_NUM_ENTRIES>& GetPointerArray() { 129 return pointers.raw; 130 } 131 132 void Clear(); 133 134 private: 135 template <class Archive> serializePageTable136 void serialize(Archive& ar, const unsigned int) { 137 ar& pointers.refs; 138 ar& special_regions; 139 ar& attributes; 140 for (std::size_t i = 0; i < PAGE_TABLE_NUM_ENTRIES; i++) { 141 pointers.raw[i] = pointers.refs[i].GetPtr(); 142 } 143 } 144 friend class boost::serialization::access; 145 }; 146 147 /// Physical memory regions as seen from the ARM11 148 enum : PAddr { 149 /// IO register area 150 IO_AREA_PADDR = 0x10100000, 151 IO_AREA_SIZE = 0x00400000, ///< IO area size (4MB) 152 IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, 153 154 /// MPCore internal memory region 155 MPCORE_RAM_PADDR = 0x17E00000, 156 MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) 157 MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, 158 159 /// Video memory 160 VRAM_PADDR = 0x18000000, 161 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) 162 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, 163 164 /// New 3DS additional memory. Supposedly faster than regular FCRAM. Part of it can be used by 165 /// applications and system modules if mapped via the ExHeader. 166 N3DS_EXTRA_RAM_PADDR = 0x1F000000, 167 N3DS_EXTRA_RAM_SIZE = 0x00400000, ///< New 3DS additional memory size (4MB) 168 N3DS_EXTRA_RAM_PADDR_END = N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_SIZE, 169 170 /// DSP memory 171 DSP_RAM_PADDR = 0x1FF00000, 172 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) 173 DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, 174 175 /// AXI WRAM 176 AXI_WRAM_PADDR = 0x1FF80000, 177 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) 178 AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, 179 180 /// Main FCRAM 181 FCRAM_PADDR = 0x20000000, 182 FCRAM_SIZE = 0x08000000, ///< FCRAM size on the Old 3DS (128MB) 183 FCRAM_N3DS_SIZE = 0x10000000, ///< FCRAM size on the New 3DS (256MB) 184 FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, 185 FCRAM_N3DS_PADDR_END = FCRAM_PADDR + FCRAM_N3DS_SIZE, 186 }; 187 188 enum class Region { FCRAM, VRAM, DSP, N3DS }; 189 190 /// Virtual user-space memory regions 191 enum : VAddr { 192 /// Where the application text, data and bss reside. 193 PROCESS_IMAGE_VADDR = 0x00100000, 194 PROCESS_IMAGE_MAX_SIZE = 0x03F00000, 195 PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, 196 197 /// Area where IPC buffers are mapped onto. 198 IPC_MAPPING_VADDR = 0x04000000, 199 IPC_MAPPING_SIZE = 0x04000000, 200 IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, 201 202 /// Application heap (includes stack). 203 HEAP_VADDR = 0x08000000, 204 HEAP_SIZE = 0x08000000, 205 HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, 206 207 /// Area where shared memory buffers are mapped onto. 208 SHARED_MEMORY_VADDR = 0x10000000, 209 SHARED_MEMORY_SIZE = 0x04000000, 210 SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, 211 212 /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical 213 /// memory. 214 LINEAR_HEAP_VADDR = 0x14000000, 215 LINEAR_HEAP_SIZE = 0x08000000, 216 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, 217 218 /// Maps 1:1 to New 3DS additional memory 219 N3DS_EXTRA_RAM_VADDR = 0x1E800000, 220 N3DS_EXTRA_RAM_VADDR_END = N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_SIZE, 221 222 /// Maps 1:1 to the IO register area. 223 IO_AREA_VADDR = 0x1EC00000, 224 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, 225 226 /// Maps 1:1 to VRAM. 227 VRAM_VADDR = 0x1F000000, 228 VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, 229 230 /// Maps 1:1 to DSP memory. 231 DSP_RAM_VADDR = 0x1FF00000, 232 DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, 233 234 /// Read-only page containing kernel and system configuration values. 235 CONFIG_MEMORY_VADDR = 0x1FF80000, 236 CONFIG_MEMORY_SIZE = 0x00001000, 237 CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, 238 239 /// Usually read-only page containing mostly values read from hardware. 240 SHARED_PAGE_VADDR = 0x1FF81000, 241 SHARED_PAGE_SIZE = 0x00001000, 242 SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, 243 244 /// Area where TLS (Thread-Local Storage) buffers are allocated. 245 TLS_AREA_VADDR = 0x1FF82000, 246 TLS_ENTRY_SIZE = 0x200, 247 248 /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. 249 NEW_LINEAR_HEAP_VADDR = 0x30000000, 250 NEW_LINEAR_HEAP_SIZE = 0x10000000, 251 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, 252 }; 253 254 /** 255 * Flushes any externally cached rasterizer resources touching the given region. 256 */ 257 void RasterizerFlushRegion(PAddr start, u32 size); 258 259 /** 260 * Invalidates any externally cached rasterizer resources touching the given region. 261 */ 262 void RasterizerInvalidateRegion(PAddr start, u32 size); 263 264 /** 265 * Flushes and invalidates any externally cached rasterizer resources touching the given region. 266 */ 267 void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 268 269 enum class FlushMode { 270 /// Write back modified surfaces to RAM 271 Flush, 272 /// Remove region from the cache 273 Invalidate, 274 /// Write back modified surfaces to RAM, and also remove them from the cache 275 FlushAndInvalidate, 276 }; 277 278 /** 279 * Flushes and invalidates all memory in the rasterizer cache and removes any leftover state 280 * If flush is true, the rasterizer should flush any cached resources to RAM before clearing 281 */ 282 void RasterizerClearAll(bool flush); 283 284 /** 285 * Flushes and invalidates any externally cached rasterizer resources touching the given virtual 286 * address region. 287 */ 288 void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); 289 290 class MemorySystem { 291 public: 292 MemorySystem(); 293 ~MemorySystem(); 294 295 /** 296 * Maps an allocated buffer onto a region of the emulated process address space. 297 * 298 * @param page_table The page table of the emulated process. 299 * @param base The address to start mapping at. Must be page-aligned. 300 * @param size The amount of bytes to map. Must be page-aligned. 301 * @param target Buffer with the memory backing the mapping. Must be of length at least `size`. 302 */ 303 void MapMemoryRegion(PageTable& page_table, VAddr base, u32 size, MemoryRef target); 304 305 /** 306 * Maps a region of the emulated process address space as a IO region. 307 * @param page_table The page table of the emulated process. 308 * @param base The address to start mapping at. Must be page-aligned. 309 * @param size The amount of bytes to map. Must be page-aligned. 310 * @param mmio_handler The handler that backs the mapping. 311 */ 312 void MapIoRegion(PageTable& page_table, VAddr base, u32 size, MMIORegionPointer mmio_handler); 313 314 void UnmapRegion(PageTable& page_table, VAddr base, u32 size); 315 316 /// Currently active page table 317 void SetCurrentPageTable(std::shared_ptr<PageTable> page_table); 318 std::shared_ptr<PageTable> GetCurrentPageTable() const; 319 320 u8 Read8(VAddr addr); 321 u16 Read16(VAddr addr); 322 u32 Read32(VAddr addr); 323 u64 Read64(VAddr addr); 324 325 void Write8(VAddr addr, u8 data); 326 void Write16(VAddr addr, u16 data); 327 void Write32(VAddr addr, u32 data); 328 void Write64(VAddr addr, u64 data); 329 330 void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, 331 std::size_t size); 332 void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, 333 std::size_t size); 334 void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size); 335 void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, 336 std::size_t size); 337 void CopyBlock(const Kernel::Process& dest_process, const Kernel::Process& src_process, 338 VAddr dest_addr, VAddr src_addr, std::size_t size); 339 340 std::string ReadCString(VAddr vaddr, std::size_t max_length); 341 342 /// Gets a pointer to the memory region beginning at the specified physical address. 343 u8* GetPhysicalPointer(PAddr address); 344 345 /// Gets a pointer to the memory region beginning at the specified physical address. 346 const u8* GetPhysicalPointer(PAddr address) const; 347 348 MemoryRef GetPhysicalRef(PAddr address) const; 349 350 u8* GetPointer(VAddr vaddr); 351 const u8* GetPointer(VAddr vaddr) const; 352 353 bool IsValidPhysicalAddress(PAddr paddr) const; 354 355 /// Gets offset in FCRAM from a pointer inside FCRAM range 356 u32 GetFCRAMOffset(const u8* pointer) const; 357 358 /// Gets pointer in FCRAM with given offset 359 u8* GetFCRAMPointer(std::size_t offset); 360 361 /// Gets pointer in FCRAM with given offset 362 const u8* GetFCRAMPointer(std::size_t offset) const; 363 364 /// Gets a serializable ref to FCRAM with the given offset 365 MemoryRef GetFCRAMRef(std::size_t offset) const; 366 367 /** 368 * Mark each page touching the region as cached. 369 */ 370 void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); 371 372 /// Registers page table for rasterizer cache marking 373 void RegisterPageTable(std::shared_ptr<PageTable> page_table); 374 375 /// Unregisters page table for rasterizer cache marking 376 void UnregisterPageTable(std::shared_ptr<PageTable> page_table); 377 378 void SetDSP(AudioCore::DspInterface& dsp); 379 380 private: 381 template <typename T> 382 T Read(const VAddr vaddr); 383 384 template <typename T> 385 void Write(const VAddr vaddr, const T data); 386 387 /** 388 * Gets the pointer for virtual memory where the page is marked as RasterizerCachedMemory. 389 * This is used to access the memory where the page pointer is nullptr due to rasterizer cache. 390 * Since the cache only happens on linear heap or VRAM, we know the exact physical address and 391 * pointer of such virtual address 392 */ 393 MemoryRef GetPointerForRasterizerCache(VAddr addr) const; 394 395 void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type); 396 397 class Impl; 398 399 std::unique_ptr<Impl> impl; 400 401 friend class boost::serialization::access; 402 template <class Archive> 403 void serialize(Archive& ar, const unsigned int file_version); 404 405 public: 406 template <Region R> 407 class BackingMemImpl; 408 }; 409 410 /// Determines if the given VAddr is valid for the specified process. 411 bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); 412 413 } // namespace Memory 414 415 BOOST_CLASS_EXPORT_KEY(Memory::MemorySystem::BackingMemImpl<Memory::Region::FCRAM>) 416 BOOST_CLASS_EXPORT_KEY(Memory::MemorySystem::BackingMemImpl<Memory::Region::VRAM>) 417 BOOST_CLASS_EXPORT_KEY(Memory::MemorySystem::BackingMemImpl<Memory::Region::DSP>) 418 BOOST_CLASS_EXPORT_KEY(Memory::MemorySystem::BackingMemImpl<Memory::Region::N3DS>) 419