source: rtems/cpukit/score/cpu/nios2/nios2-eic-il-low-level.S @ 98c95d1

Last change on this file since 98c95d1 was 98c95d1, checked in by Sebastian Huber <sebastian.huber@…>, on 01/05/21 at 09:53:35

nios2: Fix ISR dispatch variants

The thread dispatch disabled level moved to _Per_CPU_Information some
time ago.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <rtems/score/percpu.h>
16#include <rtems/score/nios2-utility.h>
17
18#define FRAME_OFFSET_RA 0
19#define FRAME_OFFSET_AT 4
20#define FRAME_OFFSET_R2 8
21#define FRAME_OFFSET_R3 12
22#define FRAME_OFFSET_R4 16
23#define FRAME_OFFSET_R5 20
24#define FRAME_OFFSET_R6 24
25#define FRAME_OFFSET_R7 28
26#define FRAME_OFFSET_R8 32
27#define FRAME_OFFSET_R9 36
28#define FRAME_OFFSET_R10 40
29#define FRAME_OFFSET_R11 44
30#define FRAME_OFFSET_R12 48
31#define FRAME_OFFSET_R13 52
32#define FRAME_OFFSET_R14 56
33#define FRAME_OFFSET_R15 60
34#define FRAME_OFFSET_STATUS 64
35#define FRAME_OFFSET_EA  68
36
37#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
38
39        .set    noat
40        .set    nobreak
41        .section        .text
42
43        .extern _Per_CPU_Information
44        .extern _Nios2_Thread_dispatch_disabled
45        .extern _Nios2_ISR_Status_interrupts_disabled
46
47        .globl  _Nios2_ISR_Dispatch_with_shadow_non_preemptive
48
49_Nios2_ISR_Dispatch_with_shadow_non_preemptive:
50
51        /* Load thread dispatch disable level */
52        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
53
54        /* Load high level handler address and argument */
55        ldw     r8, 4(et)
56        ldw     r4, 8(et)
57
58        /* Increment and store thread dispatch disable level */
59        addi    r9, r16, 1
60        stw     r9, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
61
62        /* Call high level handler with argument */
63        callr   r8
64
65        /* Load thread dispatch necessary */
66        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
67
68        /* Load Nios II specific thread dispatch disabled */
69        ldw     r13, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
70
71        /* Read status */
72        rdctl   r14, status
73
74        /* Fix return address */
75        subi    ea, ea, 4
76
77        /*
78         * Restore the thread dispatch disable level.  We must do this before
79         * we return to the normal register set, because otherwise we have
80         * problems if someone deletes or restarts the interrupted thread while
81         * we are in the thread dispatch helper.
82         */
83        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
84
85        /* Is thread dispatch allowed? */
86        bne     r16, zero, no_thread_dispatch
87
88        /* Is thread dispatch necessary? */
89        beq     r12, zero, no_thread_dispatch
90
91        /* Is outermost interrupt? */
92        andhi   r14, r14, 0x3f
93        bne     r14, zero, no_thread_dispatch
94
95        /* Is Nios II specific thread dispatch allowed? */
96        bne     r13, zero, no_thread_dispatch
97
98        /* Obtain stack frame in normal register set */
99        rdprs   r15, sp, -FRAME_SIZE
100
101        /* Disable Nios II specific thread dispatch */
102        stw     r12, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
103
104        /* Save context */
105        stw     sstatus, FRAME_OFFSET_STATUS(r15)
106        stw     ea, FRAME_OFFSET_EA(r15)
107
108        /* Set thread dispatch helper address */
109        movhi   ea, %hiadj(thread_dispatch_helper)
110        addi    ea, ea, %lo(thread_dispatch_helper)
111
112        /* Update stack pointer in normal register set */
113        wrprs   sp, r15
114
115no_thread_dispatch:
116
117        /*
118         * Return to thread dispatch helper, interrupted thread or interrupted
119         * lower level interrupt service routine.
120         */
121        eret
122
123thread_dispatch_helper:
124
125        /* This code executes in the context of the interrupted thread */
126
127        /* Save volatile registers */
128        stw     ra, FRAME_OFFSET_RA(sp)
129        stw     at, FRAME_OFFSET_AT(sp)
130        stw     r2, FRAME_OFFSET_R2(sp)
131        stw     r3, FRAME_OFFSET_R3(sp)
132        stw     r4, FRAME_OFFSET_R4(sp)
133        stw     r5, FRAME_OFFSET_R5(sp)
134        stw     r6, FRAME_OFFSET_R6(sp)
135        stw     r7, FRAME_OFFSET_R7(sp)
136        stw     r8, FRAME_OFFSET_R8(sp)
137        stw     r9, FRAME_OFFSET_R9(sp)
138        stw     r10, FRAME_OFFSET_R10(sp)
139        stw     r11, FRAME_OFFSET_R11(sp)
140        stw     r12, FRAME_OFFSET_R12(sp)
141        stw     r13, FRAME_OFFSET_R13(sp)
142        stw     r14, FRAME_OFFSET_R14(sp)
143        stw     r15, FRAME_OFFSET_R15(sp)
144
145do_thread_dispatch:
146
147        call    _Thread_Dispatch
148
149        /* Restore some volatile registers */
150        ldw     ra, FRAME_OFFSET_RA(sp)
151        ldw     at, FRAME_OFFSET_AT(sp)
152        ldw     r2, FRAME_OFFSET_R2(sp)
153        ldw     r3, FRAME_OFFSET_R3(sp)
154        ldw     r4, FRAME_OFFSET_R4(sp)
155        ldw     r5, FRAME_OFFSET_R5(sp)
156        ldw     r6, FRAME_OFFSET_R6(sp)
157        ldw     r7, FRAME_OFFSET_R7(sp)
158        ldw     r8, FRAME_OFFSET_R8(sp)
159        ldw     r9, FRAME_OFFSET_R9(sp)
160        ldw     r10, FRAME_OFFSET_R10(sp)
161        ldw     r11, FRAME_OFFSET_R11(sp)
162        ldw     r12, FRAME_OFFSET_R12(sp)
163
164        /*
165         * Disable interrupts.
166         *
167         * We have the following invariants:
168         *   1. status.RSIE == 0: thread context initialization
169         *   2. status.CRS == 0: thread context initialization
170         *   3. status.PRS: arbitrary
171         *   4. status.IL < interrupt disable IL: else we would not be here
172         *   5. status.IH == 0: thread context initialization
173         *   6. status.U == 0: thread context initialization
174         *   7. status.PIE == 1: thread context initialization
175         * Thus we can use a constant to disable interrupts.
176         */
177        rdctl   r14, status
178        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
179        wrctl   status, r15
180
181        /* Load thread dispatch necessary */
182        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
183
184        /* Is thread dispatch necessary? */
185        bne     r13, zero, enable_interrupts_before_thread_dispatch
186
187        /* Enable Nios II specific thread dispatch */
188        stw     zero, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
189
190        /* Restore remaining volatile register */
191        ldw     r13, FRAME_OFFSET_R13(sp)
192        ldw     r14, FRAME_OFFSET_R14(sp)
193        ldw     r15, FRAME_OFFSET_R15(sp)
194
195        /* Restore context */
196        ldw     et, FRAME_OFFSET_STATUS(sp)
197        ldw     ea, FRAME_OFFSET_EA(sp)
198
199        /* Release stack frame */
200        addi    sp, sp, FRAME_SIZE
201
202        /* Restore context */
203        wrctl   estatus, et
204
205        /* Return to interrupted thread */
206        eret
207
208enable_interrupts_before_thread_dispatch:
209
210        /* Restore status */
211        wrctl   status, r14
212
213        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.