Merge pull request #3213 from Raghav314/fix/libc-heap-without-gpu
fix(libc): register guest heap blocks without GPU access
This commit is contained in:
commit
19a3d0c8a9
|
|
@ -741,11 +741,38 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) {
|
||||||
tail.Upload(true);
|
tail.Upload(true);
|
||||||
reject([&] { tail.Descriptor(address + 58, 4, adjustment); }, "exceeds its GPU owner");
|
reject([&] { tail.Descriptor(address + 58, 4, adjustment); }, "exceeds its GPU owner");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
void* plain = GuestHeap::GuestHeapAllocate_nid_postfix(64);
|
||||||
|
void* gpu = GuestHeap::GuestHeapAlignForGpu_nid_postfix(16, 64);
|
||||||
|
const auto lookup = [](const void* pointer) {
|
||||||
|
GuestAllocations::Mutation mutation;
|
||||||
|
return mutation.Find(pointer);
|
||||||
|
};
|
||||||
|
Require(!lookup(plain).gpu && lookup(gpu).gpu, "a guest heap block's GPU access does not follow how it was allocated");
|
||||||
|
gpu = GuestHeap::GuestHeapReallocate_nid_postfix(gpu, 128);
|
||||||
|
plain = GuestHeap::GuestHeapRealign_nid_postfix(plain, 128, 64);
|
||||||
|
Require(!lookup(plain).gpu && lookup(gpu).gpu, "a reallocated guest heap block changed its GPU access");
|
||||||
|
{
|
||||||
|
GuestBufferMemory leased(context);
|
||||||
|
leased.AcquireRegistered();
|
||||||
|
leased.Upload(true);
|
||||||
|
const auto ranges = leased.AddressRanges();
|
||||||
|
const auto listed = [&](const void* pointer) {
|
||||||
|
const auto address = reinterpret_cast<std::uintptr_t>(pointer);
|
||||||
|
return std::any_of(ranges.begin(), ranges.end(), [&](const auto& range) { return range.begin <= address && address < range.end; });
|
||||||
|
};
|
||||||
|
Require(!listed(plain), "a guest heap block without GPU access is in an address-based build");
|
||||||
|
Require(listed(gpu), "a guest heap block with GPU access is missing from an address-based build");
|
||||||
|
leased.WriteBack();
|
||||||
|
}
|
||||||
|
GuestHeap::GuestHeapFree_nid_postfix(plain);
|
||||||
|
GuestHeap::GuestHeapFree_nid_postfix(gpu);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// The cached address space: a second build in an unchanged registry takes the first one's
|
// The cached address space: a second build in an unchanged registry takes the first one's
|
||||||
// space, and a guest free of a range pinned only by the cache goes through the pin waiter's
|
// space, and a guest free of a range pinned only by the cache goes through the pin waiter's
|
||||||
// drop (no GPU work to wait for) and empties the registry of it.
|
// drop (no GPU work to wait for) and empties the registry of it.
|
||||||
void* block = GuestHeap::GuestHeapAllocate_nid_postfix(64);
|
void* block = GuestHeap::GuestHeapAlignForGpu_nid_postfix(16, 64);
|
||||||
const auto blockAddress = reinterpret_cast<std::uintptr_t>(block);
|
const auto blockAddress = reinterpret_cast<std::uintptr_t>(block);
|
||||||
std::memset(block, 0x5a, 64);
|
std::memset(block, 0x5a, 64);
|
||||||
const auto registered = [&] {
|
const auto registered = [&] {
|
||||||
|
|
|
||||||
|
|
@ -451,8 +451,8 @@ std::array<std::uint32_t, 7> memoryCopy(const void* destination, const void* sou
|
||||||
void testCopyIntoHostMemory() {
|
void testCopyIntoHostMemory() {
|
||||||
constexpr std::size_t words = 32768;
|
constexpr std::size_t words = 32768;
|
||||||
constexpr auto bytes = static_cast<std::uint32_t>(words * 4);
|
constexpr auto bytes = static_cast<std::uint32_t>(words * 4);
|
||||||
auto* produced = static_cast<std::uint32_t*>(GuestHeap::GuestHeapAlign_nid_postfix(65536, bytes));
|
auto* produced = static_cast<std::uint32_t*>(GuestHeap::GuestHeapAlignForGpu_nid_postfix(65536, bytes));
|
||||||
auto* source = static_cast<std::uint32_t*>(GuestHeap::GuestHeapAlign_nid_postfix(65536, bytes));
|
auto* source = static_cast<std::uint32_t*>(GuestHeap::GuestHeapAlignForGpu_nid_postfix(65536, bytes));
|
||||||
std::vector<std::uint32_t> destination(words);
|
std::vector<std::uint32_t> destination(words);
|
||||||
for (const bool label : {false, true}) {
|
for (const bool label : {false, true}) {
|
||||||
for (std::size_t i = 0; i < words; ++i) {
|
for (std::size_t i = 0; i < words; ++i) {
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,17 @@ void APS5_VABI GuestDeallocate_nid_no_patch(void*, void* memory) {
|
||||||
GuestHeap::GuestHeapFree_nid_postfix(memory);
|
GuestHeap::GuestHeapFree_nid_postfix(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* APS5_VABI GuestAllocateTexture_nid_no_patch(void*, std::uint32_t alignment, std::uint32_t size) {
|
||||||
|
return GuestHeap::GuestHeapAlignForGpu_nid_postfix(std::max<std::uint32_t>(alignment, 16), size);
|
||||||
|
}
|
||||||
|
|
||||||
AvPlayerMemAllocator WithGuestHeapFallback(AvPlayerMemAllocator memory) {
|
AvPlayerMemAllocator WithGuestHeapFallback(AvPlayerMemAllocator memory) {
|
||||||
if (!memory.allocate || !memory.deallocate) {
|
if (!memory.allocate || !memory.deallocate) {
|
||||||
memory.allocate = GuestAllocate_nid_no_patch;
|
memory.allocate = GuestAllocate_nid_no_patch;
|
||||||
memory.deallocate = GuestDeallocate_nid_no_patch;
|
memory.deallocate = GuestDeallocate_nid_no_patch;
|
||||||
}
|
}
|
||||||
if (!memory.allocate_texture || !memory.deallocate_texture) {
|
if (!memory.allocate_texture || !memory.deallocate_texture) {
|
||||||
memory.allocate_texture = GuestAllocate_nid_no_patch;
|
memory.allocate_texture = GuestAllocateTexture_nid_no_patch;
|
||||||
memory.deallocate_texture = GuestDeallocate_nid_no_patch;
|
memory.deallocate_texture = GuestDeallocate_nid_no_patch;
|
||||||
}
|
}
|
||||||
return memory;
|
return memory;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ void GuestHeapFree_nid_postfix(void* pointer);
|
||||||
void* GuestHeapReallocate_nid_postfix(void* pointer, std::size_t bytes);
|
void* GuestHeapReallocate_nid_postfix(void* pointer, std::size_t bytes);
|
||||||
void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes);
|
void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes);
|
||||||
void* GuestHeapRealign_nid_postfix(void* pointer, std::size_t bytes, std::size_t alignment);
|
void* GuestHeapRealign_nid_postfix(void* pointer, std::size_t bytes, std::size_t alignment);
|
||||||
|
void* GuestHeapAlignForGpu_nid_postfix(std::size_t alignment, std::size_t bytes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ void rawFree(void* raw, std::size_t blockBytes) {
|
||||||
else std::free(raw);
|
else std::free(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std::size_t bytes) {
|
void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std::size_t bytes, bool gpu) {
|
||||||
if (alignment == 0 || (alignment & (alignment - 1)) != 0) throw std::invalid_argument("invalid guest heap alignment");
|
if (alignment == 0 || (alignment & (alignment - 1)) != 0) throw std::invalid_argument("invalid guest heap alignment");
|
||||||
alignment = std::max(alignment, MinimumAlignment);
|
alignment = std::max(alignment, MinimumAlignment);
|
||||||
const std::size_t padding = alignment > RawAlignment ? alignment : 0;
|
const std::size_t padding = alignment > RawAlignment ? alignment : 0;
|
||||||
|
|
@ -205,7 +205,7 @@ void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std:
|
||||||
reinterpret_cast<void**>(pointer)[-2] = raw;
|
reinterpret_cast<void**>(pointer)[-2] = raw;
|
||||||
reinterpret_cast<std::size_t*>(pointer)[-1] = blockBytes;
|
reinterpret_cast<std::size_t*>(pointer)[-1] = blockBytes;
|
||||||
try {
|
try {
|
||||||
mutation.Add(pointer, bytes, true, true, true);
|
mutation.Add(pointer, bytes, true, true, gpu);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
rawFree(raw, blockBytes);
|
rawFree(raw, blockBytes);
|
||||||
throw;
|
throw;
|
||||||
|
|
@ -222,7 +222,7 @@ void free(GuestAllocations::Mutation& mutation, void* pointer) {
|
||||||
|
|
||||||
void* GuestHeapAllocate_nid_postfix(std::size_t bytes) {
|
void* GuestHeapAllocate_nid_postfix(std::size_t bytes) {
|
||||||
GuestAllocations::Mutation mutation;
|
GuestAllocations::Mutation mutation;
|
||||||
return allocate(mutation, MinimumAlignment, bytes);
|
return allocate(mutation, MinimumAlignment, bytes, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuestHeapFree_nid_postfix(void* pointer) {
|
void GuestHeapFree_nid_postfix(void* pointer) {
|
||||||
|
|
@ -242,7 +242,7 @@ void* GuestHeapReallocate_nid_postfix(void* pointer, std::size_t bytes) {
|
||||||
free(mutation, pointer);
|
free(mutation, pointer);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void* result = allocate(mutation, MinimumAlignment, bytes);
|
void* result = allocate(mutation, MinimumAlignment, bytes, range.gpu);
|
||||||
std::memcpy(result, pointer, std::min(bytes, range.bytes));
|
std::memcpy(result, pointer, std::min(bytes, range.bytes));
|
||||||
free(mutation, pointer);
|
free(mutation, pointer);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -257,7 +257,7 @@ void* GuestHeapRealign_nid_postfix(void* pointer, std::size_t bytes, std::size_t
|
||||||
free(mutation, pointer);
|
free(mutation, pointer);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void* result = allocate(mutation, alignment, bytes);
|
void* result = allocate(mutation, alignment, bytes, range.gpu);
|
||||||
std::memcpy(result, pointer, std::min(bytes, range.bytes));
|
std::memcpy(result, pointer, std::min(bytes, range.bytes));
|
||||||
free(mutation, pointer);
|
free(mutation, pointer);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -271,7 +271,12 @@ std::size_t GuestHeapUsableSize_nid_postfix(const void* pointer) {
|
||||||
|
|
||||||
void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes) {
|
void* GuestHeapAlign_nid_postfix(std::size_t alignment, std::size_t bytes) {
|
||||||
GuestAllocations::Mutation mutation;
|
GuestAllocations::Mutation mutation;
|
||||||
return allocate(mutation, alignment, bytes);
|
return allocate(mutation, alignment, bytes, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GuestHeapAlignForGpu_nid_postfix(std::size_t alignment, std::size_t bytes) {
|
||||||
|
GuestAllocations::Mutation mutation;
|
||||||
|
return allocate(mutation, alignment, bytes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue