blob: 914223aca3e0156b477f3b0e6ea83f9fee588853 [file] [log] [blame]
Andrew Jeffery0247c732020-02-06 11:48:52 +10301/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10303#ifdef HAVE_CONFIG_H
Andrew Jeffery0247c732020-02-06 11:48:52 +10304#include "config.h"
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10305#endif
6
Andrew Jefferydf5f6b92020-05-12 21:39:06 +09307#include "astlpc.c"
8
9#ifdef pr_fmt
10#undef pr_fmt
11#define pr_fmt(x) "test: " x
12#endif
13
Andrew Jeffery0247c732020-02-06 11:48:52 +103014#include "libmctp-astlpc.h"
15#include "libmctp-log.h"
Przemyslaw Czarnowskiff25d7e2020-03-26 11:39:37 +010016#include "container_of.h"
Andrew Jeffery0247c732020-02-06 11:48:52 +103017
18#ifdef NDEBUG
19#undef NDEBUG
20#endif
21
Andrew Jeffery0247c732020-02-06 11:48:52 +103022#include <assert.h>
Andrew Jeffery91f09ed2020-05-22 20:52:26 +093023#include <limits.h>
Andrew Jeffery0247c732020-02-06 11:48:52 +103024#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
Andrew Jeffery91f09ed2020-05-22 20:52:26 +093029#ifndef ARRAY_SIZE
30#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
31#endif
32
Andrew Jeffery0247c732020-02-06 11:48:52 +103033struct mctp_binding_astlpc_mmio {
34 struct mctp_binding_astlpc astlpc;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093035 bool bmc;
Andrew Jeffery0247c732020-02-06 11:48:52 +103036
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093037 uint8_t (*kcs)[2];
Andrew Jeffery0247c732020-02-06 11:48:52 +103038
39 size_t lpc_size;
40 uint8_t *lpc;
41};
42
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +093043struct astlpc_endpoint {
44 struct mctp_binding_astlpc_mmio mmio;
45 struct mctp_binding_astlpc *astlpc;
46 struct mctp *mctp;
47};
48
49struct astlpc_test {
50 struct astlpc_endpoint bmc;
51 struct astlpc_endpoint host;
52 uint8_t kcs[2];
53 uint8_t *lpc_mem;
54
55 void *msg;
56 uint8_t count;
57};
58
59#define binding_to_mmio(b) \
Andrew Jeffery0247c732020-02-06 11:48:52 +103060 container_of(b, struct mctp_binding_astlpc_mmio, astlpc)
61
Andrew Jeffery53ea1472020-05-23 21:06:24 +093062static int mctp_astlpc_mmio_kcs_read(void *data,
63 enum mctp_binding_astlpc_kcs_reg reg,
64 uint8_t *val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103065{
66 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
67
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093068 *val = (*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103069
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +093070 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val,
71 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +103072
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093073 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
74 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
75 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
76 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103077
78 return 0;
79}
80
Andrew Jeffery53ea1472020-05-23 21:06:24 +093081static int mctp_astlpc_mmio_kcs_write(void *data,
82 enum mctp_binding_astlpc_kcs_reg reg,
83 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103084{
85 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093086 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103087
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093088 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
89 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103090
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093091 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
92 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
93 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
94 }
95
96 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103097 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093098 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103099 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930100 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030101
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +0930102 mctp_prdebug("%s: 0x%hhx to %s", __func__, val,
103 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +1030104
105 return 0;
106}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030107int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030108{
109 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
110
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930111 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
112
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030113 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030114 assert(offset + len < mmio->lpc_size);
115
116 memcpy(buf, mmio->lpc + offset, len);
117
Andrew Jeffery0247c732020-02-06 11:48:52 +1030118 return 0;
119}
120
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030121int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030122{
123 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
124
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930125 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
126
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030127 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030128 assert(offset + len < mmio->lpc_size);
129
130 memcpy(mmio->lpc + offset, buf, len);
131
Andrew Jeffery0247c732020-02-06 11:48:52 +1030132 return 0;
133}
134
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930135#define __unused __attribute__((unused))
136
137static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
138 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030139{
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930140 struct astlpc_test *test = data;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030141
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930142 mctp_prdebug("MCTP message received: msg: %p, len %zd", msg, len);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030143
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930144 assert(len > 0);
145 assert(msg);
146 assert(test);
147 assert(test->msg);
148 assert(!memcmp(test->msg, msg, len));
149
150 test->count++;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030151}
152
Andrew Jeffery53ea1472020-05-23 21:06:24 +0930153static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030154 .kcs_read = mctp_astlpc_mmio_kcs_read,
155 .kcs_write = mctp_astlpc_mmio_kcs_write,
156 .lpc_read = mctp_astlpc_mmio_lpc_read,
157 .lpc_write = mctp_astlpc_mmio_lpc_write,
158};
159
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930160static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
161 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
162 size_t lpc_size)
163{
164 /*
165 * Configure the direction of the KCS interface so we know whether to
166 * set or clear IBF or OBF on writes or reads.
167 */
168 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
169
170 ep->mctp = mctp_init();
171 assert(ep->mctp);
172
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930173 /* Inject KCS registers */
174 ep->mmio.kcs = kcs;
175
176 /* Inject the heap allocation as the LPC mapping */
177 ep->mmio.lpc_size = lpc_size;
178 ep->mmio.lpc = lpc_mem;
179
180 /* Initialise the binding */
Andrew Jeffery129ef932020-05-22 16:24:19 +0930181 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, lpc_mem,
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930182 &mctp_binding_astlpc_mmio_ops, &ep->mmio);
183
184 mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
185}
186
187static void endpoint_destroy(struct astlpc_endpoint *ep)
188{
189 mctp_astlpc_destroy(ep->astlpc);
190 mctp_destroy(ep->mctp);
191}
192
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930193static void network_init(struct astlpc_test *ctx)
194{
195 const size_t lpc_size = 1 * 1024 * 1024;
196
197 ctx->lpc_mem = calloc(1, lpc_size);
198 assert(ctx->lpc_mem);
199
200 /* BMC initialisation */
201 endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx->kcs,
202 ctx->lpc_mem, lpc_size);
203
204 /* Host initialisation */
205 endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &ctx->kcs,
206 ctx->lpc_mem, lpc_size);
207
208 /* BMC processes host channel init request, alerts host */
209 mctp_astlpc_poll(ctx->bmc.astlpc);
210 assert(ctx->kcs[KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
211 assert(ctx->kcs[KCS_REG_DATA] == 0xff);
212
213 /* Host dequeues channel init result */
214 mctp_astlpc_poll(ctx->host.astlpc);
215}
216
217static void network_destroy(struct astlpc_test *ctx)
218{
219 endpoint_destroy(&ctx->bmc);
220 endpoint_destroy(&ctx->host);
221 free(ctx->lpc_mem);
222}
223
Andrew Jeffery129ef932020-05-22 16:24:19 +0930224static void astlpc_assert_tx_packet(struct astlpc_endpoint *src,
225 const void *expected, size_t len)
226{
227 const size_t tx_body = src->astlpc->layout.tx.offset + 4 + 4;
228 const void *test = ((char *)src->astlpc->lpc_map) + tx_body;
229 assert(!memcmp(test, expected, len));
230}
231
Andrew Jefferye756de82020-05-22 12:30:58 +0930232static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930233{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930234 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930235 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030236 int rc;
237
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930238 /* Test harness initialisation */
239
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930240 network_init(&ctx);
241
Andrew Jeffery0247c732020-02-06 11:48:52 +1030242 memset(&msg[0], 0x5a, MCTP_BTU);
243 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
244
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930245 ctx.msg = &msg[0];
246 ctx.count = 0;
247 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030248
249 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930250 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030251 assert(rc == 0);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930252
Andrew Jeffery129ef932020-05-22 16:24:19 +0930253 /* Host receives the first packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930254 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030255
Andrew Jeffery0247c732020-02-06 11:48:52 +1030256 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930257 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030258 assert(rc == 0);
259
Andrew Jeffery129ef932020-05-22 16:24:19 +0930260 /* Host receives the next packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930261 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
262 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030263
Andrew Jeffery129ef932020-05-22 16:24:19 +0930264 astlpc_assert_tx_packet(&ctx.bmc, &msg[MCTP_BTU], MCTP_BTU);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030265
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930266 /* Host receives final packet */
267 mctp_astlpc_poll(ctx.host.astlpc);
268 assert(ctx.count == 1);
269
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930270 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930271}
272
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930273static void astlpc_test_simple_message_bmc_to_host(void)
274{
275 struct astlpc_test ctx = { 0 };
276 uint8_t msg[MCTP_BTU];
277 int rc;
278
279 /* Test harness initialisation */
280
281 network_init(&ctx);
282
283 memset(&msg[0], 0x5a, MCTP_BTU);
284
285 ctx.msg = &msg[0];
286 ctx.count = 0;
287 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
288
289 /* BMC sends the single-packet message */
290 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
291 assert(rc == 0);
292 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
293 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
294
295 astlpc_assert_tx_packet(&ctx.bmc, &msg[0], MCTP_BTU);
296
297 /* Host receives the single-packet message */
298 mctp_astlpc_poll(ctx.host.astlpc);
299 assert(ctx.count == 1);
300
301 /* Host returns Rx area ownership to BMC */
302 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
303 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
304 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
305
306 /* BMC dequeues ownership hand-over and sends the queued packet */
307 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
308 assert(rc == 0);
309
310 network_destroy(&ctx);
311}
312
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930313static void astlpc_test_simple_init(void)
314{
315 struct astlpc_endpoint bmc, host;
316 uint8_t kcs[2] = { 0 };
317 size_t lpc_size;
318 void *lpc_mem;
319
320 /* Test harness initialisation */
321 lpc_size = 1 * 1024 * 1024;
322 lpc_mem = calloc(1, lpc_size);
323 assert(lpc_mem);
324
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930325 /* BMC initialisation */
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930326 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
327 lpc_size);
328
329 /* Verify the BMC binding was initialised */
330 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
331
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930332 /* Host initialisation */
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930333 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
334 lpc_size);
335
336 /* Host sends channel init command */
337 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
338 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
339
340 /* BMC receives host channel init request */
341 mctp_astlpc_poll(bmc.astlpc);
342
343 /* BMC sends init response */
344 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
345 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
346 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
347
348 /* Host dequeues data */
349 mctp_astlpc_poll(host.astlpc);
350
351 endpoint_destroy(&bmc);
352 endpoint_destroy(&host);
353 free(lpc_mem);
354}
355
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930356/* clang-format off */
357#define TEST_CASE(test) { #test, test }
358static const struct {
359 const char *name;
360 void (*test)(void);
361} astlpc_tests[] = {
362 TEST_CASE(astlpc_test_simple_init),
363 TEST_CASE(astlpc_test_simple_message_bmc_to_host),
364 TEST_CASE(astlpc_test_packetised_message_bmc_to_host),
365};
366/* clang-format on */
367
368#ifndef BUILD_ASSERT
369#define BUILD_ASSERT(x) \
370 do { \
371 (void)sizeof(char[0 - (!(x))]); \
372 } while (0)
373#endif
374
Andrew Jefferye756de82020-05-22 12:30:58 +0930375int main(void)
376{
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930377 size_t i;
378
Andrew Jefferye756de82020-05-22 12:30:58 +0930379 mctp_set_log_stdio(MCTP_LOG_DEBUG);
380
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930381 BUILD_ASSERT(ARRAY_SIZE(astlpc_tests) < SIZE_MAX);
382 for (i = 0; i < ARRAY_SIZE(astlpc_tests); i++) {
383 mctp_prlog(MCTP_LOG_DEBUG, "begin: %s", astlpc_tests[i].name);
384 astlpc_tests[i].test();
385 mctp_prlog(MCTP_LOG_DEBUG, "end: %s\n", astlpc_tests[i].name);
386 }
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030387
Andrew Jeffery0247c732020-02-06 11:48:52 +1030388 return 0;
389}