@@ -32,7 +32,7 @@ uint8_t g_nvic_prio_bits;
3232 * @internal
3333 *
3434 * If multiple disable-/re-enable-all functions are called in the same box, a
35- * counter is respectively incremented/drecremented so that it never happens
35+ * counter is respectively incremented/decremented so that it never happens
3636 * that a nested function re-enables IRQs for the caller. */
3737uint32_t g_irq_disable_all_counter [UVISOR_MAX_BOXES ];
3838
@@ -68,7 +68,7 @@ void unvic_acl_add(uint8_t box_id, void *function, uint32_t irqn)
6868 uv = & g_unvic_vector [irqn ];
6969
7070 /* check if IRQ entry is populated */
71- if (uv -> id || uv -> hdlr )
71+ if (uv -> id != UVISOR_BOX_ID_INVALID )
7272 {
7373 HALT_ERROR (PERMISSION_DENIED ,
7474 "Permission denied: IRQ %d is owned by box %d\n\r" , irqn ,
@@ -80,9 +80,15 @@ void unvic_acl_add(uint8_t box_id, void *function, uint32_t irqn)
8080 uv -> hdlr = function ;
8181}
8282
83+ #define UNVIC_ISR_OWNER_OTHER 0
84+ #define UNVIC_ISR_OWNER_NONE 1
85+ #define UNVIC_ISR_OWNER_SELF 2
86+
87+ /* @retval 0 you do not own this interrupt
88+ * @retval 1 you own or you can claim this interrupt
89+ */
8390static int unvic_acl_check (int irqn )
8491{
85- int is_irqn_registered ;
8692 TIsrUVector * uv ;
8793
8894 /* don't allow to modify uVisor-owned IRQs */
@@ -91,113 +97,83 @@ static int unvic_acl_check(int irqn)
9197 /* get vector entry */
9298 uv = & g_unvic_vector [irqn ];
9399
94- /* an IRQn slot is considered as registered if the ISR entry in the unprivileged
95- * table is not 0 */
96- is_irqn_registered = uv -> hdlr ? 1 : 0 ;
100+ if (uv -> id == g_active_box || uv -> id == UVISOR_BOX_ID_INVALID ) {
101+ return 1 ;
102+ }
103+ DPRINTF ("Disallowed to access IRQ %d from box %d!\n\r" , irqn , g_active_box );
104+ return 0 ;
105+ }
97106
98- /* check if the same box that registered the IRQn is accessing it
99- * note: if the vector entry for a certain IRQn is 0, it means that no secure
100- * box claimed exclusive ownership for it. So, another box can claim it
101- * if it is currently un-registered (that is, if the registered handler
102- * is NULL) */
103- if (uv -> id != g_active_box && (uv -> id || is_irqn_registered ))
107+ /* @retval 0 you do not own this interrupt
108+ * @retval 1 you own this interrupt
109+ */
110+ static int unvic_isr_register (uint32_t irqn )
111+ {
112+ int isr_status = unvic_acl_check (irqn );
113+ switch (isr_status )
104114 {
105- HALT_ERROR (PERMISSION_DENIED ,
106- "Permission denied: IRQ %d is owned by box %d\n\r" , irqn ,
107- uv -> id );
115+ case UNVIC_ISR_OWNER_NONE :
116+ g_unvic_vector [irqn ].id = g_active_box ;
117+ DPRINTF ("IRQ %d registered to box %d\n\r" , irqn , g_active_box );
118+ case UNVIC_ISR_OWNER_SELF :
119+ return 1 ;
120+ default :
121+ break ;
108122 }
109-
110- return is_irqn_registered ;
123+ return 0 ;
111124}
112125
113126void unvic_isr_set (uint32_t irqn , uint32_t vector )
114127{
115128 /* verify IRQ access privileges */
116- unvic_acl_check (irqn );
117-
118- /* save unprivileged handler
119- * note: if the handler is NULL the IRQn gets de-registered for the current
120- * box, meaning that other boxes can still use it. In this way boxes
121- * can share un-exclusive IRQs. A secure box should not do that if it
122- * wants to hold exclusivity over an IRQn
123- * note: when an IRQ is released (de-registered) the corresponding IRQn is
124- * disabled, to ensure that no spurious interrupts are served */
125- if (vector ) {
126- g_unvic_vector [irqn ].id = g_active_box ;
127- }
128- else {
129- NVIC_DisableIRQ (irqn );
130- g_unvic_vector [irqn ].id = 0 ;
129+ if (!unvic_isr_register (irqn )) {
130+ return ;
131131 }
132- g_unvic_vector [irqn ].hdlr = (TIsrVector ) vector ;
133-
134- /* set default priority (SVC must always be higher) */
135- NVIC_SetPriority (irqn , __UVISOR_NVIC_MIN_PRIORITY );
136132
137- DPRINTF ("IRQ %d %s box %d\n\r" ,
138- irqn ,
139- vector ? "registered to" : "released by" ,
140- g_active_box );
133+ /* save unprivileged handler */
134+ g_unvic_vector [irqn ].hdlr = (TIsrVector ) vector ;
141135}
142136
143137uint32_t unvic_isr_get (uint32_t irqn )
144138{
145139 /* verify IRQ access privileges */
146- unvic_acl_check (irqn );
140+ if (!unvic_isr_register (irqn )) {
141+ return 0 ;
142+ }
147143
148144 return (uint32_t ) g_unvic_vector [irqn ].hdlr ;
149145}
150146
151147void unvic_irq_enable (uint32_t irqn )
152148{
153- int is_irqn_registered ;
154-
155149 /* verify IRQ access privileges */
156- is_irqn_registered = unvic_acl_check (irqn );
157-
158- /* Enable the IRQ, but only if IRQs are not globally disabled for the
159- * currently active box. */
160- if (is_irqn_registered ) {
161- /* If the counter of nested disable-all IRQs is set to 0, it means that
162- * IRQs are not globally disabled for the current box. */
163- if (!g_irq_disable_all_counter [g_active_box ]) {
164- DPRINTF ("IRQ %d enabled\n\r" , irqn );
165- NVIC_EnableIRQ (irqn );
166- } else {
167- /* We do not enable the IRQ directly, but notify uVisor to enable it
168- * when IRQs will be re-enabled globally for the current box. */
169- g_unvic_vector [irqn ].was_enabled = true;
170- }
171- return ;
172- }
173- else if (UNVIC_IS_IRQ_ENABLED (irqn )) {
174- DPRINTF ("IRQ %d is unregistered; state unchanged\n\r" , irqn );
150+ if (!unvic_isr_register (irqn )) {
175151 return ;
176152 }
177- else {
178- HALT_ERROR (NOT_ALLOWED , "IRQ %d is unregistered; state cannot be changed" , irqn );
153+
154+ /* If the counter of nested disable-all IRQs is set to 0, it means that
155+ * IRQs are not globally disabled for the current box. */
156+ if (!g_irq_disable_all_counter [g_active_box ]) {
157+ DPRINTF ("IRQ %d enabled\n\r" , irqn );
158+ NVIC_EnableIRQ (irqn );
159+ } else {
160+ /* We do not enable the IRQ directly, but notify uVisor to enable it
161+ * when IRQs will be re-enabled globally for the current box. */
162+ g_unvic_vector [irqn ].was_enabled = true;
179163 }
164+ return ;
180165}
181166
182167void unvic_irq_disable (uint32_t irqn )
183168{
184- int is_irqn_registered ;
185-
186169 /* verify IRQ access privileges */
187- is_irqn_registered = unvic_acl_check (irqn );
188-
189- if (is_irqn_registered ) {
190- DPRINTF ("IRQ %d disabled, but still owned by box %d\n\r" , irqn , g_unvic_vector [irqn ].id );
191- NVIC_DisableIRQ (irqn );
192- return ;
193- }
194- else if (!UNVIC_IS_IRQ_ENABLED (irqn )) {
195- DPRINTF ("IRQ %d is unregistered; state unchanged\n\r" , irqn );
170+ if (!unvic_isr_register (irqn )) {
196171 return ;
197172 }
198- else {
199- HALT_ERROR (NOT_ALLOWED , "IRQ %d is unregistered; state cannot be changed" , irqn );
200- }
173+
174+ DPRINTF ("IRQ %d disabled, but still owned by box %d\n\r" , irqn , g_unvic_vector [irqn ].id );
175+ NVIC_DisableIRQ (irqn );
176+ return ;
201177}
202178
203179/** Disable all interrupts for the currently active box.
@@ -296,77 +272,63 @@ void unvic_irq_enable_all(void)
296272
297273void unvic_irq_pending_clr (uint32_t irqn )
298274{
299- int is_irqn_registered ;
300-
301275 /* verify IRQ access privileges */
302- is_irqn_registered = unvic_acl_check (irqn );
303-
304- /* enable IRQ */
305- if (is_irqn_registered ) {
306- DPRINTF ("IRQ %d pending status cleared\n\r" , irqn );
307- NVIC_ClearPendingIRQ (irqn );
276+ if (!unvic_isr_register (irqn )) {
308277 return ;
309278 }
310- else {
311- HALT_ERROR (NOT_ALLOWED , "IRQ %d is unregistered; state cannot be changed" , irqn );
312- }
279+
280+ /* clear pending IRQ */
281+ DPRINTF ("IRQ %d pending status cleared\n\r" , irqn );
282+ NVIC_ClearPendingIRQ (irqn );
313283}
314284
315285void unvic_irq_pending_set (uint32_t irqn )
316286{
317- int is_irqn_registered ;
318-
319287 /* verify IRQ access privileges */
320- is_irqn_registered = unvic_acl_check (irqn );
321-
322- /* enable IRQ */
323- if (is_irqn_registered ) {
324- DPRINTF ("IRQ %d pending status set (will be served as soon as possible)\n\r" , irqn );
325- NVIC_SetPendingIRQ (irqn );
288+ if (!unvic_isr_register (irqn )) {
326289 return ;
327290 }
328- else {
329- HALT_ERROR (NOT_ALLOWED , "IRQ %d is unregistered; state cannot be changed" , irqn );
330- }
291+
292+ /* set pending IRQ */
293+ DPRINTF ("IRQ %d pending status set (will be served as soon as possible)\n\r" , irqn );
294+ NVIC_SetPendingIRQ (irqn );
331295}
332296
333297uint32_t unvic_irq_pending_get (uint32_t irqn )
334298{
335299 /* verify IRQ access privileges */
336- unvic_acl_check (irqn );
300+ if (!unvic_isr_register (irqn )) {
301+ return 0 ;
302+ }
337303
338304 /* get priority for device specific interrupts */
339305 return NVIC_GetPendingIRQ (irqn );
340306}
341307
342308void unvic_irq_priority_set (uint32_t irqn , uint32_t priority )
343309{
344- int is_irqn_registered ;
345-
346310 /* verify IRQ access privileges */
347- is_irqn_registered = unvic_acl_check (irqn );
311+ if (!unvic_isr_register (irqn )) {
312+ return ;
313+ }
348314
349315 /* check for maximum priority */
350316 if (priority > UVISOR_VIRQ_MAX_PRIORITY ) {
351317 HALT_ERROR (NOT_ALLOWED , "NVIC priority overflow; max priority allowed: %d\n\r" , UVISOR_VIRQ_MAX_PRIORITY );
352318 }
353319
354320 /* set priority for device specific interrupts */
355- if (is_irqn_registered ) {
356- DPRINTF ("IRQ %d priority set to %d (NVIC), %d (virtual)\n\r" , irqn , __UVISOR_NVIC_MIN_PRIORITY + priority ,
357- priority );
358- NVIC_SetPriority (irqn , __UVISOR_NVIC_MIN_PRIORITY + priority );
359- return ;
360- }
361- else {
362- HALT_ERROR (NOT_ALLOWED , "IRQ %d is unregistered; state cannot be changed" , irqn );
363- }
321+ DPRINTF ("IRQ %d priority set to %d (NVIC), %d (virtual)\n\r" , irqn , __UVISOR_NVIC_MIN_PRIORITY + priority ,
322+ priority );
323+ NVIC_SetPriority (irqn , __UVISOR_NVIC_MIN_PRIORITY + priority );
364324}
365325
366326uint32_t unvic_irq_priority_get (uint32_t irqn )
367327{
368328 /* verify IRQ access privileges */
369- unvic_acl_check (irqn );
329+ if (!unvic_isr_register (irqn )) {
330+ return 0 ;
331+ }
370332
371333 /* get priority for device specific interrupts */
372334 return NVIC_GetPriority (irqn ) - __UVISOR_NVIC_MIN_PRIORITY ;
@@ -560,7 +522,7 @@ void unvic_gateway_context_switch_out(uint32_t svc_sp, uint32_t msp)
560522 __set_CONTROL (__get_CONTROL () & ~2 );
561523}
562524
563- void unvic_init (void )
525+ void unvic_init (uint32_t const * const user_vtor )
564526{
565527 uint8_t prio_bits ;
566528 uint8_t volatile * prio ;
@@ -604,4 +566,12 @@ void unvic_init(void)
604566 * by IRQ number. For example, IRQ 0 has precedence over IRQ 1 if both have
605567 * the same priority level. */
606568 NVIC_SetPriorityGrouping (0 );
569+
570+ /* Copy the user interrupt table into the handlers. */
571+ for (uint32_t ii = 0 ; ii < NVIC_VECTORS ; ii ++ ) {
572+ g_unvic_vector [ii ].id = UVISOR_BOX_ID_INVALID ;
573+ g_unvic_vector [ii ].hdlr = (TIsrVector ) user_vtor [ii + NVIC_OFFSET ];
574+ /* set default priority (SVC must always be higher) */
575+ NVIC_SetPriority (ii , __UVISOR_NVIC_MIN_PRIORITY );
576+ }
607577}
0 commit comments