blob: c3c333412c27887cc777c3827fd7cc4dfaef2b4b [file] [log] [blame]
Fuad Tabbaa48d1222019-12-09 15:42:32 +00001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
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.
Fuad Tabbaa48d1222019-12-09 15:42:32 +00007 */
8
9#include "hf/dlog.h"
10
11#include "vmapi/hf/call.h"
12
13#include "../msr.h"
Fuad Tabbab86325a2020-01-10 13:38:15 +000014#include "sysregs.h"
Fuad Tabbaa48d1222019-12-09 15:42:32 +000015#include "test/hftest.h"
16
17/**
18 * Tracks the number of times the exception handler has been invoked.
19 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000020static int exception_handler_exception_count = 0;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000021
22/**
23 * Sends the number of exceptions handled to the Primary VM.
24 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000025void exception_handler_send_exception_count(void)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000026{
27 void *send_buf = SERVICE_SEND_BUFFER();
28
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000029 dlog("Sending exception_count %d to primary VM\n",
30 exception_handler_exception_count);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010031 memcpy_s(send_buf, FFA_MSG_PAYLOAD_MAX,
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000032 (const void *)&exception_handler_exception_count,
33 sizeof(exception_handler_exception_count));
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010034 EXPECT_EQ(ffa_msg_send(hf_vm_get_id(), HF_PRIMARY_VM_ID,
35 sizeof(exception_handler_exception_count), 0)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000036 .func,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010037 FFA_SUCCESS_32);
Fuad Tabbaa48d1222019-12-09 15:42:32 +000038}
39
40/**
41 * Receives the number of exceptions handled.
42 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000043int exception_handler_receive_exception_count(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010044 const struct ffa_value *send_res,
45 const struct ffa_memory_region *recv_buf)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000046{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000047 int exception_count = *((const int *)recv_buf);
Fuad Tabbaa48d1222019-12-09 15:42:32 +000048
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010049 EXPECT_EQ(send_res->func, FFA_MSG_SEND_32);
50 EXPECT_EQ(ffa_msg_send_size(*send_res), sizeof(exception_count));
51 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000052 return exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000053}
54
55/**
56 * EL1 exception handler to use in unit test VMs.
57 * Skips the instruction that triggered the exception.
58 */
59bool exception_handler_skip_instruction(void)
60{
61 dlog("%s function is triggered!\n", __func__);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000062 ++exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000063
64 /* Skip instruction that triggered the exception. */
65 uint64_t next_pc = read_msr(elr_el1);
66 next_pc += 4UL;
67 write_msr(elr_el1, next_pc);
68
69 /* Indicate that elr_el1 should not be restored. */
70 return true;
71}
72
73/**
74 * EL1 exception handler to use in unit test VMs.
75 * Yields control back to the hypervisor and sends the number of exceptions.
76 */
Fuad Tabbab86325a2020-01-10 13:38:15 +000077static bool exception_handler_yield(void)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000078{
79 dlog("%s function is triggered!\n", __func__);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000080 ++exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000081
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000082 exception_handler_send_exception_count();
Fuad Tabbaa48d1222019-12-09 15:42:32 +000083
84 /* Indicate that elr_el1 should not be restored. */
85 return true;
86}
87
88/**
Fuad Tabbab86325a2020-01-10 13:38:15 +000089 * EL1 exception handler to use in unit test VMs.
90 * Yields control back to the hypervisor and sends the number of exceptions.
91 * Asserts that the Exception Class is Unknown.
92 */
93bool exception_handler_yield_unknown(void)
94{
95 uintreg_t esr_el1 = read_msr(ESR_EL1);
Fuad Tabbac3847c72020-08-11 09:32:25 +010096 uintreg_t far_el1 = read_msr(FAR_EL1);
97
Fuad Tabbab86325a2020-01-10 13:38:15 +000098 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_UNKNOWN);
Fuad Tabbac3847c72020-08-11 09:32:25 +010099
100 /*
101 * For unknown exceptions, the value of far_el1 is UNKNOWN.
102 * Hafnium sets it to 0.
103 */
104 EXPECT_EQ(far_el1, 0);
105
Fuad Tabbab86325a2020-01-10 13:38:15 +0000106 return exception_handler_yield();
107}
108
109/**
110 * EL1 exception handler to use in unit test VMs.
111 * Yields control back to the hypervisor and sends the number of exceptions.
112 * Asserts that the Exception Class is Data Abort (same EL).
113 */
114bool exception_handler_yield_data_abort(void)
115{
116 uintreg_t esr_el1 = read_msr(ESR_EL1);
Fuad Tabbac3847c72020-08-11 09:32:25 +0100117 uintreg_t far_el1 = read_msr(FAR_EL1);
118
Fuad Tabbab86325a2020-01-10 13:38:15 +0000119 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_DATA_ABORT_SAME_EL);
Fuad Tabbac3847c72020-08-11 09:32:25 +0100120 EXPECT_NE(far_el1, 0);
121
Fuad Tabbab86325a2020-01-10 13:38:15 +0000122 return exception_handler_yield();
123}
124
125/**
126 * EL1 exception handler to use in unit test VMs.
127 * Yields control back to the hypervisor and sends the number of exceptions.
128 * Asserts that the Exception Class is Instruction Abort (same EL).
129 */
130bool exception_handler_yield_instruction_abort(void)
131{
132 uintreg_t esr_el1 = read_msr(ESR_EL1);
Fuad Tabbac3847c72020-08-11 09:32:25 +0100133 uintreg_t far_el1 = read_msr(FAR_EL1);
134
Fuad Tabbab86325a2020-01-10 13:38:15 +0000135 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_INSTRUCTION_ABORT_SAME_EL);
Fuad Tabbac3847c72020-08-11 09:32:25 +0100136 EXPECT_NE(far_el1, 0);
137
Fuad Tabbab86325a2020-01-10 13:38:15 +0000138 return exception_handler_yield();
139}
140
141/**
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000142 * Returns the number of times the instruction handler was invoked.
143 */
144int exception_handler_get_num(void)
145{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +0000146 return exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000147}
148
149/**
150 * Resets the number of exceptions counter;
151 */
152void exception_handler_reset(void)
153{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +0000154 exception_handler_exception_count = 0;
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000155}