blob: 14fe1e1de0db423b6a7abb589260d8427e20ea3a [file] [log] [blame]
Fuad Tabbaa48d1222019-12-09 15:42:32 +00001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "hf/dlog.h"
18
19#include "vmapi/hf/call.h"
20
21#include "../msr.h"
Fuad Tabbab86325a2020-01-10 13:38:15 +000022#include "sysregs.h"
Fuad Tabbaa48d1222019-12-09 15:42:32 +000023#include "test/hftest.h"
24
25/**
26 * Tracks the number of times the exception handler has been invoked.
27 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000028static int exception_handler_exception_count = 0;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000029
30/**
31 * Sends the number of exceptions handled to the Primary VM.
32 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000033void exception_handler_send_exception_count(void)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000034{
35 void *send_buf = SERVICE_SEND_BUFFER();
36
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000037 dlog("Sending exception_count %d to primary VM\n",
38 exception_handler_exception_count);
Fuad Tabbaa48d1222019-12-09 15:42:32 +000039 memcpy_s(send_buf, SPCI_MSG_PAYLOAD_MAX,
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000040 (const void *)&exception_handler_exception_count,
41 sizeof(exception_handler_exception_count));
Fuad Tabbaa48d1222019-12-09 15:42:32 +000042 EXPECT_EQ(spci_msg_send(hf_vm_get_id(), HF_PRIMARY_VM_ID,
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000043 sizeof(exception_handler_exception_count), 0)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000044 .func,
45 SPCI_SUCCESS_32);
46}
47
48/**
49 * Receives the number of exceptions handled.
50 */
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000051int exception_handler_receive_exception_count(
Fuad Tabbaa48d1222019-12-09 15:42:32 +000052 const struct spci_value *send_res,
53 const struct spci_memory_region *recv_buf)
54{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000055 int exception_count = *((const int *)recv_buf);
Fuad Tabbaa48d1222019-12-09 15:42:32 +000056
57 EXPECT_EQ(send_res->func, SPCI_MSG_SEND_32);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000058 EXPECT_EQ(spci_msg_send_size(*send_res), sizeof(exception_count));
Fuad Tabbaa48d1222019-12-09 15:42:32 +000059 EXPECT_EQ(spci_rx_release().func, SPCI_SUCCESS_32);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000060 return exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000061}
62
63/**
64 * EL1 exception handler to use in unit test VMs.
65 * Skips the instruction that triggered the exception.
66 */
67bool exception_handler_skip_instruction(void)
68{
69 dlog("%s function is triggered!\n", __func__);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000070 ++exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000071
72 /* Skip instruction that triggered the exception. */
73 uint64_t next_pc = read_msr(elr_el1);
74 next_pc += 4UL;
75 write_msr(elr_el1, next_pc);
76
77 /* Indicate that elr_el1 should not be restored. */
78 return true;
79}
80
81/**
82 * EL1 exception handler to use in unit test VMs.
83 * Yields control back to the hypervisor and sends the number of exceptions.
84 */
Fuad Tabbab86325a2020-01-10 13:38:15 +000085static bool exception_handler_yield(void)
Fuad Tabbaa48d1222019-12-09 15:42:32 +000086{
87 dlog("%s function is triggered!\n", __func__);
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000088 ++exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +000089
Fuad Tabbab0ef2a42019-12-19 11:19:25 +000090 exception_handler_send_exception_count();
Fuad Tabbaa48d1222019-12-09 15:42:32 +000091
92 /* Indicate that elr_el1 should not be restored. */
93 return true;
94}
95
96/**
Fuad Tabbab86325a2020-01-10 13:38:15 +000097 * EL1 exception handler to use in unit test VMs.
98 * Yields control back to the hypervisor and sends the number of exceptions.
99 * Asserts that the Exception Class is Unknown.
100 */
101bool exception_handler_yield_unknown(void)
102{
103 uintreg_t esr_el1 = read_msr(ESR_EL1);
104 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_UNKNOWN);
105 return exception_handler_yield();
106}
107
108/**
109 * EL1 exception handler to use in unit test VMs.
110 * Yields control back to the hypervisor and sends the number of exceptions.
111 * Asserts that the Exception Class is Data Abort (same EL).
112 */
113bool exception_handler_yield_data_abort(void)
114{
115 uintreg_t esr_el1 = read_msr(ESR_EL1);
116 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_DATA_ABORT_SAME_EL);
117 return exception_handler_yield();
118}
119
120/**
121 * EL1 exception handler to use in unit test VMs.
122 * Yields control back to the hypervisor and sends the number of exceptions.
123 * Asserts that the Exception Class is Instruction Abort (same EL).
124 */
125bool exception_handler_yield_instruction_abort(void)
126{
127 uintreg_t esr_el1 = read_msr(ESR_EL1);
128 EXPECT_EQ(GET_ESR_EC(esr_el1), EC_INSTRUCTION_ABORT_SAME_EL);
129 return exception_handler_yield();
130}
131
132/**
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000133 * Returns the number of times the instruction handler was invoked.
134 */
135int exception_handler_get_num(void)
136{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +0000137 return exception_handler_exception_count;
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000138}
139
140/**
141 * Resets the number of exceptions counter;
142 */
143void exception_handler_reset(void)
144{
Fuad Tabbab0ef2a42019-12-19 11:19:25 +0000145 exception_handler_exception_count = 0;
Fuad Tabbaa48d1222019-12-09 15:42:32 +0000146}