blob: 1bfedf1bbdec2cc8a450c3b02df95d1b0b395e5e [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_entropy.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/testing/mock_mmio.h"
#include "entropy_src_regs.h" // Generated
namespace dif_entropy_unittest {
namespace {
class DifEntropyTest : public testing::Test, public mock_mmio::MmioTest {
protected:
const dif_entropy_params_t params_ = {.base_addr = dev().region()};
const dif_entropy_t entropy_ = {
.params = {.base_addr = dev().region()},
};
};
class InitTest : public DifEntropyTest {};
TEST_F(InitTest, BadArgs) {
EXPECT_EQ(dif_entropy_init(params_, nullptr), kDifEntropyBadArg);
}
TEST_F(InitTest, Init) {
dif_entropy_t entropy;
EXPECT_EQ(dif_entropy_init(params_, &entropy), kDifEntropyOk);
}
class ConfigTest : public DifEntropyTest {
protected:
dif_entropy_config_t config_ = {
.mode = kDifEntropyModeLfsr,
.tests = {0},
.reset_health_test_registers = false,
.single_bit_mode = kDifEntropySingleBitModeDisabled,
.route_to_firmware = false,
.fips_mode = false,
.test_config = {0},
.sample_rate = 64,
.lfsr_seed = 4,
};
};
TEST_F(ConfigTest, NullArgs) {
EXPECT_EQ(dif_entropy_configure(nullptr, {}), kDifEntropyBadArg);
}
TEST_F(ConfigTest, LfsrSeedBadArg) {
config_.lfsr_seed = 16;
EXPECT_EQ(dif_entropy_configure(&entropy_, config_), kDifEntropyBadArg);
}
struct ConfigParams {
dif_entropy_mode_t mode;
dif_entropy_single_bit_mode_t single_bit_mode;
bool route_to_firmware;
bool reset_health_test_registers;
uint32_t expected_mode;
bool expected_rng_bit_en;
uint32_t expected_rng_sel;
uint32_t expected_seed;
};
class ConfigTestAllParams : public ConfigTest,
public testing::WithParamInterface<ConfigParams> {};
TEST_P(ConfigTestAllParams, ValidConfigurationMode) {
const ConfigParams &test_param = GetParam();
config_.mode = test_param.mode;
config_.single_bit_mode = test_param.single_bit_mode;
config_.route_to_firmware = test_param.route_to_firmware;
config_.reset_health_test_registers = test_param.reset_health_test_registers;
EXPECT_WRITE32(ENTROPY_SRC_SEED_REG_OFFSET, test_param.expected_seed);
EXPECT_WRITE32(ENTROPY_SRC_RATE_REG_OFFSET, 64);
EXPECT_WRITE32(ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
{
{ENTROPY_SRC_ENTROPY_CONTROL_ES_ROUTE_BIT,
test_param.route_to_firmware},
{ENTROPY_SRC_ENTROPY_CONTROL_ES_TYPE_BIT, false},
});
EXPECT_WRITE32(ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET, 0);
EXPECT_WRITE32(
ENTROPY_SRC_CONF_REG_OFFSET,
{
{ENTROPY_SRC_CONF_ENABLE_OFFSET, test_param.expected_mode},
{ENTROPY_SRC_CONF_BOOT_BYPASS_DISABLE_BIT, true},
{ENTROPY_SRC_CONF_REPCNT_DISABLE_BIT, true},
{ENTROPY_SRC_CONF_ADAPTP_DISABLE_BIT, true},
{ENTROPY_SRC_CONF_BUCKET_DISABLE_BIT, true},
{ENTROPY_SRC_CONF_MARKOV_DISABLE_BIT, true},
{ENTROPY_SRC_CONF_HEALTH_TEST_CLR_BIT,
test_param.reset_health_test_registers},
{ENTROPY_SRC_CONF_RNG_BIT_EN_BIT, test_param.expected_rng_bit_en},
{ENTROPY_SRC_CONF_RNG_BIT_SEL_OFFSET, test_param.expected_rng_sel},
{ENTROPY_SRC_CONF_EXTHT_ENABLE_BIT, false},
});
EXPECT_EQ(dif_entropy_configure(&entropy_, config_), kDifEntropyOk);
}
INSTANTIATE_TEST_SUITE_P(
ConfigTestAllParams, ConfigTestAllParams,
testing::Values(
// Test entropy mode.
ConfigParams{kDifEntropyModeDisabled, kDifEntropySingleBitModeDisabled,
false, 0, false, 0, 0},
ConfigParams{kDifEntropyModePtrng, kDifEntropySingleBitModeDisabled,
false, false, 1, false, 0, 0},
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitModeDisabled,
false, false, 2, false, 0, 4},
// Test route_to_firmware
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitModeDisabled,
true, false, 2, false, 0, 4},
// Test reset_health_test_registers
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitModeDisabled,
true, true, 2, false, 0, 4},
// Test single_bit_mode
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitMode0, true, true,
2, true, 0, 4},
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitMode1, true, true,
2, true, 1, 4},
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitMode2, true, true,
2, true, 2, 4},
ConfigParams{kDifEntropyModeLfsr, kDifEntropySingleBitMode3, true, true,
2, true, 3, 4}));
class ReadTest : public DifEntropyTest {};
TEST_F(ReadTest, EntropyBadArg) {
uint32_t word;
EXPECT_EQ(dif_entropy_read(nullptr, &word), kDifEntropyBadArg);
}
TEST_F(ReadTest, WordBadArg) {
EXPECT_EQ(dif_entropy_read(&entropy_, nullptr), kDifEntropyBadArg);
}
TEST_F(ReadTest, ReadDataUnAvailable) {
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET, 0);
uint32_t got_word;
EXPECT_EQ(dif_entropy_read(&entropy_, &got_word), kDifEntropyDataUnAvailable);
}
TEST_F(ReadTest, ReadOk) {
const uint32_t expected_word = 0x65585497;
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
EXPECT_READ32(ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET, expected_word);
EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
EXPECT_WRITE32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
{{ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT, true}});
uint32_t got_word;
EXPECT_EQ(dif_entropy_read(&entropy_, &got_word), kDifEntropyOk);
EXPECT_EQ(got_word, expected_word);
}
} // namespace
} // namespace dif_entropy_unittest