summaryrefslogtreecommitdiffstats
path: root/src/core/memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/memory.h')
-rw-r--r--src/core/memory.h211
1 files changed, 6 insertions, 205 deletions
diff --git a/src/core/memory.h b/src/core/memory.h
index dddfaf4a4..f7e6b297f 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -12,6 +12,7 @@
#include "common/scratch_buffer.h"
#include "common/typed_address.h"
+#include "core/guest_memory.h"
#include "core/hle/result.h"
namespace Common {
@@ -486,10 +487,10 @@ public:
void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug);
void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers);
- void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size);
+
bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
+
bool InvalidateSeparateHeap(void* fault_address);
- void FlushRegion(Common::ProcessAddress dest_addr, size_t size);
private:
Core::System& system;
@@ -498,209 +499,9 @@ private:
std::unique_ptr<Impl> impl;
};
-enum GuestMemoryFlags : u32 {
- Read = 1 << 0,
- Write = 1 << 1,
- Safe = 1 << 2,
- Cached = 1 << 3,
-
- SafeRead = Read | Safe,
- SafeWrite = Write | Safe,
- SafeReadWrite = SafeRead | SafeWrite,
- SafeReadCachedWrite = SafeReadWrite | Cached,
-
- UnsafeRead = Read,
- UnsafeWrite = Write,
- UnsafeReadWrite = UnsafeRead | UnsafeWrite,
- UnsafeReadCachedWrite = UnsafeReadWrite | Cached,
-};
-
-namespace {
-template <typename M, typename T, GuestMemoryFlags FLAGS>
-class GuestMemory {
- using iterator = T*;
- using const_iterator = const T*;
- using value_type = T;
- using element_type = T;
- using iterator_category = std::contiguous_iterator_tag;
-
-public:
- GuestMemory() = delete;
- explicit GuestMemory(M& memory, u64 addr, std::size_t size,
- Common::ScratchBuffer<T>* backup = nullptr)
- : m_memory{memory}, m_addr{addr}, m_size{size} {
- static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
- if constexpr (FLAGS & GuestMemoryFlags::Read) {
- Read(addr, size, backup);
- }
- }
-
- ~GuestMemory() = default;
-
- T* data() noexcept {
- return m_data_span.data();
- }
-
- const T* data() const noexcept {
- return m_data_span.data();
- }
-
- size_t size() const noexcept {
- return m_size;
- }
-
- size_t size_bytes() const noexcept {
- return this->size() * sizeof(T);
- }
-
- [[nodiscard]] T* begin() noexcept {
- return this->data();
- }
-
- [[nodiscard]] const T* begin() const noexcept {
- return this->data();
- }
-
- [[nodiscard]] T* end() noexcept {
- return this->data() + this->size();
- }
-
- [[nodiscard]] const T* end() const noexcept {
- return this->data() + this->size();
- }
-
- T& operator[](size_t index) noexcept {
- return m_data_span[index];
- }
-
- const T& operator[](size_t index) const noexcept {
- return m_data_span[index];
- }
-
- void SetAddressAndSize(u64 addr, std::size_t size) noexcept {
- m_addr = addr;
- m_size = size;
- m_addr_changed = true;
- }
-
- std::span<T> Read(u64 addr, std::size_t size,
- Common::ScratchBuffer<T>* backup = nullptr) noexcept {
- m_addr = addr;
- m_size = size;
- if (m_size == 0) {
- m_is_data_copy = true;
- return {};
- }
-
- if (this->TrySetSpan()) {
- if constexpr (FLAGS & GuestMemoryFlags::Safe) {
- m_memory.FlushRegion(m_addr, this->size_bytes());
- }
- } else {
- if (backup) {
- backup->resize_destructive(this->size());
- m_data_span = *backup;
- } else {
- m_data_copy.resize(this->size());
- m_data_span = std::span(m_data_copy);
- }
- m_is_data_copy = true;
- m_span_valid = true;
- if constexpr (FLAGS & GuestMemoryFlags::Safe) {
- m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
- } else {
- m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
- }
- }
- return m_data_span;
- }
-
- void Write(std::span<T> write_data) noexcept {
- if constexpr (FLAGS & GuestMemoryFlags::Cached) {
- m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
- } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
- m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
- } else {
- m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
- }
- }
-
- bool TrySetSpan() noexcept {
- if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
- m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
- m_span_valid = true;
- return true;
- }
- return false;
- }
-
-protected:
- bool IsDataCopy() const noexcept {
- return m_is_data_copy;
- }
-
- bool AddressChanged() const noexcept {
- return m_addr_changed;
- }
-
- M& m_memory;
- u64 m_addr{};
- size_t m_size{};
- std::span<T> m_data_span{};
- std::vector<T> m_data_copy{};
- bool m_span_valid{false};
- bool m_is_data_copy{false};
- bool m_addr_changed{false};
-};
-
-template <typename M, typename T, GuestMemoryFlags FLAGS>
-class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
-public:
- GuestMemoryScoped() = delete;
- explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
- Common::ScratchBuffer<T>* backup = nullptr)
- : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
- if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
- if (!this->TrySetSpan()) {
- if (backup) {
- this->m_data_span = *backup;
- this->m_span_valid = true;
- this->m_is_data_copy = true;
- }
- }
- }
- }
-
- ~GuestMemoryScoped() {
- if constexpr (FLAGS & GuestMemoryFlags::Write) {
- if (this->size() == 0) [[unlikely]] {
- return;
- }
-
- if (this->AddressChanged() || this->IsDataCopy()) {
- ASSERT(this->m_span_valid);
- if constexpr (FLAGS & GuestMemoryFlags::Cached) {
- this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
- } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
- this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
- } else {
- this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
- }
- } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
- (FLAGS & GuestMemoryFlags::Cached)) {
- this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
- }
- }
- }
-};
-} // namespace
-
template <typename T, GuestMemoryFlags FLAGS>
-using CpuGuestMemory = GuestMemory<Memory, T, FLAGS>;
+using CpuGuestMemory = GuestMemory<Core::Memory::Memory, T, FLAGS>;
template <typename T, GuestMemoryFlags FLAGS>
-using CpuGuestMemoryScoped = GuestMemoryScoped<Memory, T, FLAGS>;
-template <typename T, GuestMemoryFlags FLAGS>
-using GpuGuestMemory = GuestMemory<Tegra::MemoryManager, T, FLAGS>;
-template <typename T, GuestMemoryFlags FLAGS>
-using GpuGuestMemoryScoped = GuestMemoryScoped<Tegra::MemoryManager, T, FLAGS>;
+using CpuGuestMemoryScoped = GuestMemoryScoped<Core::Memory::Memory, T, FLAGS>;
+
} // namespace Core::Memory