Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame^] | 1 | From cad33cffb5be17fc0654aaf03c4d5227ae682e7a Mon Sep 17 00:00:00 2001 |
| 2 | From: Imre Kis <imre.kis@arm.com> |
| 3 | Date: Tue, 25 Apr 2023 14:19:14 +0200 |
| 4 | Subject: [PATCH] core: spmc: configure SP's NS interrupt action based on |
| 5 | the manifest |
| 6 | |
| 7 | Used mandatory ns-interrupts-action SP manifest property to configure |
| 8 | signaled or queued non-secure interrupt handling. |
| 9 | |
| 10 | Upstream-Status: Submitted [https://github.com/OP-TEE/optee_os/pull/6002] |
| 11 | |
| 12 | Signed-off-by: Imre Kis <imre.kis@arm.com> |
| 13 | Change-Id: I843e69e5dbb9613ecd8b95654e8ca1730a594ca6 |
| 14 | --- |
| 15 | .../arm/include/kernel/secure_partition.h | 2 + |
| 16 | core/arch/arm/kernel/secure_partition.c | 66 +++++++++++++++++-- |
| 17 | 2 files changed, 63 insertions(+), 5 deletions(-) |
| 18 | |
| 19 | diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h |
| 20 | index 290750936..3bf339d3c 100644 |
| 21 | --- a/core/arch/arm/include/kernel/secure_partition.h |
| 22 | +++ b/core/arch/arm/include/kernel/secure_partition.h |
| 23 | @@ -43,6 +43,8 @@ struct sp_session { |
| 24 | unsigned int spinlock; |
| 25 | const void *fdt; |
| 26 | bool is_initialized; |
| 27 | + uint32_t ns_interrupts_action; |
| 28 | + uint32_t ns_interrupts_action_inherited; |
| 29 | TAILQ_ENTRY(sp_session) link; |
| 30 | }; |
| 31 | |
| 32 | diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c |
| 33 | index 52365553b..e54069c17 100644 |
| 34 | --- a/core/arch/arm/kernel/secure_partition.c |
| 35 | +++ b/core/arch/arm/kernel/secure_partition.c |
| 36 | @@ -46,6 +46,10 @@ |
| 37 | SP_MANIFEST_ATTR_WRITE | \ |
| 38 | SP_MANIFEST_ATTR_EXEC) |
| 39 | |
| 40 | +#define SP_MANIFEST_NS_INT_QUEUED (0x0) |
| 41 | +#define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1) |
| 42 | +#define SP_MANIFEST_NS_INT_SIGNALED (0x2) |
| 43 | + |
| 44 | #define SP_PKG_HEADER_MAGIC (0x474b5053) |
| 45 | #define SP_PKG_HEADER_VERSION_V1 (0x1) |
| 46 | #define SP_PKG_HEADER_VERSION_V2 (0x2) |
| 47 | @@ -907,6 +911,30 @@ static TEE_Result sp_init_uuid(const TEE_UUID *uuid, const void * const fdt) |
| 48 | return res; |
| 49 | DMSG("endpoint is 0x%"PRIx16, sess->endpoint_id); |
| 50 | |
| 51 | + res = sp_dt_get_u32(fdt, 0, "ns-interrupts-action", |
| 52 | + &sess->ns_interrupts_action); |
| 53 | + |
| 54 | + if (res) { |
| 55 | + EMSG("Mandatory property is missing: ns-interrupts-action"); |
| 56 | + return res; |
| 57 | + } |
| 58 | + |
| 59 | + switch (sess->ns_interrupts_action) { |
| 60 | + case SP_MANIFEST_NS_INT_QUEUED: |
| 61 | + case SP_MANIFEST_NS_INT_SIGNALED: |
| 62 | + /* OK */ |
| 63 | + break; |
| 64 | + |
| 65 | + case SP_MANIFEST_NS_INT_MANAGED_EXIT: |
| 66 | + EMSG("Managed exit is not implemented"); |
| 67 | + return TEE_ERROR_NOT_IMPLEMENTED; |
| 68 | + |
| 69 | + default: |
| 70 | + EMSG("Invalid ns-interrupts-action value: %d", |
| 71 | + sess->ns_interrupts_action); |
| 72 | + return TEE_ERROR_BAD_PARAMETERS; |
| 73 | + } |
| 74 | + |
| 75 | return TEE_SUCCESS; |
| 76 | } |
| 77 | |
| 78 | @@ -989,17 +1017,45 @@ TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp) |
| 79 | return res; |
| 80 | } |
| 81 | |
| 82 | +/* |
| 83 | + * According to FF-A v1.1 section 8.3.1.4 if a caller requires less permissive |
| 84 | + * active on NS interrupt than the callee, the callee must inherit the caller's |
| 85 | + * configuration. |
| 86 | + * Each SP's own NS action setting is stored in ns_interrupts_action. The |
| 87 | + * effective action will be MIN([self action], [caller's action]) which is |
| 88 | + * stored in the ns_interrupts_action_inherited field. |
| 89 | + */ |
| 90 | +static void sp_cpsr_configure_foreing_interrupts(struct sp_session *s, |
| 91 | + struct ts_session *caller, |
| 92 | + uint64_t *cpsr) |
| 93 | +{ |
| 94 | + if (caller) { |
| 95 | + struct sp_session *caller_sp = to_sp_session(caller); |
| 96 | + |
| 97 | + s->ns_interrupts_action_inherited = |
| 98 | + MIN(caller_sp->ns_interrupts_action_inherited, |
| 99 | + s->ns_interrupts_action); |
| 100 | + } else { |
| 101 | + s->ns_interrupts_action_inherited = s->ns_interrupts_action; |
| 102 | + } |
| 103 | + |
| 104 | + if (s->ns_interrupts_action_inherited == SP_MANIFEST_NS_INT_QUEUED) |
| 105 | + *cpsr |= (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT); |
| 106 | + else |
| 107 | + *cpsr &= ~(THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT); |
| 108 | +} |
| 109 | + |
| 110 | static TEE_Result sp_enter_invoke_cmd(struct ts_session *s, |
| 111 | uint32_t cmd __unused) |
| 112 | { |
| 113 | struct sp_ctx *ctx = to_sp_ctx(s->ctx); |
| 114 | TEE_Result res = TEE_SUCCESS; |
| 115 | uint32_t exceptions = 0; |
| 116 | - uint64_t cpsr = 0; |
| 117 | struct sp_session *sp_s = to_sp_session(s); |
| 118 | struct ts_session *sess = NULL; |
| 119 | struct thread_ctx_regs *sp_regs = NULL; |
| 120 | uint32_t thread_id = THREAD_ID_INVALID; |
| 121 | + struct ts_session *caller = NULL; |
| 122 | uint32_t rpc_target_info = 0; |
| 123 | uint32_t panicked = false; |
| 124 | uint32_t panic_code = 0; |
| 125 | @@ -1009,11 +1065,12 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s, |
| 126 | sp_regs = &ctx->sp_regs; |
| 127 | ts_push_current_session(s); |
| 128 | |
| 129 | - cpsr = sp_regs->cpsr; |
| 130 | - sp_regs->cpsr = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT); |
| 131 | - |
| 132 | exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); |
| 133 | |
| 134 | + /* Enable/disable foreign interrupts in CPSR/SPSR */ |
| 135 | + caller = ts_get_calling_session(); |
| 136 | + sp_cpsr_configure_foreing_interrupts(sp_s, caller, &sp_regs->cpsr); |
| 137 | + |
| 138 | /* |
| 139 | * Store endpoint ID and thread ID in rpc_target_info. This will be used |
| 140 | * as w1 in FFA_INTERRUPT in case of a NWd interrupt. |
| 141 | @@ -1026,7 +1083,6 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s, |
| 142 | |
| 143 | __thread_enter_user_mode(sp_regs, &panicked, &panic_code); |
| 144 | |
| 145 | - sp_regs->cpsr = cpsr; |
| 146 | /* Restore rpc_target_info */ |
| 147 | thread_get_tsd()->rpc_target_info = rpc_target_info; |
| 148 | |
| 149 | -- |
| 150 | 2.17.1 |