blob: 8e5c69e2fd84e2f01fd9ae2ee7b111cbe68873bd [file] [log] [blame]
// Copyright 2019 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/mock/fake_address_space.h>
#include <lib/magma_service/mock/mock_bus_mapper.h>
#include <lib/magma_service/util/address_space.h>
#include <lib/magma_service/util/gpu_mapping.h>
#include <lib/magma_service/util/ringbuffer.h>
#include <gtest/gtest.h>
using GpuMapping = magma::GpuMapping<magma::PlatformBuffer>;
using AllocatingAddressSpace =
FakeAllocatingAddressSpace<GpuMapping, magma::AddressSpace<GpuMapping>>;
using NonAllocatingAddressSpace =
FakeNonAllocatingAddressSpace<GpuMapping, magma::AddressSpace<GpuMapping>>;
using Ringbuffer = magma::Ringbuffer<GpuMapping>;
class TestRingbuffer : public ::testing::Test {
public:
class AddressSpaceOwner : public magma::AddressSpaceOwner {
public:
virtual ~AddressSpaceOwner() = default;
magma::PlatformBusMapper* GetBusMapper() override { return &bus_mapper_; }
private:
MockBusMapper bus_mapper_;
};
static uint32_t* vaddr(Ringbuffer* ringbuffer) { return ringbuffer->vaddr(); }
};
TEST_F(TestRingbuffer, CreateAndDestroy) {
const uint32_t kMagmaPageSize = magma::page_size();
auto ringbuffer =
std::make_unique<Ringbuffer>(magma::PlatformBuffer::Create(kMagmaPageSize, "test"));
EXPECT_EQ(ringbuffer->size(), kMagmaPageSize);
EXPECT_EQ(ringbuffer->head(), 0u);
EXPECT_EQ(ringbuffer->tail(), 0u);
const uint32_t kStartOffset = kMagmaPageSize - 12;
ringbuffer->Reset(kStartOffset);
EXPECT_EQ(ringbuffer->head(), kStartOffset);
EXPECT_EQ(ringbuffer->tail(), kStartOffset);
EXPECT_EQ(ringbuffer->head(), ringbuffer->tail());
}
TEST_F(TestRingbuffer, Size) {
const uint32_t kRingbufferSize = magma::page_size();
const uint32_t kBufferSize = kRingbufferSize + magma::page_size();
auto ringbuffer = std::make_unique<Ringbuffer>(magma::PlatformBuffer::Create(kBufferSize, "test"),
kRingbufferSize);
EXPECT_EQ(ringbuffer->size(), kRingbufferSize);
const uint64_t kGpuAddr = 0x10000;
auto owner = std::make_unique<AddressSpaceOwner>();
auto address_space =
std::make_shared<NonAllocatingAddressSpace>(owner.get(), kGpuAddr + kBufferSize);
std::shared_ptr<GpuMapping> gpu_mapping;
EXPECT_TRUE(ringbuffer->MultiMap(address_space, kGpuAddr, &gpu_mapping));
EXPECT_EQ(kBufferSize, address_space->inserted_size(kGpuAddr));
EXPECT_NE(gpu_mapping, nullptr);
}
TEST_F(TestRingbuffer, Write) {
const uint32_t kMagmaPageSize = magma::page_size();
auto ringbuffer =
std::make_unique<Ringbuffer>(magma::PlatformBuffer::Create(kMagmaPageSize, "test"));
EXPECT_EQ(ringbuffer->size(), kMagmaPageSize);
EXPECT_EQ(ringbuffer->head(), 0u);
// Can't store full size because head==tail means empty
EXPECT_FALSE(ringbuffer->HasSpace(kMagmaPageSize));
EXPECT_TRUE(ringbuffer->HasSpace(kMagmaPageSize - sizeof(uint32_t)));
auto owner = std::make_unique<AddressSpaceOwner>();
auto address_space = std::make_shared<AllocatingAddressSpace>(owner.get(), 0x10000, // base
kMagmaPageSize);
uint64_t gpu_addr;
EXPECT_TRUE(ringbuffer->Map(address_space, &gpu_addr));
uint32_t* addr = vaddr(ringbuffer.get());
ASSERT_NE(addr, nullptr);
uint32_t start_index = ringbuffer->tail() / sizeof(uint32_t);
uint32_t size_dwords = kMagmaPageSize / sizeof(uint32_t);
// Stuff the ringbuffer - fill to one less
for (unsigned int i = 0; i < size_dwords - 1; i++) {
EXPECT_TRUE(ringbuffer->HasSpace(sizeof(uint32_t)));
ringbuffer->Write32(i);
EXPECT_EQ(addr[(start_index + i) % size_dwords], i);
}
ringbuffer->update_head(ringbuffer->tail());
// Do it again
for (unsigned int i = 0; i < size_dwords - 1; i++) {
EXPECT_TRUE(ringbuffer->HasSpace(sizeof(uint32_t)));
ringbuffer->Write32(i);
EXPECT_EQ(addr[(start_index + i) % size_dwords], i);
}
}
TEST_F(TestRingbuffer, MultipleAddressSpaces) {
const uint32_t kMagmaPageSize = magma::page_size();
auto ringbuffer =
std::make_unique<Ringbuffer>(magma::PlatformBuffer::Create(kMagmaPageSize, "test"));
auto owner = std::make_unique<AddressSpaceOwner>();
auto address_space = std::make_shared<NonAllocatingAddressSpace>(owner.get(), UINT32_MAX);
const uint64_t kGpuAddr = 0x10000;
std::shared_ptr<GpuMapping> gpu_mapping;
EXPECT_TRUE(ringbuffer->MultiMap(address_space, kGpuAddr, &gpu_mapping));
EXPECT_NE(gpu_mapping, nullptr);
// Try mapping additional address spaces.
auto address_space2 = std::make_shared<NonAllocatingAddressSpace>(owner.get(), UINT32_MAX);
std::shared_ptr<GpuMapping> gpu_mapping2;
EXPECT_TRUE(ringbuffer->MultiMap(address_space2, kGpuAddr, &gpu_mapping2));
EXPECT_NE(gpu_mapping2, nullptr);
auto address_space3 = std::make_shared<NonAllocatingAddressSpace>(owner.get(), UINT32_MAX);
std::shared_ptr<GpuMapping> gpu_mapping3;
EXPECT_TRUE(ringbuffer->MultiMap(address_space3, kGpuAddr, &gpu_mapping3));
EXPECT_NE(gpu_mapping3, nullptr);
}