aboutsummaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp315
1 files changed, 198 insertions, 117 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 6061d37ae..b88aa5c40 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -8,19 +8,21 @@
#include <utility>
#include "common/assert.h"
+#include "common/atomic_ops.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/swap.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
+#include "core/device_memory.h"
+#include "core/hle/kernel/memory/page_table.h"
#include "core/hle/kernel/physical_memory.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/vm_manager.h"
#include "core/memory.h"
#include "video_core/gpu.h"
-namespace Memory {
+namespace Core::Memory {
// Implementation class used to keep the specifics of the memory subsystem hidden
// from outside classes. This also allows modification to the internals of the memory
@@ -28,23 +30,15 @@ namespace Memory {
struct Memory::Impl {
explicit Impl(Core::System& system_) : system{system_} {}
- void SetCurrentPageTable(Kernel::Process& process) {
- current_page_table = &process.VMManager().page_table;
+ void SetCurrentPageTable(Kernel::Process& process, u32 core_id) {
+ current_page_table = &process.PageTable().PageTableImpl();
- const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth();
+ const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth();
- system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width);
- system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width);
- system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width);
- system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
+ system.ArmInterface(core_id).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, PAddr target) {
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
@@ -52,46 +46,27 @@ struct Memory::Impl {
void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
Common::MemoryHookPointer mmio_handler) {
- ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
- ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
- MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
- Common::PageType::Special);
-
- const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
- const Common::SpecialRegion region{Common::SpecialRegion::Type::IODevice,
- std::move(mmio_handler)};
- page_table.special_regions.add(
- std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+ UNIMPLEMENTED();
}
void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 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);
- MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
- Common::PageType::Unmapped);
-
- const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
- page_table.special_regions.erase(interval);
+ MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped);
}
void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
Common::MemoryHookPointer hook) {
- const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
- const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
- page_table.special_regions.add(
- std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+ UNIMPLEMENTED();
}
void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
Common::MemoryHookPointer hook) {
- const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
- const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
- page_table.special_regions.subtract(
- std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+ UNIMPLEMENTED();
}
bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS];
if (page_pointer != nullptr) {
@@ -113,55 +88,28 @@ struct Memory::Impl {
return IsValidVirtualAddress(*system.CurrentProcess(), vaddr);
}
- /**
- * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned)
- * using a VMA from the current process
- */
- u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) {
- const auto& vm_manager = process.VMManager();
-
- const auto it = vm_manager.FindVMA(vaddr);
- DEBUG_ASSERT(vm_manager.IsValidHandle(it));
+ u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const {
+ const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]};
- u8* direct_pointer = nullptr;
- const auto& vma = it->second;
- switch (vma.type) {
- case Kernel::VMAType::AllocatedMemoryBlock:
- direct_pointer = vma.backing_block->data() + vma.offset;
- break;
- case Kernel::VMAType::BackingMemory:
- direct_pointer = vma.backing_memory;
- break;
- case Kernel::VMAType::Free:
- return nullptr;
- default:
- UNREACHABLE();
+ if (!paddr) {
+ return {};
}
- return direct_pointer + (vaddr - vma.base);
+ return system.DeviceMemory().GetPointer(paddr) + vaddr;
}
- /**
- * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned)
- * using a VMA from the current process.
- */
- u8* GetPointerFromVMA(VAddr vaddr) {
- return GetPointerFromVMA(*system.CurrentProcess(), vaddr);
- }
-
- u8* GetPointer(const VAddr vaddr) {
- u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
- if (page_pointer != nullptr) {
+ u8* GetPointer(const VAddr vaddr) const {
+ u8* const page_pointer{current_page_table->pointers[vaddr >> PAGE_BITS]};
+ if (page_pointer) {
return page_pointer + vaddr;
}
if (current_page_table->attributes[vaddr >> PAGE_BITS] ==
Common::PageType::RasterizerCachedMemory) {
- return GetPointerFromVMA(vaddr);
+ return GetPointerFromRasterizerCachedMemory(vaddr);
}
- LOG_ERROR(HW_Memory, "Unknown GetPointer @ 0x{:016X}", vaddr);
- return nullptr;
+ return {};
}
u8 Read8(const VAddr addr) {
@@ -169,15 +117,33 @@ struct Memory::Impl {
}
u16 Read16(const VAddr addr) {
- return Read<u16_le>(addr);
+ if ((addr & 1) == 0) {
+ return Read<u16_le>(addr);
+ } else {
+ const u32 a{Read<u8>(addr)};
+ const u32 b{Read<u8>(addr + sizeof(u8))};
+ return static_cast<u16>((b << 8) | a);
+ }
}
u32 Read32(const VAddr addr) {
- return Read<u32_le>(addr);
+ if ((addr & 3) == 0) {
+ return Read<u32_le>(addr);
+ } else {
+ const u32 a{Read16(addr)};
+ const u32 b{Read16(addr + sizeof(u16))};
+ return (b << 16) | a;
+ }
}
u64 Read64(const VAddr addr) {
- return Read<u64_le>(addr);
+ if ((addr & 7) == 0) {
+ return Read<u64_le>(addr);
+ } else {
+ const u32 a{Read32(addr)};
+ const u32 b{Read32(addr + sizeof(u32))};
+ return (static_cast<u64>(b) << 32) | a;
+ }
}
void Write8(const VAddr addr, const u8 data) {
@@ -185,15 +151,46 @@ struct Memory::Impl {
}
void Write16(const VAddr addr, const u16 data) {
- Write<u16_le>(addr, data);
+ if ((addr & 1) == 0) {
+ Write<u16_le>(addr, data);
+ } else {
+ Write<u8>(addr, static_cast<u8>(data));
+ Write<u8>(addr + sizeof(u8), static_cast<u8>(data >> 8));
+ }
}
void Write32(const VAddr addr, const u32 data) {
- Write<u32_le>(addr, data);
+ if ((addr & 3) == 0) {
+ Write<u32_le>(addr, data);
+ } else {
+ Write16(addr, static_cast<u16>(data));
+ Write16(addr + sizeof(u16), static_cast<u16>(data >> 16));
+ }
}
void Write64(const VAddr addr, const u64 data) {
- Write<u64_le>(addr, data);
+ if ((addr & 7) == 0) {
+ Write<u64_le>(addr, data);
+ } else {
+ Write32(addr, static_cast<u32>(data));
+ Write32(addr + sizeof(u32), static_cast<u32>(data >> 32));
+ }
+ }
+
+ bool WriteExclusive8(const VAddr addr, const u8 data, const u8 expected) {
+ return WriteExclusive<u8>(addr, data, expected);
+ }
+
+ bool WriteExclusive16(const VAddr addr, const u16 data, const u16 expected) {
+ return WriteExclusive<u16_le>(addr, data, expected);
+ }
+
+ bool WriteExclusive32(const VAddr addr, const u32 data, const u32 expected) {
+ return WriteExclusive<u32_le>(addr, data, expected);
+ }
+
+ bool WriteExclusive64(const VAddr addr, const u64 data, const u64 expected) {
+ return WriteExclusive<u64_le>(addr, data, expected);
}
std::string ReadCString(VAddr vaddr, std::size_t max_length) {
@@ -213,7 +210,7 @@ struct Memory::Impl {
void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = src_addr >> PAGE_BITS;
@@ -241,7 +238,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
system.GPU().FlushRegion(current_vaddr, copy_amount);
std::memcpy(dest_buffer, host_ptr, copy_amount);
break;
@@ -259,7 +256,7 @@ struct Memory::Impl {
void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = src_addr >> PAGE_BITS;
@@ -287,7 +284,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
std::memcpy(dest_buffer, host_ptr, copy_amount);
break;
}
@@ -312,7 +309,7 @@ struct Memory::Impl {
void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer,
const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = dest_addr >> PAGE_BITS;
std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -338,7 +335,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
system.GPU().InvalidateRegion(current_vaddr, copy_amount);
std::memcpy(host_ptr, src_buffer, copy_amount);
break;
@@ -356,7 +353,7 @@ struct Memory::Impl {
void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr,
const void* src_buffer, const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = dest_addr >> PAGE_BITS;
std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -382,7 +379,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
std::memcpy(host_ptr, src_buffer, copy_amount);
break;
}
@@ -406,7 +403,7 @@ struct Memory::Impl {
}
void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = dest_addr >> PAGE_BITS;
std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -432,7 +429,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
system.GPU().InvalidateRegion(current_vaddr, copy_amount);
std::memset(host_ptr, 0, copy_amount);
break;
@@ -453,7 +450,7 @@ struct Memory::Impl {
void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
const std::size_t size) {
- const auto& page_table = process.VMManager().page_table;
+ const auto& page_table = process.PageTable().PageTableImpl();
std::size_t remaining_size = size;
std::size_t page_index = src_addr >> PAGE_BITS;
std::size_t page_offset = src_addr & PAGE_MASK;
@@ -479,7 +476,7 @@ struct Memory::Impl {
break;
}
case Common::PageType::RasterizerCachedMemory: {
- const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+ const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
system.GPU().FlushRegion(current_vaddr, copy_amount);
WriteBlock(process, dest_addr, host_ptr, copy_amount);
break;
@@ -512,7 +509,7 @@ struct Memory::Impl {
u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1;
for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
- Common::PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
+ Common::PageType& page_type{current_page_table->attributes[vaddr >> PAGE_BITS]};
if (cached) {
// Switch page type to cached if now cached
@@ -544,16 +541,16 @@ struct Memory::Impl {
// that this area is already unmarked as cached.
break;
case Common::PageType::RasterizerCachedMemory: {
- u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
+ u8* pointer{GetPointerFromRasterizerCachedMemory(vaddr & ~PAGE_MASK)};
if (pointer == nullptr) {
// It's possible that this function has been called while updating the
// pagetable after unmapping a VMA. In that case the underlying VMA will no
// longer exist, and we should just leave the pagetable entry blank.
page_type = Common::PageType::Unmapped;
} else {
- page_type = Common::PageType::Memory;
current_page_table->pointers[vaddr >> PAGE_BITS] =
pointer - (vaddr & ~PAGE_MASK);
+ page_type = Common::PageType::Memory;
}
break;
}
@@ -570,12 +567,12 @@ struct Memory::Impl {
* @param page_table The page table to use to perform the mapping.
* @param base The base address to begin mapping at.
* @param size The total size of the range in bytes.
- * @param memory The memory to map.
+ * @param target The target address to begin mapping from.
* @param type The page type to map the memory as.
*/
- void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory,
+ void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target,
Common::PageType type) {
- LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
+ LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * PAGE_SIZE,
(base + size) * PAGE_SIZE);
// During boot, current_page_table might not be set yet, in which case we need not flush
@@ -593,19 +590,29 @@ struct Memory::Impl {
ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
base + page_table.pointers.size());
- std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type);
+ if (!target) {
+ ASSERT_MSG(type != Common::PageType::Memory,
+ "Mapping memory page without a pointer @ {:016x}", base * PAGE_SIZE);
+
+ while (base != end) {
+ page_table.attributes[base] = type;
+ page_table.pointers[base] = nullptr;
+ page_table.backing_addr[base] = 0;
- if (memory == nullptr) {
- std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end,
- memory);
+ base += 1;
+ }
} else {
while (base != end) {
- page_table.pointers[base] = memory - (base << PAGE_BITS);
+ page_table.pointers[base] =
+ system.DeviceMemory().GetPointer(target) - (base << PAGE_BITS);
+ page_table.attributes[base] = type;
+ page_table.backing_addr[base] = target - (base << PAGE_BITS);
+
ASSERT_MSG(page_table.pointers[base],
"memory mapping base yield a nullptr within the table");
base += 1;
- memory += PAGE_SIZE;
+ target += PAGE_SIZE;
}
}
}
@@ -640,7 +647,7 @@ struct Memory::Impl {
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
break;
case Common::PageType::RasterizerCachedMemory: {
- const u8* const host_ptr = GetPointerFromVMA(vaddr);
+ const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
system.GPU().FlushRegion(vaddr, sizeof(T));
T value;
std::memcpy(&value, host_ptr, sizeof(T));
@@ -682,7 +689,7 @@ struct Memory::Impl {
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
break;
case Common::PageType::RasterizerCachedMemory: {
- u8* const host_ptr{GetPointerFromVMA(vaddr)};
+ u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
system.GPU().InvalidateRegion(vaddr, sizeof(T));
std::memcpy(host_ptr, &data, sizeof(T));
break;
@@ -692,6 +699,65 @@ struct Memory::Impl {
}
}
+ template <typename T>
+ bool WriteExclusive(const VAddr vaddr, const T data, const T expected) {
+ u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+ if (page_pointer != nullptr) {
+ // NOTE: Avoid adding any extra logic to this fast-path block
+ auto* pointer = reinterpret_cast<volatile T*>(&page_pointer[vaddr]);
+ return Common::AtomicCompareAndSwap(pointer, data, expected);
+ }
+
+ const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+ switch (type) {
+ case Common::PageType::Unmapped:
+ LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
+ static_cast<u32>(data), vaddr);
+ return true;
+ case Common::PageType::Memory:
+ ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
+ break;
+ case Common::PageType::RasterizerCachedMemory: {
+ u8* host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
+ system.GPU().InvalidateRegion(vaddr, sizeof(T));
+ auto* pointer = reinterpret_cast<volatile T*>(&host_ptr);
+ return Common::AtomicCompareAndSwap(pointer, data, expected);
+ }
+ default:
+ UNREACHABLE();
+ }
+ return true;
+ }
+
+ bool WriteExclusive128(const VAddr vaddr, const u128 data, const u128 expected) {
+ u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+ if (page_pointer != nullptr) {
+ // NOTE: Avoid adding any extra logic to this fast-path block
+ auto* pointer = reinterpret_cast<volatile u64*>(&page_pointer[vaddr]);
+ return Common::AtomicCompareAndSwap(pointer, data, expected);
+ }
+
+ const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+ switch (type) {
+ case Common::PageType::Unmapped:
+ LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}{:016X}", sizeof(data) * 8,
+ static_cast<u64>(data[1]), static_cast<u64>(data[0]), vaddr);
+ return true;
+ case Common::PageType::Memory:
+ ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
+ break;
+ case Common::PageType::RasterizerCachedMemory: {
+ u8* host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
+ system.GPU().InvalidateRegion(vaddr, sizeof(u128));
+ auto* pointer = reinterpret_cast<volatile u64*>(&host_ptr);
+ return Common::AtomicCompareAndSwap(pointer, data, expected);
+ }
+ default:
+ UNREACHABLE();
+ }
+ return true;
+ }
+
Common::PageTable* current_page_table = nullptr;
Core::System& system;
};
@@ -699,16 +765,11 @@ struct Memory::Impl {
Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
Memory::~Memory() = default;
-void Memory::SetCurrentPageTable(Kernel::Process& process) {
- impl->SetCurrentPageTable(process);
+void Memory::SetCurrentPageTable(Kernel::Process& process, u32 core_id) {
+ impl->SetCurrentPageTable(process, core_id);
}
-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, PAddr target) {
impl->MapMemoryRegion(page_table, base, size, target);
}
@@ -779,6 +840,26 @@ void Memory::Write64(VAddr addr, u64 data) {
impl->Write64(addr, data);
}
+bool Memory::WriteExclusive8(VAddr addr, u8 data, u8 expected) {
+ return impl->WriteExclusive8(addr, data, expected);
+}
+
+bool Memory::WriteExclusive16(VAddr addr, u16 data, u16 expected) {
+ return impl->WriteExclusive16(addr, data, expected);
+}
+
+bool Memory::WriteExclusive32(VAddr addr, u32 data, u32 expected) {
+ return impl->WriteExclusive32(addr, data, expected);
+}
+
+bool Memory::WriteExclusive64(VAddr addr, u64 data, u64 expected) {
+ return impl->WriteExclusive64(addr, data, expected);
+}
+
+bool Memory::WriteExclusive128(VAddr addr, u128 data, u128 expected) {
+ return impl->WriteExclusive128(addr, data, expected);
+}
+
std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) {
return impl->ReadCString(vaddr, max_length);
}
@@ -845,4 +926,4 @@ bool IsKernelVirtualAddress(const VAddr vaddr) {
return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END;
}
-} // namespace Memory
+} // namespace Core::Memory