diff options
Diffstat (limited to 'src/common/host_memory.cpp')
| -rw-r--r-- | src/common/host_memory.cpp | 45 |
1 files changed, 33 insertions, 12 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 | ||
| 648 | HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default; | 667 | HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default; |
| 649 | 668 | ||
| 650 | void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) { | 669 | void 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 | ||
| 662 | void HostMemory::Unmap(size_t virtual_offset, size_t length) { | 682 | void 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 | ||
| 672 | void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool write) { | 692 | void 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 | ||
| 682 | void HostMemory::EnableDirectMappedAddress() { | 703 | void HostMemory::EnableDirectMappedAddress() { |