blob: 9ab6e51828cea793a7b0a26f8d26e01d96cd96c3 [file] [log] [blame]
// Copyright 2022 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 "src/connectivity/ethernet/drivers/gvnic/pagelist.h"
#include <lib/dma-buffer/buffer.h>
#include <lib/fake-bti/bti.h>
#include <unordered_set>
#include <fake-dma-buffer/fake-dma-buffer.h>
#include <zxtest/zxtest.h>
#include "src/connectivity/ethernet/drivers/gvnic/bigendian.h"
using namespace std;
namespace gvnic {
TEST(PagelistTest, BasicUsage) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
EXPECT_TRUE(factory);
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
// Just create the pagelist, and verify that it has pages with addresses.
PageList page_list(factory, bti, scratch);
EXPECT_NOT_NULL(page_list.pages());
EXPECT_NOT_NULL(page_list.pages()->virt());
EXPECT_NOT_NULL(page_list.pages()->phys());
}
TEST(PagelistTest, ScratchIsPopulated) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
// Zero out the scratch page. (Set all entries to 0)
memset(scratch->virt(), 0, scratch->size());
PageList page_list(factory, bti, scratch);
// Check that they are not 0 anymore.
auto const scratch_addrs = reinterpret_cast<BigEndian<uint64_t>*>(scratch->virt());
const auto expected_length = scratch->size() / sizeof(uint64_t);
for (uint32_t i = 0; i < expected_length; i++) {
EXPECT_NE(0UL, scratch_addrs[i]);
}
}
TEST(PagelistTest, IdsIncrement) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
// The ids wont nesecarily start at 0 (since IDs are allocated by other tests), but consecutively
// created pagelists should have ids that are contiguous.
PageList pl0(factory, bti, scratch), pl1(factory, bti, scratch), pl2(factory, bti, scratch),
pl3(factory, bti, scratch), pl4(factory, bti, scratch), pl5(factory, bti, scratch);
EXPECT_EQ(pl0.id() + 1, pl1.id());
EXPECT_EQ(pl1.id() + 1, pl2.id());
EXPECT_EQ(pl2.id() + 1, pl3.id());
EXPECT_EQ(pl3.id() + 1, pl4.id());
EXPECT_EQ(pl4.id() + 1, pl5.id());
}
TEST(PagelistTest, CheckLengths) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
PageList page_list(factory, bti, scratch);
// The pagelist length and the length of the actual pages should be consistent.
const auto expected_length = scratch->size() / sizeof(uint64_t);
EXPECT_EQ(expected_length, page_list.length());
EXPECT_EQ(expected_length * zx_system_get_page_size(), page_list.pages()->size());
}
TEST(PagelistTest, AddrsAreUnique) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
PageList page_list(factory, bti, scratch);
// The addresses should all be unique, no duplicates.
const auto expected_length = scratch->size() / sizeof(uint64_t);
unordered_set<zx_paddr_t> pl_addr_set;
pl_addr_set.insert(page_list.pages()->phys(), page_list.pages()->phys() + expected_length);
EXPECT_EQ(expected_length, pl_addr_set.size());
}
TEST(PagelistTest, ScratchMatchesPagesButBigEndian) {
zx::bti bti;
ASSERT_OK(fake_bti_create(bti.reset_and_get_address()));
std::unique_ptr<dma_buffer::BufferFactory> factory(ddk_fake::CreateBufferFactory());
std::unique_ptr<dma_buffer::ContiguousBuffer> scratch;
EXPECT_OK(factory->CreateContiguous(bti, zx_system_get_page_size(), 0, &scratch));
PageList page_list(factory, bti, scratch);
// The scratch page should contain bigendian versions of the addresses in pages.
const auto expected_length = scratch->size() / sizeof(uint64_t);
auto const scratch_addrs = reinterpret_cast<BigEndian<uint64_t>*>(scratch->virt());
auto const pages_addrs = page_list.pages()->phys();
for (uint32_t i = 0; i < expected_length; i++) {
EXPECT_EQ(pages_addrs[i], scratch_addrs[i]);
}
}
} // namespace gvnic