mirror of
https://github.com/PabloMK7/citra.git
synced 2025-09-10 12:50:04 +00:00
core: Remove special regions (#7211)
This commit is contained in:
parent
dc8425a986
commit
db7b929e47
11 changed files with 4 additions and 13996 deletions
|
@ -455,7 +455,6 @@ add_library(citra_core STATIC
|
|||
loader/smdh.h
|
||||
memory.cpp
|
||||
memory.h
|
||||
mmio.h
|
||||
movie.cpp
|
||||
movie.h
|
||||
nus_download.cpp
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "core/hle/kernel/vm_manager.h"
|
||||
#include "core/hle/service/plgldr/plgldr.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/mmio.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -33,9 +32,6 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
|
|||
backing_memory.GetPtr() + size != next.backing_memory.GetPtr()) {
|
||||
return false;
|
||||
}
|
||||
if (type == VMAType::MMIO && paddr + size != next.paddr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -118,26 +114,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, Memory
|
|||
return MergeAdjacent(vma_handle);
|
||||
}
|
||||
|
||||
ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
|
||||
MemoryState state,
|
||||
Memory::MMIORegionPointer mmio_handler) {
|
||||
ASSERT(!is_locked);
|
||||
|
||||
// This is the appropriately sized VMA that will turn into our allocation.
|
||||
CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
|
||||
VirtualMemoryArea& final_vma = vma_handle->second;
|
||||
ASSERT(final_vma.size == size);
|
||||
|
||||
final_vma.type = VMAType::MMIO;
|
||||
final_vma.permissions = VMAPermission::ReadWrite;
|
||||
final_vma.meminfo_state = state;
|
||||
final_vma.paddr = paddr;
|
||||
final_vma.mmio_handler = mmio_handler;
|
||||
UpdatePageTableForVMA(final_vma);
|
||||
|
||||
return MergeAdjacent(vma_handle);
|
||||
}
|
||||
|
||||
ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expected_state,
|
||||
VMAPermission expected_perms, MemoryState new_state,
|
||||
VMAPermission new_perms) {
|
||||
|
@ -185,9 +161,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
|
|||
vma.type = VMAType::Free;
|
||||
vma.permissions = VMAPermission::None;
|
||||
vma.meminfo_state = MemoryState::Free;
|
||||
|
||||
vma.backing_memory = nullptr;
|
||||
vma.paddr = 0;
|
||||
|
||||
UpdatePageTableForVMA(vma);
|
||||
|
||||
|
@ -344,9 +318,6 @@ VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) {
|
|||
case VMAType::BackingMemory:
|
||||
new_vma.backing_memory += offset_in_vma;
|
||||
break;
|
||||
case VMAType::MMIO:
|
||||
new_vma.paddr += offset_in_vma;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(old_vma.CanBeMergedWith(new_vma));
|
||||
|
@ -381,9 +352,6 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
|
|||
case VMAType::BackingMemory:
|
||||
memory.MapMemoryRegion(*page_table, vma.base, vma.size, vma.backing_memory);
|
||||
break;
|
||||
case VMAType::MMIO:
|
||||
memory.MapIoRegion(*page_table, vma.base, vma.size, vma.mmio_handler);
|
||||
break;
|
||||
}
|
||||
|
||||
auto plgldr = Service::PLGLDR::GetService(Core::System::GetInstance());
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
|
@ -16,7 +14,6 @@
|
|||
#include "core/hle/kernel/memory.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/mmio.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -25,8 +22,6 @@ enum class VMAType : u8 {
|
|||
Free,
|
||||
/// VMA is backed by a raw, unmanaged pointer.
|
||||
BackingMemory,
|
||||
/// VMA is mapped to MMIO registers at a fixed PAddr.
|
||||
MMIO,
|
||||
};
|
||||
|
||||
/// Permissions for mapped memory blocks
|
||||
|
@ -74,15 +69,10 @@ struct VirtualMemoryArea {
|
|||
/// Tag returned by svcQueryMemory. Not otherwise used.
|
||||
MemoryState meminfo_state = MemoryState::Free;
|
||||
|
||||
// Settings for type = BackingMemory
|
||||
/// Settings for type = BackingMemory
|
||||
/// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
|
||||
MemoryRef backing_memory{};
|
||||
|
||||
// Settings for type = MMIO
|
||||
/// Physical address of the register area this VMA maps to.
|
||||
PAddr paddr = 0;
|
||||
Memory::MMIORegionPointer mmio_handler = nullptr;
|
||||
|
||||
/// Tests if this area can be merged to the right with `next`.
|
||||
bool CanBeMergedWith(const VirtualMemoryArea& next) const;
|
||||
|
||||
|
@ -96,8 +86,6 @@ private:
|
|||
ar& permissions;
|
||||
ar& meminfo_state;
|
||||
ar& backing_memory;
|
||||
ar& paddr;
|
||||
ar& mmio_handler;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,18 +154,6 @@ public:
|
|||
ResultVal<VMAHandle> MapBackingMemory(VAddr target, MemoryRef memory, u32 size,
|
||||
MemoryState state);
|
||||
|
||||
/**
|
||||
* Maps a memory-mapped IO region at a given address.
|
||||
*
|
||||
* @param target The guest address to start the mapping at.
|
||||
* @param paddr The physical address where the registers are present.
|
||||
* @param size Size of the mapping.
|
||||
* @param state MemoryState tag to attach to the VMA.
|
||||
* @param mmio_handler The handler that will implement read and write for this MMIO region.
|
||||
*/
|
||||
ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
|
||||
Memory::MMIORegionPointer mmio_handler);
|
||||
|
||||
/**
|
||||
* Updates the memory state and permissions of the specified range. The range's original memory
|
||||
* state and permissions must match the `expected` parameters.
|
||||
|
|
|
@ -156,20 +156,6 @@ public:
|
|||
return system.GetRunningCore().GetPC();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should only be called for virtual addreses with attribute `PageType::Special`.
|
||||
*/
|
||||
MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr) {
|
||||
for (const auto& region : page_table.special_regions) {
|
||||
if (vaddr >= region.base && vaddr < (region.base + region.size)) {
|
||||
return region.handler;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_MSG(false, "Mapped IO page without a handler @ {:08X}", vaddr);
|
||||
return nullptr; // Should never happen
|
||||
}
|
||||
|
||||
template <bool UNSAFE>
|
||||
void ReadBlockImpl(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
|
||||
const std::size_t size) {
|
||||
|
@ -201,12 +187,6 @@ public:
|
|||
std::memcpy(dest_buffer, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->ReadBlock(current_vaddr, dest_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
if constexpr (!UNSAFE) {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
|
@ -255,12 +235,6 @@ public:
|
|||
std::memcpy(dest_ptr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->WriteBlock(current_vaddr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
if constexpr (!UNSAFE) {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
|
@ -405,16 +379,6 @@ void MemorySystem::MapMemoryRegion(PageTable& page_table, VAddr base, u32 size,
|
|||
MapPages(page_table, base / CITRA_PAGE_SIZE, size / CITRA_PAGE_SIZE, target, PageType::Memory);
|
||||
}
|
||||
|
||||
void MemorySystem::MapIoRegion(PageTable& page_table, VAddr base, u32 size,
|
||||
MMIORegionPointer mmio_handler) {
|
||||
ASSERT_MSG((size & CITRA_PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & CITRA_PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / CITRA_PAGE_SIZE, size / CITRA_PAGE_SIZE, nullptr,
|
||||
PageType::Special);
|
||||
|
||||
page_table.special_regions.emplace_back(SpecialRegion{base, size, mmio_handler});
|
||||
}
|
||||
|
||||
void MemorySystem::UnmapRegion(PageTable& page_table, VAddr base, u32 size) {
|
||||
ASSERT_MSG((size & CITRA_PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & CITRA_PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
|
@ -437,9 +401,6 @@ void MemorySystem::UnregisterPageTable(std::shared_ptr<PageTable> page_table) {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
|
||||
|
||||
template <typename T>
|
||||
T MemorySystem::Read(const VAddr vaddr) {
|
||||
const u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
|
@ -482,8 +443,6 @@ T MemorySystem::Read(const VAddr vaddr) {
|
|||
std::memcpy(&value, GetPointerForRasterizerCache(vaddr), sizeof(T));
|
||||
return value;
|
||||
}
|
||||
case PageType::Special:
|
||||
return ReadMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -491,9 +450,6 @@ T MemorySystem::Read(const VAddr vaddr) {
|
|||
return T{};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
|
||||
|
||||
template <typename T>
|
||||
void MemorySystem::Write(const VAddr vaddr, const T data) {
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
|
@ -531,9 +487,6 @@ void MemorySystem::Write(const VAddr vaddr, const T data) {
|
|||
std::memcpy(GetPointerForRasterizerCache(vaddr), &data, sizeof(T));
|
||||
break;
|
||||
}
|
||||
case PageType::Special:
|
||||
WriteMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -564,9 +517,6 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec
|
|||
reinterpret_cast<volatile T*>(GetPointerForRasterizerCache(vaddr).GetPtr());
|
||||
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
|
||||
}
|
||||
case PageType::Special:
|
||||
WriteMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -577,18 +527,12 @@ bool MemorySystem::IsValidVirtualAddress(const Kernel::Process& process, const V
|
|||
auto& page_table = *process.vm_manager.page_table;
|
||||
|
||||
auto page_pointer = page_table.pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer)
|
||||
if (page_pointer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (page_table.attributes[vaddr >> CITRA_PAGE_BITS] == PageType::RasterizerCachedMemory)
|
||||
if (page_table.attributes[vaddr >> CITRA_PAGE_BITS] == PageType::RasterizerCachedMemory) {
|
||||
return true;
|
||||
|
||||
if (page_table.attributes[vaddr >> CITRA_PAGE_BITS] != PageType::Special)
|
||||
return false;
|
||||
|
||||
MMIORegionPointer mmio_region = impl->GetMMIOHandler(page_table, vaddr);
|
||||
if (mmio_region) {
|
||||
return mmio_region->IsValidAddress(vaddr);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -923,8 +867,6 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad
|
|||
std::size_t page_index = dest_addr >> CITRA_PAGE_BITS;
|
||||
std::size_t page_offset = dest_addr & CITRA_PAGE_MASK;
|
||||
|
||||
static const std::array<u8, CITRA_PAGE_SIZE> zeros = {};
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(CITRA_PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr =
|
||||
|
@ -945,12 +887,6 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad
|
|||
std::memset(dest_ptr, 0, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = impl->GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->WriteBlock(current_vaddr, zeros.data(), copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Invalidate);
|
||||
|
@ -1000,14 +936,6 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
|
|||
WriteBlock(dest_process, dest_addr, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = impl->GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
std::vector<u8> buffer(copy_amount);
|
||||
handler->ReadBlock(current_vaddr, buffer.data(), buffer.size());
|
||||
WriteBlock(dest_process, dest_addr, buffer.data(), buffer.size());
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Flush);
|
||||
|
@ -1027,46 +955,6 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
|
|||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) {
|
||||
return mmio_handler->Read8(addr);
|
||||
}
|
||||
|
||||
template <>
|
||||
u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) {
|
||||
return mmio_handler->Read16(addr);
|
||||
}
|
||||
|
||||
template <>
|
||||
u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) {
|
||||
return mmio_handler->Read32(addr);
|
||||
}
|
||||
|
||||
template <>
|
||||
u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) {
|
||||
return mmio_handler->Read64(addr);
|
||||
}
|
||||
|
||||
template <>
|
||||
void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) {
|
||||
mmio_handler->Write8(addr, data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) {
|
||||
mmio_handler->Write16(addr, data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) {
|
||||
mmio_handler->Write32(addr, data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) {
|
||||
mmio_handler->Write64(addr, data);
|
||||
}
|
||||
|
||||
u32 MemorySystem::GetFCRAMOffset(const u8* pointer) const {
|
||||
ASSERT(pointer >= impl->fcram.get() && pointer <= impl->fcram.get() + Memory::FCRAM_N3DS_SIZE);
|
||||
return static_cast<u32>(pointer - impl->fcram.get());
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/memory_ref.h"
|
||||
#include "core/mmio.h"
|
||||
|
||||
namespace Kernel {
|
||||
class Process;
|
||||
|
@ -43,23 +42,6 @@ enum class PageType {
|
|||
/// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
|
||||
/// invalidation
|
||||
RasterizerCachedMemory,
|
||||
/// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
|
||||
Special,
|
||||
};
|
||||
|
||||
struct SpecialRegion {
|
||||
VAddr base;
|
||||
u32 size;
|
||||
MMIORegionPointer handler;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& base;
|
||||
ar& size;
|
||||
ar& handler;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -108,12 +90,6 @@ struct PageTable {
|
|||
|
||||
Pointers pointers;
|
||||
|
||||
/**
|
||||
* Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of
|
||||
* type `Special`.
|
||||
*/
|
||||
std::vector<SpecialRegion> special_regions;
|
||||
|
||||
/**
|
||||
* Array of fine grained page attributes. If it is set to any value other than `Memory`, then
|
||||
* the corresponding entry in `pointers` MUST be set to null.
|
||||
|
@ -130,7 +106,6 @@ private:
|
|||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& pointers.refs;
|
||||
ar& special_regions;
|
||||
ar& attributes;
|
||||
for (std::size_t i = 0; i < PAGE_TABLE_NUM_ENTRIES; i++) {
|
||||
pointers.raw[i] = pointers.refs[i].GetPtr();
|
||||
|
@ -302,15 +277,6 @@ public:
|
|||
*/
|
||||
void MapMemoryRegion(PageTable& page_table, VAddr base, u32 size, MemoryRef target);
|
||||
|
||||
/**
|
||||
* Maps a region of the emulated process address space as a IO region.
|
||||
* @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 mmio_handler The handler that backs the mapping.
|
||||
*/
|
||||
void MapIoRegion(PageTable& page_table, VAddr base, u32 size, MMIORegionPointer mmio_handler);
|
||||
|
||||
void UnmapRegion(PageTable& page_table, VAddr base, u32 size);
|
||||
|
||||
/// Currently active page table
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Memory {
|
||||
|
||||
/**
|
||||
* Represents a device with memory mapped IO.
|
||||
* A device may be mapped to multiple regions of memory.
|
||||
*/
|
||||
class MMIORegion {
|
||||
public:
|
||||
virtual ~MMIORegion() = default;
|
||||
|
||||
virtual bool IsValidAddress(VAddr addr) = 0;
|
||||
|
||||
virtual u8 Read8(VAddr addr) = 0;
|
||||
virtual u16 Read16(VAddr addr) = 0;
|
||||
virtual u32 Read32(VAddr addr) = 0;
|
||||
virtual u64 Read64(VAddr addr) = 0;
|
||||
|
||||
virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0;
|
||||
|
||||
virtual void Write8(VAddr addr, u8 data) = 0;
|
||||
virtual void Write16(VAddr addr, u16 data) = 0;
|
||||
virtual void Write32(VAddr addr, u32 data) = 0;
|
||||
virtual void Write64(VAddr addr, u64 data) = 0;
|
||||
|
||||
virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) = 0;
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {}
|
||||
};
|
||||
|
||||
using MMIORegionPointer = std::shared_ptr<MMIORegion>;
|
||||
}; // namespace Memory
|
Loading…
Add table
Add a link
Reference in a new issue