1 /*
2  * Copyright 2019 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include <stdalign.h>
10 #include <stdint.h>
11 
12 #include "hf/ffa.h"
13 #include "hf/memiter.h"
14 #include "hf/std.h"
15 
16 #include "vmapi/hf/call.h"
17 #include "vmapi/hf/transport.h"
18 
19 #include "test/hftest.h"
20 #include "test/vmapi/ffa.h"
21 
22 alignas(4096) uint8_t kstack[4096];
23 
24 static alignas(HF_MAILBOX_SIZE) uint8_t send[HF_MAILBOX_SIZE];
25 static alignas(HF_MAILBOX_SIZE) uint8_t recv[HF_MAILBOX_SIZE];
26 
27 static hf_ipaddr_t send_addr = (hf_ipaddr_t)send;
28 static hf_ipaddr_t recv_addr = (hf_ipaddr_t)recv;
29 
30 static struct hftest_context global_context;
31 
hftest_get_context(void)32 struct hftest_context *hftest_get_context(void)
33 {
34 	return &global_context;
35 }
36 
abort(void)37 noreturn void abort(void)
38 {
39 	HFTEST_LOG("Service contained failures.");
40 	/* Cause a fault, as a secondary can't power down the machine. */
41 	*((volatile uint8_t *)1) = 1;
42 
43 	/* This should never be reached, but to make the compiler happy... */
44 	for (;;) {
45 	}
46 }
47 
swap(uint64_t * a,uint64_t * b)48 static void swap(uint64_t *a, uint64_t *b)
49 {
50 	uint64_t t = *a;
51 	*a = *b;
52 	*b = t;
53 }
54 
kmain(size_t memory_size)55 noreturn void kmain(size_t memory_size)
56 {
57 	struct hftest_context *ctx;
58 
59 	/* Prepare the context. */
60 
61 	/* Set up the mailbox. */
62 	ffa_rxtx_map(send_addr, recv_addr);
63 
64 	EXPECT_FFA_ERROR(ffa_rx_release(), FFA_DENIED);
65 
66 	/* Clean the context. */
67 	ctx = hftest_get_context();
68 	memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
69 	ctx->abort = abort;
70 	ctx->send = send;
71 	ctx->recv = recv;
72 	ctx->memory_size = memory_size;
73 
74 	for (;;) {
75 		struct ffa_value ret;
76 
77 		/* Receive the packet. */
78 		ret = ffa_msg_wait();
79 		EXPECT_EQ(ret.func, FFA_MSG_SEND_32);
80 		EXPECT_LE(ffa_msg_send_size(ret), FFA_MSG_PAYLOAD_MAX);
81 
82 		/* Echo the message back to the sender. */
83 		memcpy_s(send, FFA_MSG_PAYLOAD_MAX, recv,
84 			 ffa_msg_send_size(ret));
85 
86 		/* Swap the socket's source and destination ports */
87 		struct hf_msg_hdr *hdr = (struct hf_msg_hdr *)send;
88 		swap(&(hdr->src_port), &(hdr->dst_port));
89 
90 		/* Swap the destination and source ids. */
91 		ffa_id_t dst_id = ffa_sender(ret);
92 		ffa_id_t src_id = ffa_receiver(ret);
93 
94 		EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
95 		EXPECT_EQ(
96 			ffa_msg_send(src_id, dst_id, ffa_msg_send_size(ret), 0)
97 				.func,
98 			FFA_SUCCESS_32);
99 	}
100 }
101