mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
gpu: address extended guest memory without widening dense cache tables
This commit is contained in:
@@ -9,9 +9,9 @@
|
||||
namespace {
|
||||
|
||||
using Owners = std::vector<uint32_t>;
|
||||
using Table = Libs::Graphics::MultiLevelPageTable<Owners>;
|
||||
using Table = Libs::Graphics::MultiLevelPageTable<Owners, 20, 44, 14>;
|
||||
using PageOwners = Libs::Graphics::InlinePageOwnerList<uint32_t, 16>;
|
||||
using OwnerTable = Libs::Graphics::MultiLevelPageTable<PageOwners, 20, 40, 10>;
|
||||
using OwnerTable = Libs::Graphics::MultiLevelPageTable<PageOwners, 20, 44, 14>;
|
||||
|
||||
void Check(bool value, const char* text) {
|
||||
if (!value) {
|
||||
|
||||
@@ -219,17 +219,24 @@ void TestRangeSet() {
|
||||
void TestGuestRange() {
|
||||
constexpr GuestRange empty{};
|
||||
constexpr GuestRange first_byte{1, 1};
|
||||
constexpr GuestRange last_byte{TRACKER_ADDRESS_SIZE - 1, 1};
|
||||
constexpr uint64_t extended_end = Libs::LibKernel::Memory::kExtendedMemoryBase +
|
||||
Libs::LibKernel::Memory::kExtendedMemorySize;
|
||||
constexpr GuestRange last_byte{extended_end - 1, 1};
|
||||
|
||||
static_assert(empty.Empty() && !empty.Valid() && empty.ValidOrEmpty());
|
||||
static_assert(!first_byte.Empty() && first_byte.Valid() &&
|
||||
first_byte.ValidOrEmpty() && first_byte.End() == 2);
|
||||
static_assert(last_byte.Valid() && last_byte.End() == TRACKER_ADDRESS_SIZE);
|
||||
static_assert(last_byte.Valid() && last_byte.End() == extended_end);
|
||||
|
||||
Check(!GuestRange{0, 1}.Empty() && !GuestRange{0, 1}.ValidOrEmpty(),
|
||||
"zero-address nonempty guest range is rejected");
|
||||
Check(!GuestRange{1, 0}.Empty() && !GuestRange{1, 0}.ValidOrEmpty(),
|
||||
"nonzero-address empty guest range is rejected");
|
||||
Check(GuestRange{Libs::LibKernel::Memory::kExtendedMemoryBase, 1}.Valid() &&
|
||||
!GuestRange{Libs::Graphics::LOWER_ADDRESS_SIZE, 1}.Valid() &&
|
||||
!GuestRange{Libs::LibKernel::Memory::kExtendedMemoryBase - 1, 2}.Valid() &&
|
||||
!GuestRange{extended_end - 1, 2}.Valid(),
|
||||
"extended range and gap boundaries are enforced");
|
||||
Check(!GuestRange{TRACKER_ADDRESS_SIZE, 1}.Valid(),
|
||||
"first address beyond the guest range is rejected");
|
||||
Check(!GuestRange{TRACKER_ADDRESS_SIZE - 1, 2}.Valid(),
|
||||
|
||||
@@ -136,8 +136,8 @@ bool ProtectAddressSpace(uint64_t vaddr, uint64_t size,
|
||||
&old_protection) != 0;
|
||||
}
|
||||
|
||||
uint8_t *Allocate(uint64_t size, uint32_t protection = PAGE_READWRITE) {
|
||||
constexpr uintptr_t test_address = 0x0000000200010000ull;
|
||||
uint8_t *Allocate(uint64_t size, uint32_t protection = PAGE_READWRITE,
|
||||
uintptr_t test_address = 0x0000000200010000ull) {
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
auto *memory = static_cast<uint8_t *>(
|
||||
VirtualAlloc(reinterpret_cast<void *>(test_address), size,
|
||||
@@ -155,11 +155,11 @@ uint8_t *Allocate(uint64_t size, uint32_t protection = PAGE_READWRITE) {
|
||||
return memory;
|
||||
}
|
||||
|
||||
void TestWatchAndUnwatch() {
|
||||
void TestWatchAndUnwatch(uint64_t base = 0x0000000200010000ull) {
|
||||
g_protection_calls = 0;
|
||||
PageManager manager;
|
||||
const auto page_size = manager.GetPageSize();
|
||||
auto *memory = Allocate(page_size * 2);
|
||||
auto *memory = Allocate(page_size * 2, PAGE_READWRITE, base);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
|
||||
manager.UpdatePageWatchers<true>(address, page_size);
|
||||
@@ -580,6 +580,7 @@ int main(int argc, char **argv) {
|
||||
RunDeathCase(argv[2]);
|
||||
}
|
||||
TestWatchAndUnwatch();
|
||||
TestWatchAndUnwatch(Libs::LibKernel::Memory::kExtendedMemoryBase);
|
||||
TestSharedWatcherCounts();
|
||||
TestCrossRegionRange();
|
||||
TestBatchedWatcherRanges();
|
||||
|
||||
@@ -208,8 +208,8 @@ struct TextureCacheTestAccess {
|
||||
static_assert(std::same_as<decltype(TextureCache::m_slot_images),
|
||||
Common::SlotVector<Image>>);
|
||||
static_assert(TextureCache::ImagePageTable::kPageBits == 20);
|
||||
static_assert(TextureCache::ImagePageTable::kAddressSpaceBits == 40);
|
||||
static_assert(TextureCache::ImagePageTable::kFirstLevelBits == 10);
|
||||
static_assert(TextureCache::ImagePageTable::kAddressSpaceBits == 44);
|
||||
static_assert(TextureCache::ImagePageTable::kFirstLevelBits == 14);
|
||||
|
||||
static std::unique_lock<TrackingSpinLock> Lock(TextureCache &cache) {
|
||||
return std::unique_lock(cache.m_lock);
|
||||
@@ -13694,7 +13694,7 @@ public:
|
||||
(bytes + BufferCache::CACHING_PAGESIZE - 1) /
|
||||
BufferCache::CACHING_PAGESIZE;
|
||||
auto address = buffer.device_address + backing - page_offset;
|
||||
auto page = guest_base >> BufferCache::CACHING_PAGEBITS;
|
||||
auto page = BufferCache::PageIndex(guest_base);
|
||||
for (uint64_t mapped = 0; mapped < pages; mapped++) {
|
||||
cmd.updateBuffer(m_bda_pagetable_buffer.buffer,
|
||||
(page + mapped) * sizeof(vk::DeviceAddress),
|
||||
@@ -25957,6 +25957,11 @@ TestCase FlatVirtualAddressRebasesGuestAllocation() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
constexpr uint64_t GuestBase = 0x0000000110000000ull;
|
||||
constexpr uint64_t ExtendedBase = Libs::LibKernel::Memory::kExtendedMemoryBase + GuestBase;
|
||||
static_assert(BufferCache::PageIndex(ExtendedBase) ==
|
||||
((Libs::Graphics::LOWER_ADDRESS_SIZE + GuestBase) >> BufferCache::CACHING_PAGEBITS));
|
||||
static_assert(BufferCache::GuestAddress(BufferCache::PageIndex(ExtendedBase) <<
|
||||
BufferCache::CACHING_PAGEBITS) == ExtendedBase);
|
||||
std::vector<u32> code;
|
||||
AppendVMovLiteral(&code, 20, static_cast<u32>(GuestBase + 4u));
|
||||
AppendVMovLiteral(&code, 21, static_cast<u32>(GuestBase >> 32u));
|
||||
@@ -25967,17 +25972,22 @@ TestCase FlatVirtualAddressRebasesGuestAllocation() {
|
||||
AppendVMovLiteral(&code, 21, static_cast<u32>((GuestBase >> 32u) + 1u));
|
||||
code.push_back(EncodeFlat0(0x0c, 0, 0));
|
||||
code.push_back(EncodeFlat1(2, 0x7d, 0, 20));
|
||||
AppendVMovLiteral(&code, 20, static_cast<u32>(ExtendedBase + 4u));
|
||||
AppendVMovLiteral(&code, 21, static_cast<u32>(ExtendedBase >> 32u));
|
||||
code.push_back(EncodeFlat0(0x0c, 0, 0));
|
||||
code.push_back(EncodeFlat1(3, 0x7d, 0, 20));
|
||||
AppendStoreVgpr(&code, 0, 0);
|
||||
AppendStoreVgpr(&code, 1, 1);
|
||||
AppendStoreVgpr(&code, 2, 2);
|
||||
AppendStoreVgpr(&code, 3, 3);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "FlatVirtualAddressRebasesGuestAllocation";
|
||||
test.code = std::move(code);
|
||||
test.initial = {0xfeedfaceu, 0xcafebabeu, 0, 0x12345678u};
|
||||
test.expected = {0x12345678u, 0x12345678u, 0};
|
||||
test.bda_mappings = {{GuestBase, 8}};
|
||||
test.expected = {0x12345678u, 0x12345678u, 0, 0xcafebabeu};
|
||||
test.bda_mappings = {{GuestBase, 8}, {ExtendedBase, 0}};
|
||||
test.opcodes = {O::V_MOV_B32, O::FLAT_LOAD_DWORD, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
return test;
|
||||
|
||||
Reference in New Issue
Block a user