blob: 25df46622445c34dd737d863e7f36a5eab9653df [file] [log] [blame]
J-Alves35e61922021-05-06 10:01:05 +01001/*
2 * Copyright 2021 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
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080012#include "hf/fdt_handler.h"
13#include "hf/ffa.h"
14#include "hf/memiter.h"
J-Alves35e61922021-05-06 10:01:05 +010015#include "hf/mm.h"
16#include "hf/std.h"
17
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080018#include "vmapi/hf/call.h"
19
J-Alves35e61922021-05-06 10:01:05 +010020#include "test/hftest.h"
21#include "test/hftest_impl.h"
22
23HFTEST_ENABLE();
24
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080025extern struct hftest_test hftest_begin[];
26extern struct hftest_test hftest_end[];
27
28static alignas(HF_MAILBOX_SIZE) uint8_t send[HF_MAILBOX_SIZE];
29static alignas(HF_MAILBOX_SIZE) uint8_t recv[HF_MAILBOX_SIZE];
30
31static hf_ipaddr_t send_addr = (hf_ipaddr_t)send;
32static hf_ipaddr_t recv_addr = (hf_ipaddr_t)recv;
33
J-Alves35e61922021-05-06 10:01:05 +010034static struct hftest_context global_context;
35
36struct hftest_context *hftest_get_context(void)
37{
38 return &global_context;
39}
40
41noreturn void abort(void)
42{
43 HFTEST_LOG("Service contained failures.");
44 /* Cause a fault, as a secondary/SP can't power down the machine. */
45 *((volatile uint8_t *)1) = 1;
46
47 /* This should never be reached, but to make the compiler happy... */
48 for (;;) {
49 }
50}
Raghu Krishnamurthy50af6602021-12-12 15:23:09 -080051
52/** Find the service with the name passed in the arguments. */
53static hftest_test_fn find_service(struct memiter *args)
54{
55 struct memiter service_name;
56 struct hftest_test *test;
57
58 if (!memiter_parse_str(args, &service_name)) {
59 return NULL;
60 }
61
62 for (test = hftest_begin; test < hftest_end; ++test) {
63 if (test->kind == HFTEST_KIND_SERVICE &&
64 memiter_iseq(&service_name, test->name)) {
65 return test->fn;
66 }
67 }
68
69 return NULL;
70}
71
72noreturn void hftest_service_main(const void *fdt_ptr)
73{
74 struct memiter args;
75 hftest_test_fn service;
76 struct hftest_context *ctx;
77 struct ffa_value ret;
78 struct fdt fdt;
79
80 /* Prepare the context. */
81
82 /* Set up the mailbox. */
83 ffa_rxtx_map(send_addr, recv_addr);
84
85 /* Receive the name of the service to run. */
86 ret = ffa_msg_wait();
87 ASSERT_EQ(ret.func, FFA_MSG_SEND_32);
88 memiter_init(&args, recv, ffa_msg_send_size(ret));
89 service = find_service(&args);
90 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
91
92 /* Check the service was found. */
93 if (service == NULL) {
94 HFTEST_LOG_FAILURE();
95 HFTEST_LOG(HFTEST_LOG_INDENT
96 "Unable to find requested service");
97 abort();
98 }
99
100 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
101 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
102 abort();
103 }
104
105 /* Clean the context. */
106 ctx = hftest_get_context();
107 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
108 ctx->abort = abort;
109 ctx->send = send;
110 ctx->recv = recv;
111 if (!fdt_get_memory_size(&fdt, &ctx->memory_size)) {
112 HFTEST_LOG_FAILURE();
113 HFTEST_LOG(HFTEST_LOG_INDENT
114 "No entry in the FDT on memory size details");
115 abort();
116 }
117
118 /* Pause so the next time cycles are given the service will be run. */
119 ffa_yield();
120
121 /* Let the service run. */
122 service();
123
124 /* Cleanly handle it if the service returns. */
125 if (ctx->failures) {
126 abort();
127 }
128
129 for (;;) {
130 /* Hang if the service returns. */
131 }
132}