diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/host_memory.cpp | 59 | ||||
| -rw-r--r-- | src/common/host_memory.h | 4 |
2 files changed, 49 insertions, 14 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 9ae384f01..8bd70abc7 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -449,21 +449,52 @@ private: | |||
| 449 | int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create | 449 | int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create |
| 450 | }; | 450 | }; |
| 451 | 451 | ||
| 452 | #else // ^^^ Linux ^^^ | 452 | #else // ^^^ Linux ^^^ vvv Generic vvv |
| 453 | 453 | ||
| 454 | #error Please implement the host memory for your platform | 454 | class HostMemory::Impl { |
| 455 | public: | ||
| 456 | explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) { | ||
| 457 | // This is just a place holder. | ||
| 458 | // Please implement fastmem in a propper way on your platform. | ||
| 459 | throw std::bad_alloc{}; | ||
| 460 | } | ||
| 455 | 461 | ||
| 456 | #endif | 462 | void Map(size_t virtual_offset, size_t host_offset, size_t length) {} |
| 463 | |||
| 464 | void Unmap(size_t virtual_offset, size_t length) {} | ||
| 465 | |||
| 466 | void Protect(size_t virtual_offset, size_t length, bool read, bool write) {} | ||
| 467 | |||
| 468 | u8* backing_base{nullptr}; | ||
| 469 | u8* virtual_base{nullptr}; | ||
| 470 | }; | ||
| 471 | |||
| 472 | #endif // ^^^ Generic ^^^ | ||
| 457 | 473 | ||
| 458 | HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) | 474 | HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) |
| 459 | : backing_size(backing_size_), | 475 | : backing_size(backing_size_), virtual_size(virtual_size_) { |
| 460 | virtual_size(virtual_size_), impl{std::make_unique<HostMemory::Impl>( | 476 | try { |
| 461 | AlignUp(backing_size, PageAlignment), | 477 | // Try to allocate a fastmem arena. |
| 462 | AlignUp(virtual_size, PageAlignment) + 3 * HugePageSize)}, | 478 | // The implementation will fail with std::bad_alloc on errors. |
| 463 | backing_base{impl->backing_base}, virtual_base{impl->virtual_base} { | 479 | impl = std::make_unique<HostMemory::Impl>(AlignUp(backing_size, PageAlignment), |
| 464 | virtual_base += 2 * HugePageSize - 1; | 480 | AlignUp(virtual_size, PageAlignment) + |
| 465 | virtual_base -= reinterpret_cast<size_t>(virtual_base) & (HugePageSize - 1); | 481 | 3 * HugePageSize); |
| 466 | virtual_base_offset = virtual_base - impl->virtual_base; | 482 | backing_base = impl->backing_base; |
| 483 | virtual_base = impl->virtual_base; | ||
| 484 | |||
| 485 | if (virtual_base) { | ||
| 486 | virtual_base += 2 * HugePageSize - 1; | ||
| 487 | virtual_base -= reinterpret_cast<size_t>(virtual_base) & (HugePageSize - 1); | ||
| 488 | virtual_base_offset = virtual_base - impl->virtual_base; | ||
| 489 | } | ||
| 490 | |||
| 491 | } catch (const std::bad_alloc&) { | ||
| 492 | LOG_CRITICAL(HW_Memory, | ||
| 493 | "Fastmem unavailable, falling back to VirtualBuffer for memory allocation"); | ||
| 494 | fallback_buffer = std::make_unique<Common::VirtualBuffer<u8>>(backing_size); | ||
| 495 | backing_base = fallback_buffer->data(); | ||
| 496 | virtual_base = nullptr; | ||
| 497 | } | ||
| 467 | } | 498 | } |
| 468 | 499 | ||
| 469 | HostMemory::~HostMemory() = default; | 500 | HostMemory::~HostMemory() = default; |
| @@ -478,7 +509,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) { | |||
| 478 | ASSERT(length % PageAlignment == 0); | 509 | ASSERT(length % PageAlignment == 0); |
| 479 | ASSERT(virtual_offset + length <= virtual_size); | 510 | ASSERT(virtual_offset + length <= virtual_size); |
| 480 | ASSERT(host_offset + length <= backing_size); | 511 | ASSERT(host_offset + length <= backing_size); |
| 481 | if (length == 0) { | 512 | if (length == 0 || !virtual_base || !impl) { |
| 482 | return; | 513 | return; |
| 483 | } | 514 | } |
| 484 | impl->Map(virtual_offset + virtual_base_offset, host_offset, length); | 515 | impl->Map(virtual_offset + virtual_base_offset, host_offset, length); |
| @@ -488,7 +519,7 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length) { | |||
| 488 | ASSERT(virtual_offset % PageAlignment == 0); | 519 | ASSERT(virtual_offset % PageAlignment == 0); |
| 489 | ASSERT(length % PageAlignment == 0); | 520 | ASSERT(length % PageAlignment == 0); |
| 490 | ASSERT(virtual_offset + length <= virtual_size); | 521 | ASSERT(virtual_offset + length <= virtual_size); |
| 491 | if (length == 0) { | 522 | if (length == 0 || !virtual_base || !impl) { |
| 492 | return; | 523 | return; |
| 493 | } | 524 | } |
| 494 | impl->Unmap(virtual_offset + virtual_base_offset, length); | 525 | impl->Unmap(virtual_offset + virtual_base_offset, length); |
| @@ -498,7 +529,7 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w | |||
| 498 | ASSERT(virtual_offset % PageAlignment == 0); | 529 | ASSERT(virtual_offset % PageAlignment == 0); |
| 499 | ASSERT(length % PageAlignment == 0); | 530 | ASSERT(length % PageAlignment == 0); |
| 500 | ASSERT(virtual_offset + length <= virtual_size); | 531 | ASSERT(virtual_offset + length <= virtual_size); |
| 501 | if (length == 0) { | 532 | if (length == 0 || !virtual_base || !impl) { |
| 502 | return; | 533 | return; |
| 503 | } | 534 | } |
| 504 | impl->Protect(virtual_offset + virtual_base_offset, length, read, write); | 535 | impl->Protect(virtual_offset + virtual_base_offset, length, read, write); |
diff --git a/src/common/host_memory.h b/src/common/host_memory.h index eaa7d18ab..9b8326d0f 100644 --- a/src/common/host_memory.h +++ b/src/common/host_memory.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "common/virtual_buffer.h" | ||
| 9 | 10 | ||
| 10 | namespace Common { | 11 | namespace Common { |
| 11 | 12 | ||
| @@ -61,6 +62,9 @@ private: | |||
| 61 | u8* backing_base{}; | 62 | u8* backing_base{}; |
| 62 | u8* virtual_base{}; | 63 | u8* virtual_base{}; |
| 63 | size_t virtual_base_offset{}; | 64 | size_t virtual_base_offset{}; |
| 65 | |||
| 66 | // Fallback if fastmem is not supported on this platform | ||
| 67 | std::unique_ptr<Common::VirtualBuffer<u8>> fallback_buffer; | ||
| 64 | }; | 68 | }; |
| 65 | 69 | ||
| 66 | } // namespace Common | 70 | } // namespace Common |