Browse Source

[core] ignore page marking when needed

pull/4219/head
Exverge 1 week ago
parent
commit
928d04dfcd
No known key found for this signature in database GPG Key ID: DAD399BCC5FB77E4
  1. 4
      src/common/page_table.h
  2. 2
      src/core/hle/kernel/k_page_table_base.cpp
  3. 2
      src/core/hle/kernel/k_page_table_base.h
  4. 9
      src/core/memory.cpp

4
src/common/page_table.h

@ -83,9 +83,9 @@ struct PageTable {
}
/// Returns the page pointer and attribute pair, extracted from the same atomic read
[[nodiscard]] std::tuple<uintptr_t, PageType, u16> PointerTypeBlock() const noexcept {
[[nodiscard]] std::tuple<uintptr_t, PageType, u16> PointerTypeBlock(bool ignore_marked = false) const noexcept {
const Data non_atomic_raw = data.load(std::memory_order_relaxed);
return {ExtractPointer(non_atomic_raw), static_cast<PageType>(non_atomic_raw.type), static_cast<u16>(non_atomic_raw.block)};
return {ExtractPointer(non_atomic_raw, ignore_marked), static_cast<PageType>(non_atomic_raw.type), static_cast<u16>(non_atomic_raw.block)};
}
/// Write page info atomically

2
src/core/hle/kernel/k_page_table_base.cpp

@ -653,7 +653,7 @@ bool KPageTableBase::ContinueTraversal(const Common::PageTable &impl, TraversalE
// Validate that the entry is mapped.
if (auto const paddr = impl.entries[page].Pointer(true); paddr != 0) {
// Populate the results and return true
out_entry->phys_addr = GetInteger(m_system.DeviceMemory().GetPhysicalAddr(paddr)) + context->next_offset;
out_entry->phys_addr = GetInteger(m_system.DeviceMemory().GetPhysicalAddr(paddr + context->next_offset));
context->next_page += 1;
context->next_offset += PageSize;
return true;

2
src/core/hle/kernel/k_page_table_base.h

@ -482,7 +482,7 @@ private:
}
*out = m_system.DeviceMemory().GetPhysicalAddr(
this->GetImpl().entries[virt_addr >> PageBits].Pointer(true));
this->GetImpl().entries[GetInteger(virt_addr) >> PageBits].Pointer(true) + GetInteger(virt_addr));
return true;
}

9
src/core/memory.cpp

@ -410,7 +410,7 @@ struct Memory::Impl {
current_page_table->entries.CommitRegion(vaddr >> YUZU_PAGEBITS, (vaddr >> YUZU_PAGEBITS) + num_pages);
for (u64 i = 0; i < num_pages; ++i, vaddr += YUZU_PAGESIZE) {
auto& entry = current_page_table->entries.GetUnchecked(vaddr >> YUZU_PAGEBITS);
const auto [pointer, type, block] = entry.PointerTypeBlock();
const auto [pointer, type, block] = entry.PointerTypeBlock(true);
if (debug) {
// Switch page type to debug if now debug
switch (type) {
@ -505,12 +505,11 @@ struct Memory::Impl {
// that this area is already unmarked as cached.
break;
case Common::PageType::RasterizerCachedMemory: {
if (auto [ptr, _, block] = entry.PointerTypeBlock(); ptr == 0) {
if (auto [ptr, _, block] = entry.PointerTypeBlock(true); ptr == 0) {
// 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.
// TODO: can this just set entry to 0?
entry.Store(true, Common::PageType::Unmapped, block, ptr);
entry.Store(false, Common::PageType::Unmapped, block, 0);
} else {
entry.Store(false, Common::PageType::Memory, block, ptr);
}
@ -589,6 +588,7 @@ struct Memory::Impl {
return host_ptr;
}
case Common::PageType::Unmapped: [[unlikely]] {
__builtin_debugtrap();
on_unmapped();
return nullptr;
}
@ -625,7 +625,6 @@ struct Memory::Impl {
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
const u64 addr = GetInteger(vaddr);
if (auto const ptr = GetPointerImpl(addr, [addr]() {
__builtin_debugtrap();
LOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#016x}", sizeof(T) * 8, addr);
}, [&]() {
HandleRasterizerDownload(addr, sizeof(T));

Loading…
Cancel
Save