blob: 95f1651a842bcc38e81408094ae906e23cc189c4 [file] [log] [blame]
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001From 380f2cf944dd5db36c168a11d31a46ad14cdcb6d Mon Sep 17 00:00:00 2001
2From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
3Date: Tue, 26 Apr 2022 14:43:58 +0100
4Subject: [PATCH 4/5] feat: emulate interrupt controller register access
5
6This emulates ICC_SGI1R_EL1 and ICC_IGRPEN1_EL1 register
7
8Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
9Change-Id: I0c11f034f3676067597461a183a341c809adcaa4
10Upstream-Status: Inappropriate [Experimental feature]
11---
12 src/arch/aarch64/hypervisor/handler.c | 5 ++
13 src/arch/aarch64/hypervisor/perfmon.c | 84 +++++++++++++++++++++++++++
14 src/arch/aarch64/hypervisor/perfmon.h | 5 ++
15 src/arch/aarch64/msr.h | 3 +
16 4 files changed, 97 insertions(+)
17
18diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
19index c9068c5..b9aa5d8 100644
20--- a/src/arch/aarch64/hypervisor/handler.c
21+++ b/src/arch/aarch64/hypervisor/handler.c
22@@ -1282,6 +1282,11 @@ void handle_system_register_access(uintreg_t esr_el2)
23 inject_el1_unknown_exception(vcpu, esr_el2);
24 return;
25 }
26+ } else if (intr_ctrl_is_register_access(esr_el2)) {
27+ if (!intr_ctrl_el1_process_access(vcpu, vm_id, esr_el2)) {
28+ inject_el1_unknown_exception(vcpu, esr_el2);
29+ return;
30+ }
31 } else {
32 inject_el1_unknown_exception(vcpu, esr_el2);
33 return;
34diff --git a/src/arch/aarch64/hypervisor/perfmon.c b/src/arch/aarch64/hypervisor/perfmon.c
35index f13b035..05e216c 100644
36--- a/src/arch/aarch64/hypervisor/perfmon.c
37+++ b/src/arch/aarch64/hypervisor/perfmon.c
38@@ -116,6 +116,10 @@
39 X(PMEVTYPER30_EL0 , 3, 3, 14, 15, 6) \
40 X(PMCCFILTR_EL0 , 3, 3, 14, 15, 7)
41
42+#define INTR_CTRL_REGISTERS \
43+ X(ICC_IGRPEN1_EL1 , 3, 0, 12, 12, 7) \
44+ X(ICC_SGI1R_EL1 , 3, 0, 12, 11, 5) \
45+
46 /* clang-format on */
47
48 /**
49@@ -232,3 +236,83 @@ uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id)
50
51 return 0;
52 }
53+
54+bool intr_ctrl_is_register_access(uintreg_t esr)
55+{
56+ uintreg_t op0 = GET_ISS_OP0(esr);
57+ uintreg_t op1 = GET_ISS_OP1(esr);
58+ uintreg_t crn = GET_ISS_CRN(esr);
59+ uintreg_t crm = GET_ISS_CRM(esr);
60+
61+ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 12) {
62+ return true;
63+ }
64+
65+ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 11) {
66+ return true;
67+ }
68+
69+ return false;
70+}
71+
72+bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
73+ uintreg_t esr)
74+{
75+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
76+ uintreg_t rt_register = GET_ISS_RT(esr);
77+ uintreg_t value;
78+
79+ /* +1 because Rt can access register XZR */
80+ CHECK(rt_register < NUM_GP_REGS + 1);
81+
82+ if (ISS_IS_READ(esr)) {
83+ switch (sys_register) {
84+#define X(reg_name, op0, op1, crn, crm, op2) \
85+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
86+ value = read_msr(reg_name); \
87+ break;
88+ INTR_CTRL_REGISTERS
89+#undef X
90+ default:
91+ value = vcpu->regs.r[rt_register];
92+ dlog_notice(
93+ "Unsupported interrupt control register "
94+ "read: "
95+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
96+ "rt=%d.\n",
97+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
98+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
99+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
100+ break;
101+ }
102+ if (rt_register != RT_REG_XZR) {
103+ vcpu->regs.r[rt_register] = value;
104+ }
105+ } else {
106+ if (rt_register != RT_REG_XZR) {
107+ value = vcpu->regs.r[rt_register];
108+ } else {
109+ value = 0;
110+ }
111+ switch (sys_register) {
112+#define X(reg_name, op0, op1, crn, crm, op2) \
113+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
114+ write_msr(reg_name, value); \
115+ break;
116+ INTR_CTRL_REGISTERS
117+#undef X
118+ default:
119+ dlog_notice(
120+ "Unsupported interrupt control register "
121+ "write: "
122+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
123+ "rt=%d.\n",
124+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
125+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
126+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
127+ break;
128+ }
129+ }
130+
131+ return true;
132+}
133diff --git a/src/arch/aarch64/hypervisor/perfmon.h b/src/arch/aarch64/hypervisor/perfmon.h
134index 81669ba..c90d45b 100644
135--- a/src/arch/aarch64/hypervisor/perfmon.h
136+++ b/src/arch/aarch64/hypervisor/perfmon.h
137@@ -70,3 +70,8 @@ bool perfmon_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
138 uintreg_t esr_el2);
139
140 uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id);
141+
142+bool intr_ctrl_is_register_access(uintreg_t esr);
143+
144+bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
145+ uintreg_t esr);
146diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h
147index 55e7833..82aa884 100644
148--- a/src/arch/aarch64/msr.h
149+++ b/src/arch/aarch64/msr.h
150@@ -134,3 +134,6 @@
151 #define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1
152 #define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2
153 #define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0
154+
155+#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
156+#define ICC_SGI1R_EL1 S3_0_C12_C11_5
157--
1582.17.1
159