Software APIs
dif_mbx_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 
7 #include <array>
8 
9 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/mock_abs_mmio.h"
12 #include "sw/device/lib/base/mock_mmio.h"
14 
15 extern "C" {
16 #include "mbx_regs.h" // Generated.
17 } // extern "C"
18 
19 namespace dif_mbx_test {
22 using testing::Test;
23 
24 // Base class for the rest fixtures in this file.
25 class MbxTest : public testing::Test, public mock_mmio::MmioTest {};
26 
27 // Base class for the rest of the tests in this file, provides a
28 // `dif_mbx_t` instance.
29 class MbxTestInitialized : public MbxTest {
30  protected:
31  dif_mbx_t mbx_;
32  rom_test::MockAbsMmio mmio_;
33 
34  MbxTestInitialized() { EXPECT_DIF_OK(dif_mbx_init(dev().region(), &mbx_)); }
35 };
36 
38  : public MbxTestInitialized,
39  public testing::WithParamInterface<dif_mbx_range_config_t> {};
40 
41 TEST_P(MemoryRangeSuccessTests, SetSuccess) {
42  dif_mbx_range_config_t range = GetParam();
43 
44  EXPECT_WRITE32(MBX_INBOUND_BASE_ADDRESS_REG_OFFSET, range.imbx_base_addr);
45  EXPECT_WRITE32(MBX_INBOUND_LIMIT_ADDRESS_REG_OFFSET, range.imbx_limit_addr);
46  EXPECT_WRITE32(MBX_OUTBOUND_BASE_ADDRESS_REG_OFFSET, range.ombx_base_addr);
47  EXPECT_WRITE32(MBX_OUTBOUND_LIMIT_ADDRESS_REG_OFFSET, range.ombx_limit_addr);
48  EXPECT_WRITE32(MBX_ADDRESS_RANGE_VALID_REG_OFFSET, 1);
49 
50  EXPECT_DIF_OK(dif_mbx_range_set(&mbx_, range));
51 }
52 
53 // 'Limit' addresses are _inclusive_.
54 INSTANTIATE_TEST_SUITE_P(
55  MemoryRangeSuccessTests, MemoryRangeSuccessTests,
56  testing::ValuesIn(std::vector<dif_mbx_range_config_t>{{
57  {.imbx_base_addr = 0xD0CF2C50,
58  .imbx_limit_addr = 0xD1CF2C0F,
59  .ombx_base_addr = 0xD1CF3C0F,
60  .ombx_limit_addr = 0xD1CF3C10},
61  {.imbx_base_addr = 0x1000,
62  .imbx_limit_addr = 0x2000,
63  .ombx_base_addr = 0x3000,
64  .ombx_limit_addr = 0x4000},
65  {.imbx_base_addr = 0x1000,
66  .imbx_limit_addr = 0x1003, // Inbound mailbox is a single DWORD.
67  .ombx_base_addr = 0x1004,
68  .ombx_limit_addr = 0x1007}, // Single DWORD
69  }}));
70 
72  : public MbxTestInitialized,
73  public testing::WithParamInterface<dif_mbx_range_config_t> {};
74 
75 TEST_P(MemoryRangeBadArgTests, SetBadArg) {
76  dif_mbx_range_config_t range = GetParam();
77 
78  EXPECT_DIF_BADARG(dif_mbx_range_set(&mbx_, range));
79 }
80 
81 INSTANTIATE_TEST_SUITE_P(MemoryRangeBadArgTests, MemoryRangeBadArgTests,
82  testing::ValuesIn(std::vector<dif_mbx_range_config_t>{{
83  {.imbx_base_addr = 0x1000,
84  .imbx_limit_addr = 0,
85  .ombx_base_addr = 0x2000,
86  .ombx_limit_addr = 0x4000},
87  {.imbx_base_addr = 0x1000,
88  .imbx_limit_addr = 0x5000,
89  .ombx_base_addr = 0x4000,
90  .ombx_limit_addr = 0x4000},
91  {.imbx_base_addr = 0x1000,
92  .imbx_limit_addr = 0x2000,
93  .ombx_base_addr = 0x1500,
94  .ombx_limit_addr = 0x2500},
95  {.imbx_base_addr = 0x1500,
96  .imbx_limit_addr = 0x2500,
97  .ombx_base_addr = 0x1000,
98  .ombx_limit_addr = 0x2000},
99  }}));
100 
101 TEST_F(MemoryRangeBadArgTests, GetBadArg) {
103 
104  EXPECT_DIF_BADARG(dif_mbx_range_set(nullptr, range));
105 }
106 
108 
109 TEST_F(MemoryRangeTests, GetSuccess) {
110  dif_mbx_range_config_t range = {.imbx_base_addr = 0xD0CF2C50,
111  .imbx_limit_addr = 0xD1CF2C0F,
112  .ombx_base_addr = 0xD1CF3C0F,
113  .ombx_limit_addr = 0xD1CF3C19};
114 
115  EXPECT_READ32(MBX_INBOUND_BASE_ADDRESS_REG_OFFSET, range.imbx_base_addr);
116  EXPECT_READ32(MBX_INBOUND_LIMIT_ADDRESS_REG_OFFSET, range.imbx_limit_addr);
117  EXPECT_READ32(MBX_OUTBOUND_BASE_ADDRESS_REG_OFFSET, range.ombx_base_addr);
118  EXPECT_READ32(MBX_OUTBOUND_LIMIT_ADDRESS_REG_OFFSET, range.ombx_limit_addr);
119 
120  dif_mbx_range_config_t read_range;
121  EXPECT_DIF_OK(dif_mbx_range_get(&mbx_, &read_range));
122 
123  EXPECT_EQ(read_range.imbx_base_addr, range.imbx_base_addr);
124  EXPECT_EQ(read_range.imbx_limit_addr, range.imbx_limit_addr);
125  EXPECT_EQ(read_range.ombx_base_addr, range.ombx_base_addr);
126  EXPECT_EQ(read_range.ombx_limit_addr, range.ombx_limit_addr);
127 }
128 
129 TEST_F(MemoryRangeTests, GetBadArg) {
131 
132  EXPECT_DIF_BADARG(dif_mbx_range_get(nullptr, &range));
133  EXPECT_DIF_BADARG(dif_mbx_range_get(&mbx_, nullptr));
134 }
135 
137 
138 TEST_F(IpiConfigurationTests, GetSuccess) {
139  uint32_t doe_intr_addr, doe_intr_data;
140 
141  EXPECT_READ32(MBX_DOE_INTR_MSG_ADDR_REG_OFFSET, 0x52001234);
142  EXPECT_READ32(MBX_DOE_INTR_MSG_DATA_REG_OFFSET, 0xFFABCDEF);
143 
145  dif_mbx_ipi_configuration_get(&mbx_, &doe_intr_addr, &doe_intr_data));
146 
147  EXPECT_EQ(doe_intr_addr, 0x52001234);
148  EXPECT_EQ(doe_intr_data, 0xFFABCDEF);
149 }
150 
151 TEST_F(IpiConfigurationTests, GetBadArg) {
152  uint32_t doe_intr_addr, doe_intr_data;
153 
155  dif_mbx_ipi_configuration_get(nullptr, &doe_intr_addr, &doe_intr_data));
157  dif_mbx_ipi_configuration_get(&mbx_, nullptr, &doe_intr_data));
159  dif_mbx_ipi_configuration_get(&mbx_, &doe_intr_addr, nullptr));
160 }
161 
162 typedef struct status_reg {
163  uint32_t reg;
164  bool is_busy;
165 } status_reg_t;
166 
168  public testing::WithParamInterface<status_reg_t> {};
169 
170 TEST_P(ProcessBusyTests, GetSuccess) {
171  status_reg_t status_arg = GetParam();
172 
173  EXPECT_READ32(MBX_STATUS_REG_OFFSET, status_arg.reg);
174 
175  bool is_busy = !status_arg.is_busy;
176 
177  EXPECT_DIF_OK(dif_mbx_is_busy(&mbx_, &is_busy));
178  EXPECT_EQ(is_busy, status_arg.is_busy);
179 }
180 
181 INSTANTIATE_TEST_SUITE_P(ProcessBusyTests, ProcessBusyTests,
182  testing::ValuesIn(std::vector<status_reg_t>{{
183  {0, false},
184  {1 << MBX_STATUS_BUSY_BIT, true},
185  }}));
186 
187 TEST_F(ProcessBusyTests, GetBadArg) {
188  bool is_busy;
189  EXPECT_DIF_BADARG(dif_mbx_is_busy(nullptr, &is_busy));
190  EXPECT_DIF_BADARG(dif_mbx_is_busy(&mbx_, nullptr));
191 }
192 
194 
195 TEST_F(ProcessRequestTests, Success) {
196  dif_mbx_transaction_t request;
197  uint32_t data[4];
198  request.data_dwords = data;
199  request.nr_dwords = 4;
200 
201  EXPECT_READ32(MBX_INBOUND_BASE_ADDRESS_REG_OFFSET, 0x1000);
202  EXPECT_READ32(MBX_INBOUND_WRITE_PTR_REG_OFFSET, 0x1010);
203 
204  EXPECT_ABS_READ32(0x1000, 0x123456);
205  EXPECT_ABS_READ32(0x1004, 0x456789);
206  EXPECT_ABS_READ32(0x1008, 0xDEADBEEF);
207  EXPECT_ABS_READ32(0x100C, 0xCAFEDEAD);
208 
209  EXPECT_DIF_OK(dif_mbx_process_request(&mbx_, &request));
210 
211  EXPECT_EQ(request.nr_dwords, 4);
212  EXPECT_EQ(request.data_dwords[0], 0x123456);
213  EXPECT_EQ(request.data_dwords[1], 0x456789);
214  EXPECT_EQ(request.data_dwords[2], 0xDEADBEEF);
215  EXPECT_EQ(request.data_dwords[3], 0xCAFEDEAD);
216 }
217 
218 TEST_F(ProcessRequestTests, GetOutOfRangeSuccess) {
219  dif_mbx_transaction_t request;
220  uint32_t data[3];
221  request.data_dwords = data;
222  request.nr_dwords = 3;
223 
224  EXPECT_READ32(MBX_INBOUND_BASE_ADDRESS_REG_OFFSET, 0x1000);
225  EXPECT_READ32(MBX_INBOUND_WRITE_PTR_REG_OFFSET, 0x1010);
226 
227  EXPECT_ABS_READ32(0x1000, 0x123456);
228  EXPECT_ABS_READ32(0x1004, 0x456789);
229  EXPECT_ABS_READ32(0x1008, 0xDEADBEEF);
230 
232 
233  EXPECT_EQ(request.nr_dwords, 3);
234  EXPECT_EQ(request.data_dwords[0], 0x123456);
235  EXPECT_EQ(request.data_dwords[1], 0x456789);
236  EXPECT_EQ(request.data_dwords[2], 0xDEADBEEF);
237 
238  request.data_dwords = data;
239  request.nr_dwords = 1;
240 
241  EXPECT_READ32(MBX_INBOUND_BASE_ADDRESS_REG_OFFSET, 0x100C);
242  EXPECT_READ32(MBX_INBOUND_WRITE_PTR_REG_OFFSET, 0x1010);
243 
244  EXPECT_ABS_READ32(0x100C, 0xCAFEDEAD);
245 
246  EXPECT_DIF_OK(dif_mbx_process_request(&mbx_, &request));
247 
248  EXPECT_EQ(request.nr_dwords, 1);
249  EXPECT_EQ(request.data_dwords[0], 0xCAFEDEAD);
250 }
251 
252 TEST_F(ProcessRequestTests, BadArg) {
253  dif_mbx_transaction_t request;
254  request.data_dwords = nullptr;
255  request.nr_dwords = 1;
256 
257  EXPECT_DIF_BADARG(dif_mbx_process_request(nullptr, &request));
259  EXPECT_DIF_BADARG(dif_mbx_process_request(&mbx_, &request));
260 }
261 
263 
264 TEST_F(ProcessResponseTests, Success) {
265  dif_mbx_transaction_t response;
266  std::array<uint32_t, 4> data = {0x123456, 0x456789, 0xDEADBEEF, 0xCAFEDEAD};
267  response.nr_dwords = data.size();
268  response.data_dwords = data.data();
269 
270  EXPECT_READ32(MBX_OUTBOUND_READ_PTR_REG_OFFSET, 0x1000);
271  EXPECT_ABS_WRITE32(0x1000, data[0]);
272  EXPECT_ABS_WRITE32(0x1004, data[1]);
273  EXPECT_ABS_WRITE32(0x1008, data[2]);
274  EXPECT_ABS_WRITE32(0x100C, data[3]);
275  EXPECT_WRITE32(MBX_OUTBOUND_OBJECT_SIZE_REG_OFFSET, response.nr_dwords);
276 
277  EXPECT_DIF_OK(dif_mbx_generate_response(&mbx_, response));
278 }
279 
280 TEST_F(ProcessResponseTests, BadArg) {
281  dif_mbx_transaction_t response1;
282  response1.nr_dwords = DOE_MAILBOX_MAX_OBJECT_SIZE + 1;
283 
284  dif_mbx_transaction_t response2;
285  response2.data_dwords = nullptr;
286  response2.nr_dwords = 1;
287 
288  EXPECT_DIF_BADARG(dif_mbx_generate_response(nullptr, response1));
289  EXPECT_DIF_BADARG(dif_mbx_generate_response(&mbx_, response1));
290  EXPECT_DIF_BADARG(dif_mbx_generate_response(&mbx_, response2));
291 }
292 
293 } // namespace dif_mbx_test