mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #2687 from yuriks/address-mappings
Kernel: Map special regions according to ExHeader
This commit is contained in:
		
						commit
						180587bb8b
					
				
					 11 changed files with 157 additions and 80 deletions
				
			
		|  | @ -2,6 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <array> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include "audio_core/audio_core.h" | #include "audio_core/audio_core.h" | ||||||
|  | @ -10,8 +11,8 @@ | ||||||
| #include "audio_core/null_sink.h" | #include "audio_core/null_sink.h" | ||||||
| #include "audio_core/sink.h" | #include "audio_core/sink.h" | ||||||
| #include "audio_core/sink_details.h" | #include "audio_core/sink_details.h" | ||||||
|  | #include "common/common_types.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/hle/kernel/vm_manager.h" |  | ||||||
| #include "core/hle/service/dsp_dsp.h" | #include "core/hle/service/dsp_dsp.h" | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
|  | @ -39,20 +40,8 @@ void Init() { | ||||||
|     CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event); |     CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void AddAddressSpace(Kernel::VMManager& address_space) { | std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() { | ||||||
|     auto r0_vma = address_space |     return DSP::HLE::g_dsp_memory.raw_memory; | ||||||
|                       .MapBackingMemory(DSP::HLE::region0_base, |  | ||||||
|                                         reinterpret_cast<u8*>(&DSP::HLE::g_regions[0]), |  | ||||||
|                                         sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO) |  | ||||||
|                       .MoveFrom(); |  | ||||||
|     address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite); |  | ||||||
| 
 |  | ||||||
|     auto r1_vma = address_space |  | ||||||
|                       .MapBackingMemory(DSP::HLE::region1_base, |  | ||||||
|                                         reinterpret_cast<u8*>(&DSP::HLE::g_regions[1]), |  | ||||||
|                                         sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO) |  | ||||||
|                       .MoveFrom(); |  | ||||||
|     address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SelectSink(std::string sink_id) { | void SelectSink(std::string sink_id) { | ||||||
|  |  | ||||||
|  | @ -4,11 +4,10 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <array> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | #include "common/common_types.h" | ||||||
| namespace Kernel { | #include "core/memory.h" | ||||||
| class VMManager; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
|  | @ -17,8 +16,8 @@ constexpr int native_sample_rate = 32728; ///< 32kHz | ||||||
| /// Initialise Audio Core
 | /// Initialise Audio Core
 | ||||||
| void Init(); | void Init(); | ||||||
| 
 | 
 | ||||||
| /// Add DSP address spaces to a Process.
 | /// Returns a reference to the array backing DSP memory
 | ||||||
| void AddAddressSpace(Kernel::VMManager& vm_manager); | std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory(); | ||||||
| 
 | 
 | ||||||
| /// Select the sink to use based on sink id.
 | /// Select the sink to use based on sink id.
 | ||||||
| void SelectSink(std::string sink_id); | void SelectSink(std::string sink_id); | ||||||
|  | @ -29,4 +28,4 @@ void EnableStretching(bool enable); | ||||||
| /// Shutdown Audio Core
 | /// Shutdown Audio Core
 | ||||||
| void Shutdown(); | void Shutdown(); | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -16,31 +16,33 @@ namespace HLE { | ||||||
| 
 | 
 | ||||||
| // Region management
 | // Region management
 | ||||||
| 
 | 
 | ||||||
| std::array<SharedMemory, 2> g_regions; | DspMemory g_dsp_memory; | ||||||
| 
 | 
 | ||||||
| static size_t CurrentRegionIndex() { | static size_t CurrentRegionIndex() { | ||||||
|     // The region with the higher frame counter is chosen unless there is wraparound.
 |     // The region with the higher frame counter is chosen unless there is wraparound.
 | ||||||
|     // This function only returns a 0 or 1.
 |     // This function only returns a 0 or 1.
 | ||||||
|  |     u16 frame_counter_0 = g_dsp_memory.region_0.frame_counter; | ||||||
|  |     u16 frame_counter_1 = g_dsp_memory.region_1.frame_counter; | ||||||
| 
 | 
 | ||||||
|     if (g_regions[0].frame_counter == 0xFFFFu && g_regions[1].frame_counter != 0xFFFEu) { |     if (frame_counter_0 == 0xFFFFu && frame_counter_1 != 0xFFFEu) { | ||||||
|         // Wraparound has occurred.
 |         // Wraparound has occurred.
 | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (g_regions[1].frame_counter == 0xFFFFu && g_regions[0].frame_counter != 0xFFFEu) { |     if (frame_counter_1 == 0xFFFFu && frame_counter_0 != 0xFFFEu) { | ||||||
|         // Wraparound has occurred.
 |         // Wraparound has occurred.
 | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return (g_regions[0].frame_counter > g_regions[1].frame_counter) ? 0 : 1; |     return (frame_counter_0 > frame_counter_1) ? 0 : 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static SharedMemory& ReadRegion() { | static SharedMemory& ReadRegion() { | ||||||
|     return g_regions[CurrentRegionIndex()]; |     return CurrentRegionIndex() == 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static SharedMemory& WriteRegion() { | static SharedMemory& WriteRegion() { | ||||||
|     return g_regions[1 - CurrentRegionIndex()]; |     return CurrentRegionIndex() != 0 ? g_dsp_memory.region_0 : g_dsp_memory.region_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Audio processing and mixing
 | // Audio processing and mixing
 | ||||||
|  |  | ||||||
|  | @ -31,8 +31,8 @@ namespace HLE { | ||||||
| // double-buffer. The frame counter is located as the very last u16 of each region and is
 | // double-buffer. The frame counter is located as the very last u16 of each region and is
 | ||||||
| // incremented each audio tick.
 | // incremented each audio tick.
 | ||||||
| 
 | 
 | ||||||
| constexpr VAddr region0_base = 0x1FF50000; | constexpr u32 region0_offset = 0x50000; | ||||||
| constexpr VAddr region1_base = 0x1FF70000; | constexpr u32 region1_offset = 0x70000; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * The DSP is native 16-bit. The DSP also appears to be big-endian. When reading 32-bit numbers from |  * The DSP is native 16-bit. The DSP also appears to be big-endian. When reading 32-bit numbers from | ||||||
|  | @ -512,7 +512,22 @@ struct SharedMemory { | ||||||
| }; | }; | ||||||
| ASSERT_DSP_STRUCT(SharedMemory, 0x8000); | ASSERT_DSP_STRUCT(SharedMemory, 0x8000); | ||||||
| 
 | 
 | ||||||
| extern std::array<SharedMemory, 2> g_regions; | union DspMemory { | ||||||
|  |     std::array<u8, 0x80000> raw_memory; | ||||||
|  |     struct { | ||||||
|  |         u8 unused_0[0x50000]; | ||||||
|  |         SharedMemory region_0; | ||||||
|  |         u8 unused_1[0x18000]; | ||||||
|  |         SharedMemory region_1; | ||||||
|  |         u8 unused_2[0x8000]; | ||||||
|  |     }; | ||||||
|  | }; | ||||||
|  | static_assert(offsetof(DspMemory, region_0) == region0_offset, | ||||||
|  |               "DSP region 0 is at the wrong offset"); | ||||||
|  | static_assert(offsetof(DspMemory, region_1) == region1_offset, | ||||||
|  |               "DSP region 1 is at the wrong offset"); | ||||||
|  | 
 | ||||||
|  | extern DspMemory g_dsp_memory; | ||||||
| 
 | 
 | ||||||
| // Structures must have an offset that is a multiple of two.
 | // Structures must have an offset that is a multiple of two.
 | ||||||
| static_assert(offsetof(SharedMemory, frame_counter) % 2 == 0, | static_assert(offsetof(SharedMemory, frame_counter) % 2 == 0, | ||||||
|  |  | ||||||
|  | @ -13,11 +13,11 @@ | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/memory.h" |  | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| #include "core/hw/hw.h" | #include "core/hw/hw.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
|  | #include "core/memory_setup.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  | @ -123,7 +123,8 @@ void System::Reschedule() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { | System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { | ||||||
|     Memory::Init(); |     Memory::InitMemoryMap(); | ||||||
|  |     LOG_DEBUG(HW_Memory, "initialized OK"); | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.use_cpu_jit) { |     if (Settings::values.use_cpu_jit) { | ||||||
|         cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE); |         cpu_core = std::make_unique<ARM_Dynarmic>(USER32MODE); | ||||||
|  |  | ||||||
|  | @ -2,11 +2,13 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <cinttypes> | ||||||
| #include <map> | #include <map> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include "audio_core/audio_core.h" | #include "audio_core/audio_core.h" | ||||||
|  | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/hle/config_mem.h" | #include "core/hle/config_mem.h" | ||||||
|  | @ -92,52 +94,96 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | ||||||
|         UNREACHABLE(); |         UNREACHABLE(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| namespace Memory { | std::array<u8, Memory::VRAM_SIZE> vram; | ||||||
|  | std::array<u8, Memory::N3DS_EXTRA_RAM_SIZE> n3ds_extra_ram; | ||||||
| 
 | 
 | ||||||
| namespace { | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { | ||||||
|  |     using namespace Memory; | ||||||
| 
 | 
 | ||||||
|     struct MemoryArea { |     struct MemoryArea { | ||||||
|     u32 base; |         VAddr vaddr_base; | ||||||
|  |         PAddr paddr_base; | ||||||
|         u32 size; |         u32 size; | ||||||
|     const char* name; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| // We don't declare the IO regions in here since its handled by other means.
 |     // The order of entries in this array is important. The VRAM and IO VAddr ranges overlap, and
 | ||||||
| static MemoryArea memory_areas[] = { |     // VRAM must be tried first.
 | ||||||
|     {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
 |     static constexpr MemoryArea memory_areas[] = { | ||||||
|  |         {VRAM_VADDR, VRAM_PADDR, VRAM_SIZE}, | ||||||
|  |         {IO_AREA_VADDR, IO_AREA_PADDR, IO_AREA_SIZE}, | ||||||
|  |         {DSP_RAM_VADDR, DSP_RAM_PADDR, DSP_RAM_SIZE}, | ||||||
|  |         {N3DS_EXTRA_RAM_VADDR, N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE - 0x20000}, | ||||||
|     }; |     }; | ||||||
|  | 
 | ||||||
|  |     VAddr mapping_limit = mapping.address + mapping.size; | ||||||
|  |     if (mapping_limit < mapping.address) { | ||||||
|  |         LOG_CRITICAL(Loader, "Mapping size overflowed: address=0x%08" PRIX32 " size=0x%" PRIX32, | ||||||
|  |                      mapping.address, mapping.size); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| void Init() { |     auto area = | ||||||
|     InitMemoryMap(); |         std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) { | ||||||
|     LOG_DEBUG(HW_Memory, "initialized OK"); |             return mapping.address >= area.vaddr_base && | ||||||
|  |                    mapping_limit <= area.vaddr_base + area.size; | ||||||
|  |         }); | ||||||
|  |     if (area == std::end(memory_areas)) { | ||||||
|  |         LOG_ERROR(Loader, "Unhandled special mapping: address=0x%08" PRIX32 " size=0x%" PRIX32 | ||||||
|  |                           " read_only=%d unk_flag=%d", | ||||||
|  |                   mapping.address, mapping.size, mapping.read_only, mapping.unk_flag); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| void InitLegacyAddressSpace(Kernel::VMManager& address_space) { |     u32 offset_into_region = mapping.address - area->vaddr_base; | ||||||
|     using namespace Kernel; |     if (area->paddr_base == IO_AREA_PADDR) { | ||||||
| 
 |         LOG_ERROR(Loader, "MMIO mappings are not supported yet. phys_addr=0x%08" PRIX32, | ||||||
|     for (MemoryArea& area : memory_areas) { |                   area->paddr_base + offset_into_region); | ||||||
|         auto block = std::make_shared<std::vector<u8>>(area.size); |         return; | ||||||
|         address_space |  | ||||||
|             .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private) |  | ||||||
|             .Unwrap(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // TODO(yuriks): Use GetPhysicalPointer when that becomes independent of the virtual
 | ||||||
|  |     // mappings.
 | ||||||
|  |     u8* target_pointer = nullptr; | ||||||
|  |     switch (area->paddr_base) { | ||||||
|  |     case VRAM_PADDR: | ||||||
|  |         target_pointer = vram.data(); | ||||||
|  |         break; | ||||||
|  |     case DSP_RAM_PADDR: | ||||||
|  |         target_pointer = AudioCore::GetDspMemory().data(); | ||||||
|  |         break; | ||||||
|  |     case N3DS_EXTRA_RAM_PADDR: | ||||||
|  |         target_pointer = n3ds_extra_ram.data(); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         UNREACHABLE(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // TODO(yuriks): This flag seems to have some other effect, but it's unknown what
 | ||||||
|  |     MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO; | ||||||
|  | 
 | ||||||
|  |     auto vma = address_space | ||||||
|  |                    .MapBackingMemory(mapping.address, target_pointer + offset_into_region, | ||||||
|  |                                      mapping.size, memory_state) | ||||||
|  |                    .MoveFrom(); | ||||||
|  |     address_space.Reprotect(vma, | ||||||
|  |                             mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapSharedPages(VMManager& address_space) { | ||||||
|     auto cfg_mem_vma = address_space |     auto cfg_mem_vma = address_space | ||||||
|                            .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem, |                            .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR, | ||||||
|                                              CONFIG_MEMORY_SIZE, MemoryState::Shared) |                                              reinterpret_cast<u8*>(&ConfigMem::config_mem), | ||||||
|  |                                              Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared) | ||||||
|                            .MoveFrom(); |                            .MoveFrom(); | ||||||
|     address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); |     address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | ||||||
| 
 | 
 | ||||||
|     auto shared_page_vma = address_space |     auto shared_page_vma = address_space | ||||||
|                                .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page, |                                .MapBackingMemory(Memory::SHARED_PAGE_VADDR, | ||||||
|                                                  SHARED_PAGE_SIZE, MemoryState::Shared) |                                                  reinterpret_cast<u8*>(&SharedPage::shared_page), | ||||||
|  |                                                  Memory::SHARED_PAGE_SIZE, MemoryState::Shared) | ||||||
|                                .MoveFrom(); |                                .MoveFrom(); | ||||||
|     address_space.Reprotect(shared_page_vma, VMAPermission::Read); |     address_space.Reprotect(shared_page_vma, VMAPermission::Read); | ||||||
| 
 |  | ||||||
|     AudioCore::AddAddressSpace(address_space); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace Kernel
 | ||||||
|  |  | ||||||
|  | @ -23,11 +23,7 @@ struct MemoryRegionInfo { | ||||||
| void MemoryInit(u32 mem_type); | void MemoryInit(u32 mem_type); | ||||||
| void MemoryShutdown(); | void MemoryShutdown(); | ||||||
| MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| namespace Memory { | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); | ||||||
| 
 | void MapSharedPages(VMManager& address_space); | ||||||
| void Init(); | } // namespace Kernel
 | ||||||
| void InitLegacyAddressSpace(Kernel::VMManager& address_space); |  | ||||||
| 
 |  | ||||||
| } // namespace
 |  | ||||||
|  |  | ||||||
|  | @ -35,7 +35,6 @@ SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) { | ||||||
|     process->codeset = std::move(code_set); |     process->codeset = std::move(code_set); | ||||||
|     process->flags.raw = 0; |     process->flags.raw = 0; | ||||||
|     process->flags.memory_region.Assign(MemoryRegion::APPLICATION); |     process->flags.memory_region.Assign(MemoryRegion::APPLICATION); | ||||||
|     Memory::InitLegacyAddressSpace(process->vm_manager); |  | ||||||
| 
 | 
 | ||||||
|     return process; |     return process; | ||||||
| } | } | ||||||
|  | @ -78,8 +77,15 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | ||||||
| 
 | 
 | ||||||
|             AddressMapping mapping; |             AddressMapping mapping; | ||||||
|             mapping.address = descriptor << 12; |             mapping.address = descriptor << 12; | ||||||
|             mapping.size = (end_desc << 12) - mapping.address; |             VAddr end_address = end_desc << 12; | ||||||
|             mapping.writable = (descriptor & (1 << 20)) != 0; | 
 | ||||||
|  |             if (mapping.address < end_address) { | ||||||
|  |                 mapping.size = end_address - mapping.address; | ||||||
|  |             } else { | ||||||
|  |                 mapping.size = 0; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             mapping.read_only = (descriptor & (1 << 20)) != 0; | ||||||
|             mapping.unk_flag = (end_desc & (1 << 20)) != 0; |             mapping.unk_flag = (end_desc & (1 << 20)) != 0; | ||||||
| 
 | 
 | ||||||
|             address_mappings.push_back(mapping); |             address_mappings.push_back(mapping); | ||||||
|  | @ -88,8 +94,10 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | ||||||
|             AddressMapping mapping; |             AddressMapping mapping; | ||||||
|             mapping.address = descriptor << 12; |             mapping.address = descriptor << 12; | ||||||
|             mapping.size = Memory::PAGE_SIZE; |             mapping.size = Memory::PAGE_SIZE; | ||||||
|             mapping.writable = true; // TODO: Not sure if correct
 |             mapping.read_only = false; | ||||||
|             mapping.unk_flag = false; |             mapping.unk_flag = false; | ||||||
|  | 
 | ||||||
|  |             address_mappings.push_back(mapping); | ||||||
|         } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
 |         } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
 | ||||||
|             // Kernel version
 |             // Kernel version
 | ||||||
|             kernel_version = descriptor & 0xFFFF; |             kernel_version = descriptor & 0xFFFF; | ||||||
|  | @ -131,6 +139,12 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | ||||||
|     misc_memory_used += stack_size; |     misc_memory_used += stack_size; | ||||||
|     memory_region->used += stack_size; |     memory_region->used += stack_size; | ||||||
| 
 | 
 | ||||||
|  |     // Map special address mappings
 | ||||||
|  |     MapSharedPages(vm_manager); | ||||||
|  |     for (const auto& mapping : address_mappings) { | ||||||
|  |         HandleSpecialMapping(vm_manager, mapping); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     vm_manager.LogLayout(Log::Level::Debug); |     vm_manager.LogLayout(Log::Level::Debug); | ||||||
|     Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); |     Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | ||||||
| } | } | ||||||
|  | @ -138,6 +152,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | ||||||
| VAddr Process::GetLinearHeapAreaAddress() const { | VAddr Process::GetLinearHeapAreaAddress() const { | ||||||
|     return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR; |     return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| VAddr Process::GetLinearHeapBase() const { | VAddr Process::GetLinearHeapBase() const { | ||||||
|     return GetLinearHeapAreaAddress() + memory_region->base; |     return GetLinearHeapAreaAddress() + memory_region->base; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ struct AddressMapping { | ||||||
|     // Address and size must be page-aligned
 |     // Address and size must be page-aligned
 | ||||||
|     VAddr address; |     VAddr address; | ||||||
|     u32 size; |     u32 size; | ||||||
|     bool writable; |     bool read_only; | ||||||
|     bool unk_flag; |     bool unk_flag; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -672,12 +672,14 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) { | ||||||
|         return addr - VRAM_VADDR + VRAM_PADDR; |         return addr - VRAM_VADDR + VRAM_PADDR; | ||||||
|     } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { |     } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { | ||||||
|         return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; |         return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||||||
|  |     } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||||||
|  |         return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||||||
|     } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { |     } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { | ||||||
|         return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; |         return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; | ||||||
|     } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { |     } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { | ||||||
|         return addr - IO_AREA_VADDR + IO_AREA_PADDR; |         return addr - IO_AREA_VADDR + IO_AREA_PADDR; | ||||||
|     } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { |     } else if (addr >= N3DS_EXTRA_RAM_VADDR && addr < N3DS_EXTRA_RAM_VADDR_END) { | ||||||
|         return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; |         return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); |     LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); | ||||||
|  | @ -696,6 +698,8 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) { | ||||||
|         return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; |         return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; | ||||||
|     } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { |     } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { | ||||||
|         return addr - IO_AREA_PADDR + IO_AREA_VADDR; |         return addr - IO_AREA_PADDR + IO_AREA_VADDR; | ||||||
|  |     } else if (addr >= N3DS_EXTRA_RAM_PADDR && addr < N3DS_EXTRA_RAM_PADDR_END) { | ||||||
|  |         return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr); |     LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr); | ||||||
|  |  | ||||||
|  | @ -37,6 +37,12 @@ enum : PAddr { | ||||||
|     VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
 |     VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
 | ||||||
|     VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, |     VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, | ||||||
| 
 | 
 | ||||||
|  |     /// New 3DS additional memory. Supposedly faster than regular FCRAM. Part of it can be used by
 | ||||||
|  |     /// applications and system modules if mapped via the ExHeader.
 | ||||||
|  |     N3DS_EXTRA_RAM_PADDR = 0x1F000000, | ||||||
|  |     N3DS_EXTRA_RAM_SIZE = 0x00400000, ///< New 3DS additional memory size (4MB)
 | ||||||
|  |     N3DS_EXTRA_RAM_PADDR_END = N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_SIZE, | ||||||
|  | 
 | ||||||
|     /// DSP memory
 |     /// DSP memory
 | ||||||
|     DSP_RAM_PADDR = 0x1FF00000, |     DSP_RAM_PADDR = 0x1FF00000, | ||||||
|     DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
 |     DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
 | ||||||
|  | @ -81,6 +87,10 @@ enum : VAddr { | ||||||
|     LINEAR_HEAP_SIZE = 0x08000000, |     LINEAR_HEAP_SIZE = 0x08000000, | ||||||
|     LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, |     LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, | ||||||
| 
 | 
 | ||||||
|  |     /// Maps 1:1 to New 3DS additional memory
 | ||||||
|  |     N3DS_EXTRA_RAM_VADDR = 0x1E800000, | ||||||
|  |     N3DS_EXTRA_RAM_VADDR_END = N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_SIZE, | ||||||
|  | 
 | ||||||
|     /// Maps 1:1 to the IO register area.
 |     /// Maps 1:1 to the IO register area.
 | ||||||
|     IO_AREA_VADDR = 0x1EC00000, |     IO_AREA_VADDR = 0x1EC00000, | ||||||
|     IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, |     IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue