diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/config_mem.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/hle.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.cpp | 72 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.h | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 44 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 6 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 2 | ||||
| -rw-r--r-- | src/core/memory.cpp | 5 | ||||
| -rw-r--r-- | src/core/memory.h | 5 |
10 files changed, 148 insertions, 28 deletions
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index 94bca0378..b1a72dc0c 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp | |||
| @@ -25,10 +25,6 @@ void Init() { | |||
| 25 | config_mem.sys_core_ver = 0x2; | 25 | config_mem.sys_core_ver = 0x2; |
| 26 | config_mem.unit_info = 0x1; // Bit 0 set for Retail | 26 | config_mem.unit_info = 0x1; // Bit 0 set for Retail |
| 27 | config_mem.prev_firm = 0; | 27 | config_mem.prev_firm = 0; |
| 28 | config_mem.app_mem_type = 0x2; // Default app mem type is 0 | ||
| 29 | config_mem.app_mem_alloc = 0x06000000; // Set to 96MB, since some games use more than the default (64MB) | ||
| 30 | config_mem.base_mem_alloc = 0x01400000; // Default base memory is 20MB | ||
| 31 | config_mem.sys_mem_alloc = Memory::FCRAM_SIZE - (config_mem.app_mem_alloc + config_mem.base_mem_alloc); | ||
| 32 | config_mem.firm_unk = 0; | 28 | config_mem.firm_unk = 0; |
| 33 | config_mem.firm_version_rev = 0; | 29 | config_mem.firm_version_rev = 0; |
| 34 | config_mem.firm_version_min = 0x40; | 30 | config_mem.firm_version_min = 0x40; |
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 98dc8dd58..331b1b22a 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp | |||
| @@ -34,8 +34,6 @@ void Reschedule(const char *reason) { | |||
| 34 | 34 | ||
| 35 | void Init() { | 35 | void Init() { |
| 36 | Service::Init(); | 36 | Service::Init(); |
| 37 | ConfigMem::Init(); | ||
| 38 | SharedPage::Init(); | ||
| 39 | 37 | ||
| 40 | g_reschedule = false; | 38 | g_reschedule = false; |
| 41 | 39 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 5711c0405..7a401a965 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -7,11 +7,14 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | 9 | ||
| 10 | #include "core/hle/config_mem.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/resource_limit.h" | 12 | #include "core/hle/kernel/memory.h" |
| 12 | #include "core/hle/kernel/process.h" | 13 | #include "core/hle/kernel/process.h" |
| 14 | #include "core/hle/kernel/resource_limit.h" | ||
| 13 | #include "core/hle/kernel/thread.h" | 15 | #include "core/hle/kernel/thread.h" |
| 14 | #include "core/hle/kernel/timer.h" | 16 | #include "core/hle/kernel/timer.h" |
| 17 | #include "core/hle/shared_page.h" | ||
| 15 | 18 | ||
| 16 | namespace Kernel { | 19 | namespace Kernel { |
| 17 | 20 | ||
| @@ -119,6 +122,13 @@ void HandleTable::Clear() { | |||
| 119 | 122 | ||
| 120 | /// Initialize the kernel | 123 | /// Initialize the kernel |
| 121 | void Init() { | 124 | void Init() { |
| 125 | ConfigMem::Init(); | ||
| 126 | SharedPage::Init(); | ||
| 127 | |||
| 128 | // TODO(yuriks): The memory type parameter needs to be determined by the ExHeader field instead | ||
| 129 | // For now it defaults to the one with a largest allocation to the app | ||
| 130 | Kernel::MemoryInit(2); // Allocates 96MB to the application | ||
| 131 | |||
| 122 | Kernel::ResourceLimitsInit(); | 132 | Kernel::ResourceLimitsInit(); |
| 123 | Kernel::ThreadingInit(); | 133 | Kernel::ThreadingInit(); |
| 124 | Kernel::TimersInit(); | 134 | Kernel::TimersInit(); |
| @@ -131,11 +141,14 @@ void Init() { | |||
| 131 | 141 | ||
| 132 | /// Shutdown the kernel | 142 | /// Shutdown the kernel |
| 133 | void Shutdown() { | 143 | void Shutdown() { |
| 144 | g_handle_table.Clear(); // Free all kernel objects | ||
| 145 | |||
| 134 | Kernel::ThreadingShutdown(); | 146 | Kernel::ThreadingShutdown(); |
| 147 | g_current_process = nullptr; | ||
| 148 | |||
| 135 | Kernel::TimersShutdown(); | 149 | Kernel::TimersShutdown(); |
| 136 | Kernel::ResourceLimitsShutdown(); | 150 | Kernel::ResourceLimitsShutdown(); |
| 137 | g_handle_table.Clear(); // Free all kernel objects | 151 | Kernel::MemoryShutdown(); |
| 138 | g_current_process = nullptr; | ||
| 139 | } | 152 | } |
| 140 | 153 | ||
| 141 | } // namespace | 154 | } // namespace |
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 57e1912d3..e69b121eb 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | 12 | ||
| 13 | #include "core/hle/config_mem.h" | 13 | #include "core/hle/config_mem.h" |
| 14 | #include "core/hle/kernel/memory.h" | ||
| 14 | #include "core/hle/kernel/vm_manager.h" | 15 | #include "core/hle/kernel/vm_manager.h" |
| 15 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| 16 | #include "core/hle/shared_page.h" | 17 | #include "core/hle/shared_page.h" |
| @@ -19,6 +20,77 @@ | |||
| 19 | 20 | ||
| 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 21 | 22 | ||
| 23 | namespace Kernel { | ||
| 24 | |||
| 25 | static MemoryRegionInfo memory_regions[3]; | ||
| 26 | |||
| 27 | /// Size of the APPLICATION, SYSTEM and BASE memory regions (respectively) for each sytem | ||
| 28 | /// memory configuration type. | ||
| 29 | static const u32 memory_region_sizes[8][3] = { | ||
| 30 | // Old 3DS layouts | ||
| 31 | {0x04000000, 0x02C00000, 0x01400000}, // 0 | ||
| 32 | { /* This appears to be unused. */ }, // 1 | ||
| 33 | {0x06000000, 0x00C00000, 0x01400000}, // 2 | ||
| 34 | {0x05000000, 0x01C00000, 0x01400000}, // 3 | ||
| 35 | {0x04800000, 0x02400000, 0x01400000}, // 4 | ||
| 36 | {0x02000000, 0x04C00000, 0x01400000}, // 5 | ||
| 37 | |||
| 38 | // New 3DS layouts | ||
| 39 | {0x07C00000, 0x06400000, 0x02000000}, // 6 | ||
| 40 | {0x0B200000, 0x02E00000, 0x02000000}, // 7 | ||
| 41 | }; | ||
| 42 | |||
| 43 | void MemoryInit(u32 mem_type) { | ||
| 44 | // TODO(yuriks): On the n3DS, all o3DS configurations (<=5) are forced to 6 instead. | ||
| 45 | ASSERT_MSG(mem_type <= 5, "New 3DS memory configuration aren't supported yet!"); | ||
| 46 | ASSERT(mem_type != 1); | ||
| 47 | |||
| 48 | // The kernel allocation regions (APPLICATION, SYSTEM and BASE) are laid out in sequence, with | ||
| 49 | // the sizes specified in the memory_region_sizes table. | ||
| 50 | VAddr base = 0; | ||
| 51 | for (int i = 0; i < 3; ++i) { | ||
| 52 | memory_regions[i].base = base; | ||
| 53 | memory_regions[i].size = memory_region_sizes[mem_type][i]; | ||
| 54 | memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>(); | ||
| 55 | |||
| 56 | base += memory_regions[i].size; | ||
| 57 | } | ||
| 58 | |||
| 59 | // We must've allocated the entire FCRAM by the end | ||
| 60 | ASSERT(base == Memory::FCRAM_SIZE); | ||
| 61 | |||
| 62 | using ConfigMem::config_mem; | ||
| 63 | config_mem.app_mem_type = mem_type; | ||
| 64 | // app_mem_malloc does not always match the configured size for memory_region[0]: in case the | ||
| 65 | // n3DS type override is in effect it reports the size the game expects, not the real one. | ||
| 66 | config_mem.app_mem_alloc = memory_region_sizes[mem_type][0]; | ||
| 67 | config_mem.sys_mem_alloc = memory_regions[1].size; | ||
| 68 | config_mem.base_mem_alloc = memory_regions[2].size; | ||
| 69 | } | ||
| 70 | |||
| 71 | void MemoryShutdown() { | ||
| 72 | for (auto& region : memory_regions) { | ||
| 73 | region.base = 0; | ||
| 74 | region.size = 0; | ||
| 75 | region.linear_heap_memory = nullptr; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | ||
| 80 | switch (region) { | ||
| 81 | case MemoryRegion::APPLICATION: | ||
| 82 | return &memory_regions[0]; | ||
| 83 | case MemoryRegion::SYSTEM: | ||
| 84 | return &memory_regions[1]; | ||
| 85 | case MemoryRegion::BASE: | ||
| 86 | return &memory_regions[2]; | ||
| 87 | default: | ||
| 88 | UNREACHABLE(); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | } | ||
| 93 | |||
| 22 | namespace Memory { | 94 | namespace Memory { |
| 23 | 95 | ||
| 24 | namespace { | 96 | namespace { |
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h index cba8a0714..2e2cae17d 100644 --- a/src/core/hle/kernel/memory.h +++ b/src/core/hle/kernel/memory.h | |||
| @@ -4,10 +4,27 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | 10 | ||
| 11 | #include "core/hle/kernel/process.h" | ||
| 12 | |||
| 9 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | |||
| 10 | class VMManager; | 15 | class VMManager; |
| 16 | |||
| 17 | struct MemoryRegionInfo { | ||
| 18 | u32 base; // Not an address, but offset from start of FCRAM | ||
| 19 | u32 size; | ||
| 20 | |||
| 21 | std::shared_ptr<std::vector<u8>> linear_heap_memory; | ||
| 22 | }; | ||
| 23 | |||
| 24 | void MemoryInit(u32 mem_type); | ||
| 25 | void MemoryShutdown(); | ||
| 26 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | ||
| 27 | |||
| 11 | } | 28 | } |
| 12 | 29 | ||
| 13 | namespace Memory { | 30 | namespace Memory { |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 2cd1cfc14..1f45e6cf8 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -96,7 +96,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 96 | 96 | ||
| 97 | int minor = kernel_version & 0xFF; | 97 | int minor = kernel_version & 0xFF; |
| 98 | int major = (kernel_version >> 8) & 0xFF; | 98 | int major = (kernel_version >> 8) & 0xFF; |
| 99 | LOG_DEBUG(Loader, "ExHeader kernel version: %d.%d", major, minor); | 99 | LOG_INFO(Loader, "ExHeader kernel version: %d.%d", major, minor); |
| 100 | } else { | 100 | } else { |
| 101 | LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); | 101 | LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); |
| 102 | } | 102 | } |
| @@ -104,6 +104,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | void Process::Run(s32 main_thread_priority, u32 stack_size) { | 106 | void Process::Run(s32 main_thread_priority, u32 stack_size) { |
| 107 | memory_region = GetMemoryRegion(flags.memory_region); | ||
| 108 | |||
| 107 | auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { | 109 | auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { |
| 108 | auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, | 110 | auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, |
| 109 | segment.offset, segment.size, memory_state).Unwrap(); | 111 | segment.offset, segment.size, memory_state).Unwrap(); |
| @@ -124,6 +126,15 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | |||
| 124 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | 126 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); |
| 125 | } | 127 | } |
| 126 | 128 | ||
| 129 | VAddr Process::GetLinearHeapBase() const { | ||
| 130 | return (kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_SIZE) | ||
| 131 | + memory_region->base; | ||
| 132 | } | ||
| 133 | |||
| 134 | VAddr Process::GetLinearHeapLimit() const { | ||
| 135 | return GetLinearHeapBase() + memory_region->size; | ||
| 136 | } | ||
| 137 | |||
| 127 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { | 138 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { |
| 128 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { | 139 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { |
| 129 | return ERR_INVALID_ADDRESS; | 140 | return ERR_INVALID_ADDRESS; |
| @@ -166,19 +177,16 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | |||
| 166 | } | 177 | } |
| 167 | 178 | ||
| 168 | ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { | 179 | ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { |
| 169 | if (linear_heap_memory == nullptr) { | 180 | auto& linheap_memory = memory_region->linear_heap_memory; |
| 170 | // Initialize heap | ||
| 171 | linear_heap_memory = std::make_shared<std::vector<u8>>(); | ||
| 172 | } | ||
| 173 | 181 | ||
| 174 | VAddr heap_end = Memory::LINEAR_HEAP_VADDR + (u32)linear_heap_memory->size(); | 182 | VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size(); |
| 175 | // Games and homebrew only ever seem to pass 0 here (which lets the kernel decide the address), | 183 | // Games and homebrew only ever seem to pass 0 here (which lets the kernel decide the address), |
| 176 | // but explicit addresses are also accepted and respected. | 184 | // but explicit addresses are also accepted and respected. |
| 177 | if (target == 0) { | 185 | if (target == 0) { |
| 178 | target = heap_end; | 186 | target = heap_end; |
| 179 | } | 187 | } |
| 180 | 188 | ||
| 181 | if (target < Memory::LINEAR_HEAP_VADDR || target + size > Memory::LINEAR_HEAP_VADDR_END || | 189 | if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || |
| 182 | target > heap_end || target + size < target) { | 190 | target > heap_end || target + size < target) { |
| 183 | 191 | ||
| 184 | return ERR_INVALID_ADDRESS; | 192 | return ERR_INVALID_ADDRESS; |
| @@ -188,25 +196,29 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | |||
| 188 | // end. It's possible to free gaps in the middle of the heap and then reallocate them later, | 196 | // end. It's possible to free gaps in the middle of the heap and then reallocate them later, |
| 189 | // but expansions are only allowed at the end. | 197 | // but expansions are only allowed at the end. |
| 190 | if (target == heap_end) { | 198 | if (target == heap_end) { |
| 191 | linear_heap_memory->insert(linear_heap_memory->end(), size, 0); | 199 | linheap_memory->insert(linheap_memory->end(), size, 0); |
| 192 | vm_manager.RefreshMemoryBlockMappings(linear_heap_memory.get()); | 200 | vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); |
| 193 | } | 201 | } |
| 194 | 202 | ||
| 195 | size_t offset = target - Memory::LINEAR_HEAP_VADDR; | 203 | // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the |
| 196 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linear_heap_memory, offset, size, MemoryState::Continuous)); | 204 | // same region. It is unknown if or how the 3DS kernel checks against this. |
| 205 | size_t offset = target - GetLinearHeapBase(); | ||
| 206 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); | ||
| 197 | vm_manager.Reprotect(vma, perms); | 207 | vm_manager.Reprotect(vma, perms); |
| 198 | 208 | ||
| 199 | return MakeResult<VAddr>(target); | 209 | return MakeResult<VAddr>(target); |
| 200 | } | 210 | } |
| 201 | 211 | ||
| 202 | ResultCode Process::LinearFree(VAddr target, u32 size) { | 212 | ResultCode Process::LinearFree(VAddr target, u32 size) { |
| 203 | if (linear_heap_memory == nullptr || target < Memory::LINEAR_HEAP_VADDR || | 213 | auto& linheap_memory = memory_region->linear_heap_memory; |
| 204 | target + size > Memory::LINEAR_HEAP_VADDR_END || target + size < target) { | 214 | |
| 215 | if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || | ||
| 216 | target + size < target) { | ||
| 205 | 217 | ||
| 206 | return ERR_INVALID_ADDRESS; | 218 | return ERR_INVALID_ADDRESS; |
| 207 | } | 219 | } |
| 208 | 220 | ||
| 209 | VAddr heap_end = Memory::LINEAR_HEAP_VADDR + (u32)linear_heap_memory->size(); | 221 | VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size(); |
| 210 | if (target + size > heap_end) { | 222 | if (target + size > heap_end) { |
| 211 | return ERR_INVALID_ADDRESS_STATE; | 223 | return ERR_INVALID_ADDRESS_STATE; |
| 212 | } | 224 | } |
| @@ -221,8 +233,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | |||
| 221 | ASSERT(vma != vm_manager.vma_map.end()); | 233 | ASSERT(vma != vm_manager.vma_map.end()); |
| 222 | ASSERT(vma->second.type == VMAType::Free); | 234 | ASSERT(vma->second.type == VMAType::Free); |
| 223 | VAddr new_end = vma->second.base; | 235 | VAddr new_end = vma->second.base; |
| 224 | if (new_end >= Memory::LINEAR_HEAP_VADDR) { | 236 | if (new_end >= GetLinearHeapBase()) { |
| 225 | linear_heap_memory->resize(new_end - Memory::LINEAR_HEAP_VADDR); | 237 | linheap_memory->resize(new_end - GetLinearHeapBase()); |
| 226 | } | 238 | } |
| 227 | } | 239 | } |
| 228 | 240 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 5c7de9044..7c3a78b9e 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -49,6 +49,7 @@ union ProcessFlags { | |||
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | class ResourceLimit; | 51 | class ResourceLimit; |
| 52 | struct MemoryRegionInfo; | ||
| 52 | 53 | ||
| 53 | struct CodeSet final : public Object { | 54 | struct CodeSet final : public Object { |
| 54 | static SharedPtr<CodeSet> Create(std::string name, u64 program_id); | 55 | static SharedPtr<CodeSet> Create(std::string name, u64 program_id); |
| @@ -135,11 +136,14 @@ public: | |||
| 135 | // The left/right bounds of the address space covered by heap_memory. | 136 | // The left/right bounds of the address space covered by heap_memory. |
| 136 | VAddr heap_start = 0, heap_end = 0; | 137 | VAddr heap_start = 0, heap_end = 0; |
| 137 | 138 | ||
| 138 | std::shared_ptr<std::vector<u8>> linear_heap_memory; | 139 | MemoryRegionInfo* memory_region = nullptr; |
| 139 | 140 | ||
| 140 | /// Bitmask of the used TLS slots | 141 | /// Bitmask of the used TLS slots |
| 141 | std::bitset<300> used_tls_slots; | 142 | std::bitset<300> used_tls_slots; |
| 142 | 143 | ||
| 144 | VAddr GetLinearHeapBase() const; | ||
| 145 | VAddr GetLinearHeapLimit() const; | ||
| 146 | |||
| 143 | ResultVal<VAddr> HeapAllocate(VAddr target, u32 size, VMAPermission perms); | 147 | ResultVal<VAddr> HeapAllocate(VAddr target, u32 size, VMAPermission perms); |
| 144 | ResultCode HeapFree(VAddr target, u32 size); | 148 | ResultCode HeapFree(VAddr target, u32 size); |
| 145 | 149 | ||
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index b944f4af0..e1a416def 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -102,7 +102,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| 102 | if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { | 102 | if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { |
| 103 | ResultCode result = process.HeapFree(addr0, size); | 103 | ResultCode result = process.HeapFree(addr0, size); |
| 104 | if (result.IsError()) return result; | 104 | if (result.IsError()) return result; |
| 105 | } else if (addr0 >= Memory::LINEAR_HEAP_VADDR && addr0 < Memory::LINEAR_HEAP_VADDR_END) { | 105 | } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { |
| 106 | ResultCode result = process.LinearFree(addr0, size); | 106 | ResultCode result = process.LinearFree(addr0, size); |
| 107 | if (result.IsError()) return result; | 107 | if (result.IsError()) return result; |
| 108 | } else { | 108 | } else { |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 935dac90f..cde390b8a 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/swap.h" | 10 | #include "common/swap.h" |
| 11 | 11 | ||
| 12 | #include "core/hle/kernel/process.h" | ||
| 12 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 13 | #include "core/memory_setup.h" | 14 | #include "core/memory_setup.h" |
| 14 | 15 | ||
| @@ -208,6 +209,8 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) { | |||
| 208 | return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; | 209 | return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; |
| 209 | } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { | 210 | } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { |
| 210 | return addr - IO_AREA_VADDR + IO_AREA_PADDR; | 211 | return addr - IO_AREA_VADDR + IO_AREA_PADDR; |
| 212 | } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||
| 213 | return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||
| 211 | } | 214 | } |
| 212 | 215 | ||
| 213 | LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); | 216 | LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); |
| @@ -221,7 +224,7 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) { | |||
| 221 | } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | 224 | } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { |
| 222 | return addr - VRAM_PADDR + VRAM_VADDR; | 225 | return addr - VRAM_PADDR + VRAM_VADDR; |
| 223 | } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { | 226 | } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { |
| 224 | return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR; | 227 | return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapBase(); |
| 225 | } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { | 228 | } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { |
| 226 | return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; | 229 | return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; |
| 227 | } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { | 230 | } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { |
diff --git a/src/core/memory.h b/src/core/memory.h index e6da3e2a5..d1d32f0dd 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -107,6 +107,11 @@ enum : VAddr { | |||
| 107 | TLS_AREA_VADDR = 0x1FF82000, | 107 | TLS_AREA_VADDR = 0x1FF82000, |
| 108 | TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads | 108 | TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads |
| 109 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, | 109 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, |
| 110 | |||
| 111 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | ||
| 112 | NEW_LINEAR_HEAP_VADDR = 0x30000000, | ||
| 113 | NEW_LINEAR_HEAP_SIZE = 0x10000000, | ||
| 114 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | ||
| 110 | }; | 115 | }; |
| 111 | 116 | ||
| 112 | u8 Read8(VAddr addr); | 117 | u8 Read8(VAddr addr); |