blob: 6d0cb3c927e99379ed9e01390c3ccf410af0d2f9 [file] [log] [blame]
Andrew Scullf0551c82018-12-15 20:38:47 +00001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scullf0551c82018-12-15 20:38:47 +00003 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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.
Andrew Scullf0551c82018-12-15 20:38:47 +00007 */
8
9#include <stdalign.h>
10#include <stdint.h>
11
Raghu Krishnamurthyfffe7612020-12-08 14:57:28 -080012#include "hf/arch/vm/interrupts.h"
13
Fuad Tabba50469e02020-06-30 15:14:28 +010014#include "hf/fdt_handler.h"
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010015#include "hf/ffa.h"
Andrew Scullf0551c82018-12-15 20:38:47 +000016#include "hf/memiter.h"
David Brazdil711fbe92019-08-06 13:39:58 +010017#include "hf/mm.h"
Andrew Scull8d9e1212019-04-05 13:52:55 +010018#include "hf/std.h"
Andrew Scullf0551c82018-12-15 20:38:47 +000019
20#include "vmapi/hf/call.h"
21
Andrew Walbran1e7c7742019-12-13 17:10:02 +000022#include "test/hftest.h"
Andrew Scullf0551c82018-12-15 20:38:47 +000023
24alignas(4096) uint8_t kstack[4096];
25
26HFTEST_ENABLE();
27
28extern struct hftest_test hftest_begin[];
29extern struct hftest_test hftest_end[];
30
31static alignas(HF_MAILBOX_SIZE) uint8_t send[HF_MAILBOX_SIZE];
32static alignas(HF_MAILBOX_SIZE) uint8_t recv[HF_MAILBOX_SIZE];
33
34static hf_ipaddr_t send_addr = (hf_ipaddr_t)send;
35static hf_ipaddr_t recv_addr = (hf_ipaddr_t)recv;
36
37static struct hftest_context global_context;
38
39struct hftest_context *hftest_get_context(void)
40{
41 return &global_context;
42}
43
44/** Find the service with the name passed in the arguments. */
45static hftest_test_fn find_service(struct memiter *args)
46{
47 struct memiter service_name;
48 struct hftest_test *test;
49
50 if (!memiter_parse_str(args, &service_name)) {
51 return NULL;
52 }
53
54 for (test = hftest_begin; test < hftest_end; ++test) {
55 if (test->kind == HFTEST_KIND_SERVICE &&
56 memiter_iseq(&service_name, test->name)) {
57 return test->fn;
58 }
59 }
60
61 return NULL;
62}
63
Andrew Sculla59f9bc2019-04-03 15:24:35 +010064noreturn void abort(void)
Andrew Scullf0551c82018-12-15 20:38:47 +000065{
66 HFTEST_LOG("Service contained failures.");
Andrew Walbran2432e672019-04-17 15:23:38 +010067 /* Cause a fault, as a secondary can't power down the machine. */
68 *((volatile uint8_t *)1) = 1;
69
70 /* This should never be reached, but to make the compiler happy... */
Andrew Scullf0551c82018-12-15 20:38:47 +000071 for (;;) {
Andrew Scullf0551c82018-12-15 20:38:47 +000072 }
73}
74
Raghu Krishnamurthy1c264f32021-02-27 20:37:13 -080075noreturn void hftest_service_main(const void *fdt_ptr)
Andrew Scullf0551c82018-12-15 20:38:47 +000076{
77 struct memiter args;
78 hftest_test_fn service;
Andrew Scullf0551c82018-12-15 20:38:47 +000079 struct hftest_context *ctx;
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010080 struct ffa_value ret;
Fuad Tabba50469e02020-06-30 15:14:28 +010081 struct fdt fdt;
Andrew Scullf0551c82018-12-15 20:38:47 +000082
83 /* Prepare the context. */
84
85 /* Set up the mailbox. */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010086 ffa_rxtx_map(send_addr, recv_addr);
Andrew Scullf0551c82018-12-15 20:38:47 +000087
88 /* Receive the name of the service to run. */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010089 ret = ffa_msg_wait();
90 ASSERT_EQ(ret.func, FFA_MSG_SEND_32);
91 memiter_init(&args, recv, ffa_msg_send_size(ret));
Andrew Scullf0551c82018-12-15 20:38:47 +000092 service = find_service(&args);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010093 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scullf0551c82018-12-15 20:38:47 +000094
95 /* Check the service was found. */
96 if (service == NULL) {
97 HFTEST_LOG_FAILURE();
98 HFTEST_LOG(HFTEST_LOG_INDENT
99 "Unable to find requested service");
Fuad Tabba50469e02020-06-30 15:14:28 +0100100 abort();
101 }
102
103 if (!fdt_struct_from_ptr(fdt_ptr, &fdt)) {
104 HFTEST_LOG(HFTEST_LOG_INDENT "Unable to access the FDT");
105 abort();
Andrew Scullf0551c82018-12-15 20:38:47 +0000106 }
107
108 /* Clean the context. */
109 ctx = hftest_get_context();
Andrew Scull2b5fbad2019-04-05 13:55:56 +0100110 memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
Andrew Scullf0551c82018-12-15 20:38:47 +0000111 ctx->abort = abort;
Andrew Walbran70bc8622019-10-07 14:15:58 +0100112 ctx->send = send;
113 ctx->recv = recv;
Fuad Tabba50469e02020-06-30 15:14:28 +0100114 if (!fdt_get_memory_size(&fdt, &ctx->memory_size)) {
115 HFTEST_LOG_FAILURE();
116 HFTEST_LOG(HFTEST_LOG_INDENT
117 "No entry in the FDT on memory size details");
118 abort();
119 }
Andrew Scullf0551c82018-12-15 20:38:47 +0000120
121 /* Pause so the next time cycles are given the service will be run. */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100122 ffa_yield();
Andrew Scullf0551c82018-12-15 20:38:47 +0000123
124 /* Let the service run. */
125 service();
126
127 /* Cleanly handle it if the service returns. */
128 if (ctx->failures) {
129 abort();
130 }
131
132 for (;;) {
133 /* Hang if the service returns. */
134 }
135}
Raghu Krishnamurthy1c264f32021-02-27 20:37:13 -0800136
137noreturn void kmain(const void *fdt_ptr)
138{
139 /*
140 * Initialize the stage-1 MMU and identity-map the entire address space.
141 */
142 if (!hftest_mm_init()) {
143 HFTEST_LOG_FAILURE();
144 HFTEST_LOG(HFTEST_LOG_INDENT "Memory initialization failed");
145 abort();
146 }
147
148 /* Setup basic exception handling. */
149 exception_setup(NULL, NULL);
150
151 hftest_service_main(fdt_ptr);
152}