blob: 717c7e8960765cbd0ade0ada7eda3a40564417f5 [file] [edit]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/magma_service/test_util/platform_msd_device_helper.h>
#include <gtest/gtest.h>
#include "src/graphics/drivers/msd-vsi-vip/src/command_buffer.h"
#include "test_command_buffer.h"
class TestFaultRecovery : public TestCommandBuffer {};
TEST_F(TestFaultRecovery, ManyBatches) {
BufferDesc buffer_desc = {
.buffer_size = 4096,
.map_page_count = 1,
.data_size = 8,
.batch_offset = 0,
.gpu_addr = 0x10000,
};
std::vector<std::shared_ptr<magma::PlatformSemaphore>> semaphores;
// Submit a batch that jumps to an invalid address.
auto semaphore = magma::PlatformSemaphore::Create();
ASSERT_NE(semaphore, nullptr);
constexpr uint32_t fault_addr = 0x50000;
ASSERT_NO_FATAL_FAILURE(
CreateAndSubmitBuffer(default_context(), buffer_desc, semaphore->Clone(), fault_addr));
semaphores.push_back(std::move(semaphore));
// Submit more batches from the same context.
for (unsigned int i = 0; i < MsdVsiDevice::kNumEvents; i++) {
buffer_desc.gpu_addr += magma::page_size();
auto semaphore = magma::PlatformSemaphore::Create();
ASSERT_NE(semaphore, nullptr);
ASSERT_NO_FATAL_FAILURE(CreateAndSubmitBuffer(default_context(), buffer_desc,
semaphore->Clone(),
std::optional<uint32_t>{} /* fault_addr */));
semaphores.push_back(std::move(semaphore));
}
// Begin the processing of batches.
device_->StartDeviceThread();
// Wait for all batches to be signalled.
constexpr uint64_t kTimeoutMs = 1000;
for (unsigned int i = 0; i < semaphores.size(); i++) {
ASSERT_EQ(MAGMA_STATUS_OK, semaphores[i]->Wait(kTimeoutMs).get());
}
ASSERT_TRUE(default_context()->killed());
}
TEST_F(TestFaultRecovery, MultipleContexts) {
BufferDesc buffer_desc = {
.buffer_size = 4096,
.map_page_count = 1,
.data_size = 8,
.batch_offset = 0,
.gpu_addr = 0x10000,
};
std::vector<std::shared_ptr<magma::PlatformSemaphore>> semaphores;
// Submit a batch that jumps to an invalid address.
auto semaphore = magma::PlatformSemaphore::Create();
ASSERT_NE(semaphore, nullptr);
constexpr uint32_t fault_addr = 0x50000;
ASSERT_NO_FATAL_FAILURE(
CreateAndSubmitBuffer(default_context(), buffer_desc, semaphore->Clone(), fault_addr));
semaphores.push_back(std::move(semaphore));
// Create new clients that will submit valid batches.
std::vector<std::unique_ptr<Client>> clients;
constexpr uint32_t kClientsCount = 5;
constexpr uint32_t kClientStartAddressSpaceIndex = 10;
for (unsigned int i = 0; i < kClientsCount; i++) {
std::unique_ptr<Client> client;
ASSERT_NO_FATAL_FAILURE(CreateClient(kClientStartAddressSpaceIndex + i, &client));
semaphore = magma::PlatformSemaphore::Create();
ASSERT_NE(semaphore, nullptr);
std::shared_ptr<MsdVsiBuffer> buffer;
buffer_desc.gpu_addr += magma::page_size();
ASSERT_NO_FATAL_FAILURE(CreateAndSubmitBuffer(client->context, buffer_desc, semaphore->Clone(),
std::optional<uint32_t>{} /* fault_addr */,
std::nullopt /* csb */, true, &buffer));
semaphores.push_back(std::move(semaphore));
clients.emplace_back(std::move(client));
}
// Begin the processing of batches.
device_->StartDeviceThread();
// Wait for all batches to be signalled.
constexpr uint64_t kTimeoutMs = 1000;
for (unsigned int i = 0; i < semaphores.size(); i++) {
ASSERT_EQ(MAGMA_STATUS_OK, semaphores[i]->Wait(kTimeoutMs).get());
}
ASSERT_TRUE(default_context()->killed());
// Ensure we can queue and complete new batches.
ASSERT_FALSE(clients[0]->context->killed());
buffer_desc.gpu_addr += magma::page_size();
ASSERT_NO_FATAL_FAILURE(CreateAndSubmitBufferWaitCompletion(clients[0]->context, buffer_desc));
}