Read-only memory allocations handling in Wddm

- return InvalidHostPointer when createallocation
fails with NO_VIDEO_MEMORY

Change-Id: I6946eeb04d3a191550478e1d26a6ce0c32b75c34
This commit is contained in:
Hoppe, Mateusz
2018-03-23 10:07:31 +01:00
committed by sys_ocldev
parent e1a0452c6b
commit ed30f6e55f
6 changed files with 69 additions and 12 deletions

View File

@@ -516,11 +516,10 @@ bool Wddm::createAllocation64k(WddmAllocation *alloc) {
return true;
}
bool Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
NTSTATUS status = STATUS_UNSUCCESSFUL;
D3DDDI_ALLOCATIONINFO AllocationInfo[max_fragments_count] = {{0}};
D3DKMT_CREATEALLOCATION CreateAllocation = {0};
bool success = false;
auto allocationCount = 0;
for (unsigned int i = 0; i < max_fragments_count; i++) {
@@ -538,8 +537,9 @@ bool Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
allocationCount++;
}
}
if (allocationCount == 0)
return true;
if (allocationCount == 0) {
return STATUS_SUCCESS;
}
CreateAllocation.hGlobalShare = 0;
CreateAllocation.PrivateRuntimeDataSize = 0;
@@ -555,7 +555,7 @@ bool Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
CreateAllocation.pAllocationInfo = AllocationInfo;
CreateAllocation.hDevice = device;
while (!success) {
while (status == STATUS_UNSUCCESSFUL) {
status = gdi->createAllocation(&CreateAllocation);
if (status != STATUS_SUCCESS) {
@@ -569,7 +569,7 @@ bool Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
allocationIndex++;
}
osHandles.fragmentStorageData[allocationIndex].osHandleStorage->handle = AllocationInfo[i].hAllocation;
success = mapGpuVirtualAddress(&osHandles.fragmentStorageData[allocationIndex], false, false);
bool success = mapGpuVirtualAddress(&osHandles.fragmentStorageData[allocationIndex], false, false);
allocationIndex++;
if (!success) {
@@ -581,9 +581,9 @@ bool Wddm::createAllocationsAndMapGpuVa(OsHandleStorage &osHandles) {
kmDafListener->notifyWriteTarget(featureTable->ftrKmdDaf, adapter, device, AllocationInfo[i].hAllocation, gdi->escape);
}
success = true;
status = STATUS_SUCCESS;
}
return success;
return status;
}
bool Wddm::destroyAllocations(D3DKMT_HANDLE *handles, uint32_t allocationCount, uint64_t lastFenceValue, D3DKMT_HANDLE resourceHandle) {

View File

@@ -81,7 +81,7 @@ class Wddm {
MOCKABLE_VIRTUAL bool freeGpuVirtualAddres(D3DGPU_VIRTUAL_ADDRESS &gpuPtr, uint64_t size);
MOCKABLE_VIRTUAL NTSTATUS createAllocation(WddmAllocation *alloc);
MOCKABLE_VIRTUAL bool createAllocation64k(WddmAllocation *alloc);
MOCKABLE_VIRTUAL bool createAllocationsAndMapGpuVa(OsHandleStorage &osHandles);
MOCKABLE_VIRTUAL NTSTATUS createAllocationsAndMapGpuVa(OsHandleStorage &osHandles);
MOCKABLE_VIRTUAL bool destroyAllocations(D3DKMT_HANDLE *handles, uint32_t allocationCount, uint64_t lastFenceValue, D3DKMT_HANDLE resourceHandle);
MOCKABLE_VIRTUAL bool openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc);
bool openNTHandle(HANDLE handle, WddmAllocation *alloc);

View File

@@ -347,7 +347,11 @@ MemoryManager::AllocationStatus WddmMemoryManager::populateOsHandles(OsHandleSto
hostPtrManager.storeFragment(handleStorage.fragmentStorageData[i]);
}
}
wddm->createAllocationsAndMapGpuVa(handleStorage);
NTSTATUS result = wddm->createAllocationsAndMapGpuVa(handleStorage);
if (result == STATUS_GRAPHICS_NO_VIDEO_MEMORY) {
return AllocationStatus::InvalidHostPointer;
}
return AllocationStatus::Success;
}

View File

@@ -2047,3 +2047,20 @@ HWTEST_F(MockWddmMemoryManagerTest, givenRenderCompressedFlagSetWhenInternalIsUn
EXPECT_TRUE(result);
memoryManager.freeGraphicsMemory(wddmAlloc);
}
HWTEST_F(WddmMemoryManagerTest2, givenReadOnlyMemoryWhenCreateAllocationFailsThenPopulateOsHandlesReturnsInvalidPointer) {
SetUpMm<FamilyType>();
OsHandleStorage handleStorage;
handleStorage.fragmentCount = 1;
handleStorage.fragmentStorageData[0].cpuPtr = (void *)0x1000;
handleStorage.fragmentStorageData[0].fragmentSize = 0x1000;
handleStorage.fragmentStorageData[0].freeTheFragment = false;
EXPECT_CALL(*wddm, createAllocationsAndMapGpuVa(::testing::_)).WillOnce(::testing::Return(STATUS_GRAPHICS_NO_VIDEO_MEMORY));
auto result = memoryManager->populateOsHandles(handleStorage);
EXPECT_EQ(MemoryManager::AllocationStatus::InvalidHostPointer, result);
handleStorage.fragmentStorageData[0].freeTheFragment = true;
memoryManager->cleanOsHandles(handleStorage);
}

View File

@@ -125,8 +125,12 @@ class GmockWddm : public Wddm {
return tmp;
}
uintptr_t virtualAllocAddress;
MOCK_METHOD4(makeResident, bool(D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim));
MOCK_METHOD1(createAllocationsAndMapGpuVa, NTSTATUS(OsHandleStorage &osHandles));
NTSTATUS baseCreateAllocationAndMapGpuVa(OsHandleStorage &osHandles) {
return Wddm::createAllocationsAndMapGpuVa(osHandles);
}
};
class WddmMemoryManagerFixtureWithGmockWddm {
@@ -145,6 +149,8 @@ class WddmMemoryManagerFixtureWithGmockWddm {
memoryManager = new (std::nothrow) MockWddmMemoryManager(wddm);
//assert we have memory manager
ASSERT_NE(nullptr, memoryManager);
ON_CALL(*wddm, createAllocationsAndMapGpuVa(::testing::_)).WillByDefault(::testing::Invoke(wddm, &GmockWddm::baseCreateAllocationAndMapGpuVa));
}
void TearDown() {
delete memoryManager;

View File

@@ -1075,3 +1075,33 @@ HWTEST_F(WddmReserveAddressTest, givenWddmWhenFirstIsInvalidSecondNullThenReturn
EXPECT_FALSE(ret);
EXPECT_EQ(expectedReserve, reinterpret_cast<uintptr_t>(reserve));
}
HWTEST_F(WddmWithMockGdiTest, givenReadOnlyMemoryWhenCreateAllocationFailsWithNoVideoMemoryThenCorrectStatusIsReturned) {
class MockCreateAllocation {
public:
static NTSTATUS APIENTRY mockCreateAllocation(D3DKMT_CREATEALLOCATION *param) {
return STATUS_GRAPHICS_NO_VIDEO_MEMORY;
};
};
Gdi *gdi = wddm->getGdi();
gdi->createAllocation = MockCreateAllocation::mockCreateAllocation;
wddm->init<FamilyType>();
OsHandleStorage handleStorage;
OsHandle handle = {0};
ResidencyData residency;
handleStorage.fragmentCount = 1;
handleStorage.fragmentStorageData[0].cpuPtr = (void *)0x1000;
handleStorage.fragmentStorageData[0].fragmentSize = 0x1000;
handleStorage.fragmentStorageData[0].freeTheFragment = false;
handleStorage.fragmentStorageData[0].osHandleStorage = &handle;
handleStorage.fragmentStorageData[0].residency = &residency;
handleStorage.fragmentStorageData[0].osHandleStorage->gmm = getGmm(nullptr, 0);
NTSTATUS result = wddm->createAllocationsAndMapGpuVa(handleStorage);
EXPECT_EQ(STATUS_GRAPHICS_NO_VIDEO_MEMORY, result);
releaseGmm(handleStorage.fragmentStorageData[0].osHandleStorage->gmm);
}