Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 1 | From 97a8ca1835f5d9512dacda497540d5523e56c7dd Mon Sep 17 00:00:00 2001 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 2 | From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com> |
| 3 | Date: Tue, 26 Apr 2022 14:43:58 +0100 |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 4 | Subject: [PATCH] feat: emulate interrupt controller register access |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 5 | |
| 6 | This emulates ICC_SGI1R_EL1 and ICC_IGRPEN1_EL1 register |
| 7 | |
| 8 | Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com> |
| 9 | Change-Id: I0c11f034f3676067597461a183a341c809adcaa4 |
| 10 | Upstream-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 | |
| 18 | diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 19 | index 4c1b6e48..cd5146bd 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 20 | --- a/src/arch/aarch64/hypervisor/handler.c |
| 21 | +++ b/src/arch/aarch64/hypervisor/handler.c |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 22 | @@ -1283,6 +1283,11 @@ void handle_system_register_access(uintreg_t esr_el2) |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 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; |
| 34 | diff --git a/src/arch/aarch64/hypervisor/perfmon.c b/src/arch/aarch64/hypervisor/perfmon.c |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 35 | index f13b0354..05e216c8 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 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 | +} |
| 133 | diff --git a/src/arch/aarch64/hypervisor/perfmon.h b/src/arch/aarch64/hypervisor/perfmon.h |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 134 | index 81669ba1..c90d45bf 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 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); |
| 146 | diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h |
Patrick Williams | 7784c42 | 2022-11-17 07:29:11 -0600 | [diff] [blame^] | 147 | index 55e78330..82aa8846 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 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 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 157 | |