blob: a014ac332e37e24501423a565f9646400c30f4f8 [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>
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
Andrew Jeffery0247c732020-02-06 11:48:52 +103028struct mctp_binding_astlpc_mmio {
29 struct mctp_binding_astlpc astlpc;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093030 bool bmc;
Andrew Jeffery0247c732020-02-06 11:48:52 +103031
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093032 uint8_t (*kcs)[2];
Andrew Jeffery0247c732020-02-06 11:48:52 +103033
34 size_t lpc_size;
35 uint8_t *lpc;
36};
37
Andrew Jeffery0247c732020-02-06 11:48:52 +103038#define binding_to_mmio(b) \
39 container_of(b, struct mctp_binding_astlpc_mmio, astlpc)
40
Andrew Jeffery53ea1472020-05-23 21:06:24 +093041static int mctp_astlpc_mmio_kcs_read(void *data,
42 enum mctp_binding_astlpc_kcs_reg reg,
43 uint8_t *val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103044{
45 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
46
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093047 *val = (*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103048
49 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val, reg ? "status" : "data");
50
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093051 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
52 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
53 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
54 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103055
56 return 0;
57}
58
Andrew Jeffery53ea1472020-05-23 21:06:24 +093059static int mctp_astlpc_mmio_kcs_write(void *data,
60 enum mctp_binding_astlpc_kcs_reg reg,
61 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103062{
63 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093064 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103065
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093066 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
67 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103068
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093069 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
70 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
71 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
72 }
73
74 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103075 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093076 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103077 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093078 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +103079
80 mctp_prdebug("%s: 0x%hhx to %s", __func__, val, reg ? "status" : "data");
81
82 return 0;
83}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +103084int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +103085{
86 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
87
Andrew Jeffery1dbf0212020-05-12 13:53:50 +093088 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
89
Andrew Jeffery06b2cd82020-03-17 23:12:27 +103090 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +103091 assert(offset + len < mmio->lpc_size);
92
93 memcpy(buf, mmio->lpc + offset, len);
94
Andrew Jeffery0247c732020-02-06 11:48:52 +103095 return 0;
96}
97
Andrew Jeffery06b2cd82020-03-17 23:12:27 +103098int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +103099{
100 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
101
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930102 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
103
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030104 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030105 assert(offset + len < mmio->lpc_size);
106
107 memcpy(mmio->lpc + offset, buf, len);
108
Andrew Jeffery0247c732020-02-06 11:48:52 +1030109 return 0;
110}
111
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930112#define __unused __attribute__((unused))
113
114static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
115 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030116{
117 uint8_t type;
118
119 type = *(uint8_t *)msg;
120
121 mctp_prdebug("MCTP message received: len %zd, type %d",
122 len, type);
123}
124
Andrew Jeffery53ea1472020-05-23 21:06:24 +0930125static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030126 .kcs_read = mctp_astlpc_mmio_kcs_read,
127 .kcs_write = mctp_astlpc_mmio_kcs_write,
128 .lpc_read = mctp_astlpc_mmio_lpc_read,
129 .lpc_write = mctp_astlpc_mmio_lpc_write,
130};
131
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930132struct astlpc_endpoint {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030133 struct mctp_binding_astlpc_mmio mmio;
134 struct mctp_binding_astlpc *astlpc;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030135 struct mctp *mctp;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930136};
137
138static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
139 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
140 size_t lpc_size)
141{
142 /*
143 * Configure the direction of the KCS interface so we know whether to
144 * set or clear IBF or OBF on writes or reads.
145 */
146 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
147
148 ep->mctp = mctp_init();
149 assert(ep->mctp);
150
151 mctp_set_rx_all(ep->mctp, rx_message, NULL);
152
153 /* Inject KCS registers */
154 ep->mmio.kcs = kcs;
155
156 /* Inject the heap allocation as the LPC mapping */
157 ep->mmio.lpc_size = lpc_size;
158 ep->mmio.lpc = lpc_mem;
159
160 /* Initialise the binding */
Andrew Jeffery129ef932020-05-22 16:24:19 +0930161 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, lpc_mem,
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930162 &mctp_binding_astlpc_mmio_ops, &ep->mmio);
163
164 mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
165}
166
167static void endpoint_destroy(struct astlpc_endpoint *ep)
168{
169 mctp_astlpc_destroy(ep->astlpc);
170 mctp_destroy(ep->mctp);
171}
172
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930173struct astlpc_test {
174 struct astlpc_endpoint bmc;
175 struct astlpc_endpoint host;
176 uint8_t kcs[2];
177 uint8_t *lpc_mem;
178};
179
180static void network_init(struct astlpc_test *ctx)
181{
182 const size_t lpc_size = 1 * 1024 * 1024;
183
184 ctx->lpc_mem = calloc(1, lpc_size);
185 assert(ctx->lpc_mem);
186
187 /* BMC initialisation */
188 endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx->kcs,
189 ctx->lpc_mem, lpc_size);
190
191 /* Host initialisation */
192 endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &ctx->kcs,
193 ctx->lpc_mem, lpc_size);
194
195 /* BMC processes host channel init request, alerts host */
196 mctp_astlpc_poll(ctx->bmc.astlpc);
197 assert(ctx->kcs[KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
198 assert(ctx->kcs[KCS_REG_DATA] == 0xff);
199
200 /* Host dequeues channel init result */
201 mctp_astlpc_poll(ctx->host.astlpc);
202}
203
204static void network_destroy(struct astlpc_test *ctx)
205{
206 endpoint_destroy(&ctx->bmc);
207 endpoint_destroy(&ctx->host);
208 free(ctx->lpc_mem);
209}
210
Andrew Jeffery129ef932020-05-22 16:24:19 +0930211static void astlpc_assert_tx_packet(struct astlpc_endpoint *src,
212 const void *expected, size_t len)
213{
214 const size_t tx_body = src->astlpc->layout.tx.offset + 4 + 4;
215 const void *test = ((char *)src->astlpc->lpc_map) + tx_body;
216 assert(!memcmp(test, expected, len));
217}
218
Andrew Jefferye756de82020-05-22 12:30:58 +0930219static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930220{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930221 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930222 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030223 int rc;
224
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930225 /* Test harness initialisation */
226
Andrew Jeffery0247c732020-02-06 11:48:52 +1030227 memset(&msg[0], 0x5a, MCTP_BTU);
228 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
229
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930230 network_init(&ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030231
232 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930233 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030234 assert(rc == 0);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930235 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
236 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030237
Andrew Jeffery129ef932020-05-22 16:24:19 +0930238 astlpc_assert_tx_packet(&ctx.bmc, &msg[0], MCTP_BTU);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930239
Andrew Jeffery129ef932020-05-22 16:24:19 +0930240 /* Host receives the first packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930241 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030242
243 /* Host returns Rx area ownership to BMC */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930244 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
245 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
246 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030247
248 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930249 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030250 assert(rc == 0);
251
Andrew Jeffery129ef932020-05-22 16:24:19 +0930252 /* Host receives the next packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930253 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
254 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030255
Andrew Jeffery129ef932020-05-22 16:24:19 +0930256 astlpc_assert_tx_packet(&ctx.bmc, &msg[MCTP_BTU], MCTP_BTU);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030257
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930258 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930259}
260
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930261static void astlpc_test_simple_init(void)
262{
263 struct astlpc_endpoint bmc, host;
264 uint8_t kcs[2] = { 0 };
265 size_t lpc_size;
266 void *lpc_mem;
267
268 /* Test harness initialisation */
269 lpc_size = 1 * 1024 * 1024;
270 lpc_mem = calloc(1, lpc_size);
271 assert(lpc_mem);
272
273 /* Bus owner (BMC) initialisation */
274 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
275 lpc_size);
276
277 /* Verify the BMC binding was initialised */
278 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
279
280 /* Device (Host) initialisation */
281 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
282 lpc_size);
283
284 /* Host sends channel init command */
285 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
286 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
287
288 /* BMC receives host channel init request */
289 mctp_astlpc_poll(bmc.astlpc);
290
291 /* BMC sends init response */
292 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
293 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
294 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
295
296 /* Host dequeues data */
297 mctp_astlpc_poll(host.astlpc);
298
299 endpoint_destroy(&bmc);
300 endpoint_destroy(&host);
301 free(lpc_mem);
302}
303
Andrew Jefferye756de82020-05-22 12:30:58 +0930304int main(void)
305{
306 mctp_set_log_stdio(MCTP_LOG_DEBUG);
307
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930308 astlpc_test_simple_init();
Andrew Jefferye756de82020-05-22 12:30:58 +0930309 astlpc_test_packetised_message_bmc_to_host();
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030310
Andrew Jeffery0247c732020-02-06 11:48:52 +1030311 return 0;
312}