diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/physical_memory.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 37 | ||||
| -rw-r--r-- | src/core/loader/elf.cpp | 3 | ||||
| -rw-r--r-- | src/core/loader/kip.cpp | 5 | ||||
| -rw-r--r-- | src/core/loader/nso.cpp | 12 | ||||
| -rw-r--r-- | src/core/memory.cpp | 11 | ||||
| -rw-r--r-- | src/core/memory.h | 16 |
7 files changed, 54 insertions, 35 deletions
diff --git a/src/core/hle/kernel/physical_memory.h b/src/core/hle/kernel/physical_memory.h index 090565310..b689e8e8b 100644 --- a/src/core/hle/kernel/physical_memory.h +++ b/src/core/hle/kernel/physical_memory.h | |||
| @@ -14,6 +14,9 @@ namespace Kernel { | |||
| 14 | // - Second to ensure all host backing memory used is aligned to 256 bytes due | 14 | // - Second to ensure all host backing memory used is aligned to 256 bytes due |
| 15 | // to strict alignment restrictions on GPU memory. | 15 | // to strict alignment restrictions on GPU memory. |
| 16 | 16 | ||
| 17 | using PhysicalMemory = std::vector<u8, Common::AlignmentAllocator<u8, 256>>; | 17 | using PhysicalMemoryVector = std::vector<u8, Common::AlignmentAllocator<u8, 256>>; |
| 18 | class PhysicalMemory final : public PhysicalMemoryVector { | ||
| 19 | using PhysicalMemoryVector::PhysicalMemoryVector; | ||
| 20 | }; | ||
| 18 | 21 | ||
| 19 | } // namespace Kernel | 22 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index a9a20ef76..0b3500fce 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <cstring> | ||
| 6 | #include <iterator> | 7 | #include <iterator> |
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include "common/alignment.h" | 9 | #include "common/alignment.h" |
| @@ -269,18 +270,9 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) { | |||
| 269 | // If necessary, expand backing vector to cover new heap extents in | 270 | // If necessary, expand backing vector to cover new heap extents in |
| 270 | // the case of allocating. Otherwise, shrink the backing memory, | 271 | // the case of allocating. Otherwise, shrink the backing memory, |
| 271 | // if a smaller heap has been requested. | 272 | // if a smaller heap has been requested. |
| 272 | const u64 old_heap_size = GetCurrentHeapSize(); | 273 | heap_memory->resize(size); |
| 273 | if (size > old_heap_size) { | 274 | heap_memory->shrink_to_fit(); |
| 274 | const u64 alloc_size = size - old_heap_size; | 275 | RefreshMemoryBlockMappings(heap_memory.get()); |
| 275 | |||
| 276 | heap_memory->insert(heap_memory->end(), alloc_size, 0); | ||
| 277 | RefreshMemoryBlockMappings(heap_memory.get()); | ||
| 278 | } else if (size < old_heap_size) { | ||
| 279 | heap_memory->resize(size); | ||
| 280 | heap_memory->shrink_to_fit(); | ||
| 281 | |||
| 282 | RefreshMemoryBlockMappings(heap_memory.get()); | ||
| 283 | } | ||
| 284 | 276 | ||
| 285 | heap_end = heap_region_base + size; | 277 | heap_end = heap_region_base + size; |
| 286 | ASSERT(GetCurrentHeapSize() == heap_memory->size()); | 278 | ASSERT(GetCurrentHeapSize() == heap_memory->size()); |
| @@ -752,24 +744,20 @@ void VMManager::MergeAdjacentVMA(VirtualMemoryArea& left, const VirtualMemoryAre | |||
| 752 | // Always merge allocated memory blocks, even when they don't share the same backing block. | 744 | // Always merge allocated memory blocks, even when they don't share the same backing block. |
| 753 | if (left.type == VMAType::AllocatedMemoryBlock && | 745 | if (left.type == VMAType::AllocatedMemoryBlock && |
| 754 | (left.backing_block != right.backing_block || left.offset + left.size != right.offset)) { | 746 | (left.backing_block != right.backing_block || left.offset + left.size != right.offset)) { |
| 755 | const auto right_begin = right.backing_block->begin() + right.offset; | ||
| 756 | const auto right_end = right_begin + right.size; | ||
| 757 | 747 | ||
| 758 | // Check if we can save work. | 748 | // Check if we can save work. |
| 759 | if (left.offset == 0 && left.size == left.backing_block->size()) { | 749 | if (left.offset == 0 && left.size == left.backing_block->size()) { |
| 760 | // Fast case: left is an entire backing block. | 750 | // Fast case: left is an entire backing block. |
| 761 | left.backing_block->insert(left.backing_block->end(), right_begin, right_end); | 751 | left.backing_block->resize(left.size + right.size); |
| 752 | std::memcpy(left.backing_block->data() + left.size, | ||
| 753 | right.backing_block->data() + right.offset, right.size); | ||
| 762 | } else { | 754 | } else { |
| 763 | // Slow case: make a new memory block for left and right. | 755 | // Slow case: make a new memory block for left and right. |
| 764 | const auto left_begin = left.backing_block->begin() + left.offset; | ||
| 765 | const auto left_end = left_begin + left.size; | ||
| 766 | const auto left_size = static_cast<std::size_t>(std::distance(left_begin, left_end)); | ||
| 767 | const auto right_size = static_cast<std::size_t>(std::distance(right_begin, right_end)); | ||
| 768 | |||
| 769 | auto new_memory = std::make_shared<PhysicalMemory>(); | 756 | auto new_memory = std::make_shared<PhysicalMemory>(); |
| 770 | new_memory->reserve(left_size + right_size); | 757 | new_memory->resize(left.size + right.size); |
| 771 | new_memory->insert(new_memory->end(), left_begin, left_end); | 758 | std::memcpy(new_memory->data(), left.backing_block->data() + left.offset, left.size); |
| 772 | new_memory->insert(new_memory->end(), right_begin, right_end); | 759 | std::memcpy(new_memory->data() + left.size, right.backing_block->data() + right.offset, |
| 760 | right.size); | ||
| 773 | 761 | ||
| 774 | left.backing_block = std::move(new_memory); | 762 | left.backing_block = std::move(new_memory); |
| 775 | left.offset = 0; | 763 | left.offset = 0; |
| @@ -792,8 +780,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 792 | memory.UnmapRegion(page_table, vma.base, vma.size); | 780 | memory.UnmapRegion(page_table, vma.base, vma.size); |
| 793 | break; | 781 | break; |
| 794 | case VMAType::AllocatedMemoryBlock: | 782 | case VMAType::AllocatedMemoryBlock: |
| 795 | memory.MapMemoryRegion(page_table, vma.base, vma.size, | 783 | memory.MapMemoryRegion(page_table, vma.base, vma.size, *vma.backing_block, vma.offset); |
| 796 | vma.backing_block->data() + vma.offset); | ||
| 797 | break; | 784 | break; |
| 798 | case VMAType::BackingMemory: | 785 | case VMAType::BackingMemory: |
| 799 | memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory); | 786 | memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory); |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index f1795fdd6..8908e5328 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -335,7 +335,8 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) { | |||
| 335 | codeset_segment->addr = segment_addr; | 335 | codeset_segment->addr = segment_addr; |
| 336 | codeset_segment->size = aligned_size; | 336 | codeset_segment->size = aligned_size; |
| 337 | 337 | ||
| 338 | memcpy(&program_image[current_image_position], GetSegmentPtr(i), p->p_filesz); | 338 | std::memcpy(program_image.data() + current_image_position, GetSegmentPtr(i), |
| 339 | p->p_filesz); | ||
| 339 | current_image_position += aligned_size; | 340 | current_image_position += aligned_size; |
| 340 | } | 341 | } |
| 341 | } | 342 | } |
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 474b55cb1..092103abe 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 5 | #include "core/file_sys/kernel_executable.h" | 6 | #include "core/file_sys/kernel_executable.h" |
| 6 | #include "core/file_sys/program_metadata.h" | 7 | #include "core/file_sys/program_metadata.h" |
| 7 | #include "core/gdbstub/gdbstub.h" | 8 | #include "core/gdbstub/gdbstub.h" |
| @@ -76,8 +77,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) { | |||
| 76 | segment.addr = offset; | 77 | segment.addr = offset; |
| 77 | segment.offset = offset; | 78 | segment.offset = offset; |
| 78 | segment.size = PageAlignSize(static_cast<u32>(data.size())); | 79 | segment.size = PageAlignSize(static_cast<u32>(data.size())); |
| 79 | program_image.resize(offset); | 80 | program_image.resize(offset + data.size()); |
| 80 | program_image.insert(program_image.end(), data.begin(), data.end()); | 81 | std::memcpy(program_image.data() + offset, data.data(), data.size()); |
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset()); | 84 | load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset()); |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index f629892ae..515c5accb 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cinttypes> | 5 | #include <cinttypes> |
| 6 | #include <cstring> | ||
| 6 | #include <vector> | 7 | #include <vector> |
| 7 | 8 | ||
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| @@ -96,8 +97,9 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | |||
| 96 | if (nso_header.IsSegmentCompressed(i)) { | 97 | if (nso_header.IsSegmentCompressed(i)) { |
| 97 | data = DecompressSegment(data, nso_header.segments[i]); | 98 | data = DecompressSegment(data, nso_header.segments[i]); |
| 98 | } | 99 | } |
| 99 | program_image.resize(nso_header.segments[i].location); | 100 | program_image.resize(nso_header.segments[i].location + data.size()); |
| 100 | program_image.insert(program_image.end(), data.begin(), data.end()); | 101 | std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(), |
| 102 | data.size()); | ||
| 101 | codeset.segments[i].addr = nso_header.segments[i].location; | 103 | codeset.segments[i].addr = nso_header.segments[i].location; |
| 102 | codeset.segments[i].offset = nso_header.segments[i].location; | 104 | codeset.segments[i].offset = nso_header.segments[i].location; |
| 103 | codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size())); | 105 | codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size())); |
| @@ -139,12 +141,12 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, | |||
| 139 | std::vector<u8> pi_header; | 141 | std::vector<u8> pi_header; |
| 140 | pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header), | 142 | pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header), |
| 141 | reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader)); | 143 | reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader)); |
| 142 | pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.begin(), | 144 | pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(), |
| 143 | program_image.end()); | 145 | program_image.data() + program_image.size()); |
| 144 | 146 | ||
| 145 | pi_header = pm->PatchNSO(pi_header, file.GetName()); | 147 | pi_header = pm->PatchNSO(pi_header, file.GetName()); |
| 146 | 148 | ||
| 147 | std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.begin()); | 149 | std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data()); |
| 148 | } | 150 | } |
| 149 | 151 | ||
| 150 | // Apply cheats if they exist and the program has a valid title ID | 152 | // Apply cheats if they exist and the program has a valid title ID |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 3c2a29d9b..f0888327f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 15 | #include "core/arm/arm_interface.h" | 15 | #include "core/arm/arm_interface.h" |
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/hle/kernel/physical_memory.h" | ||
| 17 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/kernel/vm_manager.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| 19 | #include "core/memory.h" | 20 | #include "core/memory.h" |
| @@ -38,6 +39,11 @@ struct Memory::Impl { | |||
| 38 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); | 39 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 42 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, | ||
| 43 | Kernel::PhysicalMemory& memory, VAddr offset) { | ||
| 44 | MapMemoryRegion(page_table, base, size, memory.data() + offset); | ||
| 45 | } | ||
| 46 | |||
| 41 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { | 47 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { |
| 42 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 48 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); |
| 43 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | 49 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); |
| @@ -601,6 +607,11 @@ void Memory::SetCurrentPageTable(Kernel::Process& process) { | |||
| 601 | impl->SetCurrentPageTable(process); | 607 | impl->SetCurrentPageTable(process); |
| 602 | } | 608 | } |
| 603 | 609 | ||
| 610 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, | ||
| 611 | Kernel::PhysicalMemory& memory, VAddr offset) { | ||
| 612 | impl->MapMemoryRegion(page_table, base, size, memory, offset); | ||
| 613 | } | ||
| 614 | |||
| 604 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { | 615 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { |
| 605 | impl->MapMemoryRegion(page_table, base, size, target); | 616 | impl->MapMemoryRegion(page_table, base, size, target); |
| 606 | } | 617 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 1428a6d60..8913a9da4 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -19,8 +19,9 @@ class System; | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | namespace Kernel { | 21 | namespace Kernel { |
| 22 | class PhysicalMemory; | ||
| 22 | class Process; | 23 | class Process; |
| 23 | } | 24 | } // namespace Kernel |
| 24 | 25 | ||
| 25 | namespace Memory { | 26 | namespace Memory { |
| 26 | 27 | ||
| @@ -66,6 +67,19 @@ public: | |||
| 66 | void SetCurrentPageTable(Kernel::Process& process); | 67 | void SetCurrentPageTable(Kernel::Process& process); |
| 67 | 68 | ||
| 68 | /** | 69 | /** |
| 70 | * Maps an physical buffer onto a region of the emulated process address space. | ||
| 71 | * | ||
| 72 | * @param page_table The page table of the emulated process. | ||
| 73 | * @param base The address to start mapping at. Must be page-aligned. | ||
| 74 | * @param size The amount of bytes to map. Must be page-aligned. | ||
| 75 | * @param memory Physical buffer with the memory backing the mapping. Must be of length | ||
| 76 | * at least `size + offset`. | ||
| 77 | * @param offset The offset within the physical memory. Must be page-aligned. | ||
| 78 | */ | ||
| 79 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, | ||
| 80 | Kernel::PhysicalMemory& memory, VAddr offset); | ||
| 81 | |||
| 82 | /** | ||
| 69 | * Maps an allocated buffer onto a region of the emulated process address space. | 83 | * Maps an allocated buffer onto a region of the emulated process address space. |
| 70 | * | 84 | * |
| 71 | * @param page_table The page table of the emulated process. | 85 | * @param page_table The page table of the emulated process. |