[sw] Minor software updates for dif_entropy_src and test
- This change should now ensure the new seed is used and
the entropy reads should be different between reads.
- Lastly, a few auxillary functions are added to poll for specific
status. These likely should be replaced long term by something
more robust
- unittests are also udpated for the slightly tweaked sequence
- At the moment, since we disable / re-enable entropy_src, the
timing differences between platforms (dv vs verilator) causes
the test to spit out different results. For the time being,
favor verilator until #5941 is in.
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/sw/device/lib/dif/dif_entropy.c b/sw/device/lib/dif/dif_entropy.c
index ddbd77f..22a2621 100644
--- a/sw/device/lib/dif/dif_entropy.c
+++ b/sw/device/lib/dif/dif_entropy.c
@@ -93,12 +93,48 @@
return kDifEntropyOk;
}
+static bool get_entropy_avail(const dif_entropy_t *entropy) {
+ return mmio_region_get_bit32(entropy->params.base_addr,
+ ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+ ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
+}
+
+dif_entropy_result_t dif_entropy_avail(const dif_entropy_t *entropy) {
+ if (entropy == NULL) {
+ return kDifEntropyBadArg;
+ }
+
+ return get_entropy_avail(entropy) ? kDifEntropyOk
+ : kDifEntropyDataUnAvailable;
+}
+
dif_entropy_result_t dif_entropy_read(const dif_entropy_t *entropy,
uint32_t *word) {
if (entropy == NULL || word == NULL) {
return kDifEntropyBadArg;
}
+
+ // Check if entropy is available
+ if (!get_entropy_avail(entropy)) {
+ return kDifEntropyDataUnAvailable;
+ }
+
*word = mmio_region_read32(entropy->params.base_addr,
ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
+
+ // clear interrupt state after fetching read
+ // if there is still entropy available, the interrupt state will set again
+ mmio_region_nonatomic_set_bit32(entropy->params.base_addr,
+ ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+ ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
+
+ return kDifEntropyOk;
+}
+
+dif_entropy_result_t dif_entropy_disable(const dif_entropy_t *entropy) {
+ // TODO: should first check if entropy is locked and return error if it is.
+ mmio_region_write32(entropy->params.base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
+ 0);
+
return kDifEntropyOk;
}
diff --git a/sw/device/lib/dif/dif_entropy.h b/sw/device/lib/dif/dif_entropy.h
index ff034a4..44fc894 100644
--- a/sw/device/lib/dif/dif_entropy.h
+++ b/sw/device/lib/dif/dif_entropy.h
@@ -363,6 +363,14 @@
* succeed until hardware reset.
*/
kDifEntropyLocked = 3,
+ /**
+ * Indicates that entropy is not yet available for software consumption
+ */
+ kDifEntropyDataUnAvailable = 4,
+ /**
+ * Indicates that entropy is not idle
+ */
+ kDifEntropyNotIdle = 5,
} dif_entropy_result_t;
/**
@@ -486,6 +494,15 @@
bool *is_locked);
/**
+ * Checks to see if entropy is available for software consumption
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_avail(const dif_entropy_t *entropy);
+
+/**
* Reads off a word of entropy from the entropy source.
*
* @param entropy An entropy source handle.
@@ -682,6 +699,24 @@
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_reconnect(const dif_entropy_t *entropy);
+/**
+ * Disables the entropy module
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_disable(const dif_entropy_t *entropy);
+
+/**
+ * Get main entropy fsm idle status
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_get_idle(const dif_entropy_t *entropy);
+
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
diff --git a/sw/device/tests/dif/dif_entropy_smoketest.c b/sw/device/tests/dif/dif_entropy_smoketest.c
index e8d9b75..e78d18b 100644
--- a/sw/device/tests/dif/dif_entropy_smoketest.c
+++ b/sw/device/tests/dif/dif_entropy_smoketest.c
@@ -14,9 +14,13 @@
const test_config_t kTestConfig;
const size_t kEntropyDataNumWords = 12;
+
+// TODO: These values are specific to verilator right now and will not work
+// for DV or FPGA, see #5941
const uint32_t kExpectedEntropyData[] = {
- 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497,
- 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497,
+ 0x0a3f4df0, 0x4e36fad2, 0xb5f3e0b9, 0x918f5ec0, 0x54ddd680, 0x62f04975,
+ 0x700cf2f2, 0x61044bfe, 0x723d6c89, 0xe2d70e19, 0x5f02a234, 0xbf586fcc,
+
};
bool test_main() {
@@ -26,6 +30,9 @@
dif_entropy_t entropy;
CHECK(dif_entropy_init(params, &entropy) == kDifEntropyOk);
+ // Disable entropy for test purpose, as it has been turned on by ROM
+ CHECK(dif_entropy_disable(&entropy) == kDifEntropyOk);
+
const dif_entropy_config_t config = {
.mode = kDifEntropyModeLfsr,
.tests =
@@ -37,7 +44,8 @@
[kDifEntropyTestMailbox] = false,
[kDifEntropyTestVendorSpecific] = false,
},
- .reset_health_test_registers = true,
+ // this field needs to manually toggled by software. Disable for now
+ .reset_health_test_registers = false,
.single_bit_mode = kDifEntropySingleBitModeDisabled,
.route_to_firmware = true,
.sample_rate = 2,
@@ -47,7 +55,11 @@
uint32_t entropy_data[kEntropyDataNumWords];
for (uint32_t i = 0; i < kEntropyDataNumWords; ++i) {
- CHECK(dif_entropy_read(&entropy, &entropy_data[i]) == kDifEntropyOk);
+ // wait for entropy to become available
+ while (dif_entropy_read(&entropy, &entropy_data[i]) != kDifEntropyOk)
+ ;
+ // LOG_INFO("received %x, expectecd %x", entropy_data[i],
+ // kExpectedEntropyData[i]);
CHECK(entropy_data[i] == kExpectedEntropyData[i]);
}
diff --git a/sw/device/tests/dif/dif_entropy_unittest.cc b/sw/device/tests/dif/dif_entropy_unittest.cc
index 12e3b53..f0d4603 100644
--- a/sw/device/tests/dif/dif_entropy_unittest.cc
+++ b/sw/device/tests/dif/dif_entropy_unittest.cc
@@ -143,9 +143,21 @@
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);
diff --git a/test/systemtest/config.py b/test/systemtest/config.py
index a5b9646..45d8bc0 100644
--- a/test/systemtest/config.py
+++ b/test/systemtest/config.py
@@ -74,6 +74,7 @@
},
{
"name": "dif_entropy_smoketest",
+ "targets": ["sim_verilator"],
},
{
"name": "flash_ctrl_test",