summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar GPUCode2023-11-17 21:43:15 +0200
committerGravatar t8952023-11-25 00:46:15 -0500
commit5938a9582a238d7679eb15f9812f8a85bfdb1cc3 (patch)
tree935356a1cc03fea528e349d5027f2d885537272a /src
parenthost_memory: Switch to FreeRegionManager (diff)
downloadyuzu-5938a9582a238d7679eb15f9812f8a85bfdb1cc3.tar.gz
yuzu-5938a9582a238d7679eb15f9812f8a85bfdb1cc3.tar.xz
yuzu-5938a9582a238d7679eb15f9812f8a85bfdb1cc3.zip
core: Respect memory permissions in Map
Diffstat (limited to 'src')
-rw-r--r--src/common/host_memory.cpp45
-rw-r--r--src/common/host_memory.h13
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp32
-rw-r--r--src/core/memory.cpp8
-rw-r--r--src/core/memory.h6
-rw-r--r--src/tests/common/host_memory.cpp71
6 files changed, 117 insertions, 58 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index a66fc49e2..3e4b34de6 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -144,7 +144,7 @@ public:
144 Release(); 144 Release();
145 } 145 }
146 146
147 void Map(size_t virtual_offset, size_t host_offset, size_t length) { 147 void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) {
148 std::unique_lock lock{placeholder_mutex}; 148 std::unique_lock lock{placeholder_mutex};
149 if (!IsNiechePlaceholder(virtual_offset, length)) { 149 if (!IsNiechePlaceholder(virtual_offset, length)) {
150 Split(virtual_offset, length); 150 Split(virtual_offset, length);
@@ -163,7 +163,7 @@ public:
163 } 163 }
164 } 164 }
165 165
166 void Protect(size_t virtual_offset, size_t length, bool read, bool write) { 166 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {
167 DWORD new_flags{}; 167 DWORD new_flags{};
168 if (read && write) { 168 if (read && write) {
169 new_flags = PAGE_READWRITE; 169 new_flags = PAGE_READWRITE;
@@ -494,15 +494,29 @@ public:
494 Release(); 494 Release();
495 } 495 }
496 496
497 void Map(size_t virtual_offset, size_t host_offset, size_t length) { 497 void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) {
498 // Intersect the range with our address space. 498 // Intersect the range with our address space.
499 AdjustMap(&virtual_offset, &length); 499 AdjustMap(&virtual_offset, &length);
500 500
501 // We are removing a placeholder. 501 // We are removing a placeholder.
502 free_manager.AllocateBlock(virtual_base + virtual_offset, length); 502 free_manager.AllocateBlock(virtual_base + virtual_offset, length);
503 503
504 void* ret = mmap(virtual_base + virtual_offset, length, PROT_READ | PROT_WRITE, 504 // Deduce mapping protection flags.
505 MAP_SHARED | MAP_FIXED, fd, host_offset); 505 int flags = PROT_NONE;
506 if (True(perms & MemoryPermission::Read)) {
507 flags |= PROT_READ;
508 }
509 if (True(perms & MemoryPermission::Write)) {
510 flags |= PROT_WRITE;
511 }
512#ifdef ARCHITECTURE_arm64
513 if (True(perms & MemoryPermission::Execute)) {
514 flags |= PROT_EXEC;
515 }
516#endif
517
518 void* ret = mmap(virtual_base + virtual_offset, length, flags, MAP_SHARED | MAP_FIXED, fd,
519 host_offset);
506 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); 520 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
507 } 521 }
508 522
@@ -522,7 +536,7 @@ public:
522 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); 536 ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
523 } 537 }
524 538
525 void Protect(size_t virtual_offset, size_t length, bool read, bool write) { 539 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {
526 // Intersect the range with our address space. 540 // Intersect the range with our address space.
527 AdjustMap(&virtual_offset, &length); 541 AdjustMap(&virtual_offset, &length);
528 542
@@ -533,6 +547,11 @@ public:
533 if (write) { 547 if (write) {
534 flags |= PROT_WRITE; 548 flags |= PROT_WRITE;
535 } 549 }
550#ifdef ARCHITECTURE_arm64
551 if (execute) {
552 flags |= PROT_EXEC;
553 }
554#endif
536 int ret = mprotect(virtual_base + virtual_offset, length, flags); 555 int ret = mprotect(virtual_base + virtual_offset, length, flags);
537 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); 556 ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
538 } 557 }
@@ -602,11 +621,11 @@ public:
602 throw std::bad_alloc{}; 621 throw std::bad_alloc{};
603 } 622 }
604 623
605 void Map(size_t virtual_offset, size_t host_offset, size_t length) {} 624 void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm) {}
606 625
607 void Unmap(size_t virtual_offset, size_t length) {} 626 void Unmap(size_t virtual_offset, size_t length) {}
608 627
609 void Protect(size_t virtual_offset, size_t length, bool read, bool write) {} 628 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
610 629
611 u8* backing_base{nullptr}; 630 u8* backing_base{nullptr};
612 u8* virtual_base{nullptr}; 631 u8* virtual_base{nullptr};
@@ -647,7 +666,8 @@ HostMemory::HostMemory(HostMemory&&) noexcept = default;
647 666
648HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default; 667HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default;
649 668
650void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) { 669void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length,
670 MemoryPermission perms) {
651 ASSERT(virtual_offset % PageAlignment == 0); 671 ASSERT(virtual_offset % PageAlignment == 0);
652 ASSERT(host_offset % PageAlignment == 0); 672 ASSERT(host_offset % PageAlignment == 0);
653 ASSERT(length % PageAlignment == 0); 673 ASSERT(length % PageAlignment == 0);
@@ -656,7 +676,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) {
656 if (length == 0 || !virtual_base || !impl) { 676 if (length == 0 || !virtual_base || !impl) {
657 return; 677 return;
658 } 678 }
659 impl->Map(virtual_offset + virtual_base_offset, host_offset, length); 679 impl->Map(virtual_offset + virtual_base_offset, host_offset, length, perms);
660} 680}
661 681
662void HostMemory::Unmap(size_t virtual_offset, size_t length) { 682void HostMemory::Unmap(size_t virtual_offset, size_t length) {
@@ -669,14 +689,15 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length) {
669 impl->Unmap(virtual_offset + virtual_base_offset, length); 689 impl->Unmap(virtual_offset + virtual_base_offset, length);
670} 690}
671 691
672void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool write) { 692void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool write,
693 bool execute) {
673 ASSERT(virtual_offset % PageAlignment == 0); 694 ASSERT(virtual_offset % PageAlignment == 0);
674 ASSERT(length % PageAlignment == 0); 695 ASSERT(length % PageAlignment == 0);
675 ASSERT(virtual_offset + length <= virtual_size); 696 ASSERT(virtual_offset + length <= virtual_size);
676 if (length == 0 || !virtual_base || !impl) { 697 if (length == 0 || !virtual_base || !impl) {
677 return; 698 return;
678 } 699 }
679 impl->Protect(virtual_offset + virtual_base_offset, length, read, write); 700 impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);
680} 701}
681 702
682void HostMemory::EnableDirectMappedAddress() { 703void HostMemory::EnableDirectMappedAddress() {
diff --git a/src/common/host_memory.h b/src/common/host_memory.h
index 4014a1962..cebfacab2 100644
--- a/src/common/host_memory.h
+++ b/src/common/host_memory.h
@@ -4,11 +4,20 @@
4#pragma once 4#pragma once
5 5
6#include <memory> 6#include <memory>
7#include "common/common_funcs.h"
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "common/virtual_buffer.h" 9#include "common/virtual_buffer.h"
9 10
10namespace Common { 11namespace Common {
11 12
13enum class MemoryPermission : u32 {
14 Read = 1 << 0,
15 Write = 1 << 1,
16 ReadWrite = Read | Write,
17 Execute = 1 << 2,
18};
19DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
20
12/** 21/**
13 * A low level linear memory buffer, which supports multiple mappings 22 * A low level linear memory buffer, which supports multiple mappings
14 * Its purpose is to rebuild a given sparse memory layout, including mirrors. 23 * Its purpose is to rebuild a given sparse memory layout, including mirrors.
@@ -31,11 +40,11 @@ public:
31 HostMemory(HostMemory&& other) noexcept; 40 HostMemory(HostMemory&& other) noexcept;
32 HostMemory& operator=(HostMemory&& other) noexcept; 41 HostMemory& operator=(HostMemory&& other) noexcept;
33 42
34 void Map(size_t virtual_offset, size_t host_offset, size_t length); 43 void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms);
35 44
36 void Unmap(size_t virtual_offset, size_t length); 45 void Unmap(size_t virtual_offset, size_t length);
37 46
38 void Protect(size_t virtual_offset, size_t length, bool read, bool write); 47 void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute = false);
39 48
40 void EnableDirectMappedAddress(); 49 void EnableDirectMappedAddress();
41 50
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 47dc8fd35..dc6524146 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -88,6 +88,20 @@ Result FlushDataCache(AddressType addr, u64 size) {
88 R_SUCCEED(); 88 R_SUCCEED();
89} 89}
90 90
91constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission perm) {
92 Common::MemoryPermission perms{};
93 if (True(perm & KMemoryPermission::UserRead)) {
94 perms |= Common::MemoryPermission::Read;
95 }
96 if (True(perm & KMemoryPermission::UserWrite)) {
97 perms |= Common::MemoryPermission::Write;
98 }
99 if (True(perm & KMemoryPermission::UserExecute)) {
100 perms |= Common::MemoryPermission::Execute;
101 }
102 return perms;
103}
104
91} // namespace 105} // namespace
92 106
93void KPageTableBase::MemoryRange::Open() { 107void KPageTableBase::MemoryRange::Open() {
@@ -5643,7 +5657,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
5643 case OperationType::Map: { 5657 case OperationType::Map: {
5644 ASSERT(virt_addr != 0); 5658 ASSERT(virt_addr != 0);
5645 ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); 5659 ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize));
5646 m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr); 5660 m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr,
5661 ConvertToMemoryPermission(properties.perm));
5647 5662
5648 // Open references to pages, if we should. 5663 // Open references to pages, if we should.
5649 if (this->IsHeapPhysicalAddress(phys_addr)) { 5664 if (this->IsHeapPhysicalAddress(phys_addr)) {
@@ -5658,8 +5673,18 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
5658 } 5673 }
5659 case OperationType::ChangePermissions: 5674 case OperationType::ChangePermissions:
5660 case OperationType::ChangePermissionsAndRefresh: 5675 case OperationType::ChangePermissionsAndRefresh:
5661 case OperationType::ChangePermissionsAndRefreshAndFlush: 5676 case OperationType::ChangePermissionsAndRefreshAndFlush: {
5677 const bool read = True(properties.perm & Kernel::KMemoryPermission::UserRead);
5678 const bool write = True(properties.perm & Kernel::KMemoryPermission::UserWrite);
5679 // todo: this doesn't really belong here and should go into m_memory to handle rasterizer
5680 // access todo: ignore exec on non-direct-mapped case
5681 const bool exec = True(properties.perm & Kernel::KMemoryPermission::UserExecute);
5682 if (Settings::IsFastmemEnabled()) {
5683 m_system.DeviceMemory().buffer.Protect(GetInteger(virt_addr), num_pages * PageSize,
5684 read, write, exec);
5685 }
5662 R_SUCCEED(); 5686 R_SUCCEED();
5687 }
5663 default: 5688 default:
5664 UNREACHABLE(); 5689 UNREACHABLE();
5665 } 5690 }
@@ -5687,7 +5712,8 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
5687 const size_t size{node.GetNumPages() * PageSize}; 5712 const size_t size{node.GetNumPages() * PageSize};
5688 5713
5689 // Map the pages. 5714 // Map the pages.
5690 m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress()); 5715 m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(),
5716 ConvertToMemoryPermission(properties.perm));
5691 5717
5692 virt_addr += size; 5718 virt_addr += size;
5693 } 5719 }
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index a3431772a..14db64f9d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -53,7 +53,7 @@ struct Memory::Impl {
53 } 53 }
54 54
55 void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, 55 void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
56 Common::PhysicalAddress target) { 56 Common::PhysicalAddress target, Common::MemoryPermission perms) {
57 ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); 57 ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
58 ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); 58 ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base));
59 ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", 59 ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}",
@@ -63,7 +63,7 @@ struct Memory::Impl {
63 63
64 if (Settings::IsFastmemEnabled()) { 64 if (Settings::IsFastmemEnabled()) {
65 system.DeviceMemory().buffer.Map(GetInteger(base), 65 system.DeviceMemory().buffer.Map(GetInteger(base),
66 GetInteger(target) - DramMemoryMap::Base, size); 66 GetInteger(target) - DramMemoryMap::Base, size, perms);
67 } 67 }
68 } 68 }
69 69
@@ -831,8 +831,8 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
831} 831}
832 832
833void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, 833void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
834 Common::PhysicalAddress target) { 834 Common::PhysicalAddress target, Common::MemoryPermission perms) {
835 impl->MapMemoryRegion(page_table, base, size, target); 835 impl->MapMemoryRegion(page_table, base, size, target, perms);
836} 836}
837 837
838void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { 838void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) {
diff --git a/src/core/memory.h b/src/core/memory.h
index 13047a545..73195549f 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -15,8 +15,9 @@
15#include "core/hle/result.h" 15#include "core/hle/result.h"
16 16
17namespace Common { 17namespace Common {
18enum class MemoryPermission : u32;
18struct PageTable; 19struct PageTable;
19} 20} // namespace Common
20 21
21namespace Core { 22namespace Core {
22class System; 23class System;
@@ -82,9 +83,10 @@ public:
82 * @param size The amount of bytes to map. Must be page-aligned. 83 * @param size The amount of bytes to map. Must be page-aligned.
83 * @param target Buffer with the memory backing the mapping. Must be of length at least 84 * @param target Buffer with the memory backing the mapping. Must be of length at least
84 * `size`. 85 * `size`.
86 * @param perms The permissions to map the memory with.
85 */ 87 */
86 void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, 88 void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
87 Common::PhysicalAddress target); 89 Common::PhysicalAddress target, Common::MemoryPermission perms);
88 90
89 /** 91 /**
90 * Unmaps a region of the emulated process address space. 92 * Unmaps a region of the emulated process address space.
diff --git a/src/tests/common/host_memory.cpp b/src/tests/common/host_memory.cpp
index 1b014b632..1a28e862b 100644
--- a/src/tests/common/host_memory.cpp
+++ b/src/tests/common/host_memory.cpp
@@ -11,6 +11,7 @@ using namespace Common::Literals;
11 11
12static constexpr size_t VIRTUAL_SIZE = 1ULL << 39; 12static constexpr size_t VIRTUAL_SIZE = 1ULL << 39;
13static constexpr size_t BACKING_SIZE = 4_GiB; 13static constexpr size_t BACKING_SIZE = 4_GiB;
14static constexpr auto PERMS = Common::MemoryPermission::ReadWrite;
14 15
15TEST_CASE("HostMemory: Initialize and deinitialize", "[common]") { 16TEST_CASE("HostMemory: Initialize and deinitialize", "[common]") {
16 { HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); } 17 { HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); }
@@ -19,7 +20,7 @@ TEST_CASE("HostMemory: Initialize and deinitialize", "[common]") {
19 20
20TEST_CASE("HostMemory: Simple map", "[common]") { 21TEST_CASE("HostMemory: Simple map", "[common]") {
21 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 22 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
22 mem.Map(0x5000, 0x8000, 0x1000); 23 mem.Map(0x5000, 0x8000, 0x1000, PERMS);
23 24
24 volatile u8* const data = mem.VirtualBasePointer() + 0x5000; 25 volatile u8* const data = mem.VirtualBasePointer() + 0x5000;
25 data[0] = 50; 26 data[0] = 50;
@@ -28,8 +29,8 @@ TEST_CASE("HostMemory: Simple map", "[common]") {
28 29
29TEST_CASE("HostMemory: Simple mirror map", "[common]") { 30TEST_CASE("HostMemory: Simple mirror map", "[common]") {
30 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 31 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
31 mem.Map(0x5000, 0x3000, 0x2000); 32 mem.Map(0x5000, 0x3000, 0x2000, PERMS);
32 mem.Map(0x8000, 0x4000, 0x1000); 33 mem.Map(0x8000, 0x4000, 0x1000, PERMS);
33 34
34 volatile u8* const mirror_a = mem.VirtualBasePointer() + 0x5000; 35 volatile u8* const mirror_a = mem.VirtualBasePointer() + 0x5000;
35 volatile u8* const mirror_b = mem.VirtualBasePointer() + 0x8000; 36 volatile u8* const mirror_b = mem.VirtualBasePointer() + 0x8000;
@@ -39,7 +40,7 @@ TEST_CASE("HostMemory: Simple mirror map", "[common]") {
39 40
40TEST_CASE("HostMemory: Simple unmap", "[common]") { 41TEST_CASE("HostMemory: Simple unmap", "[common]") {
41 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 42 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
42 mem.Map(0x5000, 0x3000, 0x2000); 43 mem.Map(0x5000, 0x3000, 0x2000, PERMS);
43 44
44 volatile u8* const data = mem.VirtualBasePointer() + 0x5000; 45 volatile u8* const data = mem.VirtualBasePointer() + 0x5000;
45 data[75] = 50; 46 data[75] = 50;
@@ -50,7 +51,7 @@ TEST_CASE("HostMemory: Simple unmap", "[common]") {
50 51
51TEST_CASE("HostMemory: Simple unmap and remap", "[common]") { 52TEST_CASE("HostMemory: Simple unmap and remap", "[common]") {
52 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 53 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
53 mem.Map(0x5000, 0x3000, 0x2000); 54 mem.Map(0x5000, 0x3000, 0x2000, PERMS);
54 55
55 volatile u8* const data = mem.VirtualBasePointer() + 0x5000; 56 volatile u8* const data = mem.VirtualBasePointer() + 0x5000;
56 data[0] = 50; 57 data[0] = 50;
@@ -58,79 +59,79 @@ TEST_CASE("HostMemory: Simple unmap and remap", "[common]") {
58 59
59 mem.Unmap(0x5000, 0x2000); 60 mem.Unmap(0x5000, 0x2000);
60 61
61 mem.Map(0x5000, 0x3000, 0x2000); 62 mem.Map(0x5000, 0x3000, 0x2000, PERMS);
62 REQUIRE(data[0] == 50); 63 REQUIRE(data[0] == 50);
63 64
64 mem.Map(0x7000, 0x2000, 0x5000); 65 mem.Map(0x7000, 0x2000, 0x5000, PERMS);
65 REQUIRE(data[0x3000] == 50); 66 REQUIRE(data[0x3000] == 50);
66} 67}
67 68
68TEST_CASE("HostMemory: Nieche allocation", "[common]") { 69TEST_CASE("HostMemory: Nieche allocation", "[common]") {
69 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 70 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
70 mem.Map(0x0000, 0, 0x20000); 71 mem.Map(0x0000, 0, 0x20000, PERMS);
71 mem.Unmap(0x0000, 0x4000); 72 mem.Unmap(0x0000, 0x4000);
72 mem.Map(0x1000, 0, 0x2000); 73 mem.Map(0x1000, 0, 0x2000, PERMS);
73 mem.Map(0x3000, 0, 0x1000); 74 mem.Map(0x3000, 0, 0x1000, PERMS);
74 mem.Map(0, 0, 0x1000); 75 mem.Map(0, 0, 0x1000, PERMS);
75} 76}
76 77
77TEST_CASE("HostMemory: Full unmap", "[common]") { 78TEST_CASE("HostMemory: Full unmap", "[common]") {
78 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 79 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
79 mem.Map(0x8000, 0, 0x4000); 80 mem.Map(0x8000, 0, 0x4000, PERMS);
80 mem.Unmap(0x8000, 0x4000); 81 mem.Unmap(0x8000, 0x4000);
81 mem.Map(0x6000, 0, 0x16000); 82 mem.Map(0x6000, 0, 0x16000, PERMS);
82} 83}
83 84
84TEST_CASE("HostMemory: Right out of bounds unmap", "[common]") { 85TEST_CASE("HostMemory: Right out of bounds unmap", "[common]") {
85 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 86 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
86 mem.Map(0x0000, 0, 0x4000); 87 mem.Map(0x0000, 0, 0x4000, PERMS);
87 mem.Unmap(0x2000, 0x4000); 88 mem.Unmap(0x2000, 0x4000);
88 mem.Map(0x2000, 0x80000, 0x4000); 89 mem.Map(0x2000, 0x80000, 0x4000, PERMS);
89} 90}
90 91
91TEST_CASE("HostMemory: Left out of bounds unmap", "[common]") { 92TEST_CASE("HostMemory: Left out of bounds unmap", "[common]") {
92 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 93 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
93 mem.Map(0x8000, 0, 0x4000); 94 mem.Map(0x8000, 0, 0x4000, PERMS);
94 mem.Unmap(0x6000, 0x4000); 95 mem.Unmap(0x6000, 0x4000);
95 mem.Map(0x8000, 0, 0x2000); 96 mem.Map(0x8000, 0, 0x2000, PERMS);
96} 97}
97 98
98TEST_CASE("HostMemory: Multiple placeholder unmap", "[common]") { 99TEST_CASE("HostMemory: Multiple placeholder unmap", "[common]") {
99 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 100 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
100 mem.Map(0x0000, 0, 0x4000); 101 mem.Map(0x0000, 0, 0x4000, PERMS);
101 mem.Map(0x4000, 0, 0x1b000); 102 mem.Map(0x4000, 0, 0x1b000, PERMS);
102 mem.Unmap(0x3000, 0x1c000); 103 mem.Unmap(0x3000, 0x1c000);
103 mem.Map(0x3000, 0, 0x20000); 104 mem.Map(0x3000, 0, 0x20000, PERMS);
104} 105}
105 106
106TEST_CASE("HostMemory: Unmap between placeholders", "[common]") { 107TEST_CASE("HostMemory: Unmap between placeholders", "[common]") {
107 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 108 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
108 mem.Map(0x0000, 0, 0x4000); 109 mem.Map(0x0000, 0, 0x4000, PERMS);
109 mem.Map(0x4000, 0, 0x4000); 110 mem.Map(0x4000, 0, 0x4000, PERMS);
110 mem.Unmap(0x2000, 0x4000); 111 mem.Unmap(0x2000, 0x4000);
111 mem.Map(0x2000, 0, 0x4000); 112 mem.Map(0x2000, 0, 0x4000, PERMS);
112} 113}
113 114
114TEST_CASE("HostMemory: Unmap to origin", "[common]") { 115TEST_CASE("HostMemory: Unmap to origin", "[common]") {
115 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 116 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
116 mem.Map(0x4000, 0, 0x4000); 117 mem.Map(0x4000, 0, 0x4000, PERMS);
117 mem.Map(0x8000, 0, 0x4000); 118 mem.Map(0x8000, 0, 0x4000, PERMS);
118 mem.Unmap(0x4000, 0x4000); 119 mem.Unmap(0x4000, 0x4000);
119 mem.Map(0, 0, 0x4000); 120 mem.Map(0, 0, 0x4000, PERMS);
120 mem.Map(0x4000, 0, 0x4000); 121 mem.Map(0x4000, 0, 0x4000, PERMS);
121} 122}
122 123
123TEST_CASE("HostMemory: Unmap to right", "[common]") { 124TEST_CASE("HostMemory: Unmap to right", "[common]") {
124 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 125 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
125 mem.Map(0x4000, 0, 0x4000); 126 mem.Map(0x4000, 0, 0x4000, PERMS);
126 mem.Map(0x8000, 0, 0x4000); 127 mem.Map(0x8000, 0, 0x4000, PERMS);
127 mem.Unmap(0x8000, 0x4000); 128 mem.Unmap(0x8000, 0x4000);
128 mem.Map(0x8000, 0, 0x4000); 129 mem.Map(0x8000, 0, 0x4000, PERMS);
129} 130}
130 131
131TEST_CASE("HostMemory: Partial right unmap check bindings", "[common]") { 132TEST_CASE("HostMemory: Partial right unmap check bindings", "[common]") {
132 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 133 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
133 mem.Map(0x4000, 0x10000, 0x4000); 134 mem.Map(0x4000, 0x10000, 0x4000, PERMS);
134 135
135 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000; 136 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000;
136 ptr[0x1000] = 17; 137 ptr[0x1000] = 17;
@@ -142,7 +143,7 @@ TEST_CASE("HostMemory: Partial right unmap check bindings", "[common]") {
142 143
143TEST_CASE("HostMemory: Partial left unmap check bindings", "[common]") { 144TEST_CASE("HostMemory: Partial left unmap check bindings", "[common]") {
144 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 145 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
145 mem.Map(0x4000, 0x10000, 0x4000); 146 mem.Map(0x4000, 0x10000, 0x4000, PERMS);
146 147
147 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000; 148 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000;
148 ptr[0x3000] = 19; 149 ptr[0x3000] = 19;
@@ -156,7 +157,7 @@ TEST_CASE("HostMemory: Partial left unmap check bindings", "[common]") {
156 157
157TEST_CASE("HostMemory: Partial middle unmap check bindings", "[common]") { 158TEST_CASE("HostMemory: Partial middle unmap check bindings", "[common]") {
158 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 159 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
159 mem.Map(0x4000, 0x10000, 0x4000); 160 mem.Map(0x4000, 0x10000, 0x4000, PERMS);
160 161
161 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000; 162 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000;
162 ptr[0x0000] = 19; 163 ptr[0x0000] = 19;
@@ -170,8 +171,8 @@ TEST_CASE("HostMemory: Partial middle unmap check bindings", "[common]") {
170 171
171TEST_CASE("HostMemory: Partial sparse middle unmap and check bindings", "[common]") { 172TEST_CASE("HostMemory: Partial sparse middle unmap and check bindings", "[common]") {
172 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); 173 HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE);
173 mem.Map(0x4000, 0x10000, 0x2000); 174 mem.Map(0x4000, 0x10000, 0x2000, PERMS);
174 mem.Map(0x6000, 0x20000, 0x2000); 175 mem.Map(0x6000, 0x20000, 0x2000, PERMS);
175 176
176 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000; 177 volatile u8* const ptr = mem.VirtualBasePointer() + 0x4000;
177 ptr[0x0000] = 19; 178 ptr[0x0000] = 19;