blob: 7094c8bc8f95b48b9d13c737dd79023d30df116d [file] [log] [blame]
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001From c8bd941579fb062359b683b184b851eea2ddb761 Mon Sep 17 00:00:00 2001
2From: Ben Horgan <ben.horgan@arm.com>
3Date: Fri, 4 Mar 2022 16:48:14 +0000
4Subject: [PATCH 1/5] feat: emulate cntp timer register accesses using cnthps
5
6Upstream-Status: Inappropriate [Experimental feature]
7Signed-off-by: Ben Horgan <ben.horgan@arm.com>
8Change-Id: I67508203273baf3bd8e6be2d99717028db945715
9---
10 Makefile | 3 +-
11 src/arch/aarch64/hypervisor/BUILD.gn | 1 +
12 src/arch/aarch64/hypervisor/cpu.c | 11 ++-
13 src/arch/aarch64/hypervisor/handler.c | 6 ++
14 src/arch/aarch64/hypervisor/timer_el1.c | 104 ++++++++++++++++++++++++
15 src/arch/aarch64/hypervisor/timer_el1.h | 20 +++++
16 src/arch/aarch64/msr.h | 8 ++
17 7 files changed, 150 insertions(+), 3 deletions(-)
18 create mode 100644 src/arch/aarch64/hypervisor/timer_el1.c
19 create mode 100644 src/arch/aarch64/hypervisor/timer_el1.h
20
21diff --git a/Makefile b/Makefile
22index c9fb16f..6371a8a 100644
23--- a/Makefile
24+++ b/Makefile
25@@ -59,7 +59,8 @@ CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \
26 # debug_el1.c : uses XMACROS, which checkpatch doesn't understand.
27 # perfmon.c : uses XMACROS, which checkpatch doesn't understand.
28 # feature_id.c : uses XMACROS, which checkpatch doesn't understand.
29-CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c"
30+# timer_el1.c : uses XMACROS, which checkpatch doesn't understand.
31+CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c\|src/arch/aarch64/hypervisor/timer_el1.c"
32
33 OUT ?= out/$(PROJECT)
34 OUT_DIR = out/$(PROJECT)
35diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn
36index 6068d1e..de1a414 100644
37--- a/src/arch/aarch64/hypervisor/BUILD.gn
38+++ b/src/arch/aarch64/hypervisor/BUILD.gn
39@@ -45,6 +45,7 @@ source_set("hypervisor") {
40 "handler.c",
41 "perfmon.c",
42 "psci_handler.c",
43+ "timer_el1.c",
44 "vm.c",
45 ]
46
47diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c
48index c6cebdd..cb41e6e 100644
49--- a/src/arch/aarch64/hypervisor/cpu.c
50+++ b/src/arch/aarch64/hypervisor/cpu.c
51@@ -91,13 +91,20 @@ void arch_regs_reset(struct vcpu *vcpu)
52 if (is_primary) {
53 /*
54 * cnthctl_el2 is redefined when VHE is enabled.
55- * EL1PCTEN, don't trap phys cnt access.
56- * EL1PCEN, don't trap phys timer access.
57+ * EL1PCTEN, don't trap phys cnt access. Except when in
58+ * secure world without vhe.
59+ * EL1PCEN, don't trap phys timer access. Except when in
60+ * secure world without vhe.
61 */
62 if (has_vhe_support()) {
63 cnthctl |= (1U << 10) | (1U << 11);
64 } else {
65+#if SECURE_WORLD == 1
66+ cnthctl &= ~(1U << 0);
67+ cnthctl &= ~(1U << 1);
68+#else
69 cnthctl |= (1U << 0) | (1U << 1);
70+#endif
71 }
72 }
73
74diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
75index cd64d68..c9068c5 100644
76--- a/src/arch/aarch64/hypervisor/handler.c
77+++ b/src/arch/aarch64/hypervisor/handler.c
78@@ -34,6 +34,7 @@
79 #include "psci_handler.h"
80 #include "smc.h"
81 #include "sysregs.h"
82+#include "timer_el1.h"
83
84 /**
85 * Hypervisor Fault Address Register Non-Secure.
86@@ -1276,6 +1277,11 @@ void handle_system_register_access(uintreg_t esr_el2)
87 inject_el1_unknown_exception(vcpu, esr_el2);
88 return;
89 }
90+ } else if (timer_el1_is_register_access(esr_el2)) {
91+ if (!timer_el1_process_access(vcpu, vm_id, esr_el2)) {
92+ inject_el1_unknown_exception(vcpu, esr_el2);
93+ return;
94+ }
95 } else {
96 inject_el1_unknown_exception(vcpu, esr_el2);
97 return;
98diff --git a/src/arch/aarch64/hypervisor/timer_el1.c b/src/arch/aarch64/hypervisor/timer_el1.c
99new file mode 100644
100index 0000000..c30e554
101--- /dev/null
102+++ b/src/arch/aarch64/hypervisor/timer_el1.c
103@@ -0,0 +1,104 @@
104+/*
105+ * Copyright 2022 The Hafnium Authors.
106+ *
107+ * Use of this source code is governed by a BSD-style
108+ * license that can be found in the LICENSE file or at
109+ * https://opensource.org/licenses/BSD-3-Clause.
110+ */
111+
112+#include "timer_el1.h"
113+
114+#include "hf/dlog.h"
115+
116+#include "msr.h"
117+#include "sysregs.h"
118+
119+/*
120+ * Physical timer (CNTP) register encodings as defined in
121+ * table D13-8 of the ARMv8 ARM (DDI0487F).
122+ * TYPE, op0, op1, crn, crm, op2
123+ * The register names are the concatenation of
124+ * "CNTP_", TYPE and "_EL2".
125+ */
126+#define CNTP_REGISTERS \
127+ X(CTL, 3, 3, 14, 2, 1) \
128+ X(CVAL, 3, 3, 14, 2, 2) \
129+ X(TVAL, 3, 3, 14, 2, 0) \
130+
131+bool timer_el1_is_register_access(uintreg_t esr)
132+{
133+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
134+ bool is_timer_access;
135+ switch (sys_register) {
136+#define X(type, op0, op1, crn, crm, op2) \
137+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
138+ is_timer_access = true; \
139+ break;
140+ CNTP_REGISTERS
141+#undef X
142+ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)):
143+ is_timer_access = true;
144+ break;
145+ default:
146+ is_timer_access = false;
147+ }
148+
149+ return is_timer_access;
150+}
151+
152+/* Accesses to CNTP timer emulated with CNTHPS */
153+bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
154+ uintreg_t esr)
155+{
156+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
157+ uintreg_t rt_register = GET_ISS_RT(esr);
158+ uintreg_t value;
159+
160+ if (ISS_IS_READ(esr)) {
161+ switch (sys_register) {
162+#define X(type, op0, op1, crn, crm, op2) \
163+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
164+ value = read_msr(MSR_CNTHPS_##type##_EL2); \
165+ vcpu->regs.r[rt_register] = value; \
166+ break;
167+ CNTP_REGISTERS
168+#undef X
169+ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)):
170+ value = read_msr(cntpct_el0);
171+ vcpu->regs.r[rt_register] = value;
172+ break;
173+ default:
174+ dlog_notice(
175+ "Unsupported timer register "
176+ "read: "
177+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
178+ "rt=%d.\n",
179+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
180+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
181+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
182+ break;
183+ }
184+ } else {
185+ value = vcpu->regs.r[rt_register];
186+ switch (sys_register) {
187+#define X(type, op0, op1, crn, crm, op2) \
188+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
189+ write_msr(MSR_CNTHPS_##type##_EL2, value); \
190+ break;
191+ CNTP_REGISTERS
192+#undef X
193+ default:
194+ dlog_notice(
195+ "Unsupported timer register "
196+ "write: "
197+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
198+ "rt=%d, value=%d.\n",
199+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
200+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
201+ GET_ISS_OP2(esr), GET_ISS_RT(esr), value);
202+ break;
203+ }
204+ }
205+
206+ return true;
207+}
208diff --git a/src/arch/aarch64/hypervisor/timer_el1.h b/src/arch/aarch64/hypervisor/timer_el1.h
209new file mode 100644
210index 0000000..04a43b6
211--- /dev/null
212+++ b/src/arch/aarch64/hypervisor/timer_el1.h
213@@ -0,0 +1,20 @@
214+/*
215+ * Copyright 2022 The Hafnium Authors.
216+ *
217+ * Use of this source code is governed by a BSD-style
218+ * license that can be found in the LICENSE file or at
219+ * https://opensource.org/licenses/BSD-3-Clause.
220+ */
221+
222+#pragma once
223+
224+#include "hf/arch/types.h"
225+
226+#include "hf/cpu.h"
227+
228+#include "vmapi/hf/ffa.h"
229+
230+bool timer_el1_is_register_access(uintreg_t esr);
231+
232+bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
233+ uintreg_t esr);
234diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h
235index cd6778b..55e7833 100644
236--- a/src/arch/aarch64/msr.h
237+++ b/src/arch/aarch64/msr.h
238@@ -126,3 +126,11 @@
239 #define MSR_ELR_EL12 S3_5_C4_C0_1
240
241 #endif
242+
243+/*
244+ * Secure EL2 Physical timer (CNTHPS) register encodings as defined in
245+ * table D13-8 of the ARMv8 ARM (DDI0487F).
246+ */
247+#define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1
248+#define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2
249+#define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0
250--
2512.17.1
252