blob: 53049cab5a6f09536f36c24d1310657bb83dc4d8 [file] [log] [blame]
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -06001/*
2 * Copyright 2023 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
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -06009#include "hf/arch/barriers.h"
10
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060011#include "ffa_secure_partitions.h"
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060012#include "msr.h"
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060013#include "partition_services.h"
14#include "sp_helpers.h"
15
16#define SP_SLEEP_TIME 400U
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060017#define NS_SLEEP_TIME 200U
18
19static inline uint64_t syscounter_read(void)
20{
21 isb();
22 return read_msr(cntvct_el0);
23}
24
25static void waitus(uint64_t us)
26{
27 uint64_t start_count_val = syscounter_read();
28 uint64_t wait_cycles = (us * read_msr(cntfrq_el0)) / 1000000;
29
30 while ((syscounter_read() - start_count_val) < wait_cycles) {
31 /* Busy wait... */;
32 }
33}
34
35static void waitms(uint64_t ms)
36{
37 while (ms > 0) {
38 waitus(1000);
39 ms--;
40 }
41}
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060042
43static void configure_trusted_wdog_interrupt(ffa_vm_id_t source,
44 ffa_vm_id_t dest, bool enable)
45{
46 struct ffa_value res;
47
48 res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
49 enable, 0);
50
51 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
52 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
53}
54
55static void enable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
56{
57 configure_trusted_wdog_interrupt(source, dest, true);
58}
59
60static void disable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
61{
62 configure_trusted_wdog_interrupt(source, dest, false);
63}
64
65static void enable_trigger_trusted_wdog_timer(ffa_vm_id_t own_id,
66 ffa_vm_id_t receiver_id,
67 uint32_t timer_ms)
68{
69 struct ffa_value res;
70
71 /* Enable trusted watchdog interrupt as vIRQ in the secure side. */
72 enable_trusted_wdog_interrupt(own_id, receiver_id);
73
74 res = sp_twdog_map_cmd_send(own_id, receiver_id);
75
76 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
77 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
78
79 /*
80 * Send a message to the SP through direct messaging requesting it to
81 * start the trusted watchdog timer.
82 */
83 res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
84
85 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
86 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
87}
88
89static void check_and_disable_trusted_wdog_timer(ffa_vm_id_t own_id,
90 ffa_vm_id_t receiver_id)
91{
92 struct ffa_value res;
93
94 /* Check for the last serviced secure virtual interrupt. */
95 res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
96
97 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
98 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
99
100 /* Make sure Trusted Watchdog timer interrupt was serviced. */
101 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
102
103 /* Disable Trusted Watchdog interrupt. */
104 disable_trusted_wdog_interrupt(own_id, receiver_id);
105}
106
107/*
108 * Test secure interrupt handling while the Secure Partition is in RUNNING
109 * state.
110 */
111TEST(secure_interrupts, sp_running)
112{
113 struct ffa_value res;
114 ffa_vm_id_t own_id = hf_vm_get_id();
115 struct ffa_partition_info *service2_info = service2();
116 const ffa_vm_id_t receiver_id = service2_info->vm_id;
117
118 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
119
120 /* Send request to the SP to sleep. */
121 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME);
122
123 /*
124 * Secure interrupt should trigger during this time, SP will handle the
125 * trusted watchdog timer interrupt.
126 */
127 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
128 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
129
130 /* Make sure elapsed time not less than sleep time. */
131 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
132
133 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
134}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600135
136/*
137 * Test secure interrupt handling while the Secure Partition is in WAITING
138 * state.
139 */
140TEST(secure_interrupts, sp_waiting)
141{
142 ffa_vm_id_t own_id = hf_vm_get_id();
143 struct ffa_partition_info *service2_info = service2();
144 const ffa_vm_id_t receiver_id = service2_info->vm_id;
145 uint64_t time1;
146 volatile uint64_t time_lapsed;
147 uint64_t timer_freq = read_msr(cntfrq_el0);
148
149 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
150 time1 = syscounter_read();
151
152 /*
153 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
154 * during this time.
155 */
156 waitms(NS_SLEEP_TIME);
157
158 /* Lapsed time should be at least equal to sleep time. */
159 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
160
161 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
162
163 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
164}