blob: a9a839ea8d785187a9aa043d328c161a4ae791d7 [file] [log] [blame]
Patrick Williams7784c422022-11-17 07:29:11 -06001From f526797b83113cc64e3e658c22d8a5d269896a2a Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Ben Horgan <ben.horgan@arm.com>
3Date: Fri, 4 Mar 2022 16:48:14 +0000
Patrick Williams7784c422022-11-17 07:29:11 -06004Subject: [PATCH] feat: emulate cntp timer register accesses using cnthps
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
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
Patrick Williams7784c422022-11-17 07:29:11 -060022index 95cab9a5..21cca938 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040023--- a/Makefile
24+++ b/Makefile
Patrick Williams7784c422022-11-17 07:29:11 -060025@@ -60,7 +60,8 @@ CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \
Brad Bishopbec4ebc2022-08-03 09:55:16 -040026 # 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
Patrick Williams7784c422022-11-17 07:29:11 -060036index 6068d1e8..de1a414d 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040037--- 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
Patrick Williams7784c422022-11-17 07:29:11 -060048index bcf5ffce..d2df77d8 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040049--- a/src/arch/aarch64/hypervisor/cpu.c
50+++ b/src/arch/aarch64/hypervisor/cpu.c
Patrick Williams7784c422022-11-17 07:29:11 -060051@@ -98,13 +98,20 @@ void arch_regs_reset(struct vcpu *vcpu)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040052 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
Patrick Williams7784c422022-11-17 07:29:11 -060075index 4bd8a3b4..4c1b6e48 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040076--- 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.
Patrick Williams7784c422022-11-17 07:29:11 -060086@@ -1277,6 +1278,11 @@ void handle_system_register_access(uintreg_t esr_el2)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040087 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
Patrick Williams7784c422022-11-17 07:29:11 -0600100index 00000000..c30e5543
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400101--- /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
Patrick Williams7784c422022-11-17 07:29:11 -0600210index 00000000..04a43b6c
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400211--- /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
Patrick Williams7784c422022-11-17 07:29:11 -0600235index cd6778b4..55e78330 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400236--- 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
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400250