Merge pull request #3314 from degasus/physical_mem
core/hle/kernel: Simplify PhysicalMemory usages.
This commit is contained in:
commit
278264b9e5
|
@ -14,6 +14,9 @@ namespace Kernel {
|
||||||
// - Second to ensure all host backing memory used is aligned to 256 bytes due
|
// - Second to ensure all host backing memory used is aligned to 256 bytes due
|
||||||
// to strict alignment restrictions on GPU memory.
|
// to strict alignment restrictions on GPU memory.
|
||||||
|
|
||||||
using PhysicalMemory = std::vector<u8, Common::AlignmentAllocator<u8, 256>>;
|
using PhysicalMemoryVector = std::vector<u8, Common::AlignmentAllocator<u8, 256>>;
|
||||||
|
class PhysicalMemory final : public PhysicalMemoryVector {
|
||||||
|
using PhysicalMemoryVector::PhysicalMemoryVector;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
|
@ -269,18 +270,9 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) {
|
||||||
// If necessary, expand backing vector to cover new heap extents in
|
// If necessary, expand backing vector to cover new heap extents in
|
||||||
// the case of allocating. Otherwise, shrink the backing memory,
|
// the case of allocating. Otherwise, shrink the backing memory,
|
||||||
// if a smaller heap has been requested.
|
// if a smaller heap has been requested.
|
||||||
const u64 old_heap_size = GetCurrentHeapSize();
|
|
||||||
if (size > old_heap_size) {
|
|
||||||
const u64 alloc_size = size - old_heap_size;
|
|
||||||
|
|
||||||
heap_memory->insert(heap_memory->end(), alloc_size, 0);
|
|
||||||
RefreshMemoryBlockMappings(heap_memory.get());
|
|
||||||
} else if (size < old_heap_size) {
|
|
||||||
heap_memory->resize(size);
|
heap_memory->resize(size);
|
||||||
heap_memory->shrink_to_fit();
|
heap_memory->shrink_to_fit();
|
||||||
|
|
||||||
RefreshMemoryBlockMappings(heap_memory.get());
|
RefreshMemoryBlockMappings(heap_memory.get());
|
||||||
}
|
|
||||||
|
|
||||||
heap_end = heap_region_base + size;
|
heap_end = heap_region_base + size;
|
||||||
ASSERT(GetCurrentHeapSize() == heap_memory->size());
|
ASSERT(GetCurrentHeapSize() == heap_memory->size());
|
||||||
|
@ -752,24 +744,20 @@ void VMManager::MergeAdjacentVMA(VirtualMemoryArea& left, const VirtualMemoryAre
|
||||||
// Always merge allocated memory blocks, even when they don't share the same backing block.
|
// Always merge allocated memory blocks, even when they don't share the same backing block.
|
||||||
if (left.type == VMAType::AllocatedMemoryBlock &&
|
if (left.type == VMAType::AllocatedMemoryBlock &&
|
||||||
(left.backing_block != right.backing_block || left.offset + left.size != right.offset)) {
|
(left.backing_block != right.backing_block || left.offset + left.size != right.offset)) {
|
||||||
const auto right_begin = right.backing_block->begin() + right.offset;
|
|
||||||
const auto right_end = right_begin + right.size;
|
|
||||||
|
|
||||||
// Check if we can save work.
|
// Check if we can save work.
|
||||||
if (left.offset == 0 && left.size == left.backing_block->size()) {
|
if (left.offset == 0 && left.size == left.backing_block->size()) {
|
||||||
// Fast case: left is an entire backing block.
|
// Fast case: left is an entire backing block.
|
||||||
left.backing_block->insert(left.backing_block->end(), right_begin, right_end);
|
left.backing_block->resize(left.size + right.size);
|
||||||
|
std::memcpy(left.backing_block->data() + left.size,
|
||||||
|
right.backing_block->data() + right.offset, right.size);
|
||||||
} else {
|
} else {
|
||||||
// Slow case: make a new memory block for left and right.
|
// Slow case: make a new memory block for left and right.
|
||||||
const auto left_begin = left.backing_block->begin() + left.offset;
|
|
||||||
const auto left_end = left_begin + left.size;
|
|
||||||
const auto left_size = static_cast<std::size_t>(std::distance(left_begin, left_end));
|
|
||||||
const auto right_size = static_cast<std::size_t>(std::distance(right_begin, right_end));
|
|
||||||
|
|
||||||
auto new_memory = std::make_shared<PhysicalMemory>();
|
auto new_memory = std::make_shared<PhysicalMemory>();
|
||||||
new_memory->reserve(left_size + right_size);
|
new_memory->resize(left.size + right.size);
|
||||||
new_memory->insert(new_memory->end(), left_begin, left_end);
|
std::memcpy(new_memory->data(), left.backing_block->data() + left.offset, left.size);
|
||||||
new_memory->insert(new_memory->end(), right_begin, right_end);
|
std::memcpy(new_memory->data() + left.size, right.backing_block->data() + right.offset,
|
||||||
|
right.size);
|
||||||
|
|
||||||
left.backing_block = std::move(new_memory);
|
left.backing_block = std::move(new_memory);
|
||||||
left.offset = 0;
|
left.offset = 0;
|
||||||
|
@ -792,8 +780,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
|
||||||
memory.UnmapRegion(page_table, vma.base, vma.size);
|
memory.UnmapRegion(page_table, vma.base, vma.size);
|
||||||
break;
|
break;
|
||||||
case VMAType::AllocatedMemoryBlock:
|
case VMAType::AllocatedMemoryBlock:
|
||||||
memory.MapMemoryRegion(page_table, vma.base, vma.size,
|
memory.MapMemoryRegion(page_table, vma.base, vma.size, *vma.backing_block, vma.offset);
|
||||||
vma.backing_block->data() + vma.offset);
|
|
||||||
break;
|
break;
|
||||||
case VMAType::BackingMemory:
|
case VMAType::BackingMemory:
|
||||||
memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory);
|
memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory);
|
||||||
|
|
|
@ -335,7 +335,8 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
|
||||||
codeset_segment->addr = segment_addr;
|
codeset_segment->addr = segment_addr;
|
||||||
codeset_segment->size = aligned_size;
|
codeset_segment->size = aligned_size;
|
||||||
|
|
||||||
memcpy(&program_image[current_image_position], GetSegmentPtr(i), p->p_filesz);
|
std::memcpy(program_image.data() + current_image_position, GetSegmentPtr(i),
|
||||||
|
p->p_filesz);
|
||||||
current_image_position += aligned_size;
|
current_image_position += aligned_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <cstring>
|
||||||
#include "core/file_sys/kernel_executable.h"
|
#include "core/file_sys/kernel_executable.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
|
@ -76,8 +77,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
|
||||||
segment.addr = offset;
|
segment.addr = offset;
|
||||||
segment.offset = offset;
|
segment.offset = offset;
|
||||||
segment.size = PageAlignSize(static_cast<u32>(data.size()));
|
segment.size = PageAlignSize(static_cast<u32>(data.size()));
|
||||||
program_image.resize(offset);
|
program_image.resize(offset + data.size());
|
||||||
program_image.insert(program_image.end(), data.begin(), data.end());
|
std::memcpy(program_image.data() + offset, data.data(), data.size());
|
||||||
};
|
};
|
||||||
|
|
||||||
load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
|
load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
|
@ -96,8 +97,9 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
if (nso_header.IsSegmentCompressed(i)) {
|
if (nso_header.IsSegmentCompressed(i)) {
|
||||||
data = DecompressSegment(data, nso_header.segments[i]);
|
data = DecompressSegment(data, nso_header.segments[i]);
|
||||||
}
|
}
|
||||||
program_image.resize(nso_header.segments[i].location);
|
program_image.resize(nso_header.segments[i].location + data.size());
|
||||||
program_image.insert(program_image.end(), data.begin(), data.end());
|
std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
|
||||||
|
data.size());
|
||||||
codeset.segments[i].addr = nso_header.segments[i].location;
|
codeset.segments[i].addr = nso_header.segments[i].location;
|
||||||
codeset.segments[i].offset = nso_header.segments[i].location;
|
codeset.segments[i].offset = nso_header.segments[i].location;
|
||||||
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
|
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
|
||||||
|
@ -139,12 +141,12 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
std::vector<u8> pi_header;
|
std::vector<u8> pi_header;
|
||||||
pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header),
|
pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header),
|
||||||
reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader));
|
reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader));
|
||||||
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.begin(),
|
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(),
|
||||||
program_image.end());
|
program_image.data() + program_image.size());
|
||||||
|
|
||||||
pi_header = pm->PatchNSO(pi_header, file.GetName());
|
pi_header = pm->PatchNSO(pi_header, file.GetName());
|
||||||
|
|
||||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.begin());
|
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply cheats if they exist and the program has a valid title ID
|
// Apply cheats if they exist and the program has a valid title ID
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
#include "core/hle/kernel/vm_manager.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
@ -38,6 +39,11 @@ struct Memory::Impl {
|
||||||
system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
|
system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||||
|
Kernel::PhysicalMemory& memory, VAddr offset) {
|
||||||
|
MapMemoryRegion(page_table, base, size, memory.data() + offset);
|
||||||
|
}
|
||||||
|
|
||||||
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
||||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
||||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
||||||
|
@ -601,6 +607,11 @@ void Memory::SetCurrentPageTable(Kernel::Process& process) {
|
||||||
impl->SetCurrentPageTable(process);
|
impl->SetCurrentPageTable(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||||
|
Kernel::PhysicalMemory& memory, VAddr offset) {
|
||||||
|
impl->MapMemoryRegion(page_table, base, size, memory, offset);
|
||||||
|
}
|
||||||
|
|
||||||
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
||||||
impl->MapMemoryRegion(page_table, base, size, target);
|
impl->MapMemoryRegion(page_table, base, size, target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,9 @@ class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
class PhysicalMemory;
|
||||||
class Process;
|
class Process;
|
||||||
}
|
} // namespace Kernel
|
||||||
|
|
||||||
namespace Memory {
|
namespace Memory {
|
||||||
|
|
||||||
|
@ -65,6 +66,19 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetCurrentPageTable(Kernel::Process& process);
|
void SetCurrentPageTable(Kernel::Process& process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps an physical buffer onto a region of the emulated process address space.
|
||||||
|
*
|
||||||
|
* @param page_table The page table of the emulated process.
|
||||||
|
* @param base The address to start mapping at. Must be page-aligned.
|
||||||
|
* @param size The amount of bytes to map. Must be page-aligned.
|
||||||
|
* @param memory Physical buffer with the memory backing the mapping. Must be of length
|
||||||
|
* at least `size + offset`.
|
||||||
|
* @param offset The offset within the physical memory. Must be page-aligned.
|
||||||
|
*/
|
||||||
|
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||||
|
Kernel::PhysicalMemory& memory, VAddr offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps an allocated buffer onto a region of the emulated process address space.
|
* Maps an allocated buffer onto a region of the emulated process address space.
|
||||||
*
|
*
|
||||||
|
|
Reference in New Issue